diff options
author | stanislavh <stanislav.honcharov@sonarsource.com> | 2023-05-03 10:57:05 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2023-05-04 20:03:11 +0000 |
commit | 5032367a49ba54473c2497e3a545426a96ef6fc6 (patch) | |
tree | 2c401ce5983a3ef608f9840b049b8276fca37028 /server/sonar-web/src/main/js/components/tutorials | |
parent | d43927c62a94a3d6f9b12ef0b4b7a1f9418b560c (diff) | |
download | sonarqube-5032367a49ba54473c2497e3a545426a96ef6fc6.tar.gz sonarqube-5032367a49ba54473c2497e3a545426a96ef6fc6.zip |
SONAR-17146 Tutorial for Gradle should Consider Kotlin DSL
Diffstat (limited to 'server/sonar-web/src/main/js/components/tutorials')
18 files changed, 370 insertions, 106 deletions
diff --git a/server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/PreambuleYaml.tsx b/server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/PreambuleYaml.tsx index d54087fa9f1..87fec76d2af 100644 --- a/server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/PreambuleYaml.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/PreambuleYaml.tsx @@ -18,14 +18,10 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; -import { FormattedMessage } from 'react-intl'; -import { ClipboardIconButton } from '../../../components/controls/clipboard'; -import { translate } from '../../../helpers/l10n'; import { Component } from '../../../types/types'; -import CodeSnippet from '../../common/CodeSnippet'; import DefaultProjectKey from '../components/DefaultProjectKey'; +import GradleBuild from '../components/GradleBuild'; import { BuildTools } from '../types'; -import { buildGradleSnippet } from '../utils'; export interface PreambuleYamlProps { buildTool: BuildTools; @@ -36,24 +32,7 @@ export function PreambuleYaml(props: PreambuleYamlProps) { const { buildTool, component } = props; switch (buildTool) { case BuildTools.Gradle: - return ( - <li className="abs-width-600"> - <FormattedMessage - defaultMessage={translate('onboarding.tutorial.with.yaml.gradle')} - id="onboarding.tutorial.with.yaml.gradle" - values={{ - gradle: ( - <> - <code className="rule">build.gradle</code> - <ClipboardIconButton copyValue="build.gradle" /> - </> - ), - sq: <code className="rule">org.sonarqube</code>, - }} - /> - <CodeSnippet snippet={buildGradleSnippet(component.key, component.name)} /> - </li> - ); + return <GradleBuild component={component} />; case BuildTools.CFamily: case BuildTools.Other: return <DefaultProjectKey component={component} />; diff --git a/server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/__tests__/BitbucketPipelinesTutorial-it.tsx b/server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/__tests__/BitbucketPipelinesTutorial-it.tsx index 7d85f9e2ca5..0a1285123a2 100644 --- a/server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/__tests__/BitbucketPipelinesTutorial-it.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/__tests__/BitbucketPipelinesTutorial-it.tsx @@ -37,7 +37,7 @@ import { getTutorialActionButtons, getTutorialBuildButtons, } from '../../test-utils'; -import { TutorialModes } from '../../types'; +import { GradleBuildDSL, TutorialModes } from '../../types'; import BitbucketPipelinesTutorial, { BitbucketPipelinesTutorialProps, } from '../BitbucketPipelinesTutorial'; @@ -79,8 +79,10 @@ it('should follow and complete all steps', async () => { // Gradle await user.click(ui.gradleBuildButton.get()); - expect(getCopyToClipboardValue(1)).toMatchSnapshot('Gradle: build.gradle'); - expect(getCopyToClipboardValue(3)).toMatchSnapshot('Gradle: bitbucket-pipelines.yml'); + expect(getCopyToClipboardValue(2)).toMatchSnapshot('Groovy: build.gradle'); + await user.click(ui.gradleDSLButton(GradleBuildDSL.Kotlin).get()); + expect(getCopyToClipboardValue(2)).toMatchSnapshot('Kotlin: build.gradle.kts'); + expect(getCopyToClipboardValue(4)).toMatchSnapshot('Gradle: bitbucket-pipelines.yml'); // .NET await user.click(ui.dotnetBuildButton.get()); diff --git a/server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/__tests__/__snapshots__/BitbucketPipelinesTutorial-it.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/__tests__/__snapshots__/BitbucketPipelinesTutorial-it.tsx.snap index 4491112afda..918f9f18ec9 100644 --- a/server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/__tests__/__snapshots__/BitbucketPipelinesTutorial-it.tsx.snap +++ b/server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/__tests__/__snapshots__/BitbucketPipelinesTutorial-it.tsx.snap @@ -95,7 +95,7 @@ pipelines: - step: *build-step" `; -exports[`should follow and complete all steps: Gradle: build.gradle 1`] = ` +exports[`should follow and complete all steps: Groovy: build.gradle 1`] = ` "plugins { id "org.sonarqube" version "4.0.0.2929" } @@ -108,6 +108,19 @@ sonar { }" `; +exports[`should follow and complete all steps: Kotlin: build.gradle.kts 1`] = ` +"plugins { + id("org.sonarqube") version "4.0.0.2929" +} + +sonar { + properties { + property("sonar.projectKey", "my-project") + property("sonar.projectName", "MyProject") + } +}" +`; + exports[`should follow and complete all steps: Maven: bitbucket-pipelines.yml 1`] = ` "image: maven:3-openjdk-11 diff --git a/server/sonar-web/src/main/js/components/tutorials/components/GradleBuild.tsx b/server/sonar-web/src/main/js/components/tutorials/components/GradleBuild.tsx new file mode 100644 index 00000000000..895aadb09b1 --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/components/GradleBuild.tsx @@ -0,0 +1,63 @@ +/* + * SonarQube + * Copyright (C) 2009-2023 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import React from 'react'; +import { FormattedMessage } from 'react-intl'; +import { translate } from '../../../helpers/l10n'; +import { Component } from '../../../types/types'; +import CodeSnippet from '../../common/CodeSnippet'; +import { ClipboardIconButton } from '../../controls/clipboard'; +import { GradleBuildDSL } from '../types'; +import { buildGradleSnippet } from '../utils'; +import GradleBuildSelection from './GradleBuildSelection'; + +interface Props { + component: Component; +} + +export default function GradleBuild({ component }: Props) { + return ( + <li className="abs-width-600"> + <FormattedMessage + defaultMessage={translate('onboarding.tutorial.with.yaml.gradle')} + id="onboarding.tutorial.with.yaml.gradle" + values={{ + groovy: ( + <> + <code className="rule">{GradleBuildDSL.Groovy}</code> + <ClipboardIconButton copyValue={GradleBuildDSL.Groovy} /> + </> + ), + kotlin: ( + <> + <code className="rule">{GradleBuildDSL.Kotlin}</code> + <ClipboardIconButton copyValue={GradleBuildDSL.Kotlin} /> + </> + ), + sq: <code className="rule">org.sonarqube</code>, + }} + /> + <GradleBuildSelection className="big-spacer-top big-spacer-bottom"> + {(build) => ( + <CodeSnippet snippet={buildGradleSnippet(component.key, component.name, build)} /> + )} + </GradleBuildSelection> + </li> + ); +} diff --git a/server/sonar-web/src/main/js/components/tutorials/components/GradleBuildSelection.tsx b/server/sonar-web/src/main/js/components/tutorials/components/GradleBuildSelection.tsx new file mode 100644 index 00000000000..4ed7e7639c1 --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/components/GradleBuildSelection.tsx @@ -0,0 +1,49 @@ +/* + * SonarQube + * Copyright (C) 2009-2023 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import React from 'react'; +import ButtonToggle from '../../controls/ButtonToggle'; +import { GradleBuildDSL } from '../types'; + +interface Props { + className?: string; + children: (build: GradleBuildDSL) => React.ReactNode; +} + +export default function GradleBuildSelection({ children, className }: Props) { + const [build, setBuild] = React.useState<GradleBuildDSL>(GradleBuildDSL.Groovy); + + const buildOptions = Object.values(GradleBuildDSL).map((v: GradleBuildDSL) => ({ + label: v, + value: v, + })); + + return ( + <> + <div className={className}> + <ButtonToggle + options={buildOptions} + value={build} + onCheck={(value: GradleBuildDSL) => setBuild(value)} + /> + </div> + {children(build)} + </> + ); +} diff --git a/server/sonar-web/src/main/js/components/tutorials/github-action/__tests__/GithubActionTutorial-it.tsx b/server/sonar-web/src/main/js/components/tutorials/github-action/__tests__/GithubActionTutorial-it.tsx index 22bd3452109..06ab3f48ec5 100644 --- a/server/sonar-web/src/main/js/components/tutorials/github-action/__tests__/GithubActionTutorial-it.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/github-action/__tests__/GithubActionTutorial-it.tsx @@ -37,7 +37,7 @@ import { getTutorialActionButtons, getTutorialBuildButtons, } from '../../test-utils'; -import { TutorialModes } from '../../types'; +import { GradleBuildDSL, TutorialModes } from '../../types'; import GitHubActionTutorial, { GitHubActionTutorialProps } from '../GitHubActionTutorial'; jest.mock('../../../../api/user-tokens'); @@ -77,8 +77,10 @@ it('should follow and complete all steps', async () => { // Gradle await user.click(ui.gradleBuildButton.get()); - expect(getCopyToClipboardValue(1)).toMatchSnapshot('Gradle: build.gradle'); - expect(getCopyToClipboardValue(3)).toMatchSnapshot('Gradle: .github/workflows/build.yml'); + expect(getCopyToClipboardValue(2)).toMatchSnapshot('Groovy: build.gradle'); + await user.click(ui.gradleDSLButton(GradleBuildDSL.Kotlin).get()); + expect(getCopyToClipboardValue(2)).toMatchSnapshot('Kotlin: build.gradle.kts'); + expect(getCopyToClipboardValue(4)).toMatchSnapshot('Gradle: .github/workflows/build.yml'); // .NET await user.click(ui.dotnetBuildButton.get()); diff --git a/server/sonar-web/src/main/js/components/tutorials/github-action/__tests__/__snapshots__/GithubActionTutorial-it.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/github-action/__tests__/__snapshots__/GithubActionTutorial-it.tsx.snap index 178e17d2273..8d9f3823017 100644 --- a/server/sonar-web/src/main/js/components/tutorials/github-action/__tests__/__snapshots__/GithubActionTutorial-it.tsx.snap +++ b/server/sonar-web/src/main/js/components/tutorials/github-action/__tests__/__snapshots__/GithubActionTutorial-it.tsx.snap @@ -229,7 +229,7 @@ jobs: run: ./gradlew build sonar --info" `; -exports[`should follow and complete all steps: Gradle: build.gradle 1`] = ` +exports[`should follow and complete all steps: Groovy: build.gradle 1`] = ` "plugins { id "org.sonarqube" version "4.0.0.2929" } @@ -242,6 +242,19 @@ sonar { }" `; +exports[`should follow and complete all steps: Kotlin: build.gradle.kts 1`] = ` +"plugins { + id("org.sonarqube") version "4.0.0.2929" +} + +sonar { + properties { + property("sonar.projectKey", "my-project") + property("sonar.projectName", "MyProject") + } +}" +`; + exports[`should follow and complete all steps: Maven: .github/workflows/build.yml 1`] = ` "name: Build diff --git a/server/sonar-web/src/main/js/components/tutorials/github-action/commands/Gradle.tsx b/server/sonar-web/src/main/js/components/tutorials/github-action/commands/Gradle.tsx index 7d1a8247e21..c0e84c06cd8 100644 --- a/server/sonar-web/src/main/js/components/tutorials/github-action/commands/Gradle.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/github-action/commands/Gradle.tsx @@ -18,14 +18,10 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; -import { FormattedMessage } from 'react-intl'; -import { ClipboardIconButton } from '../../../../components/controls/clipboard'; -import { translate } from '../../../../helpers/l10n'; import { Component } from '../../../../types/types'; -import CodeSnippet from '../../../common/CodeSnippet'; import CreateYmlFile from '../../components/CreateYmlFile'; import FinishButton from '../../components/FinishButton'; -import { buildGradleSnippet } from '../../utils'; +import GradleBuild from '../../components/GradleBuild'; import { GITHUB_ACTIONS_RUNS_ON_LINUX } from '../constants'; import { generateGitHubActionsYaml } from '../utils'; @@ -65,22 +61,7 @@ export default function Gradle(props: GradleProps) { return ( <> - <li className="abs-width-600"> - <FormattedMessage - defaultMessage={translate('onboarding.tutorial.with.yaml.gradle')} - id="onboarding.tutorial.with.yaml.gradle" - values={{ - gradle: ( - <> - <code className="rule">build.gradle</code> - <ClipboardIconButton copyValue="build.gradle" /> - </> - ), - sq: <code className="rule">org.sonarqube</code>, - }} - /> - <CodeSnippet snippet={buildGradleSnippet(component.key, component.name)} /> - </li> + <GradleBuild component={component} /> <CreateYmlFile yamlFileName=".github/workflows/build.yml" yamlTemplate={generateGitHubActionsYaml( diff --git a/server/sonar-web/src/main/js/components/tutorials/gitlabci/YmlFileStep.tsx b/server/sonar-web/src/main/js/components/tutorials/gitlabci/YmlFileStep.tsx index ea255c15c0f..1b727795d95 100644 --- a/server/sonar-web/src/main/js/components/tutorials/gitlabci/YmlFileStep.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/gitlabci/YmlFileStep.tsx @@ -31,9 +31,10 @@ import CodeSnippet from '../../common/CodeSnippet'; import { withCLanguageFeature } from '../../hoc/withCLanguageFeature'; import FinishButton from '../components/FinishButton'; import GithubCFamilyExampleRepositories from '../components/GithubCFamilyExampleRepositories'; +import GradleBuildSelection from '../components/GradleBuildSelection'; import RenderOptions from '../components/RenderOptions'; import Step from '../components/Step'; -import { BuildTools, TutorialModes } from '../types'; +import { BuildTools, GradleBuildDSL, TutorialModes } from '../types'; import PipeCommand from './commands/PipeCommand'; export interface YmlFileStepProps extends WithAvailableFeaturesProps { @@ -50,7 +51,9 @@ const mavenSnippet = () => `<properties> <sonar.qualitygate.wait>true</sonar.qualitygate.wait> </properties>`; -const gradleSnippet = (key: string, name: string) => `plugins { +const gradleSnippet = (key: string, name: string, build: GradleBuildDSL) => { + const map = { + [GradleBuildDSL.Groovy]: `plugins { id "org.sonarqube" version "${GRADLE_SCANNER_VERSION}" } @@ -60,7 +63,21 @@ sonar { property "sonar.projectName", "${name}" property "sonar.qualitygate.wait", true } -}`; +}`, + [GradleBuildDSL.Kotlin]: `plugins { + id ("org.sonarqube") version "${GRADLE_SCANNER_VERSION}" +} + +sonar { + properties { + property("sonar.projectKey", "${key}") + property("sonar.projectName", "${name}") + property("sonar.qualitygate.wait", true) + } +}`, + }; + return map[build]; +}; const otherSnippet = (key: string) => `sonar.projectKey=${key} sonar.qualitygate.wait=true @@ -75,7 +92,7 @@ const snippetForBuildTool = { const filenameForBuildTool = { [BuildTools.Maven]: 'pom.xml', - [BuildTools.Gradle]: 'build.gradle', + [BuildTools.Gradle]: GradleBuildDSL.Groovy, [BuildTools.CFamily]: 'sonar-project.properties', [BuildTools.Other]: 'sonar-project.properties', }; @@ -118,19 +135,44 @@ export function YmlFileStep(props: YmlFileStepProps) { `onboarding.tutorial.with.gitlab_ci.project_key.${buildTool}.step2` )} id={`onboarding.tutorial.with.gitlab_ci.project_key.${buildTool}.step2`} - values={{ - file: ( - <> - <code className="rule">{filenameForBuildTool[buildTool]}</code> - <ClipboardIconButton - className="little-spacer-left" - copyValue={filenameForBuildTool[buildTool]} - /> - </> - ), - }} + values={Object.assign( + { + file: ( + <> + <code className="rule">{filenameForBuildTool[buildTool]}</code> + <ClipboardIconButton + className="little-spacer-left" + copyValue={filenameForBuildTool[buildTool]} + /> + </> + ), + }, + buildTool === BuildTools.Gradle + ? { + file2: ( + <> + <code className="rule">{GradleBuildDSL.Kotlin}</code> + <ClipboardIconButton + className="little-spacer-left" + copyValue={GradleBuildDSL.Kotlin} + /> + </> + ), + } + : {} + )} /> - <CodeSnippet snippet={snippetForBuildTool[buildTool](component.key, component.name)} /> + {buildTool === BuildTools.Gradle ? ( + <GradleBuildSelection className="spacer-top big-spacer-bottom"> + {(build) => ( + <CodeSnippet + snippet={snippetForBuildTool[buildTool](component.key, component.name, build)} + /> + )} + </GradleBuildSelection> + ) : ( + <CodeSnippet snippet={snippetForBuildTool[buildTool](component.key)} /> + )} </li> )} {buildTool && ( diff --git a/server/sonar-web/src/main/js/components/tutorials/gitlabci/__tests__/GitLabCITutorial-it.tsx b/server/sonar-web/src/main/js/components/tutorials/gitlabci/__tests__/GitLabCITutorial-it.tsx index d251382f17c..7d76c65e381 100644 --- a/server/sonar-web/src/main/js/components/tutorials/gitlabci/__tests__/GitLabCITutorial-it.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/gitlabci/__tests__/GitLabCITutorial-it.tsx @@ -31,7 +31,7 @@ import { getTutorialActionButtons, getTutorialBuildButtons, } from '../../test-utils'; -import { TutorialModes } from '../../types'; +import { GradleBuildDSL, TutorialModes } from '../../types'; import GitLabCITutorial, { GitLabCITutorialProps } from '../GitLabCITutorial'; jest.mock('../../../../api/user-tokens'); @@ -72,8 +72,10 @@ it('should follow and complete all steps', async () => { // Gradle await user.click(ui.gradleBuildButton.get()); - expect(getCopyToClipboardValue(1)).toMatchSnapshot('Gradle: build.gradle'); - expect(getCopyToClipboardValue(3)).toMatchSnapshot('Gradle: gitlab-ci.yml'); + expect(getCopyToClipboardValue(2)).toMatchSnapshot('Groovy: build.gradle'); + await user.click(ui.gradleDSLButton(GradleBuildDSL.Kotlin).get()); + expect(getCopyToClipboardValue(2)).toMatchSnapshot('Kotlin: build.gradle.kts'); + expect(getCopyToClipboardValue(4)).toMatchSnapshot('Gradle: gitlab-ci.yml'); // .NET await user.click(ui.dotnetBuildButton.get()); diff --git a/server/sonar-web/src/main/js/components/tutorials/gitlabci/__tests__/__snapshots__/GitLabCITutorial-it.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/gitlabci/__tests__/__snapshots__/GitLabCITutorial-it.tsx.snap index cc7c5e33d3d..d87708cae7b 100644 --- a/server/sonar-web/src/main/js/components/tutorials/gitlabci/__tests__/__snapshots__/GitLabCITutorial-it.tsx.snap +++ b/server/sonar-web/src/main/js/components/tutorials/gitlabci/__tests__/__snapshots__/GitLabCITutorial-it.tsx.snap @@ -63,20 +63,6 @@ sonar.qualitygate.wait=true " `; -exports[`should follow and complete all steps: Gradle: build.gradle 1`] = ` -"plugins { - id "org.sonarqube" version "4.0.0.2929" -} - -sonar { - properties { - property "sonar.projectKey", "my-project" - property "sonar.projectName", "MyProject" - property "sonar.qualitygate.wait", true - } -}" -`; - exports[`should follow and complete all steps: Gradle: gitlab-ci.yml 1`] = ` "sonarqube-check: image: gradle:jre11-slim @@ -94,6 +80,34 @@ exports[`should follow and complete all steps: Gradle: gitlab-ci.yml 1`] = ` " `; +exports[`should follow and complete all steps: Groovy: build.gradle 1`] = ` +"plugins { + id "org.sonarqube" version "4.0.0.2929" +} + +sonar { + properties { + property "sonar.projectKey", "my-project" + property "sonar.projectName", "MyProject" + property "sonar.qualitygate.wait", true + } +}" +`; + +exports[`should follow and complete all steps: Kotlin: build.gradle.kts 1`] = ` +"plugins { + id ("org.sonarqube") version "4.0.0.2929" +} + +sonar { + properties { + property("sonar.projectKey", "my-project") + property("sonar.projectName", "MyProject") + property("sonar.qualitygate.wait", true) + } +}" +`; + exports[`should follow and complete all steps: Maven: gitlab-ci.yml 1`] = ` "sonarqube-check: image: maven:3.6.3-jdk-11 diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/JenkinsTutorial-it.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/JenkinsTutorial-it.tsx index 045672dea7a..60c73e54192 100644 --- a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/JenkinsTutorial-it.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/JenkinsTutorial-it.tsx @@ -32,6 +32,7 @@ import { getTutorialActionButtons, getTutorialBuildButtons, } from '../../test-utils'; +import { GradleBuildDSL } from '../../types'; import JenkinsTutorial, { JenkinsTutorialProps } from '../JenkinsTutorial'; jest.mock('../../../../api/user-tokens'); @@ -117,9 +118,12 @@ it.each([AlmKeys.BitbucketCloud, AlmKeys.BitbucketServer, AlmKeys.GitHub, AlmKey await user.click(ui.mavenBuildButton.get()); expect(getCopyToClipboardValue()).toMatchSnapshot(`maven jenkinsfile`); - // Gradle + // Gradle (Groovy) await user.click(ui.gradleBuildButton.get()); - expect(getCopyToClipboardValue()).toMatchSnapshot(`build.gradle file`); + expect(getCopyToClipboardValue()).toMatchSnapshot(`Groovy: build.gradle file`); + // Gradle(Kotlin) + await user.click(ui.gradleDSLButton(GradleBuildDSL.Kotlin).get()); + expect(getCopyToClipboardValue()).toMatchSnapshot(`Kotlin: build.gradle.kts file`); expect(getCopyToClipboardValue(1)).toMatchSnapshot(`gradle jenkinsfile`); // .NET diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/JenkinsTutorial-it.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/JenkinsTutorial-it.tsx.snap index 12650e20ff1..5f8c93bd707 100644 --- a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/JenkinsTutorial-it.tsx.snap +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/JenkinsTutorial-it.tsx.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`bitbucket: can select devops platform and complete all the steps with copying code snippets: build.gradle file 1`] = ` +exports[`bitbucket: can select devops platform and complete all the steps with copying code snippets: Groovy: build.gradle file 1`] = ` "plugins { id "org.sonarqube" version "4.0.0.2929" } @@ -13,6 +13,19 @@ sonar { }" `; +exports[`bitbucket: can select devops platform and complete all the steps with copying code snippets: Kotlin: build.gradle.kts file 1`] = ` +"plugins { + id("org.sonarqube") version "4.0.0.2929" +} + +sonar { + properties { + property("sonar.projectKey", "my-project") + property("sonar.projectName", "MyProject") + } +}" +`; + exports[`bitbucket: can select devops platform and complete all the steps with copying code snippets: cfamily linux jenkinsfile 1`] = ` "node { stage('SCM') { @@ -194,7 +207,7 @@ exports[`bitbucket: can select devops platform and complete all the steps with c " `; -exports[`bitbucketcloud: can select devops platform and complete all the steps with copying code snippets: build.gradle file 1`] = ` +exports[`bitbucketcloud: can select devops platform and complete all the steps with copying code snippets: Groovy: build.gradle file 1`] = ` "plugins { id "org.sonarqube" version "4.0.0.2929" } @@ -207,6 +220,19 @@ sonar { }" `; +exports[`bitbucketcloud: can select devops platform and complete all the steps with copying code snippets: Kotlin: build.gradle.kts file 1`] = ` +"plugins { + id("org.sonarqube") version "4.0.0.2929" +} + +sonar { + properties { + property("sonar.projectKey", "my-project") + property("sonar.projectName", "MyProject") + } +}" +`; + exports[`bitbucketcloud: can select devops platform and complete all the steps with copying code snippets: cfamily linux jenkinsfile 1`] = ` "node { stage('SCM') { @@ -388,7 +414,7 @@ exports[`bitbucketcloud: can select devops platform and complete all the steps w " `; -exports[`github: can select devops platform and complete all the steps with copying code snippets: build.gradle file 1`] = ` +exports[`github: can select devops platform and complete all the steps with copying code snippets: Groovy: build.gradle file 1`] = ` "plugins { id "org.sonarqube" version "4.0.0.2929" } @@ -401,6 +427,19 @@ sonar { }" `; +exports[`github: can select devops platform and complete all the steps with copying code snippets: Kotlin: build.gradle.kts file 1`] = ` +"plugins { + id("org.sonarqube") version "4.0.0.2929" +} + +sonar { + properties { + property("sonar.projectKey", "my-project") + property("sonar.projectName", "MyProject") + } +}" +`; + exports[`github: can select devops platform and complete all the steps with copying code snippets: cfamily linux jenkinsfile 1`] = ` "node { stage('SCM') { @@ -582,7 +621,7 @@ exports[`github: can select devops platform and complete all the steps with copy " `; -exports[`gitlab: can select devops platform and complete all the steps with copying code snippets: build.gradle file 1`] = ` +exports[`gitlab: can select devops platform and complete all the steps with copying code snippets: Groovy: build.gradle file 1`] = ` "plugins { id "org.sonarqube" version "4.0.0.2929" } @@ -595,6 +634,19 @@ sonar { }" `; +exports[`gitlab: can select devops platform and complete all the steps with copying code snippets: Kotlin: build.gradle.kts file 1`] = ` +"plugins { + id("org.sonarqube") version "4.0.0.2929" +} + +sonar { + properties { + property("sonar.projectKey", "my-project") + property("sonar.projectName", "MyProject") + } +}" +`; + exports[`gitlab: can select devops platform and complete all the steps with copying code snippets: cfamily linux jenkinsfile 1`] = ` "node { stage('SCM') { diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/Gradle.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/Gradle.tsx index 478ae99d2dd..51c24f8c8ef 100644 --- a/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/Gradle.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/Gradle.tsx @@ -18,9 +18,12 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; +import { FormattedMessage } from 'react-intl'; +import { translate } from '../../../../helpers/l10n'; import CodeSnippet from '../../../common/CodeSnippet'; import FinishButton from '../../components/FinishButton'; -import SentenceWithFilename from '../../components/SentenceWithFilename'; +import GradleBuildSelection from '../../components/GradleBuildSelection'; +import { GradleBuildDSL } from '../../types'; import { buildGradleSnippet } from '../../utils'; import { LanguageProps } from '../JenkinsfileStep'; import CreateJenkinsfileBulletPoint from './CreateJenkinsfileBulletPoint'; @@ -38,14 +41,28 @@ const JENKINSFILE_SNIPPET = `node { export default function Gradle(props: LanguageProps) { const { component } = props; + return ( <> <li className="abs-width-600"> - <SentenceWithFilename - filename="build.gradle" - translationKey="onboarding.tutorial.with.jenkins.jenkinsfile.gradle.step2" - /> - <CodeSnippet snippet={buildGradleSnippet(component.key, component.name)} /> + <span className="markdown"> + <FormattedMessage + defaultMessage={translate( + 'onboarding.tutorial.with.jenkins.jenkinsfile.gradle.step2', + 'sentence' + )} + id="onboarding.tutorial.with.jenkins.jenkinsfile.gradle.step2.sentence" + values={{ + groovy: <code>{GradleBuildDSL.Groovy}</code>, + kotlin: <code>{GradleBuildDSL.Kotlin}</code>, + }} + /> + </span> + <GradleBuildSelection className="big-spacer-top big-spacer-bottom"> + {(build) => ( + <CodeSnippet snippet={buildGradleSnippet(component.key, component.name, build)} /> + )} + </GradleBuildSelection> </li> <CreateJenkinsfileBulletPoint snippet={JENKINSFILE_SNIPPET} /> <FinishButton onClick={props.onDone} /> diff --git a/server/sonar-web/src/main/js/components/tutorials/other/commands/JavaGradle.tsx b/server/sonar-web/src/main/js/components/tutorials/other/commands/JavaGradle.tsx index 929bb0e0904..d4d21baa62b 100644 --- a/server/sonar-web/src/main/js/components/tutorials/other/commands/JavaGradle.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/other/commands/JavaGradle.tsx @@ -25,6 +25,8 @@ import { Component } from '../../../../types/types'; import CodeSnippet from '../../../common/CodeSnippet'; import DocLink from '../../../common/DocLink'; import InstanceMessage from '../../../common/InstanceMessage'; +import GradleBuildSelection from '../../components/GradleBuildSelection'; +import { GradleBuildDSL } from '../../types'; import DoneNextSteps from '../DoneNextSteps'; export interface JavaGradleProps { @@ -33,11 +35,17 @@ export interface JavaGradleProps { token: string; } +const config = { + [GradleBuildDSL.Groovy]: `plugins { + id "org.sonarqube" version "${GRADLE_SCANNER_VERSION}" +}`, + [GradleBuildDSL.Kotlin]: `plugins { + id("org.sonarqube") version "${GRADLE_SCANNER_VERSION}" +}`, +}; + export default function JavaGradle(props: JavaGradleProps) { const { baseUrl, component, token } = props; - const config = `plugins { - id "org.sonarqube" version "${GRADLE_SCANNER_VERSION}" -}`; const command = [ './gradlew sonar', @@ -58,13 +66,16 @@ export default function JavaGradle(props: JavaGradleProps) { id="onboarding.analysis.java.gradle.text.1" values={{ plugin_code: <code>org.sonarqube</code>, - filename: <code>build.gradle</code>, + groovy: <code>{GradleBuildDSL.Groovy}</code>, + kotlin: <code>{GradleBuildDSL.Kotlin}</code>, }} /> </p> )} </InstanceMessage> - <CodeSnippet snippet={config} /> + <GradleBuildSelection className="big-spacer-top big-spacer-bottom"> + {(build) => <CodeSnippet snippet={config[build]} />} + </GradleBuildSelection> <p className="big-spacer-bottom markdown"> <em className="small text-muted"> <FormattedMessage diff --git a/server/sonar-web/src/main/js/components/tutorials/test-utils.ts b/server/sonar-web/src/main/js/components/tutorials/test-utils.ts index f57a2722b0d..4fa5d81d13d 100644 --- a/server/sonar-web/src/main/js/components/tutorials/test-utils.ts +++ b/server/sonar-web/src/main/js/components/tutorials/test-utils.ts @@ -19,7 +19,7 @@ */ import { screen } from '@testing-library/react'; import { byRole, byText } from 'testing-library-selector'; -import { BuildTools, OSs, TutorialModes } from './types'; +import { BuildTools, GradleBuildDSL, OSs, TutorialModes } from './types'; const CI_TRANSLATE_MAP: Partial<Record<TutorialModes, string>> = { [TutorialModes.BitbucketPipelines]: 'bitbucket_pipelines', @@ -70,6 +70,7 @@ export function getTutorialBuildButtons() { describeBuildTitle: byRole('heading', { name: 'onboarding.build' }), mavenBuildButton: byRole('button', { name: `onboarding.build.${BuildTools.Maven}` }), gradleBuildButton: byRole('button', { name: `onboarding.build.${BuildTools.Gradle}` }), + gradleDSLButton: (name: GradleBuildDSL) => byRole('button', { name }), dotnetBuildButton: byRole('button', { name: `onboarding.build.${BuildTools.DotNet}` }), cFamilyBuildButton: byRole('button', { name: `onboarding.build.${BuildTools.CFamily}` }), otherBuildButton: byRole('button', { name: `onboarding.build.${BuildTools.Other}` }), diff --git a/server/sonar-web/src/main/js/components/tutorials/types.ts b/server/sonar-web/src/main/js/components/tutorials/types.ts index 77fe8964a2d..7364208f171 100644 --- a/server/sonar-web/src/main/js/components/tutorials/types.ts +++ b/server/sonar-web/src/main/js/components/tutorials/types.ts @@ -35,6 +35,11 @@ export enum BuildTools { Other = 'other', } +export enum GradleBuildDSL { + Groovy = 'build.gradle', + Kotlin = 'build.gradle.kts', +} + export enum OSs { Linux = 'linux', Windows = 'win', diff --git a/server/sonar-web/src/main/js/components/tutorials/utils.ts b/server/sonar-web/src/main/js/components/tutorials/utils.ts index 7d271864828..e35657317d0 100644 --- a/server/sonar-web/src/main/js/components/tutorials/utils.ts +++ b/server/sonar-web/src/main/js/components/tutorials/utils.ts @@ -21,13 +21,15 @@ import { GRADLE_SCANNER_VERSION } from '../../helpers/constants'; import { convertGithubApiUrlToLink, stripTrailingSlash } from '../../helpers/urls'; import { AlmSettingsInstance, ProjectAlmBindingResponse } from '../../types/alm-settings'; import { UserToken } from '../../types/token'; +import { GradleBuildDSL } from './types'; export function quote(os: string): (s: string) => string { return os === 'win' ? (s: string) => `"${s}"` : (s: string) => s; } -export function buildGradleSnippet(key: string, name: string) { - return `plugins { +export function buildGradleSnippet(key: string, name: string, build: GradleBuildDSL) { + const map = { + [GradleBuildDSL.Groovy]: `plugins { id "org.sonarqube" version "${GRADLE_SCANNER_VERSION}" } @@ -36,7 +38,19 @@ sonar { property "sonar.projectKey", "${key}" property "sonar.projectName", "${name}" } -}`; +}`, + [GradleBuildDSL.Kotlin]: `plugins { + id("org.sonarqube") version "${GRADLE_SCANNER_VERSION}" +} + +sonar { + properties { + property("sonar.projectKey", "${key}") + property("sonar.projectName", "${name}") + } +}`, + }; + return map[build]; } export function getUniqueTokenName(tokens: UserToken[], initialTokenName: string) { |