baseUrl={baseUrl}
component={component}
currentUser={currentUser}
- mainBranchName={mainBranchName}
willRefreshAutomatically={willRefreshAutomatically}
/>
)}
baseUrl: string;
component: Component;
currentUser: LoggedInUser;
- mainBranchName: string;
willRefreshAutomatically?: boolean;
}
export default function GitLabCITutorial(props: GitLabCITutorialProps) {
- const { baseUrl, component, currentUser, willRefreshAutomatically, mainBranchName } = props;
+ const { baseUrl, component, currentUser, willRefreshAutomatically } = props;
const [step, setStep] = React.useState(Steps.ENV_VARIABLES);
<YmlFileStep
finished={step > Steps.YML}
component={component}
- mainBranchName={mainBranchName}
onDone={() => setStep(Steps.ALL_SET)}
onOpen={() => setStep(Steps.YML)}
open={step === Steps.YML}
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+
+import { FlagMessage } from 'design-system';
import * as React from 'react';
import { FormattedMessage } from 'react-intl';
import withAvailableFeatures, {
import { ClipboardIconButton } from '../../../components/controls/clipboard';
import { GRADLE_SCANNER_VERSION } from '../../../helpers/constants';
import { translate } from '../../../helpers/l10n';
-import { Feature } from '../../../types/features';
import { Component } from '../../../types/types';
import CodeSnippet from '../../common/CodeSnippet';
import { withCLanguageFeature } from '../../hoc/withCLanguageFeature';
import PipeCommand from './commands/PipeCommand';
export interface YmlFileStepProps extends WithAvailableFeaturesProps {
- finished: boolean;
component: Component;
+ finished: boolean;
hasCLanguageFeature: boolean;
onDone: () => void;
onOpen: () => void;
open: boolean;
- mainBranchName: string;
}
-const mavenSnippet = () => `<properties>
+const mavenSnippet = (key: string, name: string) => `<properties>
+ <sonar.projectKey>${key}</sonar.projectKey>
+ <sonar.projectName>${name}</sonar.projectName>
<sonar.qualitygate.wait>true</sonar.qualitygate.wait>
</properties>`;
`;
const snippetForBuildTool = {
- [BuildTools.Maven]: mavenSnippet,
- [BuildTools.Gradle]: gradleSnippet,
[BuildTools.CFamily]: otherSnippet,
+ [BuildTools.Gradle]: gradleSnippet,
+ [BuildTools.Maven]: mavenSnippet,
[BuildTools.Other]: otherSnippet,
};
const filenameForBuildTool = {
- [BuildTools.Maven]: 'pom.xml',
- [BuildTools.Gradle]: GradleBuildDSL.Groovy,
[BuildTools.CFamily]: 'sonar-project.properties',
+ [BuildTools.Gradle]: GradleBuildDSL.Groovy,
+ [BuildTools.Maven]: 'pom.xml',
[BuildTools.Other]: 'sonar-project.properties',
};
export function YmlFileStep(props: YmlFileStepProps) {
- const { open, finished, mainBranchName, hasCLanguageFeature, component } = props;
- const branchSupportEnabled = props.hasFeature(Feature.BranchSupport);
+ const { component, hasCLanguageFeature, finished, open } = props;
const [buildTool, setBuildTool] = React.useState<BuildTools>();
const buildTools = [BuildTools.Maven, BuildTools.Gradle, BuildTools.DotNet];
+
if (hasCLanguageFeature) {
buildTools.push(BuildTools.CFamily);
}
+
buildTools.push(BuildTools.Other);
const renderForm = () => (
<ol className="list-styled">
<li>
{translate('onboarding.build')}
+
<RenderOptions
- label={translate('onboarding.build')}
checked={buildTool}
+ label={translate('onboarding.build')}
onCheck={setBuildTool as (key: string) => void}
optionLabelKey="onboarding.build"
options={buildTools}
/>
+
{buildTool === BuildTools.CFamily && (
<GithubCFamilyExampleRepositories
- className="big-spacer-bottom big-spacer-top abs-width-600"
ci={TutorialModes.GitLabCI}
+ className="sw-mb-4 sw-mt-4 sw-w-[600px]"
/>
)}
</li>
- {buildTool !== undefined && buildTool !== BuildTools.DotNet && (
- <li className="abs-width-600">
- <FormattedMessage
- defaultMessage={translate(
- `onboarding.tutorial.with.gitlab_ci.project_key.${buildTool}.step2`
+
+ {buildTool !== undefined &&
+ buildTool !== BuildTools.CFamily &&
+ buildTool !== BuildTools.DotNet && (
+ <li className="sw-w-[600px]">
+ <FormattedMessage
+ defaultMessage={translate(
+ `onboarding.tutorial.with.gitlab_ci.project_key.${buildTool}.step2`
+ )}
+ id={`onboarding.tutorial.with.gitlab_ci.project_key.${buildTool}.step2`}
+ 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="sw-ml-1"
+ copyValue={GradleBuildDSL.Kotlin}
+ />
+ </>
+ ),
+ }
+ : {}
+ )}
+ />
+
+ {buildTool === BuildTools.Gradle ? (
+ <GradleBuildSelection className="sw-mb-4 sw-mt-2">
+ {(build) => (
+ <CodeSnippet
+ snippet={snippetForBuildTool[buildTool](component.key, component.name, build)}
+ />
+ )}
+ </GradleBuildSelection>
+ ) : (
+ <CodeSnippet
+ snippet={snippetForBuildTool[buildTool](component.key, component.name)}
+ />
)}
- id={`onboarding.tutorial.with.gitlab_ci.project_key.${buildTool}.step2`}
- values={Object.assign(
- {
- file: (
- <>
- <code className="rule">{filenameForBuildTool[buildTool]}</code>
- <ClipboardIconButton
- className="little-spacer-left"
- copyValue={filenameForBuildTool[buildTool]}
- />
- </>
- ),
- },
- buildTool === BuildTools.Gradle
- ? {
- file2: (
+ </li>
+ )}
+
+ {buildTool && (
+ <li className="sw-w-[600px]">
+ {buildTool !== BuildTools.CFamily && (
+ <>
+ <div className="sw-mb-4">
+ <FormattedMessage
+ defaultMessage={translate(
+ 'onboarding.tutorial.with.gitlab_ci.yaml.description'
+ )}
+ id="onboarding.tutorial.with.gitlab_ci.yaml.description"
+ values={{
+ filename: (
<>
- <code className="rule">{GradleBuildDSL.Kotlin}</code>
+ <code className="rule">
+ {translate('onboarding.tutorial.with.gitlab_ci.yaml.filename')}
+ </code>
+
<ClipboardIconButton
- className="little-spacer-left"
- copyValue={GradleBuildDSL.Kotlin}
+ className="sw-ml-1"
+ copyValue={translate(
+ 'onboarding.tutorial.with.gitlab_ci.yaml.filename'
+ )}
/>
</>
),
- }
- : {}
- )}
- />
- {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)} />
+ </div>
+
+ <div className="sw-mb-4 sw-w-[600px]">
+ <PipeCommand buildTool={buildTool} projectKey={component.key} />
+ </div>
+
+ <FlagMessage className="sw-mb-4" variant="warning">
+ {translate('onboarding.tutorial.with.gitlab_ci.yaml.premium')}
+ </FlagMessage>
+
+ <p className="sw-mb-1">
+ {translate('onboarding.tutorial.with.gitlab_ci.yaml.baseconfig')}
+ </p>
+
+ <p>{translate('onboarding.tutorial.with.gitlab_ci.yaml.existing')}</p>
+ </>
)}
- </li>
- )}
- {buildTool && (
- <li className="abs-width-600">
- <div className="big-spacer-bottom">
- <FormattedMessage
- defaultMessage={translate('onboarding.tutorial.with.gitlab_ci.yaml.description')}
- id="onboarding.tutorial.with.gitlab_ci.yaml.description"
- values={{
- filename: (
- <>
- <code className="rule">
- {translate('onboarding.tutorial.with.gitlab_ci.yaml.filename')}
- </code>
- <ClipboardIconButton
- className="little-spacer-left"
- copyValue={translate('onboarding.tutorial.with.gitlab_ci.yaml.filename')}
- />
- </>
- ),
- }}
- />
- </div>
- <div className="big-spacer-bottom abs-width-600">
- <PipeCommand
- buildTool={buildTool}
- branchesEnabled={branchSupportEnabled}
- mainBranchName={mainBranchName}
- projectKey={component.key}
- projectName={component.name}
- />
- </div>
- <p className="little-spacer-bottom">
- {branchSupportEnabled
- ? translate('onboarding.tutorial.with.gitlab_ci.yaml.baseconfig')
- : translate('onboarding.tutorial.with.gitlab_ci.yaml.baseconfig.no_branches')}
- </p>
- <p>{translate('onboarding.tutorial.with.gitlab_ci.yaml.existing')}</p>
<FinishButton onClick={props.onDone} />
</li>
)}
import UserTokensMock from '../../../../api/mocks/UserTokensMock';
import { mockComponent } from '../../../../helpers/mocks/component';
import { mockLanguage, mockLoggedInUser } from '../../../../helpers/testMocks';
-import { renderApp, RenderContext } from '../../../../helpers/testReactTestingUtils';
+import { RenderContext, renderApp } from '../../../../helpers/testReactTestingUtils';
import {
getCommonNodes,
getCopyToClipboardValue,
await user.click(ui.dotnetBuildButton.get());
expect(getCopyToClipboardValue(1)).toMatchSnapshot('.NET: gitlab-ci.yml');
- // CFamily
- await user.click(ui.cFamilyBuildButton.get());
- expect(getCopyToClipboardValue(1)).toMatchSnapshot('CFamily: sonar-project.properties');
- expect(getCopyToClipboardValue(3)).toMatchSnapshot('CFamily: gitlab-ci.yml');
-
// Other
await user.click(ui.otherBuildButton.get());
expect(getCopyToClipboardValue(1)).toMatchSnapshot('Other: sonar-project.properties');
'/',
<GitLabCITutorial
baseUrl="http://localhost:9000"
- mainBranchName="main"
component={mockComponent()}
currentUser={mockLoggedInUser()}
{...overrides}
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should follow and complete all steps: .NET: gitlab-ci.yml 1`] = `
-"sonarqube-check:
+"stages:
+ - sonarqube-check
+ - vulnerability-report
+
+sonarqube-check:
+ stage: sonarqube-check
image: mcr.microsoft.com/dotnet/core/sdk:latest
variables:
SONAR_USER_HOME: "\${CI_PROJECT_DIR}/.sonar" # Defines the location of the analysis task cache
- "dotnet build"
- "dotnet sonarscanner end /d:sonar.token=\\"$SONAR_TOKEN\\""
allow_failure: true
- rules:
- - if: $CI_COMMIT_BRANCH == 'main'
-"
-`;
-
-exports[`should follow and complete all steps: CFamily: gitlab-ci.yml 1`] = `
-"image: <image ready for your build toolchain>
-
-cache:
- paths:
- - .sonar
-
-stages:
- - download
- - build
- - scan
-
-download:
- stage: download
+ only:
+ - merge_requests
+ - master
+ - main
+ - develop
+
+vulnerability-report:
+ stage: vulnerability-report
script:
- - mkdir -p .sonar
- - curl -sSLo build-wrapper-linux-x86.zip $SONAR_HOST_URL/static/cpp/build-wrapper-linux-x86.zip
- - unzip -o build-wrapper-linux-x86.zip -d .sonar
-
-build:
- stage: build
- script:
- - .sonar/build-wrapper-linux-x86/build-wrapper-linux-x86-64 --out-dir .sonar/bw-output <your clean build command>
-
-sonarqube-check:
- stage: scan
- script:
- - curl -sSLo sonar-scanner.zip https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-4.6.2.2472-linux.zip
- - unzip -o sonar-scanner.zip -d .sonar
- - .sonar/sonar-scanner-4.6.2.2472-linux/bin/sonar-scanner -Dsonar.cfamily.build-wrapper-output=.sonar/bw-output
- allow_failure: true"
-`;
-
-exports[`should follow and complete all steps: CFamily: sonar-project.properties 1`] = `
-"sonar.projectKey=my-project
-sonar.qualitygate.wait=true
+ - 'curl -u "\${SONAR_TOKEN}:" "\${SONAR_HOST_URL}/api/issues/gitlab_sast_export?projectKey=my-project&branch=\${CI_COMMIT_BRANCH}&pullRequest=\${CI_MERGE_REQUEST_IID}" -o gl-sast-sonar-report.json'
+ allow_failure: true
+ only:
+ - merge_requests
+ - master
+ - main
+ - develop
+ artifacts:
+ expire_in: 1 day
+ reports:
+ sast: gl-sast-sonar-report.json
+ dependencies:
+ - sonarqube-check
"
`;
exports[`should follow and complete all steps: Gradle: gitlab-ci.yml 1`] = `
-"sonarqube-check:
+"stages:
+ - sonarqube-check
+ - vulnerability-report
+
+sonarqube-check:
+ stage: sonarqube-check
image: gradle:jre11-slim
variables:
SONAR_USER_HOME: "\${CI_PROJECT_DIR}/.sonar" # Defines the location of the analysis task cache
- .sonar/cache
script: gradle sonar
allow_failure: true
- rules:
- - if: $CI_COMMIT_BRANCH == 'main'
+ only:
+ - merge_requests
+ - master
+ - main
+ - develop
+
+vulnerability-report:
+ stage: vulnerability-report
+ script:
+ - 'curl -u "\${SONAR_TOKEN}:" "\${SONAR_HOST_URL}/api/issues/gitlab_sast_export?projectKey=my-project&branch=\${CI_COMMIT_BRANCH}&pullRequest=\${CI_MERGE_REQUEST_IID}" -o gl-sast-sonar-report.json'
+ allow_failure: true
+ only:
+ - merge_requests
+ - master
+ - main
+ - develop
+ artifacts:
+ expire_in: 1 day
+ reports:
+ sast: gl-sast-sonar-report.json
+ dependencies:
+ - sonarqube-check
"
`;
`;
exports[`should follow and complete all steps: Maven: gitlab-ci.yml 1`] = `
-"sonarqube-check:
+"stages:
+ - sonarqube-check
+ - vulnerability-report
+
+sonarqube-check:
+ stage: sonarqube-check
image: maven:3.6.3-jdk-11
variables:
SONAR_USER_HOME: "\${CI_PROJECT_DIR}/.sonar" # Defines the location of the analysis task cache
paths:
- .sonar/cache
script:
- - mvn verify sonar:sonar -Dsonar.projectKey=my-project -Dsonar.projectName='MyProject'
+ - mvn verify sonar:sonar
+ allow_failure: true
+ only:
+ - merge_requests
+ - master
+ - main
+ - develop
+
+vulnerability-report:
+ stage: vulnerability-report
+ script:
+ - 'curl -u "\${SONAR_TOKEN}:" "\${SONAR_HOST_URL}/api/issues/gitlab_sast_export?projectKey=my-project&branch=\${CI_COMMIT_BRANCH}&pullRequest=\${CI_MERGE_REQUEST_IID}" -o gl-sast-sonar-report.json'
allow_failure: true
- rules:
- - if: $CI_COMMIT_BRANCH == 'main'
+ only:
+ - merge_requests
+ - master
+ - main
+ - develop
+ artifacts:
+ expire_in: 1 day
+ reports:
+ sast: gl-sast-sonar-report.json
+ dependencies:
+ - sonarqube-check
"
`;
exports[`should follow and complete all steps: Maven: pom.xml 1`] = `
"<properties>
+ <sonar.projectKey>my-project</sonar.projectKey>
+ <sonar.projectName>MyProject</sonar.projectName>
<sonar.qualitygate.wait>true</sonar.qualitygate.wait>
</properties>"
`;
exports[`should follow and complete all steps: Other: gitlab-ci.yml 1`] = `
-"sonarqube-check:
+"stages:
+ - sonarqube-check
+ - vulnerability-report
+
+sonarqube-check:
+ stage: sonarqube-check
image:
name: sonarsource/sonar-scanner-cli:latest
entrypoint: [""]
script:
- sonar-scanner
allow_failure: true
- rules:
- - if: $CI_COMMIT_BRANCH == 'main'
+ only:
+ - merge_requests
+ - master
+ - main
+ - develop
+
+vulnerability-report:
+ stage: vulnerability-report
+ script:
+ - 'curl -u "\${SONAR_TOKEN}:" "\${SONAR_HOST_URL}/api/issues/gitlab_sast_export?projectKey=my-project&branch=\${CI_COMMIT_BRANCH}&pullRequest=\${CI_MERGE_REQUEST_IID}" -o gl-sast-sonar-report.json'
+ allow_failure: true
+ only:
+ - merge_requests
+ - master
+ - main
+ - develop
+ artifacts:
+ expire_in: 1 day
+ reports:
+ sast: gl-sast-sonar-report.json
+ dependencies:
+ - sonarqube-check
"
`;
* 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 CodeSnippet from '../../../common/CodeSnippet';
-import { CompilationInfo } from '../../components/CompilationInfo';
import { BuildTools } from '../../types';
export interface PipeCommandProps {
- branchesEnabled?: boolean;
- buildTool: BuildTools;
- mainBranchName: string;
+ buildTool: Exclude<BuildTools, BuildTools.CFamily>;
projectKey: string;
- projectName: string;
}
const BUILD_TOOL_SPECIFIC = {
- [BuildTools.Gradle]: { image: 'gradle:jre11-slim', script: () => 'gradle sonar' },
+ [BuildTools.Gradle]: {
+ image: 'gradle:jre11-slim',
+ script: () => 'gradle sonar',
+ },
[BuildTools.Maven]: {
image: 'maven:3.6.3-jdk-11',
- script: (projectKey: string, projectName: string) => `
- - mvn verify sonar:sonar -Dsonar.projectKey=${projectKey} -Dsonar.projectName='${projectName}'`,
+ script: () => `
+ - mvn verify sonar:sonar`,
},
[BuildTools.DotNet]: {
image: 'mcr.microsoft.com/dotnet/core/sdk:latest',
};
export default function PipeCommand(props: PipeCommandProps) {
- const { projectKey, branchesEnabled, buildTool, mainBranchName, projectName } = props;
- let command: string;
- if (buildTool === BuildTools.CFamily) {
- command = `image: <image ready for your build toolchain>
-
-cache:
- paths:
- - .sonar
+ const { projectKey, buildTool } = props;
-stages:
- - download
- - build
- - scan
+ const { image, script } = BUILD_TOOL_SPECIFIC[buildTool];
-download:
- stage: download
- script:
- - mkdir -p .sonar
- - curl -sSLo build-wrapper-linux-x86.zip $SONAR_HOST_URL/static/cpp/build-wrapper-linux-x86.zip
- - unzip -o build-wrapper-linux-x86.zip -d .sonar
-
-build:
- stage: build
- script:
- - .sonar/build-wrapper-linux-x86/build-wrapper-linux-x86-64 --out-dir .sonar/bw-output <your clean build command>
+ const command = `stages:
+ - sonarqube-check
+ - vulnerability-report
sonarqube-check:
- stage: scan
- script:
- - curl -sSLo sonar-scanner.zip https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-4.6.2.2472-linux.zip
- - unzip -o sonar-scanner.zip -d .sonar
- - .sonar/sonar-scanner-4.6.2.2472-linux/bin/sonar-scanner -Dsonar.cfamily.build-wrapper-output=.sonar/bw-output
- allow_failure: true`;
- } else {
- const onlyBlock = branchesEnabled
- ? `- if: $CI_PIPELINE_SOURCE == 'merge_request_event'
- - if: $CI_COMMIT_BRANCH == '${mainBranchName}'
- - if: $CI_COMMIT_BRANCH == 'develop'`
- : `- if: $CI_COMMIT_BRANCH == '${mainBranchName}'`;
-
- const { image, script } = BUILD_TOOL_SPECIFIC[buildTool];
-
- command = `sonarqube-check:
+ stage: sonarqube-check
image: ${image}
variables:
SONAR_USER_HOME: "\${CI_PROJECT_DIR}/.sonar" # Defines the location of the analysis task cache
key: "\${CI_JOB_NAME}"
paths:
- .sonar/cache
- script: ${script(projectKey, projectName)}
+ script: ${script(projectKey)}
+ allow_failure: true
+ only:
+ - merge_requests
+ - master
+ - main
+ - develop
+
+vulnerability-report:
+ stage: vulnerability-report
+ script:
+ - 'curl -u "\${SONAR_TOKEN}:" "\${SONAR_HOST_URL}/api/issues/gitlab_sast_export?projectKey=${projectKey}&branch=\${CI_COMMIT_BRANCH}&pullRequest=\${CI_MERGE_REQUEST_IID}" -o gl-sast-sonar-report.json'
allow_failure: true
- rules:
- ${onlyBlock}
+ only:
+ - merge_requests
+ - master
+ - main
+ - develop
+ artifacts:
+ expire_in: 1 day
+ reports:
+ sast: gl-sast-sonar-report.json
+ dependencies:
+ - sonarqube-check
`;
- }
- return (
- <>
- <CodeSnippet snippet={command} />
- {buildTool === BuildTools.CFamily && <CompilationInfo />}
- </>
- );
+
+ return <CodeSnippet snippet={command} />;
}
onboarding.tutorial.with.gitlab_ci.yaml.title=Create or update the configuration file
onboarding.tutorial.with.gitlab_ci.yaml.description=Create or update your {filename} file with the following content.
onboarding.tutorial.with.gitlab_ci.yaml.filename=.gitlab-ci.yml
-onboarding.tutorial.with.gitlab_ci.yaml.baseconfig=Note that this is a minimal base configuration to run a SonarQube analysis on your main branch and merge requests.
-onboarding.tutorial.with.gitlab_ci.yaml.baseconfig.no_branches=Note that this is a minimal base configuration to run a SonarQube analysis on your main branch.
-onboarding.tutorial.with.gitlab_ci.yaml.existing=If you already have a pipeline configured and running, you might want to add the example from this step to your existing yml file.
+onboarding.tutorial.with.gitlab_ci.yaml.baseconfig=Note that this is a minimal base configuration to run a SonarQube analysis on your main branch and merge requests, and fetch the vulnerability report (if applicable).
+onboarding.tutorial.with.gitlab_ci.yaml.existing=If you already have a pipeline configured and running, you might want to add the example above to your existing yml file.
+onboarding.tutorial.with.gitlab_ci.yaml.premium=The vulnerability report stage will only be available for Gitlab Premium users. You may safely remove it if you have not subscribed to this service.
onboarding.tutorial.with.jenkins.title=Analyze your project with Jenkins
onboarding.tutorial.with.jenkins.alm_selection.title=Select your DevOps platform