[[collapse]]
| ## Analyzing a C/C++/Obj-C project
-|In your build pipeline, insert the following steps in the order they appear here. These steps can be interleaved with other steps of your build as long as the following order is followed. All steps have to be executed on the same agent.
-| 1. Make **Build Wrapper** available on the build agent:\
-| Download and unzip the **Build Wrapper** on the build agent (see *Prerequisites* section of the [C/C++/Objective-C](/analysis/languages/cfamily/) page). The archive to download and decompress depends on the platform of the host.\
-| Please, note that:
-| - For the Microsoft-hosted build agent you will need to do it every time (as part of build pipeline), e.g. you can add **PowerShell script** task doing that. This can be done by inserting a **Command Line** task.\
+| In your build pipeline, insert the following steps in the order they appear here. These steps can be interweaved with other steps of your build as long as the following order is followed. All steps have to be executed on the same agent.
+|
+| 1. Make the **Build Wrapper** available on the build agent:
+|
+| Download and unzip the **Build Wrapper** on the build agent (see the **Prerequisites** section of the [C/C++/Objective-C](/analysis/languages/cfamily/) page). The archive to download and decompress depends on the platform of the host.
+| Please, note that:
+| - For the Microsoft-hosted build agent, you will need to make the **Build Wrapper** available on the build agent every time (as part of the build pipeline). To accomplish this, you can add a **PowerShell script** task by inserting a **Command Line** task.
| Example of PowerShell commands on a Windows host:
| ```
| Invoke-WebRequest -Uri '<sonarqube_url>/static/cpp/build-wrapper-win-x86.zip' -OutFile 'build-wrapper.zip'
| unzip build-wrapper.zip
| ```
| - For the self-hosted build agent you can either download it every time (using the same scripts) or only once (as part of manual setup of build agent).
-| 2. Add a **Prepare analysis Configuration** task and configure it as follow:\
-| Click on the **Prepare analysis on SonarQube** task to configure it:
+| 1. Add a **Prepare analysis Configuration** task and configure it as follow:
+| Click on the **Prepare analysis on SonarQube** task to configure it:
| * Select the **SonarQube Server**
| * In *Choose the way to run the analysis*, select *standalone scanner* (even if you build with *Visual Studio*/*MSBuild*)
| * In *Additional Properties* in the *Advanced* section, add the property `sonar.cfamily.build-wrapper-output` with, as its value, the output directory to which the Build Wrapper should write its results: `sonar.cfamily.build-wrapper-output=<output directory>`
-| 3. Add a **Command Line** task to run your build.\
+| 1. Add a **Command Line** task to run your build.
| For the analysis to happen, your build has to be run through a command line so that it can be wrapped-up by the build-wrapper.
| To do so,
-| * Run **Build Wrapper** executable. Pass in as the arguments (1) the output directory configured in the previous task and (2) the command that runs a clean build of your project (not an incremental build).\
+| * Run **Build Wrapper** executable. Pass in as the arguments (1) the output directory configured in the previous task and (2) the command that runs a clean build of your project (not an incremental build).
| Example of PowerShell commands on a Windows host with an *MSBuild* build:
| ```
| build-wrapper-win-x86/build-wrapper-win-x86-64.exe --out-dir <output directory> MSBuild.exe /t:Rebuild
| ```
| build-wrapper-macosx-x86/build-wrapper-macos-x86 --out-dir <output directory> xcodebuild -project myproject.xcodeproj -configuration Release clean build
| ```
-| 4. Add a **Run Code Analysis** task to run the code analysis and make the results available to SonarQube. Consider running this task right after the previous one as the build environment should not be significantly altered before running the analysis.
-| 5. Add a **Publish Quality Gate Result** task.
+| 1. Add a **Run Code Analysis** task to run the code analysis and make the results available to SonarQube. Consider running this task right after the previous one as the build environment should not be significantly altered before running the analysis.
+| 1. Add a **Publish Quality Gate Result** task.
+|
+| **.yml example**:
+| ```
+| trigger:
+| - master
+| - feature/*
+|
+| steps:
+| # Make Build Wrapper available
+| - task: Bash@3
+| displayName: Download Build Wrapper
+| inputs:
+| targetType: inline
+| script: >
+| curl '<SONARQUBE_HOST>/static/cpp/build-wrapper-linux-x86.zip' --output build-wrapper.zip
+| unzip build-wrapper.zip
+|
+| # Prepare Analysis Configuration task
+| - task: SonarQubePrepare@4
+| inputs:
+| SonarQube: 'YourSonarqubeServerEndpoint'
+| scannerMode: 'CLI'
+| configMode: 'manual'
+| cliProjectKey: 'YourProjectKey'
+| extraProperties: "sonar.cfamily.build-wrapper-output=bw_output"
+| # Command Line task to run your build.
+| - task: Bash@3
+| displayName: Bash Script
+| inputs:
+| targetType: inline
+| script: >
+| ./build-wrapper-linux-x86/build-wrapper-linux-x86-64 --out-dir bw_output <Your build command>
+|
+| # Run Code Analysis task
+| - task: SonarQubeAnalyze@4
+|
+| # Publish Quality Gate Result task
+| - task: SonarQubePublish@4
+| inputs:
+| pollingTimeoutSec: '300'
+| ```
+| *Note: You need to choose your correct image and adapt the correct wrapper depending on the agent os. See above example to have the correct wrapper.*
### Running your pipeline
Commit and push your code to trigger the pipeline execution and SonarQube analysis. New pushes on your branches (and pull requests if you set up pull request analysis) trigger a new analysis in SonarQube.
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
+import { connect } from 'react-redux';
import { translate } from 'sonar-ui-common/helpers/l10n';
+import { getLanguages, Store } from '../../../store/rootReducer';
import RenderOptions from '../components/RenderOptions';
import { BuildTools } from '../types';
import AnalysisCommand from './commands/AnalysisCommand';
export interface BranchesAnalysisStepProps {
+ languages: T.Languages;
component: T.Component;
onStepValidationChange: (isValid: boolean) => void;
}
BuildTools.Other
];
-export default function BranchAnalysisStepContent(props: BranchesAnalysisStepProps) {
- const { component, onStepValidationChange } = props;
+export function BranchAnalysisStepContent(props: BranchesAnalysisStepProps) {
+ const { component, onStepValidationChange, languages } = props;
const [buildTechnology, setBuildTechnology] = React.useState<BuildTools | undefined>();
-
+ const buildToolsList = languages['c']
+ ? BUILD_TOOLS_ORDERED
+ : BUILD_TOOLS_ORDERED.filter(t => t !== BuildTools.CFamily);
return (
<>
<span>{translate('onboarding.build')}</span>
name="buildTechnology"
onCheck={value => setBuildTechnology(value as BuildTools)}
optionLabelKey="onboarding.build"
- options={BUILD_TOOLS_ORDERED}
+ options={buildToolsList}
/>
<AnalysisCommand
onStepValidationChange={onStepValidationChange}
</>
);
}
+
+const mapStateToProps = (state: Store) => ({
+ languages: getLanguages(state)
+});
+
+export default connect(mapStateToProps)(BranchAnalysisStepContent);
import { mockComponent } from '../../../../helpers/testMocks';
import RenderOptions from '../../components/RenderOptions';
import { BuildTools } from '../../types';
-import BranchAnalysisStepContent, { BranchesAnalysisStepProps } from '../BranchAnalysisStepContent';
+import { BranchAnalysisStepContent, BranchesAnalysisStepProps } from '../BranchAnalysisStepContent';
it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot();
+ expect(shallowRender({ languages: {} })).toMatchSnapshot('without C');
});
it.each([BuildTools.DotNet, BuildTools.Gradle, BuildTools.Maven, BuildTools.Other])(
function shallowRender(props: Partial<BranchesAnalysisStepProps> = {}) {
return shallow(
<BranchAnalysisStepContent
+ languages={{ c: { key: 'c', name: 'test' } }}
component={mockComponent()}
onStepValidationChange={jest.fn()}
{...props}
/>
</Fragment>
`;
+
+exports[`should render correctly: without C 1`] = `
+<Fragment>
+ <span>
+ onboarding.build
+ </span>
+ <RenderOptions
+ name="buildTechnology"
+ onCheck={[Function]}
+ optionLabelKey="onboarding.build"
+ options={
+ Array [
+ "dotnet",
+ "maven",
+ "gradle",
+ "other",
+ ]
+ }
+ />
+ <AnalysisCommand
+ onStepValidationChange={[MockFunction]}
+ projectKey="my-project"
+ />
+</Fragment>
+`;
React.useEffect(() => {
if (buildTool && buildTool !== BuildTools.CFamily) {
props.onStepValidationChange(true);
- } else {
- props.onStepValidationChange(false);
}
}, [buildTool, props.onStepValidationChange]);
highlightScriptKey:
'onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build_wrapper.ccpp.nix',
scriptBuild:
- './build-wrapper-linux-x86/build-wrapper-linux-x86-64 --out-dir <output directory> make clean all'
+ './build-wrapper-linux-x86/build-wrapper-linux-x86-64 --out-dir bw-output make clean all'
},
[OSs.Windows]: {
script: `Invoke-WebRequest -Uri '${host}/static/cpp/build-wrapper-win-x86.zip' -OutFile 'build-wrapper.zip'
highlightScriptKey:
'onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build_wrapper.ccpp.win',
scriptBuild:
- 'build-wrapper-win-x86/build-wrapper-win-x86-64.exe --out-dir <output directory> MSBuild.exe /t:Rebuild'
+ 'build-wrapper-win-x86/build-wrapper-win-x86-64.exe --out-dir bw-output MSBuild.exe /t:Rebuild'
},
[OSs.MacOS]: {
script: `curl '${host}/static/cpp/build-wrapper-macosx-x86.zip' --output build-wrapper.zip
highlightScriptKey:
'onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build_wrapper.ccpp.nix',
scriptBuild:
- './build-wrapper-macos-x86/build-wrapper-macos-x86 --out-dir <output directory> xcodebuild' +
+ './build-wrapper-macos-x86/build-wrapper-macos-x86 --out-dir bw-output xcodebuild' +
' -project myproject.xcodeproj -configuration Release clean build'
}
};
React.useEffect(() => {
if (os) {
props.onStepValidationChange(true);
+ } else {
+ props.onStepValidationChange(false);
}
}, [os, props.onStepValidationChange]);
+ const handlOsChange = (value: OSs) => {
+ setOs(value);
+ };
+
return (
<>
<span className="big-spacer-top display-block">
<RenderOptions
checked={os}
name="os"
- onCheck={value => setOs(value as OSs)}
+ onCheck={handlOsChange}
optionLabelKey="onboarding.build.other.os"
options={Object.values(OSs)}
/>
<SentenceWithHighlights
translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build_wrapper.ccpp.script"
highlightPrefixKeys={codeSnippetDownload[os].highlightScriptKey}
- highlightKeys={['task']}
+ highlightKeys={['task', 'inline']}
/>
<CodeSnippet snippet={codeSnippetDownload[os].script} />
</li>
export default function PrepareAnalysisCommand(props: PrepareAnalysisCommandProps) {
const { buildTool, kind, projectKey } = props;
- const ADDITIONAL_PROPERTY = 'sonar.cfamily.build-wrapper-output=<output directory>';
+ const ADDITIONAL_PROPERTY = 'sonar.cfamily.build-wrapper-output=bw-output';
const MAVEN_GRADLE_PROPS_SNIPPET = `# Additional properties that will be passed to the scanner,
# Put one key=value per line, example:
highlightKeys={
Array [
"task",
+ "inline",
]
}
highlightPrefixKeys="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build_wrapper.ccpp.nix"
translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build_script.ccpp"
/>
<CodeSnippet
- snippet="./build-wrapper-linux-x86/build-wrapper-linux-x86-64 --out-dir <output directory> make clean all"
+ snippet="./build-wrapper-linux-x86/build-wrapper-linux-x86-64 --out-dir bw-output make clean all"
/>
</li>
</ul>
highlightKeys={
Array [
"task",
+ "inline",
]
}
highlightPrefixKeys="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build_wrapper.ccpp.nix"
translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build_script.ccpp"
/>
<CodeSnippet
- snippet="./build-wrapper-macos-x86/build-wrapper-macos-x86 --out-dir <output directory> xcodebuild -project myproject.xcodeproj -configuration Release clean build"
+ snippet="./build-wrapper-macos-x86/build-wrapper-macos-x86 --out-dir bw-output xcodebuild -project myproject.xcodeproj -configuration Release clean build"
/>
</li>
</ul>
highlightKeys={
Array [
"task",
+ "inline",
]
}
highlightPrefixKeys="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build_wrapper.ccpp.win"
translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build_script.ccpp"
/>
<CodeSnippet
- snippet="build-wrapper-win-x86/build-wrapper-win-x86-64.exe --out-dir <output directory> MSBuild.exe /t:Rebuild"
+ snippet="build-wrapper-win-x86/build-wrapper-win-x86-64.exe --out-dir bw-output MSBuild.exe /t:Rebuild"
/>
</li>
</ul>
onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare_additional.ccpp.advanced
</b>,
"button": <ClipboardIconButton
- copyValue="sonar.cfamily.build-wrapper-output=<output directory>"
+ copyValue="sonar.cfamily.build-wrapper-output=bw-output"
/>,
"property": <code
className="rule"
>
- sonar.cfamily.build-wrapper-output=<output directory>
+ sonar.cfamily.build-wrapper-output=bw-output
</code>,
}
}
* 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 RenderOptions from '../components/RenderOptions';
import { BuildTools, ManualTutorialConfig, OSs } from '../types';
interface Props {
+ languages: T.Languages;
config?: ManualTutorialConfig;
onDone: (config: ManualTutorialConfig) => void;
}
config: ManualTutorialConfig;
}
-export default class BuildToolForm extends React.PureComponent<Props, State> {
+export class BuildToolForm extends React.PureComponent<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
render() {
const { config } = this.state;
- const buildTools = [
- BuildTools.Maven,
- BuildTools.Gradle,
- BuildTools.DotNet,
- BuildTools.CFamily,
- BuildTools.Other
- ];
+ const { languages } = this.props;
+ const buildTools = [BuildTools.Maven, BuildTools.Gradle, BuildTools.DotNet];
+ if (languages['c']) {
+ buildTools.push(BuildTools.CFamily);
+ }
+ buildTools.push(BuildTools.Other);
return (
<>
);
}
}
+
+const mapStateToProps = (state: Store) => ({
+ languages: getLanguages(state)
+});
+
+export default connect(mapStateToProps)(BuildToolForm);
import { shallow } from 'enzyme';
import * as React from 'react';
import { BuildTools, OSs } from '../../types';
-import BuildToolForm from '../BuildToolForm';
+import { BuildToolForm } from '../BuildToolForm';
it('renders correctly', () => {
expect(shallowRender()).toMatchSnapshot('default');
+ expect(shallowRender({ languages: {} })).toMatchSnapshot('without C');
expect(shallowRender().setState({ config: { buildTool: BuildTools.Maven } })).toMatchSnapshot(
'with "maven" selected'
);
});
function shallowRender(props: Partial<BuildToolForm['props']> = {}) {
- return shallow<BuildToolForm>(<BuildToolForm onDone={jest.fn()} {...props} />);
+ return shallow<BuildToolForm>(
+ <BuildToolForm onDone={jest.fn()} languages={{ c: { key: 'c', name: 'test' } }} {...props} />
+ );
}
/>
</Fragment>
`;
+
+exports[`renders correctly: without C 1`] = `
+<Fragment>
+ <div>
+ <h4
+ className="spacer-bottom"
+ >
+ onboarding.build
+ </h4>
+ <RadioToggle
+ disabled={false}
+ name="language"
+ onCheck={[Function]}
+ options={
+ Array [
+ Object {
+ "label": "onboarding.build.maven",
+ "value": "maven",
+ },
+ Object {
+ "label": "onboarding.build.gradle",
+ "value": "gradle",
+ },
+ Object {
+ "label": "onboarding.build.dotnet",
+ "value": "dotnet",
+ },
+ Object {
+ "label": "onboarding.build.other",
+ "value": "other",
+ },
+ ]
+ }
+ value={null}
+ />
+ </div>
+</Fragment>
+`;
onboarding.analysis.header=Run analysis on your project
onboarding.analysis.auto_refresh_after_analysis=Once the analysis is completed, this page will automatically refresh and you will be able to browse the analysis results.
-onboarding.build=What is your build technology?
+onboarding.build=What option best describes your build?
onboarding.build.maven=Maven
onboarding.build.gradle=Gradle
onboarding.build.make=Make
onboarding.tutorial.with.azure_pipelines.ExtensionInstallation.sentence=From your Azure DevOps instance, navigate to the Visual Studio Marketplace and install the {link} by clicking the {button} button.
onboarding.tutorial.with.azure_pipelines.ExtensionInstallation.sentence.link=SonarQube extension
onboarding.tutorial.with.azure_pipelines.ExtensionInstallation.sentence.button=Get it free
-onboarding.tutorial.with.azure_pipelines.ServiceEndpoint.title=Add a new SonarQube Service Endpoint
+onboarding.tutorial.with.azure_pipelines.ServiceEndpoint.title=Add a new SonarQube Service Endpoint in your project
onboarding.tutorial.with.azure_pipelines.ServiceEndpoint.step1.sentence=In Azure DevOps, go to {menu}
onboarding.tutorial.with.azure_pipelines.ServiceEndpoint.step1.sentence.menu=Project settings > Service connections
onboarding.tutorial.with.azure_pipelines.ServiceEndpoint.step2.sentence=Add a new service connection of type {type}
onboarding.tutorial.with.azure_pipelines.BranchAnalysis.info=The following steps assume you are using the Azure Pipelines classic editor. Check out our {doc_link} for the yaml counterpart.
onboarding.tutorial.with.azure_pipelines.BranchAnalysis.info.doc_link=Azure DevOps integration page
-onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build_wrapper.ccpp.sentence=In Azure DevOps, create or edit a {pipeline} to make Build Wrapper available on the build agent.
-onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build_wrapper.ccpp.script.sentence=Add a {task} task to download and decompress the Build Wrapper on the build agent.
+onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build_wrapper.ccpp.sentence=In Azure DevOps, create or edit a build {pipeline} to make Build Wrapper available on the build agent.
+onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build_wrapper.ccpp.script.sentence=Add a {task} task, select {inline} mode and add the following script to download and decompress the Build Wrapper on the build agent.
onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build_wrapper.ccpp.win.sentence.task=PowerShell script
onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build_wrapper.ccpp.nix.sentence.task=Bash script
+onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build_wrapper.ccpp.win.sentence.inline=inline
+onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build_wrapper.ccpp.nix.sentence.inline=inline
onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.ccpp.sentence=Add a new {task} task {before} your build task
onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare_additional.ccpp=In {additional} in the {advanced} section, add a new property to set the output directory to which the Build Wrapper should write its results: {property} {button}
onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare_additional.ccpp.additional=Additional Properties
onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare_additional.ccpp.advanced=Advanced
-onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build.ccpp.sentence=Add or modify your {task} task. For the analysis to happen, your build has to be run through a command line so that it can be wrapped-up by the build-wrapper.
-onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build.ccpp.sentence.task=Build Command Line
+onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build.ccpp.sentence=Add or modify your build {task} task. For the analysis to happen, your build has to be run through a command line so that it can be wrapped-up by the build-wrapper.
+onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build.ccpp.sentence.task=Command Line
onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build_script.ccpp.sentence=Run {build_wrapper} executable. Pass in as the arguments (1) the output directory configured in the previous task and (2) the command that runs a clean build of your project (not an incremental build). Example:
onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build_script.ccpp.sentence.build_wrapper=Build Wrapper
onboarding.tutorial.with.azure_pipelines.BranchAnalysis.run.ccpp.sentence=Add a new {task} task {after} your build task. Consider running this task right after the previous one as the build environment should not be significantly altered before running the analysis.
-onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.sentence=In Azure DevOps, create or edit a {pipeline} and add a new {task} task {before} your build task
-onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.sentence.pipeline=Build Pipeline
+onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.sentence=In Azure DevOps, create or edit a build {pipeline} and add a new {task} task {before} your build task
+onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.sentence.pipeline=Pipeline
onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.sentence.task=Prepare Analysis Configuration
onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.sentence.before=before
onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.endpoint.sentence=Select the {endpoint} you created in Step 2