]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-14468 Add CFamily tutorial for Azure DevOps.
authorMathieu Suen <mathieu.suen@sonarsource.com>
Fri, 12 Feb 2021 11:12:58 +0000 (12:12 +0100)
committersonartech <sonartech@sonarsource.com>
Mon, 15 Feb 2021 20:07:05 +0000 (20:07 +0000)
34 files changed:
server/sonar-web/src/main/js/components/tutorials/azure-pipelines/BranchAnalysisStepContent.tsx
server/sonar-web/src/main/js/components/tutorials/azure-pipelines/__tests__/BranchAnalysisStepContent-test.tsx
server/sonar-web/src/main/js/components/tutorials/azure-pipelines/__tests__/__snapshots__/BranchAnalysisStepContent-test.tsx.snap
server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/AlertClassicEditor.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/AnalysisCommand.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/ClangGCC.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/DotNet.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/JavaGradle.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/JavaMaven.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/Other.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/PrepareAnalysisCommand.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/PublishSteps.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/AlertClassicEditor-test.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/AnalysisCommand-test.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/ClangGCC-test.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/DotNet-test.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/JavaGradle-test.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/JavaMaven-test.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/Other-test.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/PrepareAnalysisCommand-test.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/PublishSteps-test.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/__snapshots__/AlertClassicEditor-test.tsx.snap [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/__snapshots__/AnalysisCommand-test.tsx.snap [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/__snapshots__/ClangGCC-test.tsx.snap [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/__snapshots__/DotNet-test.tsx.snap [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/__snapshots__/JavaGradle-test.tsx.snap [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/__snapshots__/JavaMaven-test.tsx.snap [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/__snapshots__/Other-test.tsx.snap [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/__snapshots__/PrepareAnalysisCommand-test.tsx.snap [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/__snapshots__/PublishSteps-test.tsx.snap [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/components/SentenceWithHighlights.tsx
server/sonar-web/src/main/js/components/tutorials/manual/commands/__tests__/AnalysisCommand-test.tsx
server/sonar-web/src/main/js/components/tutorials/manual/commands/__tests__/__snapshots__/AnalysisCommand-test.tsx.snap
sonar-core/src/main/resources/org/sonar/l10n/core.properties

index 755a685a000b4023fcdb1884640064ce0bb8f6c4..1ec5a67b2c7662ada8066e80b73611b0abed66bd 100644 (file)
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 import * as React from 'react';
-import { FormattedMessage } from 'react-intl';
-import { Link } from 'react-router';
-import { ClipboardIconButton } from 'sonar-ui-common/components/controls/clipboard';
-import { Alert } from 'sonar-ui-common/components/ui/Alert';
-import { translate, translateWithParameters } from 'sonar-ui-common/helpers/l10n';
-import { ALM_DOCUMENTATION_PATHS } from '../../../helpers/constants';
-import { AlmKeys } from '../../../types/alm-settings';
-import CodeSnippet from '../../common/CodeSnippet';
-import { withAppState } from '../../hoc/withAppState';
+import { translate } from 'sonar-ui-common/helpers/l10n';
 import RenderOptions from '../components/RenderOptions';
-import SentenceWithHighlights from '../components/SentenceWithHighlights';
+import { BuildTools } from '../types';
+import AnalysisCommand from './commands/AnalysisCommand';
 
 export interface BranchesAnalysisStepProps {
-  appState: T.AppState;
   component: T.Component;
   onStepValidationChange: (isValid: boolean) => void;
 }
 
-export enum BuildTechnology {
-  DotNet = 'dotnet',
-  Maven = 'maven',
-  Gradle = 'gradle',
-  Other = 'other'
-}
-
-export function BranchAnalysisStepContent(props: BranchesAnalysisStepProps) {
-  const {
-    appState: { branchesEnabled },
-    component,
-    onStepValidationChange
-  } = props;
-
-  const [buildTechnology, setBuildTechnology] = React.useState<BuildTechnology | undefined>();
+const BUILD_TOOLS_ORDERED: Array<BuildTools> = [
+  BuildTools.DotNet,
+  BuildTools.Maven,
+  BuildTools.Gradle,
+  BuildTools.CFamily,
+  BuildTools.Other
+];
 
-  React.useEffect(() => {
-    if (buildTechnology) {
-      onStepValidationChange(true);
-    }
-  }, [buildTechnology, onStepValidationChange]);
+export default function BranchAnalysisStepContent(props: BranchesAnalysisStepProps) {
+  const { component, onStepValidationChange } = props;
 
-  const MAVEN_GRADLE_PROPS_SNIPPET = `# Additional properties that will be passed to the scanner,
-# Put one key=value per line, example:
-# sonar.exclusions=**/*.bin
-sonar.projectKey=${component.key}`;
+  const [buildTechnology, setBuildTechnology] = React.useState<BuildTools | undefined>();
 
   return (
     <>
@@ -69,174 +47,15 @@ sonar.projectKey=${component.key}`;
       <RenderOptions
         checked={buildTechnology}
         name="buildTechnology"
-        onCheck={value => setBuildTechnology(value as BuildTechnology)}
+        onCheck={value => setBuildTechnology(value as BuildTools)}
         optionLabelKey="onboarding.build"
-        options={Object.values(BuildTechnology)}
+        options={BUILD_TOOLS_ORDERED}
+      />
+      <AnalysisCommand
+        onStepValidationChange={onStepValidationChange}
+        buildTool={buildTechnology}
+        projectKey={component.key}
       />
-      {buildTechnology && (
-        <>
-          <Alert variant="info" className="big-spacer-top">
-            <FormattedMessage
-              id="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.info"
-              defaultMessage={translate(
-                'onboarding.tutorial.with.azure_pipelines.BranchAnalysis.info'
-              )}
-              values={{
-                doc_link: (
-                  <Link to={ALM_DOCUMENTATION_PATHS[AlmKeys.Azure]} target="_blank">
-                    {translate(
-                      'onboarding.tutorial.with.azure_pipelines.BranchAnalysis.info.doc_link'
-                    )}
-                  </Link>
-                )
-              }}
-            />
-          </Alert>
-          <ol className="list-styled big-spacer-top">
-            <li>
-              <SentenceWithHighlights
-                translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare"
-                highlightKeys={['pipeline', 'task', 'before']}
-              />
-            </li>
-            <ul className="list-styled">
-              <li>
-                <SentenceWithHighlights
-                  translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.endpoint"
-                  highlightKeys={['endpoint']}
-                />
-              </li>
-              <li>
-                <FormattedMessage
-                  id="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis"
-                  defaultMessage={translate(
-                    'onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis'
-                  )}
-                  values={{
-                    section: (
-                      <strong>
-                        {translate(
-                          'onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis.section'
-                        )}
-                      </strong>
-                    ),
-                    run_analysis_value: (
-                      <strong>
-                        {translate(
-                          'onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis.values',
-                          buildTechnology
-                        )}
-                      </strong>
-                    )
-                  }}
-                />
-              </li>
-              {buildTechnology === BuildTechnology.Other && (
-                <li>
-                  <SentenceWithHighlights
-                    translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.manual"
-                    highlightKeys={['mode']}
-                  />
-                </li>
-              )}
-              {[BuildTechnology.DotNet, BuildTechnology.Other].includes(buildTechnology) && (
-                <li>
-                  <FormattedMessage
-                    id="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.run.key.sentence"
-                    defaultMessage={translate(
-                      'onboarding.tutorial.with.azure_pipelines.BranchAnalysis.run.key.sentence'
-                    )}
-                    values={{
-                      key: <code className="rule">{component.key}</code>,
-                      button: <ClipboardIconButton copyValue={component.key} />
-                    }}
-                  />
-                </li>
-              )}
-              {[BuildTechnology.Maven, BuildTechnology.Gradle].includes(buildTechnology) && (
-                <li>
-                  <SentenceWithHighlights
-                    translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.advanced_properties"
-                    highlightKeys={['section', 'properties']}
-                  />
-                  :
-                  <CodeSnippet snippet={MAVEN_GRADLE_PROPS_SNIPPET} />
-                </li>
-              )}
-            </ul>
-            {[BuildTechnology.DotNet, BuildTechnology.Other].includes(buildTechnology) && (
-              <li>
-                <SentenceWithHighlights
-                  translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.run"
-                  highlightKeys={['task', 'after']}
-                />
-              </li>
-            )}
-            {[BuildTechnology.Maven, BuildTechnology.Gradle].includes(buildTechnology) && (
-              <>
-                <li>
-                  {translateWithParameters(
-                    'onboarding.tutorial.with.azure_pipelines.BranchAnalysis.java',
-                    translate('onboarding.build', buildTechnology)
-                  )}
-                </li>
-                <ul className="list-styled big-spacer-bottom">
-                  <li>
-                    <SentenceWithHighlights
-                      translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.java.settings"
-                      highlightKeys={['section', 'option']}
-                    />
-                  </li>
-                </ul>
-              </>
-            )}
-
-            <li>
-              <SentenceWithHighlights
-                translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.publish_qg"
-                highlightKeys={['task']}
-              />
-              <Alert variant="info" className="spacer-top">
-                {translate(
-                  'onboarding.tutorial.with.azure_pipelines.BranchAnalysis.publish_qg.info.sentence1'
-                )}
-              </Alert>
-            </li>
-            <li>
-              <SentenceWithHighlights
-                translationKey={
-                  branchesEnabled
-                    ? 'onboarding.tutorial.with.azure_pipelines.BranchAnalysis.continous_integration'
-                    : 'onboarding.tutorial.with.azure_pipelines.BranchAnalysis.continous_integration.no_branches'
-                }
-                highlightKeys={['tab', 'continuous_integration']}
-              />
-            </li>
-            {branchesEnabled && (
-              <>
-                <hr />
-                <FormattedMessage
-                  id="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.branch_protection"
-                  defaultMessage={translate(
-                    'onboarding.tutorial.with.azure_pipelines.BranchAnalysis.branch_protection'
-                  )}
-                  values={{
-                    link: (
-                      <Link to={ALM_DOCUMENTATION_PATHS[AlmKeys.Azure]} target="_blank">
-                        {translate(
-                          'onboarding.tutorial.with.azure_pipelines.BranchAnalysis.branch_protection.link'
-                        )}
-                      </Link>
-                    )
-                  }}
-                />
-              </>
-            )}
-          </ol>
-        </>
-      )}
     </>
   );
 }
-
-export default withAppState(BranchAnalysisStepContent);
index 16e004a6c3893ee4c40a0386fccd5ef5836b9942..a865469b760ddd92ba11258f5cf421cb31bafdfc 100644 (file)
  */
 import { shallow } from 'enzyme';
 import * as React from 'react';
-import { mockAppState, mockComponent } from '../../../../helpers/testMocks';
+import { mockComponent } from '../../../../helpers/testMocks';
 import RenderOptions from '../../components/RenderOptions';
-import {
-  BranchAnalysisStepContent,
-  BranchesAnalysisStepProps,
-  BuildTechnology
-} from '../BranchAnalysisStepContent';
+import { BuildTools } from '../../types';
+import BranchAnalysisStepContent, { BranchesAnalysisStepProps } from '../BranchAnalysisStepContent';
 
 it('should render correctly', () => {
-  expect(shallowRender()).toMatchSnapshot('branches enabled');
-  expect(shallowRender({ appState: mockAppState({ branchesEnabled: false }) })).toMatchSnapshot(
-    'branches not enabled'
-  );
+  expect(shallowRender()).toMatchSnapshot();
 });
 
-it.each([
-  BuildTechnology.DotNet,
-  BuildTechnology.Gradle,
-  BuildTechnology.Maven,
-  BuildTechnology.Other
-])('should render correctly', (buildTech: BuildTechnology) => {
-  const wrapper = shallowRender();
-  wrapper
-    .find(RenderOptions)
-    .props()
-    .onCheck(buildTech);
+it.each([BuildTools.DotNet, BuildTools.Gradle, BuildTools.Maven, BuildTools.Other])(
+  'should render correctly',
+  (buildTech: BuildTools) => {
+    const wrapper = shallowRender();
+    wrapper
+      .find(RenderOptions)
+      .props()
+      .onCheck(buildTech);
 
-  expect(wrapper).toMatchSnapshot(buildTech);
-});
+    expect(wrapper).toMatchSnapshot(buildTech);
+  }
+);
 
 function shallowRender(props: Partial<BranchesAnalysisStepProps> = {}) {
   return shallow(
     <BranchAnalysisStepContent
-      appState={mockAppState({ branchesEnabled: true })}
       component={mockComponent()}
       onStepValidationChange={jest.fn()}
       {...props}
index fd282d774be398ac36ba6a30e58517b4f66f487e..3b1aacd4defec58072c9409eadd4fe4968ab3b0f 100644 (file)
@@ -1,6 +1,6 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
-exports[`should render correctly: branches enabled 1`] = `
+exports[`should render correctly 1`] = `
 <Fragment>
   <span>
     onboarding.build
@@ -14,30 +14,14 @@ exports[`should render correctly: branches enabled 1`] = `
         "dotnet",
         "maven",
         "gradle",
+        "cfamily",
         "other",
       ]
     }
   />
-</Fragment>
-`;
-
-exports[`should render correctly: branches not enabled 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>
 `;
@@ -57,150 +41,16 @@ exports[`should render correctly: dotnet 1`] = `
         "dotnet",
         "maven",
         "gradle",
+        "cfamily",
         "other",
       ]
     }
   />
-  <Alert
-    className="big-spacer-top"
-    variant="info"
-  >
-    <FormattedMessage
-      defaultMessage="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.info"
-      id="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.info"
-      values={
-        Object {
-          "doc_link": <Link
-            onlyActiveOnIndex={false}
-            style={Object {}}
-            target="_blank"
-            to="/documentation/analysis/azuredevops-integration/"
-          >
-            onboarding.tutorial.with.azure_pipelines.BranchAnalysis.info.doc_link
-          </Link>,
-        }
-      }
-    />
-  </Alert>
-  <ol
-    className="list-styled big-spacer-top"
-  >
-    <li>
-      <SentenceWithHighlights
-        highlightKeys={
-          Array [
-            "pipeline",
-            "task",
-            "before",
-          ]
-        }
-        translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare"
-      />
-    </li>
-    <ul
-      className="list-styled"
-    >
-      <li>
-        <SentenceWithHighlights
-          highlightKeys={
-            Array [
-              "endpoint",
-            ]
-          }
-          translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.endpoint"
-        />
-      </li>
-      <li>
-        <FormattedMessage
-          defaultMessage="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis"
-          id="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis"
-          values={
-            Object {
-              "run_analysis_value": <strong>
-                onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis.values.dotnet
-              </strong>,
-              "section": <strong>
-                onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis.section
-              </strong>,
-            }
-          }
-        />
-      </li>
-      <li>
-        <FormattedMessage
-          defaultMessage="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.run.key.sentence"
-          id="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.run.key.sentence"
-          values={
-            Object {
-              "button": <ClipboardIconButton
-                copyValue="my-project"
-              />,
-              "key": <code
-                className="rule"
-              >
-                my-project
-              </code>,
-            }
-          }
-        />
-      </li>
-    </ul>
-    <li>
-      <SentenceWithHighlights
-        highlightKeys={
-          Array [
-            "task",
-            "after",
-          ]
-        }
-        translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.run"
-      />
-    </li>
-    <li>
-      <SentenceWithHighlights
-        highlightKeys={
-          Array [
-            "task",
-          ]
-        }
-        translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.publish_qg"
-      />
-      <Alert
-        className="spacer-top"
-        variant="info"
-      >
-        onboarding.tutorial.with.azure_pipelines.BranchAnalysis.publish_qg.info.sentence1
-      </Alert>
-    </li>
-    <li>
-      <SentenceWithHighlights
-        highlightKeys={
-          Array [
-            "tab",
-            "continuous_integration",
-          ]
-        }
-        translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.continous_integration"
-      />
-    </li>
-    <hr />
-    <FormattedMessage
-      defaultMessage="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.branch_protection"
-      id="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.branch_protection"
-      values={
-        Object {
-          "link": <Link
-            onlyActiveOnIndex={false}
-            style={Object {}}
-            target="_blank"
-            to="/documentation/analysis/azuredevops-integration/"
-          >
-            onboarding.tutorial.with.azure_pipelines.BranchAnalysis.branch_protection.link
-          </Link>,
-        }
-      }
-    />
-  </ol>
+  <AnalysisCommand
+    buildTool="dotnet"
+    onStepValidationChange={[MockFunction]}
+    projectKey="my-project"
+  />
 </Fragment>
 `;
 
@@ -219,157 +69,16 @@ exports[`should render correctly: gradle 1`] = `
         "dotnet",
         "maven",
         "gradle",
+        "cfamily",
         "other",
       ]
     }
   />
-  <Alert
-    className="big-spacer-top"
-    variant="info"
-  >
-    <FormattedMessage
-      defaultMessage="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.info"
-      id="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.info"
-      values={
-        Object {
-          "doc_link": <Link
-            onlyActiveOnIndex={false}
-            style={Object {}}
-            target="_blank"
-            to="/documentation/analysis/azuredevops-integration/"
-          >
-            onboarding.tutorial.with.azure_pipelines.BranchAnalysis.info.doc_link
-          </Link>,
-        }
-      }
-    />
-  </Alert>
-  <ol
-    className="list-styled big-spacer-top"
-  >
-    <li>
-      <SentenceWithHighlights
-        highlightKeys={
-          Array [
-            "pipeline",
-            "task",
-            "before",
-          ]
-        }
-        translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare"
-      />
-    </li>
-    <ul
-      className="list-styled"
-    >
-      <li>
-        <SentenceWithHighlights
-          highlightKeys={
-            Array [
-              "endpoint",
-            ]
-          }
-          translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.endpoint"
-        />
-      </li>
-      <li>
-        <FormattedMessage
-          defaultMessage="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis"
-          id="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis"
-          values={
-            Object {
-              "run_analysis_value": <strong>
-                onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis.values.gradle
-              </strong>,
-              "section": <strong>
-                onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis.section
-              </strong>,
-            }
-          }
-        />
-      </li>
-      <li>
-        <SentenceWithHighlights
-          highlightKeys={
-            Array [
-              "section",
-              "properties",
-            ]
-          }
-          translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.advanced_properties"
-        />
-        :
-        <CodeSnippet
-          snippet="# Additional properties that will be passed to the scanner,
-# Put one key=value per line, example:
-# sonar.exclusions=**/*.bin
-sonar.projectKey=my-project"
-        />
-      </li>
-    </ul>
-    <li>
-      onboarding.tutorial.with.azure_pipelines.BranchAnalysis.java.onboarding.build.gradle
-    </li>
-    <ul
-      className="list-styled big-spacer-bottom"
-    >
-      <li>
-        <SentenceWithHighlights
-          highlightKeys={
-            Array [
-              "section",
-              "option",
-            ]
-          }
-          translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.java.settings"
-        />
-      </li>
-    </ul>
-    <li>
-      <SentenceWithHighlights
-        highlightKeys={
-          Array [
-            "task",
-          ]
-        }
-        translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.publish_qg"
-      />
-      <Alert
-        className="spacer-top"
-        variant="info"
-      >
-        onboarding.tutorial.with.azure_pipelines.BranchAnalysis.publish_qg.info.sentence1
-      </Alert>
-    </li>
-    <li>
-      <SentenceWithHighlights
-        highlightKeys={
-          Array [
-            "tab",
-            "continuous_integration",
-          ]
-        }
-        translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.continous_integration"
-      />
-    </li>
-    <hr />
-    <FormattedMessage
-      defaultMessage="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.branch_protection"
-      id="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.branch_protection"
-      values={
-        Object {
-          "link": <Link
-            onlyActiveOnIndex={false}
-            style={Object {}}
-            target="_blank"
-            to="/documentation/analysis/azuredevops-integration/"
-          >
-            onboarding.tutorial.with.azure_pipelines.BranchAnalysis.branch_protection.link
-          </Link>,
-        }
-      }
-    />
-  </ol>
+  <AnalysisCommand
+    buildTool="gradle"
+    onStepValidationChange={[MockFunction]}
+    projectKey="my-project"
+  />
 </Fragment>
 `;
 
@@ -388,157 +97,16 @@ exports[`should render correctly: maven 1`] = `
         "dotnet",
         "maven",
         "gradle",
+        "cfamily",
         "other",
       ]
     }
   />
-  <Alert
-    className="big-spacer-top"
-    variant="info"
-  >
-    <FormattedMessage
-      defaultMessage="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.info"
-      id="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.info"
-      values={
-        Object {
-          "doc_link": <Link
-            onlyActiveOnIndex={false}
-            style={Object {}}
-            target="_blank"
-            to="/documentation/analysis/azuredevops-integration/"
-          >
-            onboarding.tutorial.with.azure_pipelines.BranchAnalysis.info.doc_link
-          </Link>,
-        }
-      }
-    />
-  </Alert>
-  <ol
-    className="list-styled big-spacer-top"
-  >
-    <li>
-      <SentenceWithHighlights
-        highlightKeys={
-          Array [
-            "pipeline",
-            "task",
-            "before",
-          ]
-        }
-        translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare"
-      />
-    </li>
-    <ul
-      className="list-styled"
-    >
-      <li>
-        <SentenceWithHighlights
-          highlightKeys={
-            Array [
-              "endpoint",
-            ]
-          }
-          translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.endpoint"
-        />
-      </li>
-      <li>
-        <FormattedMessage
-          defaultMessage="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis"
-          id="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis"
-          values={
-            Object {
-              "run_analysis_value": <strong>
-                onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis.values.maven
-              </strong>,
-              "section": <strong>
-                onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis.section
-              </strong>,
-            }
-          }
-        />
-      </li>
-      <li>
-        <SentenceWithHighlights
-          highlightKeys={
-            Array [
-              "section",
-              "properties",
-            ]
-          }
-          translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.advanced_properties"
-        />
-        :
-        <CodeSnippet
-          snippet="# Additional properties that will be passed to the scanner,
-# Put one key=value per line, example:
-# sonar.exclusions=**/*.bin
-sonar.projectKey=my-project"
-        />
-      </li>
-    </ul>
-    <li>
-      onboarding.tutorial.with.azure_pipelines.BranchAnalysis.java.onboarding.build.maven
-    </li>
-    <ul
-      className="list-styled big-spacer-bottom"
-    >
-      <li>
-        <SentenceWithHighlights
-          highlightKeys={
-            Array [
-              "section",
-              "option",
-            ]
-          }
-          translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.java.settings"
-        />
-      </li>
-    </ul>
-    <li>
-      <SentenceWithHighlights
-        highlightKeys={
-          Array [
-            "task",
-          ]
-        }
-        translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.publish_qg"
-      />
-      <Alert
-        className="spacer-top"
-        variant="info"
-      >
-        onboarding.tutorial.with.azure_pipelines.BranchAnalysis.publish_qg.info.sentence1
-      </Alert>
-    </li>
-    <li>
-      <SentenceWithHighlights
-        highlightKeys={
-          Array [
-            "tab",
-            "continuous_integration",
-          ]
-        }
-        translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.continous_integration"
-      />
-    </li>
-    <hr />
-    <FormattedMessage
-      defaultMessage="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.branch_protection"
-      id="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.branch_protection"
-      values={
-        Object {
-          "link": <Link
-            onlyActiveOnIndex={false}
-            style={Object {}}
-            target="_blank"
-            to="/documentation/analysis/azuredevops-integration/"
-          >
-            onboarding.tutorial.with.azure_pipelines.BranchAnalysis.branch_protection.link
-          </Link>,
-        }
-      }
-    />
-  </ol>
+  <AnalysisCommand
+    buildTool="maven"
+    onStepValidationChange={[MockFunction]}
+    projectKey="my-project"
+  />
 </Fragment>
 `;
 
@@ -557,159 +125,15 @@ exports[`should render correctly: other 1`] = `
         "dotnet",
         "maven",
         "gradle",
+        "cfamily",
         "other",
       ]
     }
   />
-  <Alert
-    className="big-spacer-top"
-    variant="info"
-  >
-    <FormattedMessage
-      defaultMessage="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.info"
-      id="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.info"
-      values={
-        Object {
-          "doc_link": <Link
-            onlyActiveOnIndex={false}
-            style={Object {}}
-            target="_blank"
-            to="/documentation/analysis/azuredevops-integration/"
-          >
-            onboarding.tutorial.with.azure_pipelines.BranchAnalysis.info.doc_link
-          </Link>,
-        }
-      }
-    />
-  </Alert>
-  <ol
-    className="list-styled big-spacer-top"
-  >
-    <li>
-      <SentenceWithHighlights
-        highlightKeys={
-          Array [
-            "pipeline",
-            "task",
-            "before",
-          ]
-        }
-        translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare"
-      />
-    </li>
-    <ul
-      className="list-styled"
-    >
-      <li>
-        <SentenceWithHighlights
-          highlightKeys={
-            Array [
-              "endpoint",
-            ]
-          }
-          translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.endpoint"
-        />
-      </li>
-      <li>
-        <FormattedMessage
-          defaultMessage="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis"
-          id="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis"
-          values={
-            Object {
-              "run_analysis_value": <strong>
-                onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis.values.other
-              </strong>,
-              "section": <strong>
-                onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis.section
-              </strong>,
-            }
-          }
-        />
-      </li>
-      <li>
-        <SentenceWithHighlights
-          highlightKeys={
-            Array [
-              "mode",
-            ]
-          }
-          translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.manual"
-        />
-      </li>
-      <li>
-        <FormattedMessage
-          defaultMessage="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.run.key.sentence"
-          id="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.run.key.sentence"
-          values={
-            Object {
-              "button": <ClipboardIconButton
-                copyValue="my-project"
-              />,
-              "key": <code
-                className="rule"
-              >
-                my-project
-              </code>,
-            }
-          }
-        />
-      </li>
-    </ul>
-    <li>
-      <SentenceWithHighlights
-        highlightKeys={
-          Array [
-            "task",
-            "after",
-          ]
-        }
-        translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.run"
-      />
-    </li>
-    <li>
-      <SentenceWithHighlights
-        highlightKeys={
-          Array [
-            "task",
-          ]
-        }
-        translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.publish_qg"
-      />
-      <Alert
-        className="spacer-top"
-        variant="info"
-      >
-        onboarding.tutorial.with.azure_pipelines.BranchAnalysis.publish_qg.info.sentence1
-      </Alert>
-    </li>
-    <li>
-      <SentenceWithHighlights
-        highlightKeys={
-          Array [
-            "tab",
-            "continuous_integration",
-          ]
-        }
-        translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.continous_integration"
-      />
-    </li>
-    <hr />
-    <FormattedMessage
-      defaultMessage="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.branch_protection"
-      id="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.branch_protection"
-      values={
-        Object {
-          "link": <Link
-            onlyActiveOnIndex={false}
-            style={Object {}}
-            target="_blank"
-            to="/documentation/analysis/azuredevops-integration/"
-          >
-            onboarding.tutorial.with.azure_pipelines.BranchAnalysis.branch_protection.link
-          </Link>,
-        }
-      }
-    />
-  </ol>
+  <AnalysisCommand
+    buildTool="other"
+    onStepValidationChange={[MockFunction]}
+    projectKey="my-project"
+  />
 </Fragment>
 `;
diff --git a/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/AlertClassicEditor.tsx b/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/AlertClassicEditor.tsx
new file mode 100644 (file)
index 0000000..06aca83
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * 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 { FormattedMessage } from 'react-intl';
+import { Link } from 'react-router';
+import { Alert } from 'sonar-ui-common/components/ui/Alert';
+import { translate } from 'sonar-ui-common/helpers/l10n';
+import { ALM_DOCUMENTATION_PATHS } from '../../../../helpers/constants';
+import { AlmKeys } from '../../../../types/alm-settings';
+
+export default function AlertClassicEditor() {
+  return (
+    <Alert variant="info" className="big-spacer-top">
+      <FormattedMessage
+        id="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.info"
+        defaultMessage={translate('onboarding.tutorial.with.azure_pipelines.BranchAnalysis.info')}
+        values={{
+          doc_link: (
+            <Link to={ALM_DOCUMENTATION_PATHS[AlmKeys.Azure]} target="_blank">
+              {translate('onboarding.tutorial.with.azure_pipelines.BranchAnalysis.info.doc_link')}
+            </Link>
+          )
+        }}
+      />
+    </Alert>
+  );
+}
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
new file mode 100644 (file)
index 0000000..d050667
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * 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 { BuildTools } from '../../types';
+import ClangGCC from './ClangGCC';
+import DotNet from './DotNet';
+import JavaGradle from './JavaGradle';
+import JavaMaven from './JavaMaven';
+import Other from './Other';
+
+export interface AnalysisCommandProps {
+  projectKey: string;
+  buildTool?: BuildTools;
+  onStepValidationChange: (isValid: boolean) => void;
+}
+
+export default function AnalysisCommand(props: AnalysisCommandProps) {
+  const { buildTool, projectKey } = props;
+
+  React.useEffect(() => {
+    if (buildTool && buildTool !== BuildTools.CFamily) {
+      props.onStepValidationChange(true);
+    } else {
+      props.onStepValidationChange(false);
+    }
+  }, [buildTool, props.onStepValidationChange]);
+
+  if (!buildTool) {
+    return null;
+  }
+  switch (buildTool) {
+    case BuildTools.Maven:
+      return <JavaMaven projectKey={projectKey} />;
+
+    case BuildTools.Gradle:
+      return <JavaGradle projectKey={projectKey} />;
+
+    case BuildTools.DotNet:
+      return <DotNet projectKey={projectKey} />;
+
+    case BuildTools.CFamily:
+      return (
+        <ClangGCC onStepValidationChange={props.onStepValidationChange} projectKey={projectKey} />
+      );
+
+    case BuildTools.Other:
+      return <Other projectKey={projectKey} />;
+
+    default:
+      return null;
+  }
+}
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
new file mode 100644 (file)
index 0000000..59880e0
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * 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 { getHostUrl } from 'sonar-ui-common/helpers/urls';
+import CodeSnippet from '../../../common/CodeSnippet';
+import RenderOptions from '../../components/RenderOptions';
+import SentenceWithHighlights from '../../components/SentenceWithHighlights';
+import { BuildTools, OSs } from '../../types';
+import AlertClassicEditor from './AlertClassicEditor';
+import PrepareAnalysisCommand, { PrepareType } from './PrepareAnalysisCommand';
+import PublishSteps from './PublishSteps';
+
+export interface ClangGCCProps {
+  projectKey: string;
+  onStepValidationChange: (isValid: boolean) => void;
+}
+
+type OsConstant = {
+  [key in OSs]: {
+    highlightScriptKey: string;
+    script: string;
+    scriptBuild: string;
+  };
+};
+
+export default function ClangGCC(props: ClangGCCProps) {
+  const { projectKey } = props;
+  const [os, setOs] = React.useState<OSs | undefined>();
+  const host = getHostUrl();
+
+  const codeSnippetDownload: OsConstant = {
+    [OSs.Linux]: {
+      script: `curl '${host}/static/cpp/build-wrapper-linux-x86.zip' --output build-wrapper.zip
+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 <output directory> make clean all'
+    },
+    [OSs.Windows]: {
+      script: `Invoke-WebRequest -Uri '${host}/static/cpp/build-wrapper-win-x86.zip' -OutFile 'build-wrapper.zip'
+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 <output directory> MSBuild.exe /t:Rebuild'
+    },
+    [OSs.MacOS]: {
+      script: `curl '${host}/static/cpp/build-wrapper-macosx-x86.zip' --output build-wrapper.zip
+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 <output directory> xcodebuild' +
+        ' -project myproject.xcodeproj -configuration Release clean build'
+    }
+  };
+
+  React.useEffect(() => {
+    if (os) {
+      props.onStepValidationChange(true);
+    }
+  }, [os, props.onStepValidationChange]);
+
+  return (
+    <>
+      <span className="big-spacer-top display-block">
+        {translate('onboarding.tutorial.with.azure_pipelines.os')}
+      </span>
+      <RenderOptions
+        checked={os}
+        name="os"
+        onCheck={value => setOs(value as OSs)}
+        optionLabelKey="onboarding.build.other.os"
+        options={Object.values(OSs)}
+      />
+
+      {os && (
+        <>
+          <AlertClassicEditor />
+          <ol className="list-styled big-spacer-top">
+            <li>
+              <SentenceWithHighlights
+                translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build_wrapper.ccpp"
+                highlightPrefixKeys="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare"
+                highlightKeys={['pipeline']}
+              />
+            </li>
+            <ul className="list-styled">
+              <li>
+                <SentenceWithHighlights
+                  translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build_wrapper.ccpp.script"
+                  highlightPrefixKeys={codeSnippetDownload[os].highlightScriptKey}
+                  highlightKeys={['task']}
+                />
+                <CodeSnippet snippet={codeSnippetDownload[os].script} />
+              </li>
+            </ul>
+            <li>
+              <SentenceWithHighlights
+                translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.ccpp"
+                highlightPrefixKeys="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare"
+                highlightKeys={['task', 'before']}
+              />
+            </li>
+            <PrepareAnalysisCommand
+              buildTool={BuildTools.CFamily}
+              kind={PrepareType.StandAlone}
+              projectKey={projectKey}
+            />
+            <li>
+              <SentenceWithHighlights
+                translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build.ccpp"
+                highlightKeys={['task']}
+              />
+            </li>
+            <ul className="list-styled">
+              <li>
+                <SentenceWithHighlights
+                  translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build_script.ccpp"
+                  highlightKeys={['build_wrapper']}
+                />
+                <CodeSnippet snippet={codeSnippetDownload[os].scriptBuild} />
+              </li>
+            </ul>
+            <li>
+              <SentenceWithHighlights
+                translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.run.ccpp"
+                highlightPrefixKeys="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.run"
+                highlightKeys={['task', 'after']}
+              />
+            </li>
+            <PublishSteps />
+          </ol>
+        </>
+      )}
+    </>
+  );
+}
diff --git a/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/DotNet.tsx b/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/DotNet.tsx
new file mode 100644 (file)
index 0000000..dfc3cab
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * 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 SentenceWithHighlights from '../../components/SentenceWithHighlights';
+import { BuildTools } from '../../types';
+import AlertClassicEditor from './AlertClassicEditor';
+import PrepareAnalysisCommand, { PrepareType } from './PrepareAnalysisCommand';
+import PublishSteps from './PublishSteps';
+
+export interface DotNetProps {
+  projectKey: string;
+}
+
+export default function DotNet(props: DotNetProps): JSX.Element {
+  const { projectKey } = props;
+  return (
+    <>
+      <AlertClassicEditor />
+      <ol className="list-styled big-spacer-top">
+        <li>
+          <SentenceWithHighlights
+            translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare"
+            highlightKeys={['pipeline', 'task', 'before']}
+          />
+        </li>
+        <PrepareAnalysisCommand
+          buildTool={BuildTools.Gradle}
+          kind={PrepareType.MSBuild}
+          projectKey={projectKey}
+        />
+        <li>
+          <SentenceWithHighlights
+            translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.run"
+            highlightKeys={['task', 'after']}
+          />
+        </li>
+
+        <PublishSteps />
+      </ol>
+    </>
+  );
+}
diff --git a/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/JavaGradle.tsx b/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/JavaGradle.tsx
new file mode 100644 (file)
index 0000000..3736f53
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * 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, translateWithParameters } from 'sonar-ui-common/helpers/l10n';
+import SentenceWithHighlights from '../../components/SentenceWithHighlights';
+import { BuildTools } from '../../types';
+import AlertClassicEditor from './AlertClassicEditor';
+import PrepareAnalysisCommand, { PrepareType } from './PrepareAnalysisCommand';
+import PublishSteps from './PublishSteps';
+
+export interface JavaGradleProps {
+  projectKey: string;
+}
+
+export default function JavaGradle(props: JavaGradleProps) {
+  const { projectKey } = props;
+
+  return (
+    <>
+      <AlertClassicEditor />
+      <ol className="list-styled big-spacer-top">
+        <li>
+          <SentenceWithHighlights
+            translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare"
+            highlightKeys={['pipeline', 'task', 'before']}
+          />
+        </li>
+        <PrepareAnalysisCommand
+          buildTool={BuildTools.Gradle}
+          kind={PrepareType.JavaMavenGradle}
+          projectKey={projectKey}
+        />
+        <li>
+          {translateWithParameters(
+            'onboarding.tutorial.with.azure_pipelines.BranchAnalysis.java',
+            translate('onboarding.build', BuildTools.Gradle)
+          )}
+        </li>
+        <ul className="list-styled big-spacer-bottom">
+          <li>
+            <SentenceWithHighlights
+              translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.java.settings"
+              highlightKeys={['section', 'option']}
+            />
+          </li>
+        </ul>
+
+        <PublishSteps />
+      </ol>
+    </>
+  );
+}
diff --git a/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/JavaMaven.tsx b/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/JavaMaven.tsx
new file mode 100644 (file)
index 0000000..c73f380
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * 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, translateWithParameters } from 'sonar-ui-common/helpers/l10n';
+import SentenceWithHighlights from '../../components/SentenceWithHighlights';
+import { BuildTools } from '../../types';
+import AlertClassicEditor from './AlertClassicEditor';
+import PrepareAnalysisCommand, { PrepareType } from './PrepareAnalysisCommand';
+import PublishSteps from './PublishSteps';
+
+export interface JavaMavenProps {
+  projectKey: string;
+}
+
+export default function JavaMaven(props: JavaMavenProps) {
+  const { projectKey } = props;
+  return (
+    <>
+      <AlertClassicEditor />
+      <ol className="list-styled big-spacer-top">
+        <li>
+          <SentenceWithHighlights
+            translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare"
+            highlightKeys={['pipeline', 'task', 'before']}
+          />
+        </li>
+        <PrepareAnalysisCommand
+          buildTool={BuildTools.Gradle}
+          kind={PrepareType.JavaMavenGradle}
+          projectKey={projectKey}
+        />
+
+        <li>
+          {translateWithParameters(
+            'onboarding.tutorial.with.azure_pipelines.BranchAnalysis.java',
+            translate('onboarding.build', BuildTools.Maven)
+          )}
+        </li>
+        <ul className="list-styled big-spacer-bottom">
+          <li>
+            <SentenceWithHighlights
+              translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.java.settings"
+              highlightKeys={['section', 'option']}
+            />
+          </li>
+        </ul>
+
+        <PublishSteps />
+      </ol>
+    </>
+  );
+}
diff --git a/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/Other.tsx b/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/Other.tsx
new file mode 100644 (file)
index 0000000..66ee5b0
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * 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 SentenceWithHighlights from '../../components/SentenceWithHighlights';
+import { BuildTools } from '../../types';
+import AlertClassicEditor from './AlertClassicEditor';
+import PrepareAnalysisCommand, { PrepareType } from './PrepareAnalysisCommand';
+import PublishSteps from './PublishSteps';
+
+export interface OtherProps {
+  projectKey: string;
+}
+
+export default function Other(props: OtherProps) {
+  const { projectKey } = props;
+  return (
+    <>
+      <AlertClassicEditor />
+      <ol className="list-styled big-spacer-top">
+        <li>
+          <SentenceWithHighlights
+            translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare"
+            highlightKeys={['pipeline', 'task', 'before']}
+          />
+        </li>
+        <PrepareAnalysisCommand
+          buildTool={BuildTools.Other}
+          kind={PrepareType.StandAlone}
+          projectKey={projectKey}
+        />
+
+        <li>
+          <SentenceWithHighlights
+            translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.run"
+            highlightKeys={['task', 'after']}
+          />
+        </li>
+
+        <PublishSteps />
+      </ol>
+    </>
+  );
+}
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
new file mode 100644 (file)
index 0000000..60bfbf8
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * 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 { FormattedMessage } from 'react-intl';
+import { ClipboardIconButton } from 'sonar-ui-common/components/controls/clipboard';
+import { translate } from 'sonar-ui-common/helpers/l10n';
+import CodeSnippet from '../../../common/CodeSnippet';
+import SentenceWithHighlights from '../../components/SentenceWithHighlights';
+import { BuildTools } from '../../types';
+
+export enum PrepareType {
+  JavaMavenGradle,
+  StandAlone,
+  MSBuild
+}
+
+export interface PrepareAnalysisCommandProps {
+  buildTool: BuildTools;
+  kind: PrepareType;
+  projectKey: string;
+}
+
+export default function PrepareAnalysisCommand(props: PrepareAnalysisCommandProps) {
+  const { buildTool, kind, projectKey } = props;
+
+  const ADDITIONAL_PROPERTY = 'sonar.cfamily.build-wrapper-output=<output directory>';
+
+  const MAVEN_GRADLE_PROPS_SNIPPET = `# Additional properties that will be passed to the scanner,
+# Put one key=value per line, example:
+# sonar.exclusions=**/*.bin
+sonar.projectKey=${projectKey}`;
+
+  return (
+    <ul className="list-styled">
+      <li>
+        <SentenceWithHighlights
+          translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.endpoint"
+          highlightKeys={['endpoint']}
+        />
+      </li>
+      <li>
+        <FormattedMessage
+          id="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis"
+          defaultMessage={translate(
+            'onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis'
+          )}
+          values={{
+            section: (
+              <strong>
+                {translate(
+                  'onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis.section'
+                )}
+              </strong>
+            ),
+            run_analysis_value: (
+              <strong>
+                {translate(
+                  'onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis.values',
+                  buildTool
+                )}
+              </strong>
+            )
+          }}
+        />
+      </li>
+
+      {kind === PrepareType.StandAlone && (
+        <>
+          <li>
+            <SentenceWithHighlights
+              translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.manual"
+              highlightKeys={['mode']}
+            />
+          </li>
+
+          <li>
+            <FormattedMessage
+              id="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.run.key.sentence"
+              defaultMessage={translate(
+                'onboarding.tutorial.with.azure_pipelines.BranchAnalysis.run.key.sentence'
+              )}
+              values={{
+                project_key: (
+                  <b>
+                    {translate(
+                      'onboarding.tutorial.with.azure_pipelines.BranchAnalysis.run.key.sentence.project_key'
+                    )}
+                  </b>
+                ),
+                key: <code className="rule">{projectKey}</code>,
+                button: <ClipboardIconButton copyValue={projectKey} />
+              }}
+            />
+          </li>
+          {buildTool === BuildTools.CFamily && (
+            <li>
+              <FormattedMessage
+                id="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare_additional.ccpp"
+                defaultMessage={translate(
+                  'onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare_additional.ccpp'
+                )}
+                values={{
+                  advanced: (
+                    <b>
+                      {translate(
+                        'onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare_additional.ccpp.advanced'
+                      )}
+                    </b>
+                  ),
+                  additional: (
+                    <b>
+                      {translate(
+                        'onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare_additional.ccpp.additional'
+                      )}
+                    </b>
+                  ),
+                  property: <code className="rule">{ADDITIONAL_PROPERTY}</code>,
+                  button: <ClipboardIconButton copyValue={ADDITIONAL_PROPERTY} />
+                }}
+              />
+            </li>
+          )}
+        </>
+      )}
+
+      {kind === PrepareType.JavaMavenGradle && (
+        <li>
+          <SentenceWithHighlights
+            translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.advanced_properties"
+            highlightKeys={['section', 'properties']}
+          />
+          :
+          <CodeSnippet snippet={MAVEN_GRADLE_PROPS_SNIPPET} />
+        </li>
+      )}
+      {kind === PrepareType.MSBuild && (
+        <li>
+          <FormattedMessage
+            id="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.run.key.sentence"
+            defaultMessage={translate(
+              'onboarding.tutorial.with.azure_pipelines.BranchAnalysis.run.key.sentence'
+            )}
+            values={{
+              project_key: (
+                <b>
+                  {translate(
+                    'onboarding.tutorial.with.azure_pipelines.BranchAnalysis.run.key.sentence.project_key'
+                  )}
+                </b>
+              ),
+              key: <code className="rule">{projectKey}</code>,
+              button: <ClipboardIconButton copyValue={projectKey} />
+            }}
+          />
+        </li>
+      )}
+    </ul>
+  );
+}
diff --git a/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/PublishSteps.tsx b/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/PublishSteps.tsx
new file mode 100644 (file)
index 0000000..580301e
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * 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 { FormattedMessage } from 'react-intl';
+import { Link } from 'react-router';
+import { Alert } from 'sonar-ui-common/components/ui/Alert';
+import { translate } from 'sonar-ui-common/helpers/l10n';
+import { ALM_DOCUMENTATION_PATHS } from '../../../../helpers/constants';
+import { AlmKeys } from '../../../../types/alm-settings';
+import { withAppState } from '../../../hoc/withAppState';
+import SentenceWithHighlights from '../../components/SentenceWithHighlights';
+
+export interface PublishStepsProps {
+  appState: T.AppState;
+}
+export function PublishSteps(props: PublishStepsProps) {
+  const {
+    appState: { branchesEnabled }
+  } = props;
+
+  return (
+    <>
+      <li>
+        <SentenceWithHighlights
+          translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.publish_qg"
+          highlightKeys={['task']}
+        />
+        <Alert variant="info" className="spacer-top">
+          {translate(
+            'onboarding.tutorial.with.azure_pipelines.BranchAnalysis.publish_qg.info.sentence1'
+          )}
+        </Alert>
+      </li>
+      <li>
+        <SentenceWithHighlights
+          translationKey={
+            branchesEnabled
+              ? 'onboarding.tutorial.with.azure_pipelines.BranchAnalysis.continous_integration'
+              : 'onboarding.tutorial.with.azure_pipelines.BranchAnalysis.continous_integration.no_branches'
+          }
+          highlightKeys={['tab', 'continuous_integration']}
+        />
+      </li>
+      {branchesEnabled && (
+        <>
+          <hr />
+          <FormattedMessage
+            id="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.branch_protection"
+            defaultMessage={translate(
+              'onboarding.tutorial.with.azure_pipelines.BranchAnalysis.branch_protection'
+            )}
+            values={{
+              link: (
+                <Link to={ALM_DOCUMENTATION_PATHS[AlmKeys.Azure]} target="_blank">
+                  {translate(
+                    'onboarding.tutorial.with.azure_pipelines.BranchAnalysis.branch_protection.link'
+                  )}
+                </Link>
+              )
+            }}
+          />
+        </>
+      )}
+    </>
+  );
+}
+
+export default withAppState(PublishSteps);
diff --git a/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/AlertClassicEditor-test.tsx b/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/AlertClassicEditor-test.tsx
new file mode 100644 (file)
index 0000000..0bfb335
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * 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 AlertClassicEditor from '../AlertClassicEditor';
+
+it('should render correctly', () => {
+  expect(shallowRender()).toMatchSnapshot();
+});
+
+function shallowRender() {
+  return shallow(<AlertClassicEditor />);
+}
diff --git a/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/AnalysisCommand-test.tsx b/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/AnalysisCommand-test.tsx
new file mode 100644 (file)
index 0000000..001f901
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * 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 { BuildTools } from '../../../types';
+import AnalysisCommand, { AnalysisCommandProps } from '../AnalysisCommand';
+
+it.each([
+  undefined,
+  BuildTools.CFamily,
+  BuildTools.DotNet,
+  BuildTools.Gradle,
+  BuildTools.Maven,
+  BuildTools.Other
+])('should render correctly for %p', buildTool => {
+  expect(shallowRender({ buildTool })).toMatchSnapshot();
+});
+
+function shallowRender(props: Partial<AnalysisCommandProps> = {}) {
+  return shallow<AnalysisCommandProps>(
+    <AnalysisCommand onStepValidationChange={jest.fn()} projectKey="projectKey" {...props} />
+  );
+}
diff --git a/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/ClangGCC-test.tsx b/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/ClangGCC-test.tsx
new file mode 100644 (file)
index 0000000..81406de
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * 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 RenderOptions from '../../../components/RenderOptions';
+import { OSs } from '../../../types';
+import ClangGCC, { ClangGCCProps } from '../ClangGCC';
+
+it.each([OSs.Linux, OSs.Windows, OSs.MacOS])('should render correctly for %p', buildTool => {
+  const wrapper = shallowRender();
+
+  wrapper.find(RenderOptions).simulate('check', buildTool);
+  expect(wrapper).toMatchSnapshot();
+});
+
+function shallowRender(props: Partial<ClangGCCProps> = {}) {
+  return shallow<ClangGCCProps>(
+    <ClangGCC onStepValidationChange={jest.fn()} projectKey="projectKey" {...props} />
+  );
+}
diff --git a/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/DotNet-test.tsx b/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/DotNet-test.tsx
new file mode 100644 (file)
index 0000000..ab7f78e
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * 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 DotNet, { DotNetProps } from '../DotNet';
+
+it('should render correctly', () => {
+  expect(shallowRender()).toMatchSnapshot();
+});
+
+function shallowRender(props: Partial<DotNetProps> = {}) {
+  return shallow<DotNetProps>(<DotNet projectKey="projectKey" {...props} />);
+}
diff --git a/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/JavaGradle-test.tsx b/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/JavaGradle-test.tsx
new file mode 100644 (file)
index 0000000..3c1224b
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * 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 JavaGradle, { JavaGradleProps } from '../JavaGradle';
+
+it('should render correctly', () => {
+  expect(shallowRender()).toMatchSnapshot();
+});
+
+function shallowRender(props: Partial<JavaGradleProps> = {}) {
+  return shallow<JavaGradleProps>(<JavaGradle projectKey="projectKey" {...props} />);
+}
diff --git a/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/JavaMaven-test.tsx b/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/JavaMaven-test.tsx
new file mode 100644 (file)
index 0000000..ab4c57f
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * 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 JavaMaven, { JavaMavenProps } from '../JavaMaven';
+
+it('should render correctly', () => {
+  expect(shallowRender()).toMatchSnapshot();
+});
+
+function shallowRender(props: Partial<JavaMavenProps> = {}) {
+  return shallow<JavaMavenProps>(<JavaMaven projectKey="projectKey" {...props} />);
+}
diff --git a/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/Other-test.tsx b/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/Other-test.tsx
new file mode 100644 (file)
index 0000000..ae5a5c4
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * 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 Other, { OtherProps } from '../Other';
+
+it('should render correctly', () => {
+  expect(shallowRender()).toMatchSnapshot();
+});
+
+function shallowRender(props: Partial<OtherProps> = {}) {
+  return shallow<OtherProps>(<Other projectKey="projectKey" {...props} />);
+}
diff --git a/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/PrepareAnalysisCommand-test.tsx b/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/PrepareAnalysisCommand-test.tsx
new file mode 100644 (file)
index 0000000..fe05916
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * 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 { BuildTools } from '../../../types';
+import PrepareAnalysisCommand, {
+  PrepareAnalysisCommandProps,
+  PrepareType
+} from '../PrepareAnalysisCommand';
+
+it.each([
+  [PrepareType.JavaMavenGradle, BuildTools.Gradle],
+  [PrepareType.JavaMavenGradle, BuildTools.Maven],
+  [PrepareType.StandAlone, BuildTools.Other],
+  [PrepareType.StandAlone, BuildTools.CFamily],
+  [PrepareType.MSBuild, BuildTools.DotNet]
+])('should render correctly', (kind, buildTool) => {
+  expect(shallowRender({ kind, buildTool })).toMatchSnapshot();
+});
+
+function shallowRender(props: Partial<PrepareAnalysisCommandProps> = {}) {
+  return shallow<PrepareAnalysisCommandProps>(
+    <PrepareAnalysisCommand
+      kind={PrepareType.JavaMavenGradle}
+      buildTool={BuildTools.CFamily}
+      projectKey="projectKey"
+      {...props}
+    />
+  );
+}
diff --git a/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/PublishSteps-test.tsx b/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/PublishSteps-test.tsx
new file mode 100644 (file)
index 0000000..3e8f30c
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * 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 { mockAppState } from '../../../../../helpers/testMocks';
+import { PublishSteps, PublishStepsProps } from '../PublishSteps';
+
+it('should render correctly', () => {
+  expect(shallowRender()).toMatchSnapshot();
+  expect(shallowRender({ appState: mockAppState({ branchesEnabled: true }) })).toMatchSnapshot();
+});
+
+function shallowRender(props: Partial<PublishStepsProps> = {}) {
+  return shallow<PublishStepsProps>(<PublishSteps appState={mockAppState()} {...props} />);
+}
diff --git a/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/__snapshots__/AlertClassicEditor-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/__snapshots__/AlertClassicEditor-test.tsx.snap
new file mode 100644 (file)
index 0000000..287d3d1
--- /dev/null
@@ -0,0 +1,25 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly 1`] = `
+<Alert
+  className="big-spacer-top"
+  variant="info"
+>
+  <FormattedMessage
+    defaultMessage="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.info"
+    id="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.info"
+    values={
+      Object {
+        "doc_link": <Link
+          onlyActiveOnIndex={false}
+          style={Object {}}
+          target="_blank"
+          to="/documentation/analysis/azuredevops-integration/"
+        >
+          onboarding.tutorial.with.azure_pipelines.BranchAnalysis.info.doc_link
+        </Link>,
+      }
+    }
+  />
+</Alert>
+`;
diff --git a/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/__snapshots__/AnalysisCommand-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/__snapshots__/AnalysisCommand-test.tsx.snap
new file mode 100644 (file)
index 0000000..af15f04
--- /dev/null
@@ -0,0 +1,34 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly for "cfamily" 1`] = `
+<ClangGCC
+  onStepValidationChange={[MockFunction]}
+  projectKey="projectKey"
+/>
+`;
+
+exports[`should render correctly for "dotnet" 1`] = `
+<DotNet
+  projectKey="projectKey"
+/>
+`;
+
+exports[`should render correctly for "gradle" 1`] = `
+<JavaGradle
+  projectKey="projectKey"
+/>
+`;
+
+exports[`should render correctly for "maven" 1`] = `
+<JavaMaven
+  projectKey="projectKey"
+/>
+`;
+
+exports[`should render correctly for "other" 1`] = `
+<Other
+  projectKey="projectKey"
+/>
+`;
+
+exports[`should render correctly for undefined 1`] = `""`;
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
new file mode 100644 (file)
index 0000000..e2cfc17
--- /dev/null
@@ -0,0 +1,346 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly for "linux" 1`] = `
+<Fragment>
+  <span
+    className="big-spacer-top display-block"
+  >
+    onboarding.tutorial.with.azure_pipelines.os
+  </span>
+  <RenderOptions
+    checked="linux"
+    name="os"
+    onCheck={[Function]}
+    optionLabelKey="onboarding.build.other.os"
+    options={
+      Array [
+        "linux",
+        "win",
+        "mac",
+      ]
+    }
+  />
+  <AlertClassicEditor />
+  <ol
+    className="list-styled big-spacer-top"
+  >
+    <li>
+      <SentenceWithHighlights
+        highlightKeys={
+          Array [
+            "pipeline",
+          ]
+        }
+        highlightPrefixKeys="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare"
+        translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build_wrapper.ccpp"
+      />
+    </li>
+    <ul
+      className="list-styled"
+    >
+      <li>
+        <SentenceWithHighlights
+          highlightKeys={
+            Array [
+              "task",
+            ]
+          }
+          highlightPrefixKeys="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build_wrapper.ccpp.nix"
+          translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build_wrapper.ccpp.script"
+        />
+        <CodeSnippet
+          snippet="curl 'http://localhost/static/cpp/build-wrapper-linux-x86.zip' --output build-wrapper.zip
+unzip build-wrapper.zip"
+        />
+      </li>
+    </ul>
+    <li>
+      <SentenceWithHighlights
+        highlightKeys={
+          Array [
+            "task",
+            "before",
+          ]
+        }
+        highlightPrefixKeys="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare"
+        translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.ccpp"
+      />
+    </li>
+    <PrepareAnalysisCommand
+      buildTool="cfamily"
+      kind={1}
+      projectKey="projectKey"
+    />
+    <li>
+      <SentenceWithHighlights
+        highlightKeys={
+          Array [
+            "task",
+          ]
+        }
+        translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build.ccpp"
+      />
+    </li>
+    <ul
+      className="list-styled"
+    >
+      <li>
+        <SentenceWithHighlights
+          highlightKeys={
+            Array [
+              "build_wrapper",
+            ]
+          }
+          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"
+        />
+      </li>
+    </ul>
+    <li>
+      <SentenceWithHighlights
+        highlightKeys={
+          Array [
+            "task",
+            "after",
+          ]
+        }
+        highlightPrefixKeys="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.run"
+        translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.run.ccpp"
+      />
+    </li>
+    <Connect(withAppState(PublishSteps)) />
+  </ol>
+</Fragment>
+`;
+
+exports[`should render correctly for "mac" 1`] = `
+<Fragment>
+  <span
+    className="big-spacer-top display-block"
+  >
+    onboarding.tutorial.with.azure_pipelines.os
+  </span>
+  <RenderOptions
+    checked="mac"
+    name="os"
+    onCheck={[Function]}
+    optionLabelKey="onboarding.build.other.os"
+    options={
+      Array [
+        "linux",
+        "win",
+        "mac",
+      ]
+    }
+  />
+  <AlertClassicEditor />
+  <ol
+    className="list-styled big-spacer-top"
+  >
+    <li>
+      <SentenceWithHighlights
+        highlightKeys={
+          Array [
+            "pipeline",
+          ]
+        }
+        highlightPrefixKeys="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare"
+        translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build_wrapper.ccpp"
+      />
+    </li>
+    <ul
+      className="list-styled"
+    >
+      <li>
+        <SentenceWithHighlights
+          highlightKeys={
+            Array [
+              "task",
+            ]
+          }
+          highlightPrefixKeys="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build_wrapper.ccpp.nix"
+          translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build_wrapper.ccpp.script"
+        />
+        <CodeSnippet
+          snippet="curl 'http://localhost/static/cpp/build-wrapper-macosx-x86.zip' --output build-wrapper.zip
+unzip build-wrapper.zip"
+        />
+      </li>
+    </ul>
+    <li>
+      <SentenceWithHighlights
+        highlightKeys={
+          Array [
+            "task",
+            "before",
+          ]
+        }
+        highlightPrefixKeys="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare"
+        translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.ccpp"
+      />
+    </li>
+    <PrepareAnalysisCommand
+      buildTool="cfamily"
+      kind={1}
+      projectKey="projectKey"
+    />
+    <li>
+      <SentenceWithHighlights
+        highlightKeys={
+          Array [
+            "task",
+          ]
+        }
+        translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build.ccpp"
+      />
+    </li>
+    <ul
+      className="list-styled"
+    >
+      <li>
+        <SentenceWithHighlights
+          highlightKeys={
+            Array [
+              "build_wrapper",
+            ]
+          }
+          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"
+        />
+      </li>
+    </ul>
+    <li>
+      <SentenceWithHighlights
+        highlightKeys={
+          Array [
+            "task",
+            "after",
+          ]
+        }
+        highlightPrefixKeys="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.run"
+        translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.run.ccpp"
+      />
+    </li>
+    <Connect(withAppState(PublishSteps)) />
+  </ol>
+</Fragment>
+`;
+
+exports[`should render correctly for "win" 1`] = `
+<Fragment>
+  <span
+    className="big-spacer-top display-block"
+  >
+    onboarding.tutorial.with.azure_pipelines.os
+  </span>
+  <RenderOptions
+    checked="win"
+    name="os"
+    onCheck={[Function]}
+    optionLabelKey="onboarding.build.other.os"
+    options={
+      Array [
+        "linux",
+        "win",
+        "mac",
+      ]
+    }
+  />
+  <AlertClassicEditor />
+  <ol
+    className="list-styled big-spacer-top"
+  >
+    <li>
+      <SentenceWithHighlights
+        highlightKeys={
+          Array [
+            "pipeline",
+          ]
+        }
+        highlightPrefixKeys="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare"
+        translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build_wrapper.ccpp"
+      />
+    </li>
+    <ul
+      className="list-styled"
+    >
+      <li>
+        <SentenceWithHighlights
+          highlightKeys={
+            Array [
+              "task",
+            ]
+          }
+          highlightPrefixKeys="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build_wrapper.ccpp.win"
+          translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build_wrapper.ccpp.script"
+        />
+        <CodeSnippet
+          snippet="Invoke-WebRequest -Uri 'http://localhost/static/cpp/build-wrapper-win-x86.zip' -OutFile 'build-wrapper.zip'
+Expand-Archive -Path 'build-wrapper.zip' -DestinationPath '.'"
+        />
+      </li>
+    </ul>
+    <li>
+      <SentenceWithHighlights
+        highlightKeys={
+          Array [
+            "task",
+            "before",
+          ]
+        }
+        highlightPrefixKeys="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare"
+        translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.ccpp"
+      />
+    </li>
+    <PrepareAnalysisCommand
+      buildTool="cfamily"
+      kind={1}
+      projectKey="projectKey"
+    />
+    <li>
+      <SentenceWithHighlights
+        highlightKeys={
+          Array [
+            "task",
+          ]
+        }
+        translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.build.ccpp"
+      />
+    </li>
+    <ul
+      className="list-styled"
+    >
+      <li>
+        <SentenceWithHighlights
+          highlightKeys={
+            Array [
+              "build_wrapper",
+            ]
+          }
+          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"
+        />
+      </li>
+    </ul>
+    <li>
+      <SentenceWithHighlights
+        highlightKeys={
+          Array [
+            "task",
+            "after",
+          ]
+        }
+        highlightPrefixKeys="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.run"
+        translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.run.ccpp"
+      />
+    </li>
+    <Connect(withAppState(PublishSteps)) />
+  </ol>
+</Fragment>
+`;
diff --git a/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/__snapshots__/DotNet-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/__snapshots__/DotNet-test.tsx.snap
new file mode 100644 (file)
index 0000000..1434c1e
--- /dev/null
@@ -0,0 +1,40 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly 1`] = `
+<Fragment>
+  <AlertClassicEditor />
+  <ol
+    className="list-styled big-spacer-top"
+  >
+    <li>
+      <SentenceWithHighlights
+        highlightKeys={
+          Array [
+            "pipeline",
+            "task",
+            "before",
+          ]
+        }
+        translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare"
+      />
+    </li>
+    <PrepareAnalysisCommand
+      buildTool="gradle"
+      kind={2}
+      projectKey="projectKey"
+    />
+    <li>
+      <SentenceWithHighlights
+        highlightKeys={
+          Array [
+            "task",
+            "after",
+          ]
+        }
+        translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.run"
+      />
+    </li>
+    <Connect(withAppState(PublishSteps)) />
+  </ol>
+</Fragment>
+`;
diff --git a/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/__snapshots__/JavaGradle-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/__snapshots__/JavaGradle-test.tsx.snap
new file mode 100644 (file)
index 0000000..66f4880
--- /dev/null
@@ -0,0 +1,47 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly 1`] = `
+<Fragment>
+  <AlertClassicEditor />
+  <ol
+    className="list-styled big-spacer-top"
+  >
+    <li>
+      <SentenceWithHighlights
+        highlightKeys={
+          Array [
+            "pipeline",
+            "task",
+            "before",
+          ]
+        }
+        translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare"
+      />
+    </li>
+    <PrepareAnalysisCommand
+      buildTool="gradle"
+      kind={0}
+      projectKey="projectKey"
+    />
+    <li>
+      onboarding.tutorial.with.azure_pipelines.BranchAnalysis.java.onboarding.build.gradle
+    </li>
+    <ul
+      className="list-styled big-spacer-bottom"
+    >
+      <li>
+        <SentenceWithHighlights
+          highlightKeys={
+            Array [
+              "section",
+              "option",
+            ]
+          }
+          translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.java.settings"
+        />
+      </li>
+    </ul>
+    <Connect(withAppState(PublishSteps)) />
+  </ol>
+</Fragment>
+`;
diff --git a/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/__snapshots__/JavaMaven-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/__snapshots__/JavaMaven-test.tsx.snap
new file mode 100644 (file)
index 0000000..5c22db0
--- /dev/null
@@ -0,0 +1,47 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly 1`] = `
+<Fragment>
+  <AlertClassicEditor />
+  <ol
+    className="list-styled big-spacer-top"
+  >
+    <li>
+      <SentenceWithHighlights
+        highlightKeys={
+          Array [
+            "pipeline",
+            "task",
+            "before",
+          ]
+        }
+        translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare"
+      />
+    </li>
+    <PrepareAnalysisCommand
+      buildTool="gradle"
+      kind={0}
+      projectKey="projectKey"
+    />
+    <li>
+      onboarding.tutorial.with.azure_pipelines.BranchAnalysis.java.onboarding.build.maven
+    </li>
+    <ul
+      className="list-styled big-spacer-bottom"
+    >
+      <li>
+        <SentenceWithHighlights
+          highlightKeys={
+            Array [
+              "section",
+              "option",
+            ]
+          }
+          translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.java.settings"
+        />
+      </li>
+    </ul>
+    <Connect(withAppState(PublishSteps)) />
+  </ol>
+</Fragment>
+`;
diff --git a/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/__snapshots__/Other-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/__snapshots__/Other-test.tsx.snap
new file mode 100644 (file)
index 0000000..44c9b28
--- /dev/null
@@ -0,0 +1,40 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly 1`] = `
+<Fragment>
+  <AlertClassicEditor />
+  <ol
+    className="list-styled big-spacer-top"
+  >
+    <li>
+      <SentenceWithHighlights
+        highlightKeys={
+          Array [
+            "pipeline",
+            "task",
+            "before",
+          ]
+        }
+        translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare"
+      />
+    </li>
+    <PrepareAnalysisCommand
+      buildTool="other"
+      kind={1}
+      projectKey="projectKey"
+    />
+    <li>
+      <SentenceWithHighlights
+        highlightKeys={
+          Array [
+            "task",
+            "after",
+          ]
+        }
+        translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.run"
+      />
+    </li>
+    <Connect(withAppState(PublishSteps)) />
+  </ol>
+</Fragment>
+`;
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
new file mode 100644 (file)
index 0000000..8085026
--- /dev/null
@@ -0,0 +1,309 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly 1`] = `
+<ul
+  className="list-styled"
+>
+  <li>
+    <SentenceWithHighlights
+      highlightKeys={
+        Array [
+          "endpoint",
+        ]
+      }
+      translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.endpoint"
+    />
+  </li>
+  <li>
+    <FormattedMessage
+      defaultMessage="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis"
+      id="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis"
+      values={
+        Object {
+          "run_analysis_value": <strong>
+            onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis.values.gradle
+          </strong>,
+          "section": <strong>
+            onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis.section
+          </strong>,
+        }
+      }
+    />
+  </li>
+  <li>
+    <SentenceWithHighlights
+      highlightKeys={
+        Array [
+          "section",
+          "properties",
+        ]
+      }
+      translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.advanced_properties"
+    />
+    :
+    <CodeSnippet
+      snippet="# Additional properties that will be passed to the scanner,
+# Put one key=value per line, example:
+# sonar.exclusions=**/*.bin
+sonar.projectKey=projectKey"
+    />
+  </li>
+</ul>
+`;
+
+exports[`should render correctly 2`] = `
+<ul
+  className="list-styled"
+>
+  <li>
+    <SentenceWithHighlights
+      highlightKeys={
+        Array [
+          "endpoint",
+        ]
+      }
+      translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.endpoint"
+    />
+  </li>
+  <li>
+    <FormattedMessage
+      defaultMessage="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis"
+      id="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis"
+      values={
+        Object {
+          "run_analysis_value": <strong>
+            onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis.values.maven
+          </strong>,
+          "section": <strong>
+            onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis.section
+          </strong>,
+        }
+      }
+    />
+  </li>
+  <li>
+    <SentenceWithHighlights
+      highlightKeys={
+        Array [
+          "section",
+          "properties",
+        ]
+      }
+      translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.advanced_properties"
+    />
+    :
+    <CodeSnippet
+      snippet="# Additional properties that will be passed to the scanner,
+# Put one key=value per line, example:
+# sonar.exclusions=**/*.bin
+sonar.projectKey=projectKey"
+    />
+  </li>
+</ul>
+`;
+
+exports[`should render correctly 3`] = `
+<ul
+  className="list-styled"
+>
+  <li>
+    <SentenceWithHighlights
+      highlightKeys={
+        Array [
+          "endpoint",
+        ]
+      }
+      translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.endpoint"
+    />
+  </li>
+  <li>
+    <FormattedMessage
+      defaultMessage="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis"
+      id="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis"
+      values={
+        Object {
+          "run_analysis_value": <strong>
+            onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis.values.other
+          </strong>,
+          "section": <strong>
+            onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis.section
+          </strong>,
+        }
+      }
+    />
+  </li>
+  <li>
+    <SentenceWithHighlights
+      highlightKeys={
+        Array [
+          "mode",
+        ]
+      }
+      translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.manual"
+    />
+  </li>
+  <li>
+    <FormattedMessage
+      defaultMessage="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.run.key.sentence"
+      id="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.run.key.sentence"
+      values={
+        Object {
+          "button": <ClipboardIconButton
+            copyValue="projectKey"
+          />,
+          "key": <code
+            className="rule"
+          >
+            projectKey
+          </code>,
+          "project_key": <b>
+            onboarding.tutorial.with.azure_pipelines.BranchAnalysis.run.key.sentence.project_key
+          </b>,
+        }
+      }
+    />
+  </li>
+</ul>
+`;
+
+exports[`should render correctly 4`] = `
+<ul
+  className="list-styled"
+>
+  <li>
+    <SentenceWithHighlights
+      highlightKeys={
+        Array [
+          "endpoint",
+        ]
+      }
+      translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.endpoint"
+    />
+  </li>
+  <li>
+    <FormattedMessage
+      defaultMessage="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis"
+      id="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis"
+      values={
+        Object {
+          "run_analysis_value": <strong>
+            onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis.values.cfamily
+          </strong>,
+          "section": <strong>
+            onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis.section
+          </strong>,
+        }
+      }
+    />
+  </li>
+  <li>
+    <SentenceWithHighlights
+      highlightKeys={
+        Array [
+          "mode",
+        ]
+      }
+      translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.manual"
+    />
+  </li>
+  <li>
+    <FormattedMessage
+      defaultMessage="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.run.key.sentence"
+      id="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.run.key.sentence"
+      values={
+        Object {
+          "button": <ClipboardIconButton
+            copyValue="projectKey"
+          />,
+          "key": <code
+            className="rule"
+          >
+            projectKey
+          </code>,
+          "project_key": <b>
+            onboarding.tutorial.with.azure_pipelines.BranchAnalysis.run.key.sentence.project_key
+          </b>,
+        }
+      }
+    />
+  </li>
+  <li>
+    <FormattedMessage
+      defaultMessage="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare_additional.ccpp"
+      id="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare_additional.ccpp"
+      values={
+        Object {
+          "additional": <b>
+            onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare_additional.ccpp.additional
+          </b>,
+          "advanced": <b>
+            onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare_additional.ccpp.advanced
+          </b>,
+          "button": <ClipboardIconButton
+            copyValue="sonar.cfamily.build-wrapper-output=<output directory>"
+          />,
+          "property": <code
+            className="rule"
+          >
+            sonar.cfamily.build-wrapper-output=&lt;output directory&gt;
+          </code>,
+        }
+      }
+    />
+  </li>
+</ul>
+`;
+
+exports[`should render correctly 5`] = `
+<ul
+  className="list-styled"
+>
+  <li>
+    <SentenceWithHighlights
+      highlightKeys={
+        Array [
+          "endpoint",
+        ]
+      }
+      translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.endpoint"
+    />
+  </li>
+  <li>
+    <FormattedMessage
+      defaultMessage="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis"
+      id="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis"
+      values={
+        Object {
+          "run_analysis_value": <strong>
+            onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis.values.dotnet
+          </strong>,
+          "section": <strong>
+            onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis.section
+          </strong>,
+        }
+      }
+    />
+  </li>
+  <li>
+    <FormattedMessage
+      defaultMessage="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.run.key.sentence"
+      id="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.run.key.sentence"
+      values={
+        Object {
+          "button": <ClipboardIconButton
+            copyValue="projectKey"
+          />,
+          "key": <code
+            className="rule"
+          >
+            projectKey
+          </code>,
+          "project_key": <b>
+            onboarding.tutorial.with.azure_pipelines.BranchAnalysis.run.key.sentence.project_key
+          </b>,
+        }
+      }
+    />
+  </li>
+</ul>
+`;
diff --git a/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/__snapshots__/PublishSteps-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/__snapshots__/PublishSteps-test.tsx.snap
new file mode 100644 (file)
index 0000000..346a354
--- /dev/null
@@ -0,0 +1,82 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly 1`] = `
+<Fragment>
+  <li>
+    <SentenceWithHighlights
+      highlightKeys={
+        Array [
+          "task",
+        ]
+      }
+      translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.publish_qg"
+    />
+    <Alert
+      className="spacer-top"
+      variant="info"
+    >
+      onboarding.tutorial.with.azure_pipelines.BranchAnalysis.publish_qg.info.sentence1
+    </Alert>
+  </li>
+  <li>
+    <SentenceWithHighlights
+      highlightKeys={
+        Array [
+          "tab",
+          "continuous_integration",
+        ]
+      }
+      translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.continous_integration.no_branches"
+    />
+  </li>
+</Fragment>
+`;
+
+exports[`should render correctly 2`] = `
+<Fragment>
+  <li>
+    <SentenceWithHighlights
+      highlightKeys={
+        Array [
+          "task",
+        ]
+      }
+      translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.publish_qg"
+    />
+    <Alert
+      className="spacer-top"
+      variant="info"
+    >
+      onboarding.tutorial.with.azure_pipelines.BranchAnalysis.publish_qg.info.sentence1
+    </Alert>
+  </li>
+  <li>
+    <SentenceWithHighlights
+      highlightKeys={
+        Array [
+          "tab",
+          "continuous_integration",
+        ]
+      }
+      translationKey="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.continous_integration"
+    />
+  </li>
+  <hr />
+  <FormattedMessage
+    defaultMessage="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.branch_protection"
+    id="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.branch_protection"
+    values={
+      Object {
+        "link": <Link
+          onlyActiveOnIndex={false}
+          style={Object {}}
+          target="_blank"
+          to="/documentation/analysis/azuredevops-integration/"
+        >
+          onboarding.tutorial.with.azure_pipelines.BranchAnalysis.branch_protection.link
+        </Link>,
+      }
+    }
+  />
+</Fragment>
+`;
index b25ab41ab3075af38b4e5eb238c151f413329f15..0a4d57d3bc7e005c4b9743069f592464019c6399 100644 (file)
@@ -24,15 +24,19 @@ import { translate } from 'sonar-ui-common/helpers/l10n';
 export interface SentenceWithHighlightsProps {
   highlightKeys: string[];
   translationKey: string;
+  highlightPrefixKeys?: string;
 }
 
 export default function SentenceWithHighlights({
   highlightKeys,
-  translationKey
+  translationKey,
+  highlightPrefixKeys
 }: SentenceWithHighlightsProps) {
   const values: T.Dict<JSX.Element> = {};
+
+  const transhighlightPrefixKeys = highlightPrefixKeys || translationKey;
   highlightKeys.forEach(key => {
-    values[key] = <strong>{translate(translationKey, 'sentence', key)}</strong>;
+    values[key] = <strong>{translate(transhighlightPrefixKeys, 'sentence', key)}</strong>;
   });
   return (
     <FormattedMessage
index 3d32cbaa79e33e34c9fc2b04c80946381cc68b27..b4687447326f6975adc6b0392c550b2c3998f4db 100644 (file)
@@ -37,6 +37,12 @@ it('renders correctly', () => {
   expect(shallowRender({ languageConfig: { buildTool: BuildTools.DotNet } })).toMatchSnapshot(
     '.NET'
   );
+  expect(
+    shallowRender({ languageConfig: { buildTool: BuildTools.CFamily, os: OSs.Linux } })
+  ).toMatchSnapshot('CFamily');
+  expect(shallowRender({ languageConfig: { buildTool: BuildTools.CFamily } })).toMatchSnapshot(
+    'Empty CFamily'
+  );
   expect(
     shallowRender({ languageConfig: { buildTool: BuildTools.Other, os: OSs.Windows } })
   ).toMatchSnapshot('other');
index bb48fe6b8850794e7c0da615c3a279ffae943cc2..2df0e23b2b8b7fcbfc9e98bf99a7ee44990ab9b8 100644 (file)
@@ -8,6 +8,17 @@ exports[`renders correctly: .NET 1`] = `
 />
 `;
 
+exports[`renders correctly: CFamily 1`] = `
+<ClangGCCCustom
+  host="HOST"
+  os="linux"
+  projectKey="my-project"
+  token="myToken"
+/>
+`;
+
+exports[`renders correctly: Empty CFamily 1`] = `""`;
+
 exports[`renders correctly: gradle 1`] = `
 <JavaGradle
   host="HOST"
