Browse Source

SONAR-15033 Add C/C++ tutorial for Jenkins

tags/9.0.0.45539
Mathieu Suen 3 years ago
parent
commit
1cff339b79
24 changed files with 544 additions and 65 deletions
  1. 1
    0
      server/sonar-web/src/main/js/components/tutorials/TutorialSelectionRenderer.tsx
  2. 1
    0
      server/sonar-web/src/main/js/components/tutorials/__tests__/__snapshots__/TutorialSelectionRenderer-test.tsx.snap
  3. 8
    2
      server/sonar-web/src/main/js/components/tutorials/jenkins/JenkinsTutorial.tsx
  4. 28
    9
      server/sonar-web/src/main/js/components/tutorials/jenkins/JenkinsfileStep.tsx
  5. 1
    0
      server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/JenkinsTutorial-test.tsx
  6. 5
    1
      server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/JenkinsfileStep-test.tsx
  7. 4
    2
      server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/JenkinsTutorial-test.tsx.snap
  8. 15
    0
      server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/JenkinsfileStep-test.tsx.snap
  9. 131
    0
      server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/CFamilly.tsx
  10. 9
    5
      server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/CreateJenkinsfileBulletPoint.tsx
  11. 2
    5
      server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/DotNet.tsx
  12. 2
    5
      server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/Gradle.tsx
  13. 2
    5
      server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/Maven.tsx
  14. 2
    5
      server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/Other.tsx
  15. 41
    0
      server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/CFamilly-test.tsx
  16. 4
    3
      server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/DotNet-test.tsx
  17. 4
    3
      server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/Gradle-test.tsx
  18. 4
    3
      server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/Maven-test.tsx
  19. 4
    3
      server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/Other-test.tsx
  20. 266
    0
      server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/__snapshots__/CFamilly-test.tsx.snap
  21. 2
    2
      server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/__snapshots__/CreateJenkinsfileBulletPoint-test.tsx.snap
  22. 5
    10
      server/sonar-web/src/main/js/components/tutorials/manual/BuildToolForm.tsx
  23. 2
    2
      server/sonar-web/src/main/js/components/tutorials/manual/__tests__/BuildToolForm-test.tsx
  24. 1
    0
      sonar-core/src/main/resources/org/sonar/l10n/core.properties

+ 1
- 0
server/sonar-web/src/main/js/components/tutorials/TutorialSelectionRenderer.tsx View File

@@ -215,6 +215,7 @@ export default function TutorialSelectionRenderer(props: TutorialSelectionRender
{selectedTutorial === TutorialModes.Jenkins && (
<JenkinsTutorial
almBinding={almBinding}
baseUrl={baseUrl}
component={component}
projectBinding={projectBinding}
/>

+ 1
- 0
server/sonar-web/src/main/js/components/tutorials/__tests__/__snapshots__/TutorialSelectionRenderer-test.tsx.snap View File

@@ -494,6 +494,7 @@ exports[`should render correctly: jenkins tutorial 1`] = `
"key": "key",
}
}
baseUrl="http://localhost:9000"
component={
Object {
"breadcrumbs": Array [],

+ 8
- 2
server/sonar-web/src/main/js/components/tutorials/jenkins/JenkinsTutorial.tsx View File

@@ -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}
/>
</>
)}
</>

+ 28
- 9
server/sonar-web/src/main/js/components/tutorials/jenkins/JenkinsfileStep.tsx View File

@@ -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);

+ 1
- 0
server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/JenkinsTutorial-test.tsx View File

@@ -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()}

+ 5
- 1
server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/JenkinsfileStep-test.tsx View File

@@ -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}
/>

+ 4
- 2
server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/JenkinsTutorial-test.tsx.snap View File

@@ -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 [],

+ 15
- 0
server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/JenkinsfileStep-test.tsx.snap View File

@@ -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",
]
}

+ 131
- 0
server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/CFamilly.tsx View File

@@ -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>
)}
</>
);
}

+ 9
- 5
server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/CreateJenkinsfileBulletPoint.tsx View File

@@ -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>
);
}

+ 2
- 5
server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/DotNet.tsx View File

@@ -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 (

+ 2
- 5
server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/Gradle.tsx View File

@@ -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">

+ 2
- 5
server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/Maven.tsx View File

@@ -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">

+ 2
- 5
server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/Other.tsx View File

@@ -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} />

+ 41
- 0
server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/CFamilly-test.tsx View File

@@ -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} />
);
}

+ 4
- 3
server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/DotNet-test.tsx View File

@@ -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} />);
}

+ 4
- 3
server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/Gradle-test.tsx View File

@@ -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} />);
}

+ 4
- 3
server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/Maven-test.tsx View File

@@ -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} />);
}

+ 4
- 3
server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/Other-test.tsx View File

@@ -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} />);
}

+ 266
- 0
server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/__snapshots__/CFamilly-test.tsx.snap View File

@@ -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>
`;

+ 2
- 2
server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/__snapshots__/CreateJenkinsfileBulletPoint-test.tsx.snap View File

@@ -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() }"

+ 5
- 10
server/sonar-web/src/main/js/components/tutorials/manual/BuildToolForm.tsx View File

@@ -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);

+ 2
- 2
server/sonar-web/src/main/js/components/tutorials/manual/__tests__/BuildToolForm-test.tsx View File

@@ -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} />
);
}

+ 1
- 0
sonar-core/src/main/resources/org/sonar/l10n/core.properties View File

@@ -3770,6 +3770,7 @@ onboarding.tutorial.with.jenkins.jenkinsfile.other.step3.help1.sentence.path=Man
onboarding.tutorial.with.jenkins.jenkinsfile.other.step3.help2.sentence=The name is located under the {path} section, in the {name} field.
onboarding.tutorial.with.jenkins.jenkinsfile.other.step3.help2.sentence.path=SonarQube Scanner > SonarQube Scanner installations
onboarding.tutorial.with.jenkins.jenkinsfile.other.step3.help2.sentence.name=Name
onboarding.tutorial.with.jenkins.jenkinsfile.cfamilly.agent_setup=We assume the Jenkins agent has the necessary tools to build your project.


onboarding.tutorial.with.azure_pipelines.os=What is your agent host?

Loading…
Cancel
Save