]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-14893 Adding Bitbucket pipline tutorial
authorMathieu Suen <mathieu.suen@sonarsource.com>
Fri, 4 Jun 2021 14:57:22 +0000 (16:57 +0200)
committersonartech <sonartech@sonarsource.com>
Wed, 9 Jun 2021 20:03:05 +0000 (20:03 +0000)
37 files changed:
server/sonar-web/src/main/js/components/tutorials/TutorialSelectionRenderer.tsx
server/sonar-web/src/main/js/components/tutorials/__tests__/TutorialSelectionRenderer-test.tsx
server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/AnalysisCommand.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/BitbucketPipelinesTutorial.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/PreambuleYaml.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/RepositoryVariables.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/__tests__/AnalysisCommand-test.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/__tests__/BitbucketPipelinesTutorial-test.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/__tests__/PreambuleYaml-test.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/__tests__/RepositoryVariables-test.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/__tests__/__snapshots__/AnalysisCommand-test.tsx.snap [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/__tests__/__snapshots__/BitbucketPipelinesTutorial-test.tsx.snap [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/__tests__/__snapshots__/PreambuleYaml-test.tsx.snap [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/__tests__/__snapshots__/RepositoryVariables-test.tsx.snap [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/components/CreateYmlFile.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/components/YamlFileStep.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/components/__tests__/CreateYmlFile-test.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/components/__tests__/YamlFileStep-test.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/components/__tests__/__snapshots__/CreateYmlFile-test.tsx.snap [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/components/__tests__/__snapshots__/YamlFileStep-test.tsx.snap [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/github-action/GitHubActionTutorial.tsx
server/sonar-web/src/main/js/components/tutorials/github-action/YamlFileStep.tsx [deleted file]
server/sonar-web/src/main/js/components/tutorials/github-action/__tests__/YamlFileStep-test.tsx [deleted file]
server/sonar-web/src/main/js/components/tutorials/github-action/__tests__/__snapshots__/YamlFileStep-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/components/tutorials/github-action/commands/CreateYmlFile.tsx [deleted file]
server/sonar-web/src/main/js/components/tutorials/github-action/commands/DotNet.tsx
server/sonar-web/src/main/js/components/tutorials/github-action/commands/Gradle.tsx
server/sonar-web/src/main/js/components/tutorials/github-action/commands/JavaMaven.tsx
server/sonar-web/src/main/js/components/tutorials/github-action/commands/Others.tsx
server/sonar-web/src/main/js/components/tutorials/github-action/commands/__tests__/CreateYmlFile-test.tsx [deleted file]
server/sonar-web/src/main/js/components/tutorials/github-action/commands/__tests__/__snapshots__/CreateYmlFile-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/components/tutorials/github-action/commands/__tests__/__snapshots__/DotNet-test.tsx.snap
server/sonar-web/src/main/js/components/tutorials/github-action/commands/__tests__/__snapshots__/Gradle-test.tsx.snap
server/sonar-web/src/main/js/components/tutorials/github-action/commands/__tests__/__snapshots__/JavaMaven-test.tsx.snap
server/sonar-web/src/main/js/components/tutorials/github-action/commands/__tests__/__snapshots__/Others-test.tsx.snap
server/sonar-web/src/main/js/components/tutorials/types.ts
sonar-core/src/main/resources/org/sonar/l10n/core.properties

index e2d2afbf34dd9b94e996646f5ae6cd337dc64298..b724e53b3b638b274a1e3616f0e4df9e6b285174 100644 (file)
@@ -22,6 +22,7 @@ import { translate } from 'sonar-ui-common/helpers/l10n';
 import { getBaseUrl } from 'sonar-ui-common/helpers/urls';
 import { AlmKeys, AlmSettingsInstance, ProjectAlmBindingResponse } from '../../types/alm-settings';
 import AzurePipelinesTutorial from './azure-pipelines/AzurePipelinesTutorial';
+import BitbucketPipelinesTutorial from './bitbucket-pipelines/BitbucketPipelinesTutorial';
 import GitHubActionTutorial from './github-action/GitHubActionTutorial';
 import GitLabCITutorial from './gitlabci/GitLabCITutorial';
 import JenkinsTutorial from './jenkins/JenkinsTutorial';
@@ -120,6 +121,22 @@ export default function TutorialSelectionRenderer(props: TutorialSelectionRender
               </button>
             )}
 
+            {projectBinding?.alm === AlmKeys.BitbucketCloud && (
+              <button
+                className="button button-huge display-flex-column spacer-left spacer-right bitbucket-pipelines"
+                onClick={() => props.onSelectTutorial(TutorialModes.BitbucketPipelines)}
+                type="button">
+                <img
+                  alt="" // Should be ignored by screen readers
+                  height={80}
+                  src={`${getBaseUrl()}/images/alm/bitbucket.svg`}
+                />
+                <div className="medium big-spacer-top">
+                  {translate('onboarding.tutorial.choose_method.bitbucket_pipelines')}
+                </div>
+              </button>
+            )}
+
             {jenkinsAvailable && (
               <button
                 className="button button-huge display-flex-column spacer-left spacer-right tutorial-mode-jenkins"
@@ -157,6 +174,16 @@ export default function TutorialSelectionRenderer(props: TutorialSelectionRender
         <ManualTutorial component={component} currentUser={currentUser} />
       )}
 
+      {selectedTutorial === TutorialModes.BitbucketPipelines && projectBinding !== undefined && (
+        <BitbucketPipelinesTutorial
+          almBinding={almBinding}
+          baseUrl={baseUrl}
+          component={component}
+          currentUser={currentUser}
+          projectBinding={projectBinding}
+        />
+      )}
+
       {selectedTutorial === TutorialModes.GitHubActions && projectBinding !== undefined && (
         <GitHubActionTutorial
           almBinding={almBinding}
index bad6a40ffbe9bfffb22cfd36d44fed5b2cca4584..9004e28527921aa3fa47046e677d2a8d889d0775 100644 (file)
@@ -24,6 +24,7 @@ import {
   mockAlmSettingsInstance,
   mockProjectAzureBindingResponse,
   mockProjectBitbucketBindingResponse,
+  mockProjectBitbucketCloudBindingResponse,
   mockProjectGithubBindingResponse,
   mockProjectGitLabBindingResponse
 } from '../../../helpers/mocks/alm-settings';
@@ -122,6 +123,23 @@ it('should allow mode selection for GitLab', () => {
   expect(onSelectTutorial).toHaveBeenLastCalledWith(TutorialModes.Manual);
 });
 
+it('should allow mode selection for Bitbucket pipepline', () => {
+  const onSelectTutorial = jest.fn();
+  const wrapper = shallowRender({
+    onSelectTutorial,
+    projectBinding: mockProjectBitbucketCloudBindingResponse()
+  });
+
+  click(wrapper.find('button.tutorial-mode-jenkins'));
+  expect(onSelectTutorial).toHaveBeenLastCalledWith(TutorialModes.Jenkins);
+
+  click(wrapper.find('button.bitbucket-pipelines'));
+  expect(onSelectTutorial).toHaveBeenLastCalledWith(TutorialModes.BitbucketPipelines);
+
+  click(wrapper.find('button.tutorial-mode-manual'));
+  expect(onSelectTutorial).toHaveBeenLastCalledWith(TutorialModes.Manual);
+});
+
 it('should allow mode selection for Azure DevOps', () => {
   const onSelectTutorial = jest.fn();
   const wrapper = shallowRender({
diff --git a/server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/AnalysisCommand.tsx b/server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/AnalysisCommand.tsx
new file mode 100644 (file)
index 0000000..84c136e
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ * 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 { Dictionary } from 'lodash';
+import * as React from 'react';
+import { withAppState } from '../../hoc/withAppState';
+import CreateYmlFile from '../components/CreateYmlFile';
+import { BuildTools } from '../types';
+import { PreambuleYaml } from './PreambuleYaml';
+
+export interface AnalysisCommandProps {
+  appState: T.AppState;
+  buildTool?: BuildTools;
+  component: T.Component;
+}
+
+const YamlTemplate: Dictionary<(branchesEnabled?: boolean, projectKey?: string) => string> = {
+  [BuildTools.Gradle]: branchesEnabled => `image: openjdk:8
+
+clone:
+  depth: full
+  
+pipelines:
+  branches:
+    '{master}':
+      - step:
+          name: SonarQube analysis
+          caches:
+            - gradle
+            - sonar
+          script:
+            - bash ./gradlew sonarqube
+${
+  branchesEnabled
+    ? `
+  pull-requests:
+    '**':
+      - step:
+          name: SonarQube analysis
+          caches:
+            - gradle
+            - sonar
+          script:
+            - bash ./gradlew sonarqube
+`
+    : ''
+}
+definitions:
+  caches:
+    sonar: ~/.sonar`,
+  [BuildTools.Maven]: branchesEnabled => `image: maven:3.3.9
+
+clone:
+  depth: full
+  
+pipelines:
+  branches:
+    '{master}':
+      - step:
+          name: SonarQube analysis
+          caches:
+            - maven
+            - sonar
+          script:
+            - mvn verify sonar:sonar
+${
+  branchesEnabled
+    ? `
+  pull-requests:
+    '**':
+      - step:
+          name: SonarQube analysis
+          caches:
+            - maven
+            - sonar
+          script:
+            - mvn verify sonar:sonar
+`
+    : ''
+}  
+definitions:
+  caches:
+    sonar: ~/.sonar`,
+  [BuildTools.DotNet]: (
+    branchesEnabled,
+    projectKey
+  ) => `image: mcr.microsoft.com/dotnet/core/sdk:latest
+     
+pipelines:
+  branches:
+    '{master}':
+      - step:
+          name: SonarQube analysis
+          caches:
+            - dotnetcore
+            - sonar
+          script:
+            - apt-get update
+            - apt-get install --yes openjdk-11-jre
+            - dotnet tool install --global dotnet-sonarscanner
+            - export PATH="$PATH:/root/.dotnet/tools"
+            - dotnet sonarscanner begin /k:"${projectKey}" /d:"sonar.login=\${SONAR_TOKEN}"  /d:"sonar.host.url=\${SONAR_HOST_URL}"
+            - dotnet build 
+            - dotnet sonarscanner end /d:"sonar.login=\${SONAR_TOKEN}"
+            ${
+              branchesEnabled
+                ? `
+  pull-requests:
+    '**':
+      - step:
+          name: SonarQube analysis
+          caches:
+            - dotnetcore
+            - sonar
+          script:
+            - apt-get update
+            - apt-get install --yes openjdk-11-jre
+            - dotnet tool install --global dotnet-sonarscanner
+            - export PATH="$PATH:/root/.dotnet/tools"
+            - dotnet sonarscanner begin /k:"${projectKey}" /d:"sonar.login=\${SONAR_TOKEN}"  /d:"sonar.host.url=\${SONAR_HOST_URL}"
+            - dotnet build 
+            - dotnet sonarscanner end /d:"sonar.login=\${SONAR_TOKEN}"
+                `
+                : ''
+            }  
+definitions:
+  caches:
+    sonar: ~/.sonar`,
+  [BuildTools.Other]: branchesEnabled => `image: maven:3.3.9
+
+clone:
+  depth: full
+
+pipelines:
+  branches:
+    '{master}':
+      - step:
+          name: SonarQube analysis
+          script:
+            - pipe: sonarsource/sonarqube-scan:1.0.0
+              variables:
+                SONAR_HOST_URL: \${SONAR_HOST_URL} # Get the value from the repository/workspace variable.
+                SONAR_TOKEN: \${SONAR_TOKEN} # Get the value from the repository/workspace variable. You shouldn't set secret in clear text here.
+${
+  branchesEnabled
+    ? `
+  pull-requests:
+    '**':
+      - step:
+          name: SonarQube analysis
+          script:
+            - pipe: sonarsource/sonarqube-scan:1.0.0
+              variables:
+                SONAR_HOST_URL: \${SONAR_HOST_URL} # Get the value from the repository/workspace variable.
+                SONAR_TOKEN: \${SONAR_TOKEN} # Get the value from the repository/workspace variable. You shouldn't set secret in clear text here.
+`
+    : ''
+}  
+definitions:
+  caches:
+    sonar: ~/.sonar`
+};
+
+export function AnalysisCommand(props: AnalysisCommandProps) {
+  const {
+    buildTool,
+    component,
+    appState: { branchesEnabled }
+  } = props;
+
+  if (!buildTool) {
+    return null;
+  }
+
+  const yamlTemplate = YamlTemplate[buildTool](branchesEnabled, component.key);
+
+  return (
+    <>
+      <PreambuleYaml buildTool={buildTool} component={component} />
+      <CreateYmlFile yamlFileName="bitbucket-pipelines.yml" yamlTemplate={yamlTemplate} />
+    </>
+  );
+}
+
+export default withAppState(AnalysisCommand);
diff --git a/server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/BitbucketPipelinesTutorial.tsx b/server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/BitbucketPipelinesTutorial.tsx
new file mode 100644 (file)
index 0000000..a4e2887
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * 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 { AlmSettingsInstance, ProjectAlmBindingResponse } from '../../../types/alm-settings';
+import Step from '../components/Step';
+import YamlFileStep from '../components/YamlFileStep';
+import AnalysisCommand from './AnalysisCommand';
+import RepositoryVariables from './RepositoryVariables';
+
+export enum Steps {
+  REPOSITORY_VARIABLES = 1,
+  YAML = 2
+}
+
+export interface BitbucketPipelinesTutorialProps {
+  almBinding?: AlmSettingsInstance;
+  baseUrl: string;
+  component: T.Component;
+  currentUser: T.LoggedInUser;
+  projectBinding: ProjectAlmBindingResponse;
+}
+
+export default function BitbucketPipelinesTutorial(props: BitbucketPipelinesTutorialProps) {
+  const { almBinding, baseUrl, currentUser, component, projectBinding } = props;
+
+  const [step, setStep] = React.useState<Steps>(Steps.REPOSITORY_VARIABLES);
+  return (
+    <>
+      <Step
+        finished={step > Steps.REPOSITORY_VARIABLES}
+        onOpen={() => setStep(Steps.REPOSITORY_VARIABLES)}
+        open={step === Steps.REPOSITORY_VARIABLES}
+        renderForm={() => (
+          <RepositoryVariables
+            almBinding={almBinding}
+            baseUrl={baseUrl}
+            component={component}
+            currentUser={currentUser}
+            onDone={() => setStep(Steps.YAML)}
+            projectBinding={projectBinding}
+          />
+        )}
+        stepNumber={Steps.REPOSITORY_VARIABLES}
+        stepTitle={translate('onboarding.tutorial.with.bitbucket_pipelines.create_secret.title')}
+      />
+      <Step
+        onOpen={() => setStep(Steps.YAML)}
+        open={step === Steps.YAML}
+        renderForm={() => (
+          <YamlFileStep>
+            {buildTool => <AnalysisCommand buildTool={buildTool} component={component} />}
+          </YamlFileStep>
+        )}
+        stepNumber={Steps.YAML}
+        stepTitle={translate('onboarding.tutorial.with.bitbucket_pipelines.yaml.title')}
+      />
+    </>
+  );
+}
diff --git a/server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/PreambuleYaml.tsx b/server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/PreambuleYaml.tsx
new file mode 100644 (file)
index 0000000..f27c17e
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * 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 DefaultProjectKey from '../components/DefaultProjectKey';
+import { BuildTools } from '../types';
+import { buildGradleSnippet, mavenPomSnippet } from '../utils';
+
+export interface PreambuleYamlProps {
+  buildTool: BuildTools;
+  component: T.Component;
+}
+
+export function PreambuleYaml(props: PreambuleYamlProps) {
+  const { buildTool, component } = props;
+  switch (buildTool) {
+    case BuildTools.Gradle:
+      return (
+        <li className="abs-width-600">
+          <FormattedMessage
+            defaultMessage={translate('onboarding.tutorial.with.yaml.gradle')}
+            id="onboarding.tutorial.with.yaml.gradle"
+            values={{
+              gradle: (
+                <>
+                  <code className="rule">build.gradle</code>
+                  <ClipboardIconButton copyValue="build.gradle" />
+                </>
+              ),
+              sq: <code className="rule">org.sonarqube</code>
+            }}
+          />
+          <CodeSnippet snippet={buildGradleSnippet(component.key)} />
+        </li>
+      );
+    case BuildTools.Maven:
+      return (
+        <li className="abs-width-600">
+          <FormattedMessage
+            defaultMessage={translate('onboarding.tutorial.with.yaml.maven.pom')}
+            id="onboarding.tutorial.with.yaml.maven.pom"
+            values={{
+              pom: (
+                <>
+                  <code className="rule">pom.xml</code>
+                  <ClipboardIconButton copyValue="pom.xml" />
+                </>
+              )
+            }}
+          />
+          <CodeSnippet snippet={mavenPomSnippet(component.key)} />
+        </li>
+      );
+    case BuildTools.Other:
+      return <DefaultProjectKey component={component} />;
+    default:
+      return null;
+  }
+}
diff --git a/server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/RepositoryVariables.tsx b/server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/RepositoryVariables.tsx
new file mode 100644 (file)
index 0000000..b0d2e1a
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * 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 { Button } from 'sonar-ui-common/components/controls/buttons';
+import { ClipboardIconButton } from 'sonar-ui-common/components/controls/clipboard';
+import { translate } from 'sonar-ui-common/helpers/l10n';
+import { AlmSettingsInstance, ProjectAlmBindingResponse } from '../../../types/alm-settings';
+import SentenceWithHighlights from '../components/SentenceWithHighlights';
+import TokenStepGenerator from '../components/TokenStepGenerator';
+
+export interface RepositoryVariablesProps {
+  almBinding?: AlmSettingsInstance;
+  baseUrl: string;
+  component: T.Component;
+  currentUser: T.LoggedInUser;
+  onDone: () => void;
+  projectBinding: ProjectAlmBindingResponse;
+}
+
+export default function RepositoryVariables(props: RepositoryVariablesProps) {
+  const { almBinding, baseUrl, component, currentUser, projectBinding } = props;
+  return (
+    <div className="boxed-group-inner">
+      <p className="big-spacer-bottom">
+        <FormattedMessage
+          defaultMessage={translate('onboarding.tutorial.with.bitbucket_pipelines.variables.intro')}
+          id="onboarding.tutorial.with.bitbucket_pipelines.variables.intro"
+          values={{
+            repository_variables: almBinding?.url ? (
+              <a
+                href={`${almBinding.url}/${projectBinding.slug}/admin/addon/admin/pipelines/repository-variables`}
+                target="_blank"
+                rel="noopener noreferrer">
+                {translate('onboarding.tutorial.with.bitbucket_pipelines.variables.intro.link')}
+              </a>
+            ) : (
+              <b>
+                {translate('onboarding.tutorial.with.bitbucket_pipelines.variables.intro.link')}
+              </b>
+            )
+          }}
+        />
+      </p>
+      <ol className="list-styled">
+        <li>
+          <SentenceWithHighlights
+            translationKey="onboarding.tutorial.with.bitbucket_pipelines.variables.name"
+            highlightKeys={['name']}
+          />
+          <code className="rule little-spacer-left">SONAR_TOKEN</code>
+          <ClipboardIconButton copyValue="SONAR_TOKEN" />
+        </li>
+        <TokenStepGenerator component={component} currentUser={currentUser} />
+        <li>
+          <SentenceWithHighlights
+            translationKey="onboarding.tutorial.with.bitbucket_pipelines.variables.secured"
+            highlightKeys={['secured']}
+          />
+        </li>
+        <li>
+          <SentenceWithHighlights
+            translationKey="onboarding.tutorial.with.bitbucket_pipelines.variables.add"
+            highlightKeys={['add']}
+          />
+        </li>
+      </ol>
+
+      <hr className="no-horizontal-margins" />
+
+      <ol className="list-styled big-spacer-top big-spacer-bottom">
+        <li>
+          <SentenceWithHighlights
+            translationKey="onboarding.tutorial.with.bitbucket_pipelines.variables.name"
+            highlightKeys={['name']}
+          />
+
+          <code className="rule little-spacer-left">SONAR_HOST_URL</code>
+          <ClipboardIconButton copyValue="SONAR_HOST_URL" />
+        </li>
+        <li className="big-spacer-bottom">
+          <FormattedMessage
+            defaultMessage={translate('onboarding.tutorial.env_variables')}
+            id="onboarding.tutorial.env_variables"
+            values={{
+              extra: <ClipboardIconButton copyValue={baseUrl} />,
+              field: <strong>{translate('onboarding.tutorial.env_variables.field')}</strong>,
+              value: <code className="rule">{baseUrl}</code>
+            }}
+          />
+        </li>
+        <li>
+          <SentenceWithHighlights
+            translationKey="onboarding.tutorial.with.bitbucket_pipelines.variables.add"
+            highlightKeys={['add']}
+          />
+        </li>
+      </ol>
+      <Button onClick={props.onDone}>{translate('continue')}</Button>
+    </div>
+  );
+}
diff --git a/server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/__tests__/AnalysisCommand-test.tsx b/server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/__tests__/AnalysisCommand-test.tsx
new file mode 100644 (file)
index 0000000..fe163ec
--- /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 { shallow } from 'enzyme';
+import * as React from 'react';
+import { mockAppState, mockComponent } from '../../../../helpers/testMocks';
+import { BuildTools } from '../../types';
+import { AnalysisCommand, AnalysisCommandProps } from '../AnalysisCommand';
+
+it.each([[BuildTools.DotNet], [BuildTools.Gradle], [BuildTools.Maven], [BuildTools.Other]])(
+  'should render correctly for %s',
+  buildTool => {
+    expect(shallowRender({ buildTool })).toMatchSnapshot();
+    expect(
+      shallowRender({ appState: mockAppState({ branchesEnabled: true }), buildTool })
+    ).toMatchSnapshot('with branch enabled');
+  }
+);
+
+function shallowRender(props: Partial<AnalysisCommandProps> = {}) {
+  return shallow<AnalysisCommandProps>(
+    <AnalysisCommand
+      appState={mockAppState()}
+      buildTool={BuildTools.DotNet}
+      component={mockComponent()}
+      {...props}
+    />
+  );
+}
diff --git a/server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/__tests__/BitbucketPipelinesTutorial-test.tsx b/server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/__tests__/BitbucketPipelinesTutorial-test.tsx
new file mode 100644 (file)
index 0000000..6557441
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * 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 {
+  mockAlmSettingsInstance,
+  mockProjectBitbucketCloudBindingResponse
+} from '../../../../helpers/mocks/alm-settings';
+import { mockComponent, mockLoggedInUser } from '../../../../helpers/testMocks';
+import Step from '../../components/Step';
+import BitbucketPipelinesTutorial, {
+  BitbucketPipelinesTutorialProps
+} from '../BitbucketPipelinesTutorial';
+
+it('should render correctly', () => {
+  const wrapper = shallowRender();
+  expect(wrapper).toMatchSnapshot('For variable steps');
+  const stepYaml = wrapper.find(Step).at(1);
+  stepYaml.simulate('open');
+  expect(wrapper).toMatchSnapshot('For yaml steps');
+});
+
+function shallowRender(props: Partial<BitbucketPipelinesTutorialProps> = {}) {
+  return shallow<BitbucketPipelinesTutorialProps>(
+    <BitbucketPipelinesTutorial
+      almBinding={mockAlmSettingsInstance()}
+      baseUrl="test"
+      currentUser={mockLoggedInUser()}
+      component={mockComponent()}
+      projectBinding={mockProjectBitbucketCloudBindingResponse()}
+      {...props}
+    />
+  );
+}
diff --git a/server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/__tests__/PreambuleYaml-test.tsx b/server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/__tests__/PreambuleYaml-test.tsx
new file mode 100644 (file)
index 0000000..c8c5a52
--- /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 { mockComponent } from '../../../../helpers/testMocks';
+import { BuildTools } from '../../types';
+import { PreambuleYaml, PreambuleYamlProps } from '../PreambuleYaml';
+
+it.each([[BuildTools.DotNet], [BuildTools.Gradle], [BuildTools.Maven], [BuildTools.Other]])(
+  'should render correctly for %s',
+  buildTool => {
+    expect(shallowRender({ buildTool })).toMatchSnapshot();
+  }
+);
+
+function shallowRender(props: Partial<PreambuleYamlProps> = {}) {
+  return shallow<PreambuleYamlProps>(
+    <PreambuleYaml buildTool={BuildTools.DotNet} component={mockComponent()} {...props} />
+  );
+}
diff --git a/server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/__tests__/RepositoryVariables-test.tsx b/server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/__tests__/RepositoryVariables-test.tsx
new file mode 100644 (file)
index 0000000..14413eb
--- /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 { shallow } from 'enzyme';
+import * as React from 'react';
+import {
+  mockAlmSettingsInstance,
+  mockProjectBitbucketCloudBindingResponse
+} from '../../../../helpers/mocks/alm-settings';
+import { mockComponent, mockLoggedInUser } from '../../../../helpers/testMocks';
+import RepositoryVariables, { RepositoryVariablesProps } from '../RepositoryVariables';
+
+it('should render correctly', () => {
+  expect(shallowRender()).toMatchSnapshot();
+});
+
+function shallowRender(props: Partial<RepositoryVariablesProps> = {}) {
+  return shallow<RepositoryVariablesProps>(
+    <RepositoryVariables
+      almBinding={mockAlmSettingsInstance()}
+      currentUser={mockLoggedInUser()}
+      baseUrl="test"
+      onDone={jest.fn()}
+      component={mockComponent()}
+      projectBinding={mockProjectBitbucketCloudBindingResponse()}
+      {...props}
+    />
+  );
+}
diff --git a/server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/__tests__/__snapshots__/AnalysisCommand-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/__tests__/__snapshots__/AnalysisCommand-test.tsx.snap
new file mode 100644 (file)
index 0000000..51a6080
--- /dev/null
@@ -0,0 +1,469 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly for dotnet 1`] = `
+<Fragment>
+  <PreambuleYaml
+    buildTool="dotnet"
+    component={
+      Object {
+        "breadcrumbs": Array [],
+        "key": "my-project",
+        "name": "MyProject",
+        "qualifier": "TRK",
+        "qualityGate": Object {
+          "isDefault": true,
+          "key": "30",
+          "name": "Sonar way",
+        },
+        "qualityProfiles": Array [
+          Object {
+            "deleted": false,
+            "key": "my-qp",
+            "language": "ts",
+            "name": "Sonar way",
+          },
+        ],
+        "tags": Array [],
+      }
+    }
+  />
+  <CreateYmlFile
+    yamlFileName="bitbucket-pipelines.yml"
+    yamlTemplate="image: mcr.microsoft.com/dotnet/core/sdk:latest
+     
+pipelines:
+  branches:
+    '{master}':
+      - step:
+          name: SonarQube analysis
+          caches:
+            - dotnetcore
+            - sonar
+          script:
+            - apt-get update
+            - apt-get install --yes openjdk-11-jre
+            - dotnet tool install --global dotnet-sonarscanner
+            - export PATH=\\"$PATH:/root/.dotnet/tools\\"
+            - dotnet sonarscanner begin /k:\\"my-project\\" /d:\\"sonar.login=\${SONAR_TOKEN}\\"  /d:\\"sonar.host.url=\${SONAR_HOST_URL}\\"
+            - dotnet build 
+            - dotnet sonarscanner end /d:\\"sonar.login=\${SONAR_TOKEN}\\"
+              
+definitions:
+  caches:
+    sonar: ~/.sonar"
+  />
+</Fragment>
+`;
+
+exports[`should render correctly for dotnet: with branch enabled 1`] = `
+<Fragment>
+  <PreambuleYaml
+    buildTool="dotnet"
+    component={
+      Object {
+        "breadcrumbs": Array [],
+        "key": "my-project",
+        "name": "MyProject",
+        "qualifier": "TRK",
+        "qualityGate": Object {
+          "isDefault": true,
+          "key": "30",
+          "name": "Sonar way",
+        },
+        "qualityProfiles": Array [
+          Object {
+            "deleted": false,
+            "key": "my-qp",
+            "language": "ts",
+            "name": "Sonar way",
+          },
+        ],
+        "tags": Array [],
+      }
+    }
+  />
+  <CreateYmlFile
+    yamlFileName="bitbucket-pipelines.yml"
+    yamlTemplate="image: mcr.microsoft.com/dotnet/core/sdk:latest
+     
+pipelines:
+  branches:
+    '{master}':
+      - step:
+          name: SonarQube analysis
+          caches:
+            - dotnetcore
+            - sonar
+          script:
+            - apt-get update
+            - apt-get install --yes openjdk-11-jre
+            - dotnet tool install --global dotnet-sonarscanner
+            - export PATH=\\"$PATH:/root/.dotnet/tools\\"
+            - dotnet sonarscanner begin /k:\\"my-project\\" /d:\\"sonar.login=\${SONAR_TOKEN}\\"  /d:\\"sonar.host.url=\${SONAR_HOST_URL}\\"
+            - dotnet build 
+            - dotnet sonarscanner end /d:\\"sonar.login=\${SONAR_TOKEN}\\"
+            
+  pull-requests:
+    '**':
+      - step:
+          name: SonarQube analysis
+          caches:
+            - dotnetcore
+            - sonar
+          script:
+            - apt-get update
+            - apt-get install --yes openjdk-11-jre
+            - dotnet tool install --global dotnet-sonarscanner
+            - export PATH=\\"$PATH:/root/.dotnet/tools\\"
+            - dotnet sonarscanner begin /k:\\"my-project\\" /d:\\"sonar.login=\${SONAR_TOKEN}\\"  /d:\\"sonar.host.url=\${SONAR_HOST_URL}\\"
+            - dotnet build 
+            - dotnet sonarscanner end /d:\\"sonar.login=\${SONAR_TOKEN}\\"
+                  
+definitions:
+  caches:
+    sonar: ~/.sonar"
+  />
+</Fragment>
+`;
+
+exports[`should render correctly for gradle 1`] = `
+<Fragment>
+  <PreambuleYaml
+    buildTool="gradle"
+    component={
+      Object {
+        "breadcrumbs": Array [],
+        "key": "my-project",
+        "name": "MyProject",
+        "qualifier": "TRK",
+        "qualityGate": Object {
+          "isDefault": true,
+          "key": "30",
+          "name": "Sonar way",
+        },
+        "qualityProfiles": Array [
+          Object {
+            "deleted": false,
+            "key": "my-qp",
+            "language": "ts",
+            "name": "Sonar way",
+          },
+        ],
+        "tags": Array [],
+      }
+    }
+  />
+  <CreateYmlFile
+    yamlFileName="bitbucket-pipelines.yml"
+    yamlTemplate="image: openjdk:8
+
+clone:
+  depth: full
+  
+pipelines:
+  branches:
+    '{master}':
+      - step:
+          name: SonarQube analysis
+          caches:
+            - gradle
+            - sonar
+          script:
+            - bash ./gradlew sonarqube
+
+definitions:
+  caches:
+    sonar: ~/.sonar"
+  />
+</Fragment>
+`;
+
+exports[`should render correctly for gradle: with branch enabled 1`] = `
+<Fragment>
+  <PreambuleYaml
+    buildTool="gradle"
+    component={
+      Object {
+        "breadcrumbs": Array [],
+        "key": "my-project",
+        "name": "MyProject",
+        "qualifier": "TRK",
+        "qualityGate": Object {
+          "isDefault": true,
+          "key": "30",
+          "name": "Sonar way",
+        },
+        "qualityProfiles": Array [
+          Object {
+            "deleted": false,
+            "key": "my-qp",
+            "language": "ts",
+            "name": "Sonar way",
+          },
+        ],
+        "tags": Array [],
+      }
+    }
+  />
+  <CreateYmlFile
+    yamlFileName="bitbucket-pipelines.yml"
+    yamlTemplate="image: openjdk:8
+
+clone:
+  depth: full
+  
+pipelines:
+  branches:
+    '{master}':
+      - step:
+          name: SonarQube analysis
+          caches:
+            - gradle
+            - sonar
+          script:
+            - bash ./gradlew sonarqube
+
+  pull-requests:
+    '**':
+      - step:
+          name: SonarQube analysis
+          caches:
+            - gradle
+            - sonar
+          script:
+            - bash ./gradlew sonarqube
+
+definitions:
+  caches:
+    sonar: ~/.sonar"
+  />
+</Fragment>
+`;
+
+exports[`should render correctly for maven 1`] = `
+<Fragment>
+  <PreambuleYaml
+    buildTool="maven"
+    component={
+      Object {
+        "breadcrumbs": Array [],
+        "key": "my-project",
+        "name": "MyProject",
+        "qualifier": "TRK",
+        "qualityGate": Object {
+          "isDefault": true,
+          "key": "30",
+          "name": "Sonar way",
+        },
+        "qualityProfiles": Array [
+          Object {
+            "deleted": false,
+            "key": "my-qp",
+            "language": "ts",
+            "name": "Sonar way",
+          },
+        ],
+        "tags": Array [],
+      }
+    }
+  />
+  <CreateYmlFile
+    yamlFileName="bitbucket-pipelines.yml"
+    yamlTemplate="image: maven:3.3.9
+
+clone:
+  depth: full
+  
+pipelines:
+  branches:
+    '{master}':
+      - step:
+          name: SonarQube analysis
+          caches:
+            - maven
+            - sonar
+          script:
+            - mvn verify sonar:sonar
+  
+definitions:
+  caches:
+    sonar: ~/.sonar"
+  />
+</Fragment>
+`;
+
+exports[`should render correctly for maven: with branch enabled 1`] = `
+<Fragment>
+  <PreambuleYaml
+    buildTool="maven"
+    component={
+      Object {
+        "breadcrumbs": Array [],
+        "key": "my-project",
+        "name": "MyProject",
+        "qualifier": "TRK",
+        "qualityGate": Object {
+          "isDefault": true,
+          "key": "30",
+          "name": "Sonar way",
+        },
+        "qualityProfiles": Array [
+          Object {
+            "deleted": false,
+            "key": "my-qp",
+            "language": "ts",
+            "name": "Sonar way",
+          },
+        ],
+        "tags": Array [],
+      }
+    }
+  />
+  <CreateYmlFile
+    yamlFileName="bitbucket-pipelines.yml"
+    yamlTemplate="image: maven:3.3.9
+
+clone:
+  depth: full
+  
+pipelines:
+  branches:
+    '{master}':
+      - step:
+          name: SonarQube analysis
+          caches:
+            - maven
+            - sonar
+          script:
+            - mvn verify sonar:sonar
+
+  pull-requests:
+    '**':
+      - step:
+          name: SonarQube analysis
+          caches:
+            - maven
+            - sonar
+          script:
+            - mvn verify sonar:sonar
+  
+definitions:
+  caches:
+    sonar: ~/.sonar"
+  />
+</Fragment>
+`;
+
+exports[`should render correctly for other 1`] = `
+<Fragment>
+  <PreambuleYaml
+    buildTool="other"
+    component={
+      Object {
+        "breadcrumbs": Array [],
+        "key": "my-project",
+        "name": "MyProject",
+        "qualifier": "TRK",
+        "qualityGate": Object {
+          "isDefault": true,
+          "key": "30",
+          "name": "Sonar way",
+        },
+        "qualityProfiles": Array [
+          Object {
+            "deleted": false,
+            "key": "my-qp",
+            "language": "ts",
+            "name": "Sonar way",
+          },
+        ],
+        "tags": Array [],
+      }
+    }
+  />
+  <CreateYmlFile
+    yamlFileName="bitbucket-pipelines.yml"
+    yamlTemplate="image: maven:3.3.9
+
+clone:
+  depth: full
+
+pipelines:
+  branches:
+    '{master}':
+      - step:
+          name: SonarQube analysis
+          script:
+            - pipe: sonarsource/sonarqube-scan:1.0.0
+              variables:
+                SONAR_HOST_URL: \${SONAR_HOST_URL} # Get the value from the repository/workspace variable.
+                SONAR_TOKEN: \${SONAR_TOKEN} # Get the value from the repository/workspace variable. You shouldn't set secret in clear text here.
+  
+definitions:
+  caches:
+    sonar: ~/.sonar"
+  />
+</Fragment>
+`;
+
+exports[`should render correctly for other: with branch enabled 1`] = `
+<Fragment>
+  <PreambuleYaml
+    buildTool="other"
+    component={
+      Object {
+        "breadcrumbs": Array [],
+        "key": "my-project",
+        "name": "MyProject",
+        "qualifier": "TRK",
+        "qualityGate": Object {
+          "isDefault": true,
+          "key": "30",
+          "name": "Sonar way",
+        },
+        "qualityProfiles": Array [
+          Object {
+            "deleted": false,
+            "key": "my-qp",
+            "language": "ts",
+            "name": "Sonar way",
+          },
+        ],
+        "tags": Array [],
+      }
+    }
+  />
+  <CreateYmlFile
+    yamlFileName="bitbucket-pipelines.yml"
+    yamlTemplate="image: maven:3.3.9
+
+clone:
+  depth: full
+
+pipelines:
+  branches:
+    '{master}':
+      - step:
+          name: SonarQube analysis
+          script:
+            - pipe: sonarsource/sonarqube-scan:1.0.0
+              variables:
+                SONAR_HOST_URL: \${SONAR_HOST_URL} # Get the value from the repository/workspace variable.
+                SONAR_TOKEN: \${SONAR_TOKEN} # Get the value from the repository/workspace variable. You shouldn't set secret in clear text here.
+
+  pull-requests:
+    '**':
+      - step:
+          name: SonarQube analysis
+          script:
+            - pipe: sonarsource/sonarqube-scan:1.0.0
+              variables:
+                SONAR_HOST_URL: \${SONAR_HOST_URL} # Get the value from the repository/workspace variable.
+                SONAR_TOKEN: \${SONAR_TOKEN} # Get the value from the repository/workspace variable. You shouldn't set secret in clear text here.
+  
+definitions:
+  caches:
+    sonar: ~/.sonar"
+  />
+</Fragment>
+`;
diff --git a/server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/__tests__/__snapshots__/BitbucketPipelinesTutorial-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/__tests__/__snapshots__/BitbucketPipelinesTutorial-test.tsx.snap
new file mode 100644 (file)
index 0000000..0e33b55
--- /dev/null
@@ -0,0 +1,41 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly: For variable steps 1`] = `
+<Fragment>
+  <Step
+    finished={false}
+    onOpen={[Function]}
+    open={true}
+    renderForm={[Function]}
+    stepNumber={1}
+    stepTitle="onboarding.tutorial.with.bitbucket_pipelines.create_secret.title"
+  />
+  <Step
+    onOpen={[Function]}
+    open={false}
+    renderForm={[Function]}
+    stepNumber={2}
+    stepTitle="onboarding.tutorial.with.bitbucket_pipelines.yaml.title"
+  />
+</Fragment>
+`;
+
+exports[`should render correctly: For yaml steps 1`] = `
+<Fragment>
+  <Step
+    finished={true}
+    onOpen={[Function]}
+    open={false}
+    renderForm={[Function]}
+    stepNumber={1}
+    stepTitle="onboarding.tutorial.with.bitbucket_pipelines.create_secret.title"
+  />
+  <Step
+    onOpen={[Function]}
+    open={true}
+    renderForm={[Function]}
+    stepNumber={2}
+    stepTitle="onboarding.tutorial.with.bitbucket_pipelines.yaml.title"
+  />
+</Fragment>
+`;
diff --git a/server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/__tests__/__snapshots__/PreambuleYaml-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/__tests__/__snapshots__/PreambuleYaml-test.tsx.snap
new file mode 100644 (file)
index 0000000..79f07d6
--- /dev/null
@@ -0,0 +1,101 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly for dotnet 1`] = `""`;
+
+exports[`should render correctly for gradle 1`] = `
+<li
+  className="abs-width-600"
+>
+  <FormattedMessage
+    defaultMessage="onboarding.tutorial.with.yaml.gradle"
+    id="onboarding.tutorial.with.yaml.gradle"
+    values={
+      Object {
+        "gradle": <React.Fragment>
+          <code
+            className="rule"
+          >
+            build.gradle
+          </code>
+          <ClipboardIconButton
+            copyValue="build.gradle"
+          />
+        </React.Fragment>,
+        "sq": <code
+          className="rule"
+        >
+          org.sonarqube
+        </code>,
+      }
+    }
+  />
+  <CodeSnippet
+    snippet="plugins {
+  id \\"org.sonarqube\\" version \\"3.2.0\\"
+}
+
+sonarqube {
+  properties {
+    property \\"sonar.projectKey\\", \\"my-project\\"
+  }
+}"
+  />
+</li>
+`;
+
+exports[`should render correctly for maven 1`] = `
+<li
+  className="abs-width-600"
+>
+  <FormattedMessage
+    defaultMessage="onboarding.tutorial.with.yaml.maven.pom"
+    id="onboarding.tutorial.with.yaml.maven.pom"
+    values={
+      Object {
+        "pom": <React.Fragment>
+          <code
+            className="rule"
+          >
+            pom.xml
+          </code>
+          <ClipboardIconButton
+            copyValue="pom.xml"
+          />
+        </React.Fragment>,
+      }
+    }
+  />
+  <CodeSnippet
+    snippet="<properties>
+  <sonar.projectKey>my-project</sonar.projectKey>
+</properties>"
+  />
+</li>
+`;
+
+exports[`should render correctly for other 1`] = `
+<DefaultProjectKey
+  component={
+    Object {
+      "breadcrumbs": Array [],
+      "key": "my-project",
+      "name": "MyProject",
+      "qualifier": "TRK",
+      "qualityGate": Object {
+        "isDefault": true,
+        "key": "30",
+        "name": "Sonar way",
+      },
+      "qualityProfiles": Array [
+        Object {
+          "deleted": false,
+          "key": "my-qp",
+          "language": "ts",
+          "name": "Sonar way",
+        },
+      ],
+      "tags": Array [],
+    }
+  }
+/>
+`;
diff --git a/server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/__tests__/__snapshots__/RepositoryVariables-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/__tests__/__snapshots__/RepositoryVariables-test.tsx.snap
new file mode 100644 (file)
index 0000000..2bd1948
--- /dev/null
@@ -0,0 +1,161 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly 1`] = `
+<div
+  className="boxed-group-inner"
+>
+  <p
+    className="big-spacer-bottom"
+  >
+    <FormattedMessage
+      defaultMessage="onboarding.tutorial.with.bitbucket_pipelines.variables.intro"
+      id="onboarding.tutorial.with.bitbucket_pipelines.variables.intro"
+      values={
+        Object {
+          "repository_variables": <b>
+            onboarding.tutorial.with.bitbucket_pipelines.variables.intro.link
+          </b>,
+        }
+      }
+    />
+  </p>
+  <ol
+    className="list-styled"
+  >
+    <li>
+      <SentenceWithHighlights
+        highlightKeys={
+          Array [
+            "name",
+          ]
+        }
+        translationKey="onboarding.tutorial.with.bitbucket_pipelines.variables.name"
+      />
+      <code
+        className="rule little-spacer-left"
+      >
+        SONAR_TOKEN
+      </code>
+      <ClipboardIconButton
+        copyValue="SONAR_TOKEN"
+      />
+    </li>
+    <TokenStepGenerator
+      component={
+        Object {
+          "breadcrumbs": Array [],
+          "key": "my-project",
+          "name": "MyProject",
+          "qualifier": "TRK",
+          "qualityGate": Object {
+            "isDefault": true,
+            "key": "30",
+            "name": "Sonar way",
+          },
+          "qualityProfiles": Array [
+            Object {
+              "deleted": false,
+              "key": "my-qp",
+              "language": "ts",
+              "name": "Sonar way",
+            },
+          ],
+          "tags": Array [],
+        }
+      }
+      currentUser={
+        Object {
+          "groups": Array [],
+          "isLoggedIn": true,
+          "login": "luke",
+          "name": "Skywalker",
+          "scmAccounts": Array [],
+        }
+      }
+    />
+    <li>
+      <SentenceWithHighlights
+        highlightKeys={
+          Array [
+            "secured",
+          ]
+        }
+        translationKey="onboarding.tutorial.with.bitbucket_pipelines.variables.secured"
+      />
+    </li>
+    <li>
+      <SentenceWithHighlights
+        highlightKeys={
+          Array [
+            "add",
+          ]
+        }
+        translationKey="onboarding.tutorial.with.bitbucket_pipelines.variables.add"
+      />
+    </li>
+  </ol>
+  <hr
+    className="no-horizontal-margins"
+  />
+  <ol
+    className="list-styled big-spacer-top big-spacer-bottom"
+  >
+    <li>
+      <SentenceWithHighlights
+        highlightKeys={
+          Array [
+            "name",
+          ]
+        }
+        translationKey="onboarding.tutorial.with.bitbucket_pipelines.variables.name"
+      />
+      <code
+        className="rule little-spacer-left"
+      >
+        SONAR_HOST_URL
+      </code>
+      <ClipboardIconButton
+        copyValue="SONAR_HOST_URL"
+      />
+    </li>
+    <li
+      className="big-spacer-bottom"
+    >
+      <FormattedMessage
+        defaultMessage="onboarding.tutorial.env_variables"
+        id="onboarding.tutorial.env_variables"
+        values={
+          Object {
+            "extra": <ClipboardIconButton
+              copyValue="test"
+            />,
+            "field": <strong>
+              onboarding.tutorial.env_variables.field
+            </strong>,
+            "value": <code
+              className="rule"
+            >
+              test
+            </code>,
+          }
+        }
+      />
+    </li>
+    <li>
+      <SentenceWithHighlights
+        highlightKeys={
+          Array [
+            "add",
+          ]
+        }
+        translationKey="onboarding.tutorial.with.bitbucket_pipelines.variables.add"
+      />
+    </li>
+  </ol>
+  <Button
+    onClick={[MockFunction]}
+  >
+    continue
+  </Button>
+</div>
+`;
diff --git a/server/sonar-web/src/main/js/components/tutorials/components/CreateYmlFile.tsx b/server/sonar-web/src/main/js/components/tutorials/components/CreateYmlFile.tsx
new file mode 100644 (file)
index 0000000..395aadb
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * 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';
+
+export interface CreateYmlFileProps {
+  yamlFileName: string;
+  yamlTemplate: string;
+}
+
+export default function CreateYmlFile(props: CreateYmlFileProps) {
+  const { yamlTemplate, yamlFileName } = props;
+  return (
+    <li className="abs-width-800">
+      <FormattedMessage
+        defaultMessage={translate('onboarding.tutorial.with.github_action.yaml.create_yml')}
+        id="onboarding.tutorial.with.github_action.yaml.create_yml"
+        values={{
+          file: (
+            <>
+              <code className="rule">{yamlFileName}</code>
+              <ClipboardIconButton copyValue={yamlFileName} />
+            </>
+          )
+        }}
+      />
+      <CodeSnippet snippet={yamlTemplate} />
+    </li>
+  );
+}
diff --git a/server/sonar-web/src/main/js/components/tutorials/components/YamlFileStep.tsx b/server/sonar-web/src/main/js/components/tutorials/components/YamlFileStep.tsx
new file mode 100644 (file)
index 0000000..007c9a8
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * 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 RenderOptions from '../components/RenderOptions';
+import { BuildTools } from '../types';
+import AllSet from './AllSet';
+
+export interface YamlFileStepProps {
+  children?: (buildTool?: BuildTools) => React.ReactElement<{}>;
+}
+
+export interface AnalysisCommandProps {
+  appState: T.AppState;
+  buildTool?: BuildTools;
+  component: T.Component;
+}
+
+export default function YamlFileStep(props: YamlFileStepProps) {
+  const { children } = props;
+  const buildTools = [BuildTools.Maven, BuildTools.Gradle, BuildTools.DotNet, BuildTools.Other];
+  const [buildToolSelected, setBuildToolSelected] = React.useState<BuildTools>();
+
+  return (
+    <>
+      <ol className="list-styled big-spacer-top big-spacer-bottom">
+        <li>
+          {translate('onboarding.build')}
+
+          <RenderOptions
+            checked={buildToolSelected}
+            name="language"
+            onCheck={value => setBuildToolSelected(value as BuildTools)}
+            options={buildTools}
+            optionLabelKey="onboarding.build"
+          />
+        </li>
+        {children && children(buildToolSelected)}
+      </ol>
+      {buildToolSelected !== undefined && (
+        <>
+          <hr className="huge-spacer-top huge-spacer-bottom" />
+          <AllSet />
+        </>
+      )}
+    </>
+  );
+}
diff --git a/server/sonar-web/src/main/js/components/tutorials/components/__tests__/CreateYmlFile-test.tsx b/server/sonar-web/src/main/js/components/tutorials/components/__tests__/CreateYmlFile-test.tsx
new file mode 100644 (file)
index 0000000..136fee4
--- /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 { GradleProps } from '../../github-action/commands/Gradle';
+import CreateYmlFile, { CreateYmlFileProps } from '../CreateYmlFile';
+
+it('should render correctly', () => {
+  expect(shallowRender()).toMatchSnapshot();
+});
+
+function shallowRender(props: Partial<CreateYmlFileProps> = {}) {
+  return shallow<GradleProps>(
+    <CreateYmlFile yamlFileName="test.yml" yamlTemplate="temaplate" {...props} />
+  );
+}
diff --git a/server/sonar-web/src/main/js/components/tutorials/components/__tests__/YamlFileStep-test.tsx b/server/sonar-web/src/main/js/components/tutorials/components/__tests__/YamlFileStep-test.tsx
new file mode 100644 (file)
index 0000000..9b70ee7
--- /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 YamlFileStep, { YamlFileStepProps } from '../YamlFileStep';
+
+it('should render correctly', () => {
+  expect(shallowRender()).toMatchSnapshot();
+});
+
+function shallowRender(props: Partial<YamlFileStepProps> = {}) {
+  return shallow<YamlFileStepProps>(<YamlFileStep {...props} />);
+}
diff --git a/server/sonar-web/src/main/js/components/tutorials/components/__tests__/__snapshots__/CreateYmlFile-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/components/__tests__/__snapshots__/CreateYmlFile-test.tsx.snap
new file mode 100644 (file)
index 0000000..098d9b2
--- /dev/null
@@ -0,0 +1,29 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly 1`] = `
+<li
+  className="abs-width-800"
+>
+  <FormattedMessage
+    defaultMessage="onboarding.tutorial.with.github_action.yaml.create_yml"
+    id="onboarding.tutorial.with.github_action.yaml.create_yml"
+    values={
+      Object {
+        "file": <React.Fragment>
+          <code
+            className="rule"
+          >
+            test.yml
+          </code>
+          <ClipboardIconButton
+            copyValue="test.yml"
+          />
+        </React.Fragment>,
+      }
+    }
+  />
+  <CodeSnippet
+    snippet="temaplate"
+  />
+</li>
+`;
diff --git a/server/sonar-web/src/main/js/components/tutorials/components/__tests__/__snapshots__/YamlFileStep-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/components/__tests__/__snapshots__/YamlFileStep-test.tsx.snap
new file mode 100644 (file)
index 0000000..4682c79
--- /dev/null
@@ -0,0 +1,26 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly 1`] = `
+<Fragment>
+  <ol
+    className="list-styled big-spacer-top big-spacer-bottom"
+  >
+    <li>
+      onboarding.build
+      <RenderOptions
+        name="language"
+        onCheck={[Function]}
+        optionLabelKey="onboarding.build"
+        options={
+          Array [
+            "maven",
+            "gradle",
+            "dotnet",
+            "other",
+          ]
+        }
+      />
+    </li>
+  </ol>
+</Fragment>
+`;
index 61eded6385460f373101f0258ceda779525da980..6779481065a6f66ca40662d968073ea64d69ed7a 100644 (file)
@@ -21,8 +21,9 @@ import * as React from 'react';
 import { translate } from 'sonar-ui-common/helpers/l10n';
 import { AlmSettingsInstance, ProjectAlmBindingResponse } from '../../../types/alm-settings';
 import Step from '../components/Step';
+import YamlFileStep from '../components/YamlFileStep';
+import AnalysisCommand from './AnalysisCommand';
 import SecretStep from './SecretStep';
-import YamlFileStep from './YamlFileStep';
 
 export enum Steps {
   CREATE_SECRET = 1,
@@ -63,7 +64,11 @@ export default function GitHubActionTutorial(props: GitHubActionTutorialProps) {
       <Step
         onOpen={() => setStep(Steps.YAML)}
         open={step === Steps.YAML}
-        renderForm={() => <YamlFileStep component={component} />}
+        renderForm={() => (
+          <YamlFileStep>
+            {buildTool => <AnalysisCommand buildTool={buildTool} component={component} />}
+          </YamlFileStep>
+        )}
         stepNumber={Steps.YAML}
         stepTitle={translate('onboarding.tutorial.with.github_action.yaml.title')}
       />
diff --git a/server/sonar-web/src/main/js/components/tutorials/github-action/YamlFileStep.tsx b/server/sonar-web/src/main/js/components/tutorials/github-action/YamlFileStep.tsx
deleted file mode 100644 (file)
index e76055a..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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 AllSet from '../components/AllSet';
-import RenderOptions from '../components/RenderOptions';
-import { BuildTools } from '../types';
-import AnalysisCommand from './AnalysisCommand';
-
-export interface YamlFileStepProps {
-  component: T.Component;
-}
-
-export default function YamlFileStep(props: YamlFileStepProps) {
-  const { component } = props;
-  const buildTools = [BuildTools.Maven, BuildTools.Gradle, BuildTools.DotNet, BuildTools.Other];
-  const [buildToolSelected, setBuildToolSelected] = React.useState<BuildTools>();
-
-  return (
-    <>
-      <ol className="list-styled big-spacer-top big-spacer-bottom">
-        <li>
-          {translate('onboarding.build')}
-
-          <RenderOptions
-            checked={buildToolSelected}
-            name="language"
-            onCheck={value => setBuildToolSelected(value as BuildTools)}
-            options={buildTools}
-            optionLabelKey="onboarding.build"
-          />
-        </li>
-        <AnalysisCommand buildTool={buildToolSelected} component={component} />
-      </ol>
-      {buildToolSelected !== undefined && (
-        <>
-          <hr className="huge-spacer-top huge-spacer-bottom" />
-          <AllSet />
-        </>
-      )}
-    </>
-  );
-}
diff --git a/server/sonar-web/src/main/js/components/tutorials/github-action/__tests__/YamlFileStep-test.tsx b/server/sonar-web/src/main/js/components/tutorials/github-action/__tests__/YamlFileStep-test.tsx
deleted file mode 100644 (file)
index 1d1f3c0..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2021 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-import { shallow } from 'enzyme';
-import * as React from 'react';
-import { mockComponent } from '../../../../helpers/testMocks';
-import YamlFileStep, { YamlFileStepProps } from '../YamlFileStep';
-
-it('should render correctly', () => {
-  expect(shallowRender()).toMatchSnapshot();
-});
-
-function shallowRender(props: Partial<YamlFileStepProps> = {}) {
-  return shallow<YamlFileStepProps>(<YamlFileStep component={mockComponent()} {...props} />);
-}
diff --git a/server/sonar-web/src/main/js/components/tutorials/github-action/__tests__/__snapshots__/YamlFileStep-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/github-action/__tests__/__snapshots__/YamlFileStep-test.tsx.snap
deleted file mode 100644 (file)
index 8f3bfa8..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly 1`] = `
-<Fragment>
-  <ol
-    className="list-styled big-spacer-top big-spacer-bottom"
-  >
-    <li>
-      onboarding.build
-      <RenderOptions
-        name="language"
-        onCheck={[Function]}
-        optionLabelKey="onboarding.build"
-        options={
-          Array [
-            "maven",
-            "gradle",
-            "dotnet",
-            "other",
-          ]
-        }
-      />
-    </li>
-    <Connect(withAppState(AnalysisCommand))
-      component={
-        Object {
-          "breadcrumbs": Array [],
-          "key": "my-project",
-          "name": "MyProject",
-          "qualifier": "TRK",
-          "qualityGate": Object {
-            "isDefault": true,
-            "key": "30",
-            "name": "Sonar way",
-          },
-          "qualityProfiles": Array [
-            Object {
-              "deleted": false,
-              "key": "my-qp",
-              "language": "ts",
-              "name": "Sonar way",
-            },
-          ],
-          "tags": Array [],
-        }
-      }
-    />
-  </ol>
-</Fragment>
-`;
diff --git a/server/sonar-web/src/main/js/components/tutorials/github-action/commands/CreateYmlFile.tsx b/server/sonar-web/src/main/js/components/tutorials/github-action/commands/CreateYmlFile.tsx
deleted file mode 100644 (file)
index e7c47ed..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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';
-
-export interface CreateYmlFileProps {
-  yamlTemplate: string;
-}
-
-export default function CreateYmlFile(props: CreateYmlFileProps) {
-  const { yamlTemplate } = props;
-  return (
-    <li className="abs-width-800">
-      <FormattedMessage
-        defaultMessage={translate('onboarding.tutorial.with.github_action.yaml.create_yml')}
-        id="onboarding.tutorial.with.github_action.yaml.create_yml"
-        values={{
-          file: (
-            <>
-              <code className="rule">.github/workflows/build.yml</code>
-              <ClipboardIconButton copyValue=".github/workflows/build.yml" />
-            </>
-          )
-        }}
-      />
-      <CodeSnippet snippet={yamlTemplate} />
-    </li>
-  );
-}
index f8a5d5edb14b0e83871d05c8133109f5255f1004..c99e812057fe6c39e0d50a3ced382fb25b78f0cb 100644 (file)
@@ -18,7 +18,7 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 import * as React from 'react';
-import CreateYmlFile from './CreateYmlFile';
+import CreateYmlFile from '../../components/CreateYmlFile';
 
 export interface DotNetProps {
   branchesEnabled?: boolean;
@@ -73,5 +73,10 @@ jobs:
 
 export default function DotNet(props: DotNetProps) {
   const { component, branchesEnabled } = props;
-  return <CreateYmlFile yamlTemplate={dotnetYamlTemplate(component.key, !!branchesEnabled)} />;
+  return (
+    <CreateYmlFile
+      yamlFileName=".github/workflows/build.yml"
+      yamlTemplate={dotnetYamlTemplate(component.key, !!branchesEnabled)}
+    />
+  );
 }
index 6f3d323f13f3b8b1b5bd836af1d485f4c95d6e81..42cffc2d98c2388b86e83fbfb752cf62f6fc9a0a 100644 (file)
@@ -22,8 +22,8 @@ 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 CreateYmlFile from '../../components/CreateYmlFile';
 import { buildGradleSnippet } from '../../utils';
-import CreateYmlFile from './CreateYmlFile';
 
 export interface GradleProps {
   branchesEnabled?: boolean;
@@ -73,8 +73,8 @@ export default function Gradle(props: GradleProps) {
     <>
       <li className="abs-width-600">
         <FormattedMessage
-          defaultMessage={translate('onboarding.tutorial.with.github_action.yaml.gradle')}
-          id="onboarding.tutorial.with.github_action.yaml.gradle"
+          defaultMessage={translate('onboarding.tutorial.with.yaml.gradle')}
+          id="onboarding.tutorial.with.yaml.gradle"
           values={{
             gradle: (
               <>
@@ -87,7 +87,10 @@ export default function Gradle(props: GradleProps) {
         />
         <CodeSnippet snippet={buildGradleSnippet(component.key)} />
       </li>
-      <CreateYmlFile yamlTemplate={gradleYamlTemplate(!!branchesEnabled)} />
+      <CreateYmlFile
+        yamlFileName=".github/workflows/build.yml"
+        yamlTemplate={gradleYamlTemplate(!!branchesEnabled)}
+      />
     </>
   );
 }
index cbafc007bf54f78b0af415f7cdca72b6fb4d0af8..54d21e2232cc14de681219fc6bf55db69bd1fd8d 100644 (file)
@@ -22,8 +22,8 @@ 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 CreateYmlFile from '../../components/CreateYmlFile';
 import { mavenPomSnippet } from '../../utils';
-import CreateYmlFile from './CreateYmlFile';
 
 export interface JavaMavenProps {
   branchesEnabled?: boolean;
@@ -73,8 +73,8 @@ export default function JavaMaven(props: JavaMavenProps) {
     <>
       <li className="abs-width-600">
         <FormattedMessage
-          defaultMessage={translate('onboarding.tutorial.with.github_action.yaml.maven.pom')}
-          id="onboarding.tutorial.with.github_action.yaml.maven.pom"
+          defaultMessage={translate('onboarding.tutorial.with.yaml.maven.pom')}
+          id="onboarding.tutorial.with.yaml.maven.pom"
           values={{
             pom: (
               <>
@@ -86,7 +86,10 @@ export default function JavaMaven(props: JavaMavenProps) {
         />
         <CodeSnippet snippet={mavenPomSnippet(component.key)} />
       </li>
-      <CreateYmlFile yamlTemplate={mavenYamlTemplte(!!branchesEnabled)} />
+      <CreateYmlFile
+        yamlFileName=".github/workflows/build.yml"
+        yamlTemplate={mavenYamlTemplte(!!branchesEnabled)}
+      />
     </>
   );
 }
index 11320042f68cbef471c729c2e1aac39541992eb6..ea4f93e419f2ca8de75eaa6157defe9de39cf3b6 100644 (file)
@@ -18,8 +18,8 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 import * as React from 'react';
+import CreateYmlFile from '../../components/CreateYmlFile';
 import DefaultProjectKey from '../../components/DefaultProjectKey';
-import CreateYmlFile from './CreateYmlFile';
 
 export interface OthersProps {
   branchesEnabled?: boolean;
@@ -75,7 +75,10 @@ export default function Others(props: OthersProps) {
   return (
     <>
       <DefaultProjectKey component={component} />
-      <CreateYmlFile yamlTemplate={yamlTemplate(!!branchesEnabled)} />
+      <CreateYmlFile
+        yamlFileName=".github/workflows/build.yml"
+        yamlTemplate={yamlTemplate(!!branchesEnabled)}
+      />
     </>
   );
 }
diff --git a/server/sonar-web/src/main/js/components/tutorials/github-action/commands/__tests__/CreateYmlFile-test.tsx b/server/sonar-web/src/main/js/components/tutorials/github-action/commands/__tests__/CreateYmlFile-test.tsx
deleted file mode 100644 (file)
index 9dfe3cb..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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 CreateYmlFile, { CreateYmlFileProps } from '../CreateYmlFile';
-import { GradleProps } from '../Gradle';
-
-it('should render correctly', () => {
-  expect(shallowRender()).toMatchSnapshot();
-});
-
-function shallowRender(props: Partial<CreateYmlFileProps> = {}) {
-  return shallow<GradleProps>(<CreateYmlFile yamlTemplate="temaplate" {...props} />);
-}
diff --git a/server/sonar-web/src/main/js/components/tutorials/github-action/commands/__tests__/__snapshots__/CreateYmlFile-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/github-action/commands/__tests__/__snapshots__/CreateYmlFile-test.tsx.snap
deleted file mode 100644 (file)
index 61e32f7..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly 1`] = `
-<li
-  className="abs-width-800"
->
-  <FormattedMessage
-    defaultMessage="onboarding.tutorial.with.github_action.yaml.create_yml"
-    id="onboarding.tutorial.with.github_action.yaml.create_yml"
-    values={
-      Object {
-        "file": <React.Fragment>
-          <code
-            className="rule"
-          >
-            .github/workflows/build.yml
-          </code>
-          <ClipboardIconButton
-            copyValue=".github/workflows/build.yml"
-          />
-        </React.Fragment>,
-      }
-    }
-  />
-  <CodeSnippet
-    snippet="temaplate"
-  />
-</li>
-`;
index ae1bd7ae9cd85c5f74a34713ec7cc5a800202ecb..afb06fa5683bd33ea88c72880532f92d0897209c 100644 (file)
@@ -2,6 +2,7 @@
 
 exports[`should render correctly 1`] = `
 <CreateYmlFile
+  yamlFileName=".github/workflows/build.yml"
   yamlTemplate="name: Build
 on:
   push:
@@ -53,6 +54,7 @@ jobs:
 
 exports[`should render correctly: without branch enabled 1`] = `
 <CreateYmlFile
+  yamlFileName=".github/workflows/build.yml"
   yamlTemplate="name: Build
 on:
   push:
index e3ae52afb7d7f371ec764afcb19a36d12e9a06ca..f5b8f934e0abb91ad9b70bec52f819117bd7ac77 100644 (file)
@@ -6,8 +6,8 @@ exports[`should render correctly 1`] = `
     className="abs-width-600"
   >
     <FormattedMessage
-      defaultMessage="onboarding.tutorial.with.github_action.yaml.gradle"
-      id="onboarding.tutorial.with.github_action.yaml.gradle"
+      defaultMessage="onboarding.tutorial.with.yaml.gradle"
+      id="onboarding.tutorial.with.yaml.gradle"
       values={
         Object {
           "gradle": <React.Fragment>
@@ -41,6 +41,7 @@ sonarqube {
     />
   </li>
   <CreateYmlFile
+    yamlFileName=".github/workflows/build.yml"
     yamlTemplate="name: Build
 on:
   push:
@@ -88,8 +89,8 @@ exports[`should render correctly: without branch enabled 1`] = `
     className="abs-width-600"
   >
     <FormattedMessage
-      defaultMessage="onboarding.tutorial.with.github_action.yaml.gradle"
-      id="onboarding.tutorial.with.github_action.yaml.gradle"
+      defaultMessage="onboarding.tutorial.with.yaml.gradle"
+      id="onboarding.tutorial.with.yaml.gradle"
       values={
         Object {
           "gradle": <React.Fragment>
@@ -123,6 +124,7 @@ sonarqube {
     />
   </li>
   <CreateYmlFile
+    yamlFileName=".github/workflows/build.yml"
     yamlTemplate="name: Build
 on:
   push:
index 66617347189eb4fe5564b6a4fffacff548edcfdf..6aa14eb97deed0e73ba10fd3ed382061dadf73a0 100644 (file)
@@ -6,8 +6,8 @@ exports[`should render correctly 1`] = `
     className="abs-width-600"
   >
     <FormattedMessage
-      defaultMessage="onboarding.tutorial.with.github_action.yaml.maven.pom"
-      id="onboarding.tutorial.with.github_action.yaml.maven.pom"
+      defaultMessage="onboarding.tutorial.with.yaml.maven.pom"
+      id="onboarding.tutorial.with.yaml.maven.pom"
       values={
         Object {
           "pom": <React.Fragment>
@@ -30,6 +30,7 @@ exports[`should render correctly 1`] = `
     />
   </li>
   <CreateYmlFile
+    yamlFileName=".github/workflows/build.yml"
     yamlTemplate="name: Build
 on:
   push:
@@ -77,8 +78,8 @@ exports[`should render correctly: without branch enabled 1`] = `
     className="abs-width-600"
   >
     <FormattedMessage
-      defaultMessage="onboarding.tutorial.with.github_action.yaml.maven.pom"
-      id="onboarding.tutorial.with.github_action.yaml.maven.pom"
+      defaultMessage="onboarding.tutorial.with.yaml.maven.pom"
+      id="onboarding.tutorial.with.yaml.maven.pom"
       values={
         Object {
           "pom": <React.Fragment>
@@ -101,6 +102,7 @@ exports[`should render correctly: without branch enabled 1`] = `
     />
   </li>
   <CreateYmlFile
+    yamlFileName=".github/workflows/build.yml"
     yamlTemplate="name: Build
 on:
   push:
index 7fe6d432e9c308519f3a5f042e2feffa7513195f..1f02cbc2cc75c88bffdbce12ac4967b1ed171c18 100644 (file)
@@ -27,6 +27,7 @@ exports[`should render correctly 1`] = `
     }
   />
   <CreateYmlFile
+    yamlFileName=".github/workflows/build.yml"
     yamlTemplate="name: Build
 on:
   push:
@@ -85,6 +86,7 @@ exports[`should render correctly: without branch enabled 1`] = `
     }
   />
   <CreateYmlFile
+    yamlFileName=".github/workflows/build.yml"
     yamlTemplate="name: Build
 on:
   push:
index ddfe8881ade76b60d75b8933c6bcbd25071e0c7a..364d8886ab5f7851d1f78f301bbf7e7e36a06233 100644 (file)
@@ -20,6 +20,7 @@
 export enum TutorialModes {
   Manual = 'manual',
   Jenkins = 'jenkins',
+  BitbucketPipelines = 'bitbucket-pipelines',
   GitLabCI = 'gitlab-ci',
   GitHubActions = 'github-actions',
   AzurePipelines = 'azure-pipelines'
index b3b866fde7be6456709923aca7801084d2a71921..774264c96a99b62b9b88a4ba3fc8a824412779f6 100644 (file)
@@ -3435,6 +3435,24 @@ onboarding.tutorial.choose_method.jenkins=With Jenkins
 onboarding.tutorial.choose_method.github_action=With GitHub Actions
 onboarding.tutorial.choose_method.gitlab_ci=With GitLab CI
 onboarding.tutorial.choose_method.azure_pipelines=With Azure Pipelines
+onboarding.tutorial.choose_method.bitbucket_pipelines=With Bitbucket Pipelines
+
+
+onboarding.tutorial.with.yaml.maven.pom=Update your {pom} file with the following properties:
+onboarding.tutorial.with.yaml.gradle=Update your {gradle} file with the {sq} plugin and it's configuration:
+
+
+
+onboarding.tutorial.with.bitbucket_pipelines.create_secret.title=Create repository variables
+onboarding.tutorial.with.bitbucket_pipelines.yaml.title=Create your pipelines builds configuration
+onboarding.tutorial.with.bitbucket_pipelines.variables.intro=In your Bitbucket repository, go to {repository_variables} and create two new variables:
+onboarding.tutorial.with.bitbucket_pipelines.variables.intro.link=Repository settings > Repository variables
+onboarding.tutorial.with.bitbucket_pipelines.variables.name.sentence=In the {name} field, enter
+onboarding.tutorial.with.bitbucket_pipelines.variables.name.sentence.name=Name
+onboarding.tutorial.with.bitbucket_pipelines.variables.add.sentence=Click on {add}
+onboarding.tutorial.with.bitbucket_pipelines.variables.add.sentence.add=Add
+onboarding.tutorial.with.bitbucket_pipelines.variables.secured.sentence=Make sure {secured} is check
+onboarding.tutorial.with.bitbucket_pipelines.variables.secured.sentence.secured=Secured
 
 onboarding.tutorial.with.github_action.create_secret.title=Create GitHub Secrets
 onboarding.tutorial.with.github_action.secret.intro=In your GitHub repository, go to {settings_secret} and create two new secrets:
@@ -3447,9 +3465,6 @@ onboarding.tutorial.with.github_action.secret.add.sentence=Click on {add_secret}
 onboarding.tutorial.with.github_action.secret.add.sentence.add_secret=Add secret
 onboarding.tutorial.with.github_action.yaml.title=Create Workflow YAML File
 onboarding.tutorial.with.github_action.yaml.create_yml=Create or update your {file} YAML file with the following content:
-onboarding.tutorial.with.github_action.yaml.maven.pom=Update your {pom} file with the following properties:
-onboarding.tutorial.with.github_action.yaml.gradle=Update your {gradle} file with the {sq} plugin and it's configuration:
-
 
 onboarding.tutorial.with.gitlab_ci.title=Analyze your project with GitLab CI
 onboarding.tutorial.with.gitlab_ci.unsupported=This tutorial is only available for projects bound to GitLab.