index 93ca2e332071b072a8115d206ab60807966542bd..7f8e0e19de395c0eaf4b0d88610943052643572d 100644 (file)
@@ -3539,6 +3539,7 @@ onboarding.tutorial.with.jenkins.commit.why.no_branches=Each new push you make o
 onboarding.tutorial.with.jenkins.refresh=This page will then refresh with your analysis results.
 onboarding.tutorial.with.jenkins.refresh.why=If the page doesn't refresh after a while, please double-check the analysis configuration.
 
+onboarding.tutorial.with.azure_pipelines.os=What is your agent host?
 onboarding.tutorial.with.azure_pipelines.title=Analyze your project with Azure DevOps Pipelines
 onboarding.tutorial.with.azure_pipelines.unsupported=This tutorial is only available for projects bound to Azure DevOps.
 onboarding.tutorial.with.azure_pipelines.ExtensionInstallation.title=Install SonarQube extension for Azure DevOps
@@ -3557,6 +3558,20 @@ onboarding.tutorial.with.azure_pipelines.ServiceEndpoint.step6.sentence=Create t
 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.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.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_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.task=Prepare Analysis Configuration
@@ -3568,13 +3583,15 @@ onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis.sec
 onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis.values.dotnet=Integrate with MSBuild
 onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis.values.maven=Integrate with Maven or Gradle
 onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis.values.gradle=Integrate with Maven or Gradle
+onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis.values.cfamily=Use standalone scanner
 onboarding.tutorial.with.azure_pipelines.BranchAnalysis.prepare.run_analysis.values.other=Use standalone scanner
 onboarding.tutorial.with.azure_pipelines.BranchAnalysis.manual.sentence=Select the {mode} mode
 onboarding.tutorial.with.azure_pipelines.BranchAnalysis.manual.sentence.mode=Manually provide configuration
 onboarding.tutorial.with.azure_pipelines.BranchAnalysis.run.sentence=Add a new {task} task {after} your build task
 onboarding.tutorial.with.azure_pipelines.BranchAnalysis.run.sentence.task=Run Code Analysis
 onboarding.tutorial.with.azure_pipelines.BranchAnalysis.run.sentence.after=after
-onboarding.tutorial.with.azure_pipelines.BranchAnalysis.run.key.sentence=In the project key field, enter {key} {button}
+onboarding.tutorial.with.azure_pipelines.BranchAnalysis.run.key.sentence=In the {project_key} field, enter {key} {button}
+onboarding.tutorial.with.azure_pipelines.BranchAnalysis.run.key.sentence.project_key=Project Key
 onboarding.tutorial.with.azure_pipelines.BranchAnalysis.advanced_properties.sentence=Expand the {section} and replace the {properties} with the following snippet
 onboarding.tutorial.with.azure_pipelines.BranchAnalysis.advanced_properties.sentence.section=Advanced section
 onboarding.tutorial.with.azure_pipelines.BranchAnalysis.advanced_properties.sentence.properties=Additional Properties