diff options
author | Mathieu Suen <mathieu.suen@sonarsource.com> | 2021-06-15 14:48:21 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2021-06-22 20:03:14 +0000 |
commit | 1cff339b791904f0bb887231cbb527088a3d41bd (patch) | |
tree | 426ef45972d9ac9ed93408fa00d70ffa6dd7fe6b /server/sonar-web | |
parent | 38352a0684015dcd5865a253f507cac8d4a6d259 (diff) | |
download | sonarqube-1cff339b791904f0bb887231cbb527088a3d41bd.tar.gz sonarqube-1cff339b791904f0bb887231cbb527088a3d41bd.zip |
SONAR-15033 Add C/C++ tutorial for Jenkins
Diffstat (limited to 'server/sonar-web')
23 files changed, 543 insertions, 65 deletions
diff --git a/server/sonar-web/src/main/js/components/tutorials/TutorialSelectionRenderer.tsx b/server/sonar-web/src/main/js/components/tutorials/TutorialSelectionRenderer.tsx index acaf2ed20a8..46afc8cebfb 100644 --- a/server/sonar-web/src/main/js/components/tutorials/TutorialSelectionRenderer.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/TutorialSelectionRenderer.tsx @@ -215,6 +215,7 @@ export default function TutorialSelectionRenderer(props: TutorialSelectionRender {selectedTutorial === TutorialModes.Jenkins && ( <JenkinsTutorial almBinding={almBinding} + baseUrl={baseUrl} component={component} projectBinding={projectBinding} /> diff --git a/server/sonar-web/src/main/js/components/tutorials/__tests__/__snapshots__/TutorialSelectionRenderer-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/__tests__/__snapshots__/TutorialSelectionRenderer-test.tsx.snap index 096b3d93d8a..5cc2057e2d3 100644 --- a/server/sonar-web/src/main/js/components/tutorials/__tests__/__snapshots__/TutorialSelectionRenderer-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/tutorials/__tests__/__snapshots__/TutorialSelectionRenderer-test.tsx.snap @@ -494,6 +494,7 @@ exports[`should render correctly: jenkins tutorial 1`] = ` "key": "key", } } + baseUrl="http://localhost:9000" component={ Object { "breadcrumbs": Array [], diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/JenkinsTutorial.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/JenkinsTutorial.tsx index 89c2e1181cf..f88416c3d25 100644 --- a/server/sonar-web/src/main/js/components/tutorials/jenkins/JenkinsTutorial.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/JenkinsTutorial.tsx @@ -36,6 +36,7 @@ import WebhookStep from './WebhookStep'; export interface JenkinsTutorialProps { almBinding?: AlmSettingsInstance; + baseUrl: string; branchesEnabled: boolean; component: T.Component; projectBinding?: ProjectAlmBindingResponse; @@ -54,7 +55,7 @@ enum Steps { const USER_SETTING_SKIP_BITBUCKET_PREREQS = 'tutorials.jenkins.skipBitbucketPreReqs'; export function JenkinsTutorial(props: JenkinsTutorialProps) { - const { almBinding, branchesEnabled, component, projectBinding, skipPreReqs } = props; + const { almBinding, baseUrl, branchesEnabled, component, projectBinding, skipPreReqs } = props; const hasSelectAlmStep = projectBinding?.alm === undefined; const [alm, setAlm] = React.useState<AlmKeys | undefined>(projectBinding?.alm); @@ -133,7 +134,12 @@ export function JenkinsTutorial(props: JenkinsTutorialProps) { projectBinding={projectBinding} /> - <JenkinsfileStep alm={alm} component={component} open={step === Steps.Jenkinsfile} /> + <JenkinsfileStep + alm={alm} + component={component} + baseUrl={baseUrl} + open={step === Steps.Jenkinsfile} + /> </> )} </> diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/JenkinsfileStep.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/JenkinsfileStep.tsx index c3077e3ebc5..c52cbde5667 100644 --- a/server/sonar-web/src/main/js/components/tutorials/jenkins/JenkinsfileStep.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/JenkinsfileStep.tsx @@ -18,12 +18,15 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; +import { Alert } from 'sonar-ui-common/components/ui/Alert'; import { translate } from 'sonar-ui-common/helpers/l10n'; import { AlmKeys } from '../../../types/alm-settings'; +import { withCLanguageFeature } from '../../hoc/withCLanguageFeature'; import AllSet from '../components/AllSet'; import RenderOptions from '../components/RenderOptions'; import Step from '../components/Step'; import { BuildTools } from '../types'; +import CFamilly from './buildtool-steps/CFamilly'; import DotNet from './buildtool-steps/DotNet'; import Gradle from './buildtool-steps/Gradle'; import Maven from './buildtool-steps/Maven'; @@ -31,25 +34,34 @@ import Other from './buildtool-steps/Other'; export interface JenkinsfileStepProps { alm: AlmKeys; + baseUrl: string; component: T.Component; + hasCLanguageFeature: boolean; open: boolean; } -// To remove when CFamily is includ in this tutorial -type BuildToolsWithoutCFamily = Exclude<BuildTools, BuildTools.CFamily>; +export interface LanguageProps { + component: T.Component; + baseUrl: string; +} const BUILDTOOL_COMPONENT_MAP: { - [x in BuildToolsWithoutCFamily]: React.ComponentType<{ component: T.Component }>; + [x in BuildTools]: React.ComponentType<LanguageProps>; } = { [BuildTools.Maven]: Maven, [BuildTools.Gradle]: Gradle, [BuildTools.DotNet]: DotNet, + [BuildTools.CFamily]: CFamilly, [BuildTools.Other]: Other }; -export default function JenkinsfileStep(props: JenkinsfileStepProps) { - const { alm, component, open } = props; - const [buildTool, setBuildTool] = React.useState<BuildToolsWithoutCFamily | undefined>(undefined); +export function JenkinsfileStep(props: JenkinsfileStepProps) { + const { alm, component, hasCLanguageFeature, baseUrl, open } = props; + const [buildTool, setBuildTool] = React.useState<BuildTools>(); + const buildToolOrder = Object.keys(BUILDTOOL_COMPONENT_MAP); + if (!hasCLanguageFeature) { + buildToolOrder.splice(buildToolOrder.indexOf(BuildTools.CFamily), 1); + } return ( <Step finished={false} @@ -62,13 +74,18 @@ export default function JenkinsfileStep(props: JenkinsfileStepProps) { <RenderOptions checked={buildTool} name="buildtool" - onCheck={value => setBuildTool(value as BuildToolsWithoutCFamily)} + onCheck={value => setBuildTool(value as BuildTools)} optionLabelKey="onboarding.build" - options={Object.keys(BUILDTOOL_COMPONENT_MAP)} + options={buildToolOrder} /> + {buildTool === BuildTools.CFamily && ( + <Alert variant="info" className="spacer-top abs-width-600"> + {translate('onboarding.tutorial.with.jenkins.jenkinsfile.cfamilly.agent_setup')} + </Alert> + )} </li> {buildTool !== undefined && - React.createElement(BUILDTOOL_COMPONENT_MAP[buildTool], { component })} + React.createElement(BUILDTOOL_COMPONENT_MAP[buildTool], { component, baseUrl })} </ol> {buildTool !== undefined && ( <> @@ -83,3 +100,5 @@ export default function JenkinsfileStep(props: JenkinsfileStepProps) { /> ); } + +export default withCLanguageFeature(JenkinsfileStep); diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/JenkinsTutorial-test.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/JenkinsTutorial-test.tsx index 35afd47c594..b01c8d7e8d4 100644 --- a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/JenkinsTutorial-test.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/JenkinsTutorial-test.tsx @@ -132,6 +132,7 @@ it('should correctly select an ALM if no project is bound', () => { function shallowRender(props: Partial<JenkinsTutorialProps> = {}) { return shallow<JenkinsTutorialProps>( <JenkinsTutorial + baseUrl="" branchesEnabled={true} component={mockComponent()} projectBinding={mockProjectBitbucketBindingResponse()} diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/JenkinsfileStep-test.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/JenkinsfileStep-test.tsx index 79057f46dc6..be6fc8508a7 100644 --- a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/JenkinsfileStep-test.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/JenkinsfileStep-test.tsx @@ -25,11 +25,13 @@ import RenderOptions from '../../components/RenderOptions'; import Step from '../../components/Step'; import { renderStepContent } from '../../test-utils'; import { BuildTools } from '../../types'; -import JenkinsfileStep, { JenkinsfileStepProps } from '../JenkinsfileStep'; +import { JenkinsfileStep, JenkinsfileStepProps } from '../JenkinsfileStep'; it('should render correctly', () => { const wrapper = shallowRender(); expect(wrapper).toMatchSnapshot('Step wrapper'); + wrapper.setProps({ hasCLanguageFeature: true }); + expect(wrapper).toMatchSnapshot('Step wrapper with C'); expect(renderStepContent(wrapper)).toMatchSnapshot('initial content'); }); @@ -71,7 +73,9 @@ function shallowRender(props: Partial<JenkinsfileStepProps> = {}) { return shallow<JenkinsfileStepProps>( <JenkinsfileStep alm={AlmKeys.BitbucketCloud} + baseUrl="nice_url" component={mockComponent()} + hasCLanguageFeature={false} open={true} {...props} /> diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/JenkinsTutorial-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/JenkinsTutorial-test.tsx.snap index 7cbcb626874..57eb0d2e22b 100644 --- a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/JenkinsTutorial-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/JenkinsTutorial-test.tsx.snap @@ -45,8 +45,9 @@ exports[`should render correctly: branches not enabled 1`] = ` } } /> - <JenkinsfileStep + <Connect(withCLanguageFeature(JenkinsfileStep)) alm="bitbucket" + baseUrl="" component={ Object { "breadcrumbs": Array [], @@ -128,8 +129,9 @@ exports[`should render correctly: default 1`] = ` } } /> - <JenkinsfileStep + <Connect(withCLanguageFeature(JenkinsfileStep)) alm="bitbucket" + baseUrl="" component={ Object { "breadcrumbs": Array [], diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/JenkinsfileStep-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/JenkinsfileStep-test.tsx.snap index 83aa3aaa962..8ab1bb20420 100644 --- a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/JenkinsfileStep-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/JenkinsfileStep-test.tsx.snap @@ -25,6 +25,7 @@ exports[`should render correctly for .NET 1`] = ` /> </li> <DotNet + baseUrl="nice_url" component={ Object { "breadcrumbs": Array [], @@ -85,6 +86,7 @@ exports[`should render correctly for Gradle 1`] = ` /> </li> <Gradle + baseUrl="nice_url" component={ Object { "breadcrumbs": Array [], @@ -145,6 +147,7 @@ exports[`should render correctly for Maven 1`] = ` /> </li> <Maven + baseUrl="nice_url" component={ Object { "breadcrumbs": Array [], @@ -205,6 +208,7 @@ exports[`should render correctly for Other 1`] = ` /> </li> <Other + baseUrl="nice_url" component={ Object { "breadcrumbs": Array [], @@ -250,6 +254,16 @@ exports[`should render correctly: Step wrapper 1`] = ` /> `; +exports[`should render correctly: Step wrapper with C 1`] = ` +<Step + finished={false} + open={true} + renderForm={[Function]} + stepNumber={3} + stepTitle="onboarding.tutorial.with.jenkins.jenkinsfile.title" +/> +`; + exports[`should render correctly: initial content 1`] = ` <div className="boxed-group-inner" @@ -268,6 +282,7 @@ exports[`should render correctly: initial content 1`] = ` "maven", "gradle", "dotnet", + "cfamily", "other", ] } diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/CFamilly.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/CFamilly.tsx new file mode 100644 index 00000000000..e1af3004dff --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/CFamilly.tsx @@ -0,0 +1,131 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 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 * as React from 'react'; +import { translate } from 'sonar-ui-common/helpers/l10n'; +import { CompilationInfo } from '../../components/CompilationInfo'; +import DefaultProjectKey from '../../components/DefaultProjectKey'; +import RenderOptions from '../../components/RenderOptions'; +import { OSs } from '../../types'; +import CreateJenkinsfileBulletPoint from './CreateJenkinsfileBulletPoint'; + +export interface CFamillyProps { + component: T.Component; + baseUrl: string; +} + +const YAML_MAP: Record<OSs, (baseUrl: string) => string> = { + [OSs.Linux]: baseUrl => `node { + stage('SCM') { + checkout scm + } + stage('Download Build Wrapper') { + sh "mkdir -p .sonar" + sh "curl -sSLo build-wrapper-linux-x86.zip ${baseUrl}/static/cpp/build-wrapper-linux-x86.zip" + sh "unzip -o build-wrapper-linux-x86.zip -d .sonar" + } + stage('Build') { + sh ".sonar/build-wrapper-linux-x86/build-wrapper-linux-x86-64 --out-dir bw-output <your clean build command>" + } + stage('SonarQube Analysis') { + def scannerHome = tool 'SonarScanner'; + withSonarQubeEnv() { + sh "\${scannerHome}/bin/sonar-scanner -Dsonar.cfamily.build-wrapper-output=bw-output" + } + } +}`, + [OSs.MacOS]: baseUrl => `node { + stage('SCM') { + checkout scm + } + stage('Download Build Wrapper') { + sh ''' + mkdir -p .sonar + curl -sSLo build-wrapper-macosx-x86.zip ${baseUrl}/static/cpp/build-wrapper-macosx-x86.zip + unzip -o build-wrapper-macosx-x86.zip -d .sonar + ''' + } + stage('Build') { + sh ''' + .sonar/build-wrapper-macosx-x86/build-wrapper-macosx-x86 --out-dir bw-output <your clean build command> + ''' + } + stage('SonarQube Analysis') { + def scannerHome = tool 'SonarScanner'; + withSonarQubeEnv() { + sh "\${scannerHome}/bin/sonar-scanner -Dsonar.cfamily.build-wrapper-output=bw-output" + } + } +}`, + [OSs.Windows]: baseUrl => `node { + stage('SCM') { + checkout scm + } + stage('Download Build Wrapper') { + powershell ''' + $path = "$HOME/.sonar/build-wrapper-win-x86.zip" + rm build-wrapper-win-x86 -Recurse -Force -ErrorAction SilentlyContinue + rm $path -Force -ErrorAction SilentlyContinue + mkdir $HOME/.sonar + [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 + (New-Object System.Net.WebClient).DownloadFile(${baseUrl}/static/cpp/build-wrapper-win-x86.zip", $path) + Add-Type -AssemblyName System.IO.Compression.FileSystem + [System.IO.Compression.ZipFile]::ExtractToDirectory($path, "$HOME/.sonar") + ''' + } + stage('Build') { + powershell ''' + $env:Path += ";$HOME/.sonar/build-wrapper-win-x86" + build-wrapper-win-x86-64 --out-dir bw-output <your clean build command> + ''' + } + stage('SonarQube Analysis') { + def scannerHome = tool 'SonarScanner'; + withSonarQubeEnv() { + powershell "\${scannerHome}/bin/sonar-scanner -Dsonar.cfamily.build-wrapper-output=bw-output" + } + } +}` +}; + +export default function CFamilly({ baseUrl, component }: CFamillyProps) { + const [os, setOs] = React.useState<OSs>(); + return ( + <> + <DefaultProjectKey component={component} /> + <li> + {translate('onboarding.build.other.os')} + <RenderOptions + checked={os} + name="flavorComponent" + optionLabelKey="onboarding.build.other.os" + onCheck={value => setOs(value as OSs)} + options={Object.values(OSs)} + /> + </li> + {os && ( + <CreateJenkinsfileBulletPoint + alertTranslationKeyPart="onboarding.tutorial.with.jenkins.jenkinsfile.other.step3" + snippet={YAML_MAP[os](baseUrl)}> + <CompilationInfo /> + </CreateJenkinsfileBulletPoint> + )} + </> + ); +} diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/CreateJenkinsfileBulletPoint.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/CreateJenkinsfileBulletPoint.tsx index b08fca05a4e..f87c1c9616f 100644 --- a/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/CreateJenkinsfileBulletPoint.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/CreateJenkinsfileBulletPoint.tsx @@ -25,12 +25,14 @@ import SentenceWithFilename from '../../components/SentenceWithFilename'; import SentenceWithHighlights from '../../components/SentenceWithHighlights'; export interface CreateJenkinsfileBulletPointProps { - snippet: string; alertTranslationKeyPart?: string; + children?: React.ReactNode; + otherAlert?: JSX.Element; + snippet: string; } export default function CreateJenkinsfileBulletPoint(props: CreateJenkinsfileBulletPointProps) { - const { snippet, alertTranslationKeyPart } = props; + const { children, snippet, alertTranslationKeyPart, otherAlert } = props; return ( <li className="abs-width-600"> @@ -38,9 +40,9 @@ export default function CreateJenkinsfileBulletPoint(props: CreateJenkinsfileBul filename="Jenkinsfile" translationKey="onboarding.tutorial.with.jenkins.jenkinsfile.jenkinsfile_step" /> - {alertTranslationKeyPart !== undefined && ( + {alertTranslationKeyPart && ( <Alert className="spacer-top" variant="info"> - <p className="text-middle"> + <div className="text-middle"> <SentenceWithHighlights highlightKeys={['default', 'in_jenkins']} translationKey={`${alertTranslationKeyPart}.replace`} @@ -64,10 +66,12 @@ export default function CreateJenkinsfileBulletPoint(props: CreateJenkinsfileBul </> } /> - </p> + {otherAlert} + </div> </Alert> )} <CodeSnippet snippet={snippet} /> + {children} </li> ); } diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/DotNet.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/DotNet.tsx index 413536eda21..194a04cd58b 100644 --- a/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/DotNet.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/DotNet.tsx @@ -21,13 +21,10 @@ import * as React from 'react'; import { translate } from 'sonar-ui-common/helpers/l10n'; import RenderOptions from '../../components/RenderOptions'; import { OSs } from '../../types'; +import { LanguageProps } from '../JenkinsfileStep'; import DotNetCore from './DotNetCore'; import DotNetFramework from './DotNetFramework'; -export interface DotNetProps { - component: T.Component; -} - export interface DotNetCoreFrameworkProps { component: T.Component; os: OSDotNet; @@ -42,7 +39,7 @@ const DotOS: { [key in keyof typeof DotNetFlavor]: OSDotNet } = { linux_core: OSs.Linux }; -export default function DotNet({ component }: DotNetProps) { +export default function DotNet({ component }: LanguageProps) { const [flavorComponent, setFlavorComponet] = React.useState<keyof typeof DotNetFlavor>(); const DotNetTutorial = flavorComponent && DotNetFlavor[flavorComponent]; return ( 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 9436298c2f8..887737f269d 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 @@ -21,12 +21,9 @@ import * as React from 'react'; import CodeSnippet from '../../../common/CodeSnippet'; import SentenceWithFilename from '../../components/SentenceWithFilename'; import { buildGradleSnippet } from '../../utils'; +import { LanguageProps } from '../JenkinsfileStep'; import CreateJenkinsfileBulletPoint from './CreateJenkinsfileBulletPoint'; -export interface GradleProps { - component: T.Component; -} - const JENKINSFILE_SNIPPET = `node { stage('SCM') { checkout scm @@ -38,7 +35,7 @@ const JENKINSFILE_SNIPPET = `node { } }`; -export default function Gradle({ component }: GradleProps) { +export default function Gradle({ component }: LanguageProps) { return ( <> <li className="abs-width-600"> diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/Maven.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/Maven.tsx index 669ed20f4c9..b4d5fc5f178 100644 --- a/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/Maven.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/Maven.tsx @@ -21,12 +21,9 @@ import * as React from 'react'; import CodeSnippet from '../../../common/CodeSnippet'; import SentenceWithFilename from '../../components/SentenceWithFilename'; import { mavenPomSnippet } from '../../utils'; +import { LanguageProps } from '../JenkinsfileStep'; import CreateJenkinsfileBulletPoint from './CreateJenkinsfileBulletPoint'; -export interface MavenProps { - component: T.Component; -} - const JENKINSFILE_SNIPPET = `node { stage('SCM') { checkout scm @@ -39,7 +36,7 @@ const JENKINSFILE_SNIPPET = `node { } }`; -export default function Maven({ component }: MavenProps) { +export default function Maven({ component }: LanguageProps) { return ( <> <li className="abs-width-600"> diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/Other.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/Other.tsx index c66cd92cca6..0656f5d3020 100644 --- a/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/Other.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/Other.tsx @@ -19,12 +19,9 @@ */ import * as React from 'react'; import DefaultProjectKey from '../../components/DefaultProjectKey'; +import { LanguageProps } from '../JenkinsfileStep'; import CreateJenkinsfileBulletPoint from './CreateJenkinsfileBulletPoint'; -export interface OtherProps { - component: T.Component; -} - const JENKINSFILE_SNIPPET = `node { stage('SCM') { checkout scm @@ -37,7 +34,7 @@ const JENKINSFILE_SNIPPET = `node { } }`; -export default function Other({ component }: OtherProps) { +export default function Other({ component }: LanguageProps) { return ( <> <DefaultProjectKey component={component} /> diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/CFamilly-test.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/CFamilly-test.tsx new file mode 100644 index 00000000000..fe4bfbb201c --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/CFamilly-test.tsx @@ -0,0 +1,41 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 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 { shallow } from 'enzyme'; +import * as React from 'react'; +import { mockComponent } from '../../../../../helpers/testMocks'; +import RenderOptions from '../../../components/RenderOptions'; +import { OSs } from '../../../types'; +import CFamilly, { CFamillyProps } from '../CFamilly'; + +it('should render correctly for', () => { + expect(shallowRender()).toMatchSnapshot(); +}); + +it.each([[OSs.Linux], [OSs.MacOS], [OSs.Windows]])('should render correctly for %s', os => { + const wrapper = shallowRender(); + wrapper.find(RenderOptions).simulate('check', os); + expect(wrapper).toMatchSnapshot(os); +}); + +function shallowRender(props: Partial<CFamillyProps> = {}) { + return shallow<CFamillyProps>( + <CFamilly component={mockComponent()} baseUrl="nice_url_sample" {...props} /> + ); +} diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/DotNet-test.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/DotNet-test.tsx index d6345532ea4..778c46cb5df 100644 --- a/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/DotNet-test.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/DotNet-test.tsx @@ -20,12 +20,13 @@ import { shallow } from 'enzyme'; import * as React from 'react'; import { mockComponent } from '../../../../../helpers/testMocks'; -import DotNet, { DotNetProps } from '../DotNet'; +import { LanguageProps } from '../../JenkinsfileStep'; +import DotNet from '../DotNet'; it('should render correctly', () => { expect(shallowRender()).toMatchSnapshot(); }); -function shallowRender(props: Partial<DotNetProps> = {}) { - return shallow<DotNetProps>(<DotNet component={mockComponent()} {...props} />); +function shallowRender(props: Partial<LanguageProps> = {}) { + return shallow<LanguageProps>(<DotNet component={mockComponent()} baseUrl="" {...props} />); } diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/Gradle-test.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/Gradle-test.tsx index fc47ef58094..d516ed091df 100644 --- a/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/Gradle-test.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/Gradle-test.tsx @@ -20,12 +20,13 @@ import { shallow } from 'enzyme'; import * as React from 'react'; import { mockComponent } from '../../../../../helpers/testMocks'; -import Gradle, { GradleProps } from '../Gradle'; +import { LanguageProps } from '../../JenkinsfileStep'; +import Gradle from '../Gradle'; it('should render correctly', () => { expect(shallowRender()).toMatchSnapshot(); }); -function shallowRender(props: Partial<GradleProps> = {}) { - return shallow<GradleProps>(<Gradle component={mockComponent()} {...props} />); +function shallowRender(props: Partial<LanguageProps> = {}) { + return shallow<LanguageProps>(<Gradle component={mockComponent()} baseUrl="" {...props} />); } diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/Maven-test.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/Maven-test.tsx index 2afce30de1d..7bbf42c309e 100644 --- a/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/Maven-test.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/Maven-test.tsx @@ -20,12 +20,13 @@ import { shallow } from 'enzyme'; import * as React from 'react'; import { mockComponent } from '../../../../../helpers/testMocks'; -import Maven, { MavenProps } from '../Maven'; +import { LanguageProps } from '../../JenkinsfileStep'; +import Maven from '../Maven'; it('should render correctly', () => { expect(shallowRender()).toMatchSnapshot(); }); -function shallowRender(props: Partial<MavenProps> = {}) { - return shallow<MavenProps>(<Maven component={mockComponent()} {...props} />); +function shallowRender(props: Partial<LanguageProps> = {}) { + return shallow<LanguageProps>(<Maven component={mockComponent()} baseUrl="" {...props} />); } diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/Other-test.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/Other-test.tsx index 578ef473529..1e1a8f71392 100644 --- a/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/Other-test.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/Other-test.tsx @@ -20,12 +20,13 @@ import { shallow } from 'enzyme'; import * as React from 'react'; import { mockComponent } from '../../../../../helpers/testMocks'; -import Other, { OtherProps } from '../Other'; +import { LanguageProps } from '../../JenkinsfileStep'; +import Other from '../Other'; it('should render correctly', () => { expect(shallowRender()).toMatchSnapshot(); }); -function shallowRender(props: Partial<OtherProps> = {}) { - return shallow<OtherProps>(<Other component={mockComponent()} {...props} />); +function shallowRender(props: Partial<LanguageProps> = {}) { + return shallow<LanguageProps>(<Other component={mockComponent()} baseUrl="" {...props} />); } diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/__snapshots__/CFamilly-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/__snapshots__/CFamilly-test.tsx.snap new file mode 100644 index 00000000000..fb390f35e17 --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/__snapshots__/CFamilly-test.tsx.snap @@ -0,0 +1,266 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render correctly for 1`] = ` +<Fragment> + <DefaultProjectKey + component={ + Object { + "breadcrumbs": Array [], + "key": "my-project", + "name": "MyProject", + "qualifier": "TRK", + "qualityGate": Object { + "isDefault": true, + "key": "30", + "name": "Sonar way", + }, + "qualityProfiles": Array [ + Object { + "deleted": false, + "key": "my-qp", + "language": "ts", + "name": "Sonar way", + }, + ], + "tags": Array [], + } + } + /> + <li> + onboarding.build.other.os + <RenderOptions + name="flavorComponent" + onCheck={[Function]} + optionLabelKey="onboarding.build.other.os" + options={ + Array [ + "linux", + "win", + "mac", + ] + } + /> + </li> +</Fragment> +`; + +exports[`should render correctly for linux: linux 1`] = ` +<Fragment> + <DefaultProjectKey + component={ + Object { + "breadcrumbs": Array [], + "key": "my-project", + "name": "MyProject", + "qualifier": "TRK", + "qualityGate": Object { + "isDefault": true, + "key": "30", + "name": "Sonar way", + }, + "qualityProfiles": Array [ + Object { + "deleted": false, + "key": "my-qp", + "language": "ts", + "name": "Sonar way", + }, + ], + "tags": Array [], + } + } + /> + <li> + onboarding.build.other.os + <RenderOptions + checked="linux" + name="flavorComponent" + onCheck={[Function]} + optionLabelKey="onboarding.build.other.os" + options={ + Array [ + "linux", + "win", + "mac", + ] + } + /> + </li> + <CreateJenkinsfileBulletPoint + alertTranslationKeyPart="onboarding.tutorial.with.jenkins.jenkinsfile.other.step3" + snippet="node { + stage('SCM') { + checkout scm + } + stage('Download Build Wrapper') { + sh \\"mkdir -p .sonar\\" + sh \\"curl -sSLo build-wrapper-linux-x86.zip nice_url_sample/static/cpp/build-wrapper-linux-x86.zip\\" + sh \\"unzip -o build-wrapper-linux-x86.zip -d .sonar\\" + } + stage('Build') { + sh \\".sonar/build-wrapper-linux-x86/build-wrapper-linux-x86-64 --out-dir bw-output <your clean build command>\\" + } + stage('SonarQube Analysis') { + def scannerHome = tool 'SonarScanner'; + withSonarQubeEnv() { + sh \\"\${scannerHome}/bin/sonar-scanner -Dsonar.cfamily.build-wrapper-output=bw-output\\" + } + } +}" + > + <CompilationInfo /> + </CreateJenkinsfileBulletPoint> +</Fragment> +`; + +exports[`should render correctly for mac: mac 1`] = ` +<Fragment> + <DefaultProjectKey + component={ + Object { + "breadcrumbs": Array [], + "key": "my-project", + "name": "MyProject", + "qualifier": "TRK", + "qualityGate": Object { + "isDefault": true, + "key": "30", + "name": "Sonar way", + }, + "qualityProfiles": Array [ + Object { + "deleted": false, + "key": "my-qp", + "language": "ts", + "name": "Sonar way", + }, + ], + "tags": Array [], + } + } + /> + <li> + onboarding.build.other.os + <RenderOptions + checked="mac" + name="flavorComponent" + onCheck={[Function]} + optionLabelKey="onboarding.build.other.os" + options={ + Array [ + "linux", + "win", + "mac", + ] + } + /> + </li> + <CreateJenkinsfileBulletPoint + alertTranslationKeyPart="onboarding.tutorial.with.jenkins.jenkinsfile.other.step3" + snippet="node { + stage('SCM') { + checkout scm + } + stage('Download Build Wrapper') { + sh ''' + mkdir -p .sonar + curl -sSLo build-wrapper-macosx-x86.zip nice_url_sample/static/cpp/build-wrapper-macosx-x86.zip + unzip -o build-wrapper-macosx-x86.zip -d .sonar + ''' + } + stage('Build') { + sh ''' + .sonar/build-wrapper-macosx-x86/build-wrapper-macosx-x86 --out-dir bw-output <your clean build command> + ''' + } + stage('SonarQube Analysis') { + def scannerHome = tool 'SonarScanner'; + withSonarQubeEnv() { + sh \\"\${scannerHome}/bin/sonar-scanner -Dsonar.cfamily.build-wrapper-output=bw-output\\" + } + } +}" + > + <CompilationInfo /> + </CreateJenkinsfileBulletPoint> +</Fragment> +`; + +exports[`should render correctly for win: win 1`] = ` +<Fragment> + <DefaultProjectKey + component={ + Object { + "breadcrumbs": Array [], + "key": "my-project", + "name": "MyProject", + "qualifier": "TRK", + "qualityGate": Object { + "isDefault": true, + "key": "30", + "name": "Sonar way", + }, + "qualityProfiles": Array [ + Object { + "deleted": false, + "key": "my-qp", + "language": "ts", + "name": "Sonar way", + }, + ], + "tags": Array [], + } + } + /> + <li> + onboarding.build.other.os + <RenderOptions + checked="win" + name="flavorComponent" + onCheck={[Function]} + optionLabelKey="onboarding.build.other.os" + options={ + Array [ + "linux", + "win", + "mac", + ] + } + /> + </li> + <CreateJenkinsfileBulletPoint + alertTranslationKeyPart="onboarding.tutorial.with.jenkins.jenkinsfile.other.step3" + snippet="node { + stage('SCM') { + checkout scm + } + stage('Download Build Wrapper') { + powershell ''' + $path = \\"$HOME/.sonar/build-wrapper-win-x86.zip\\" + rm build-wrapper-win-x86 -Recurse -Force -ErrorAction SilentlyContinue + rm $path -Force -ErrorAction SilentlyContinue + mkdir $HOME/.sonar + [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 + (New-Object System.Net.WebClient).DownloadFile(nice_url_sample/static/cpp/build-wrapper-win-x86.zip\\", $path) + Add-Type -AssemblyName System.IO.Compression.FileSystem + [System.IO.Compression.ZipFile]::ExtractToDirectory($path, \\"$HOME/.sonar\\") + ''' + } + stage('Build') { + powershell ''' + $env:Path += \\";$HOME/.sonar/build-wrapper-win-x86\\" + build-wrapper-win-x86-64 --out-dir bw-output <your clean build command> + ''' + } + stage('SonarQube Analysis') { + def scannerHome = tool 'SonarScanner'; + withSonarQubeEnv() { + powershell \\"\${scannerHome}/bin/sonar-scanner -Dsonar.cfamily.build-wrapper-output=bw-output\\" + } + } +}" + > + <CompilationInfo /> + </CreateJenkinsfileBulletPoint> +</Fragment> +`; diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/__snapshots__/CreateJenkinsfileBulletPoint-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/__snapshots__/CreateJenkinsfileBulletPoint-test.tsx.snap index b56d3e42589..cdb54d98b3a 100644 --- a/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/__snapshots__/CreateJenkinsfileBulletPoint-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/__snapshots__/CreateJenkinsfileBulletPoint-test.tsx.snap @@ -26,7 +26,7 @@ exports[`should render correctly: with alert 1`] = ` className="spacer-top" variant="info" > - <p + <div className="text-middle" > <SentenceWithHighlights @@ -68,7 +68,7 @@ exports[`should render correctly: with alert 1`] = ` </React.Fragment> } /> - </p> + </div> </Alert> <CodeSnippet snippet="foo { bar() }" diff --git a/server/sonar-web/src/main/js/components/tutorials/manual/BuildToolForm.tsx b/server/sonar-web/src/main/js/components/tutorials/manual/BuildToolForm.tsx index 1da982e10e3..c805794317f 100644 --- a/server/sonar-web/src/main/js/components/tutorials/manual/BuildToolForm.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/manual/BuildToolForm.tsx @@ -18,15 +18,14 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; -import { connect } from 'react-redux'; import RadioToggle from 'sonar-ui-common/components/controls/RadioToggle'; import { translate } from 'sonar-ui-common/helpers/l10n'; -import { getLanguages, Store } from '../../../store/rootReducer'; +import { withCLanguageFeature } from '../../hoc/withCLanguageFeature'; import RenderOptions from '../components/RenderOptions'; import { BuildTools, ManualTutorialConfig, OSs } from '../types'; interface Props { - languages: T.Languages; + hasCLanguageFeature: boolean; config?: ManualTutorialConfig; onDone: (config: ManualTutorialConfig) => void; } @@ -60,9 +59,9 @@ export class BuildToolForm extends React.PureComponent<Props, State> { render() { const { config } = this.state; - const { languages } = this.props; + const { hasCLanguageFeature } = this.props; const buildTools = [BuildTools.Maven, BuildTools.Gradle, BuildTools.DotNet]; - if (languages['c']) { + if (hasCLanguageFeature) { buildTools.push(BuildTools.CFamily); } buildTools.push(BuildTools.Other); @@ -97,8 +96,4 @@ export class BuildToolForm extends React.PureComponent<Props, State> { } } -const mapStateToProps = (state: Store) => ({ - languages: getLanguages(state) -}); - -export default connect(mapStateToProps)(BuildToolForm); +export default withCLanguageFeature(BuildToolForm); diff --git a/server/sonar-web/src/main/js/components/tutorials/manual/__tests__/BuildToolForm-test.tsx b/server/sonar-web/src/main/js/components/tutorials/manual/__tests__/BuildToolForm-test.tsx index 3cd4d25b405..add856b4b0f 100644 --- a/server/sonar-web/src/main/js/components/tutorials/manual/__tests__/BuildToolForm-test.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/manual/__tests__/BuildToolForm-test.tsx @@ -24,7 +24,7 @@ import { BuildToolForm } from '../BuildToolForm'; it('renders correctly', () => { expect(shallowRender()).toMatchSnapshot('default'); - expect(shallowRender({ languages: {} })).toMatchSnapshot('without C'); + expect(shallowRender({ hasCLanguageFeature: false })).toMatchSnapshot('without C'); expect(shallowRender().setState({ config: { buildTool: BuildTools.Maven } })).toMatchSnapshot( 'with "maven" selected' ); @@ -49,6 +49,6 @@ it('correctly calls the onDone prop', () => { function shallowRender(props: Partial<BuildToolForm['props']> = {}) { return shallow<BuildToolForm>( - <BuildToolForm onDone={jest.fn()} languages={{ c: { key: 'c', name: 'test' } }} {...props} /> + <BuildToolForm onDone={jest.fn()} hasCLanguageFeature={true} {...props} /> ); } |