From: Mathieu Suen Date: Thu, 4 Mar 2021 14:10:23 +0000 (+0100) Subject: SONAR-14468, SONAR-14435 Improve C/C++/OjbC tutorial X-Git-Tag: 8.8.0.42792~60 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=0d9ba430312caf9af1cab82a9cd1db01db89f4c3;p=sonarqube.git SONAR-14468, SONAR-14435 Improve C/C++/OjbC tutorial --- diff --git a/server/sonar-docs/src/pages/analysis/azuredevops-integration.md b/server/sonar-docs/src/pages/analysis/azuredevops-integration.md index 644a235515d..249030dcb63 100644 --- a/server/sonar-docs/src/pages/analysis/azuredevops-integration.md +++ b/server/sonar-docs/src/pages/analysis/azuredevops-integration.md @@ -189,11 +189,13 @@ Select your build technology below to expand the instructions for configuring br [[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 '/static/cpp/build-wrapper-win-x86.zip' -OutFile 'build-wrapper.zip' @@ -210,15 +212,15 @@ Select your build technology below to expand the instructions for configuring br | 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=` -| 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 MSBuild.exe /t:Rebuild @@ -231,8 +233,50 @@ Select your build technology below to expand the instructions for configuring br | ``` | build-wrapper-macosx-x86/build-wrapper-macos-x86 --out-dir 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 '/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 +| +| # 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. diff --git a/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/BranchAnalysisStepContent.tsx b/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/BranchAnalysisStepContent.tsx index 1ec5a67b2c7..e8fd38050d4 100644 --- a/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/BranchAnalysisStepContent.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/BranchAnalysisStepContent.tsx @@ -18,12 +18,15 @@ * 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; } @@ -36,11 +39,13 @@ const BUILD_TOOLS_ORDERED: Array = [ 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(); - + const buildToolsList = languages['c'] + ? BUILD_TOOLS_ORDERED + : BUILD_TOOLS_ORDERED.filter(t => t !== BuildTools.CFamily); return ( <> {translate('onboarding.build')} @@ -49,7 +54,7 @@ export default function BranchAnalysisStepContent(props: BranchesAnalysisStepPro name="buildTechnology" onCheck={value => setBuildTechnology(value as BuildTools)} optionLabelKey="onboarding.build" - options={BUILD_TOOLS_ORDERED} + options={buildToolsList} /> ); } + +const mapStateToProps = (state: Store) => ({ + languages: getLanguages(state) +}); + +export default connect(mapStateToProps)(BranchAnalysisStepContent); diff --git a/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/__tests__/BranchAnalysisStepContent-test.tsx b/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/__tests__/BranchAnalysisStepContent-test.tsx index a865469b760..ac649569b3b 100644 --- a/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/__tests__/BranchAnalysisStepContent-test.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/__tests__/BranchAnalysisStepContent-test.tsx @@ -22,10 +22,11 @@ import * as React from 'react'; 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])( @@ -44,6 +45,7 @@ it.each([BuildTools.DotNet, BuildTools.Gradle, BuildTools.Maven, BuildTools.Othe function shallowRender(props: Partial = {}) { return shallow( `; + +exports[`should render correctly: without C 1`] = ` + + + onboarding.build + + + + +`; diff --git a/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/AnalysisCommand.tsx b/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/AnalysisCommand.tsx index d0506670b06..9c3ced3d9ef 100644 --- a/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/AnalysisCommand.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/AnalysisCommand.tsx @@ -38,8 +38,6 @@ export default function AnalysisCommand(props: AnalysisCommandProps) { React.useEffect(() => { if (buildTool && buildTool !== BuildTools.CFamily) { props.onStepValidationChange(true); - } else { - props.onStepValidationChange(false); } }, [buildTool, props.onStepValidationChange]); diff --git a/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/ClangGCC.tsx b/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/ClangGCC.tsx index 59880e0c93f..1baf28d923c 100644 --- a/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/ClangGCC.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/ClangGCC.tsx @@ -54,7 +54,7 @@ unzip build-wrapper.zip`, highlightScriptKey: 'onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build_wrapper.ccpp.nix', scriptBuild: - './build-wrapper-linux-x86/build-wrapper-linux-x86-64 --out-dir 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' @@ -62,7 +62,7 @@ Expand-Archive -Path 'build-wrapper.zip' -DestinationPath '.'`, highlightScriptKey: 'onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build_wrapper.ccpp.win', scriptBuild: - 'build-wrapper-win-x86/build-wrapper-win-x86-64.exe --out-dir 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 @@ -70,7 +70,7 @@ unzip 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 xcodebuild' + + './build-wrapper-macos-x86/build-wrapper-macos-x86 --out-dir bw-output xcodebuild' + ' -project myproject.xcodeproj -configuration Release clean build' } }; @@ -78,9 +78,15 @@ unzip build-wrapper.zip`, React.useEffect(() => { if (os) { props.onStepValidationChange(true); + } else { + props.onStepValidationChange(false); } }, [os, props.onStepValidationChange]); + const handlOsChange = (value: OSs) => { + setOs(value); + }; + return ( <> @@ -89,7 +95,7 @@ unzip build-wrapper.zip`, setOs(value as OSs)} + onCheck={handlOsChange} optionLabelKey="onboarding.build.other.os" options={Object.values(OSs)} /> @@ -110,7 +116,7 @@ unzip build-wrapper.zip`, diff --git a/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/PrepareAnalysisCommand.tsx b/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/PrepareAnalysisCommand.tsx index 60bfbf86b15..744a22da66e 100644 --- a/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/PrepareAnalysisCommand.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/PrepareAnalysisCommand.tsx @@ -41,7 +41,7 @@ export interface PrepareAnalysisCommandProps { export default function PrepareAnalysisCommand(props: PrepareAnalysisCommandProps) { const { buildTool, kind, projectKey } = props; - const ADDITIONAL_PROPERTY = 'sonar.cfamily.build-wrapper-output='; + 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: diff --git a/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/__snapshots__/ClangGCC-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/__snapshots__/ClangGCC-test.tsx.snap index e2cfc176ab3..24e43f76355 100644 --- a/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/__snapshots__/ClangGCC-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/__snapshots__/ClangGCC-test.tsx.snap @@ -43,6 +43,7 @@ exports[`should render correctly for "linux" 1`] = ` highlightKeys={ Array [ "task", + "inline", ] } highlightPrefixKeys="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build_wrapper.ccpp.nix" @@ -94,7 +95,7 @@ unzip build-wrapper.zip" translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build_script.ccpp" /> @@ -158,6 +159,7 @@ exports[`should render correctly for "mac" 1`] = ` highlightKeys={ Array [ "task", + "inline", ] } highlightPrefixKeys="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build_wrapper.ccpp.nix" @@ -209,7 +211,7 @@ unzip build-wrapper.zip" translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build_script.ccpp" /> @@ -273,6 +275,7 @@ exports[`should render correctly for "win" 1`] = ` highlightKeys={ Array [ "task", + "inline", ] } highlightPrefixKeys="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build_wrapper.ccpp.win" @@ -324,7 +327,7 @@ Expand-Archive -Path 'build-wrapper.zip' -DestinationPath '.'" translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build_script.ccpp" /> diff --git a/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/__snapshots__/PrepareAnalysisCommand-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/__snapshots__/PrepareAnalysisCommand-test.tsx.snap index 8085026aff0..170210c11f5 100644 --- a/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/__snapshots__/PrepareAnalysisCommand-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/__snapshots__/PrepareAnalysisCommand-test.tsx.snap @@ -240,12 +240,12 @@ exports[`should render correctly 4`] = ` onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare_additional.ccpp.advanced , "button": , "property": - sonar.cfamily.build-wrapper-output=<output directory> + sonar.cfamily.build-wrapper-output=bw-output , } } 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 f9bb51a0a97..1da982e10e3 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,12 +18,15 @@ * 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; } @@ -32,7 +35,7 @@ interface State { config: ManualTutorialConfig; } -export default class BuildToolForm extends React.PureComponent { +export class BuildToolForm extends React.PureComponent { constructor(props: Props) { super(props); this.state = { @@ -57,13 +60,12 @@ export default class BuildToolForm extends React.PureComponent { 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 ( <> @@ -94,3 +96,9 @@ export default class BuildToolForm extends React.PureComponent { ); } } + +const mapStateToProps = (state: Store) => ({ + languages: getLanguages(state) +}); + +export default connect(mapStateToProps)(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 cf789d91a2d..3cd4d25b405 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 @@ -20,10 +20,11 @@ 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' ); @@ -47,5 +48,7 @@ it('correctly calls the onDone prop', () => { }); function shallowRender(props: Partial = {}) { - return shallow(); + return shallow( + + ); } diff --git a/server/sonar-web/src/main/js/components/tutorials/manual/__tests__/__snapshots__/BuildToolForm-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/manual/__tests__/__snapshots__/BuildToolForm-test.tsx.snap index a478aa8017b..4f1c17201a7 100644 --- a/server/sonar-web/src/main/js/components/tutorials/manual/__tests__/__snapshots__/BuildToolForm-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/tutorials/manual/__tests__/__snapshots__/BuildToolForm-test.tsx.snap @@ -138,3 +138,41 @@ exports[`renders correctly: with "other" selected 1`] = ` /> `; + +exports[`renders correctly: without C 1`] = ` + +
+

+ onboarding.build +

+ +
+
+`; diff --git a/sonar-core/src/main/resources/org/sonar/l10n/core.properties b/sonar-core/src/main/resources/org/sonar/l10n/core.properties index 829fc92b5e5..2b86440b6d3 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -3299,7 +3299,7 @@ onboarding.token.invalid_format=The token you have entered has invalid format. 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 @@ -3644,7 +3644,7 @@ onboarding.tutorial.with.azure_pipelines.ExtensionInstallation.title=Install Son 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} @@ -3657,21 +3657,23 @@ onboarding.tutorial.with.azure_pipelines.BranchAnalysis.title=Configure analysis 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