]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-23112 Add tutorials for Dart
authorEvgeny Mandrikov <138671+Godin@users.noreply.github.com>
Wed, 25 Sep 2024 19:34:08 +0000 (21:34 +0200)
committersonartech <sonartech@sonarsource.com>
Wed, 25 Sep 2024 20:02:55 +0000 (20:02 +0000)
26 files changed:
server/sonar-web/src/main/js/components/tutorials/azure-pipelines/__tests__/AzurePipelinesTutorial-it.tsx
server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/AnalysisCommand.tsx
server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/AnalysisCommand.tsx
server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/PreambuleYaml.tsx
server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/__tests__/BitbucketPipelinesTutorial-it.tsx
server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/__tests__/__snapshots__/BitbucketPipelinesTutorial-it.tsx.snap
server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/commands/Dart.ts [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/github-action/AnalysisCommand.tsx
server/sonar-web/src/main/js/components/tutorials/github-action/__tests__/GithubActionTutorial-it.tsx
server/sonar-web/src/main/js/components/tutorials/github-action/__tests__/__snapshots__/GithubActionTutorial-it.tsx.snap
server/sonar-web/src/main/js/components/tutorials/github-action/commands/Dart.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/gitlabci/YmlFileStep.tsx
server/sonar-web/src/main/js/components/tutorials/gitlabci/__tests__/GitLabCITutorial-it.tsx
server/sonar-web/src/main/js/components/tutorials/gitlabci/__tests__/__snapshots__/GitLabCITutorial-it.tsx.snap
server/sonar-web/src/main/js/components/tutorials/gitlabci/commands/PipeCommand.tsx
server/sonar-web/src/main/js/components/tutorials/jenkins/JenkinsStep.tsx
server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/JenkinsTutorial-it.tsx
server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/JenkinsTutorial-it.tsx.snap
server/sonar-web/src/main/js/components/tutorials/other/BuildToolForm.tsx
server/sonar-web/src/main/js/components/tutorials/other/__tests__/OtherTutorial-it.tsx
server/sonar-web/src/main/js/components/tutorials/other/__tests__/__snapshots__/OtherTutorial-it.tsx.snap
server/sonar-web/src/main/js/components/tutorials/other/commands/AnalysisCommand.tsx
server/sonar-web/src/main/js/components/tutorials/test-utils.ts
server/sonar-web/src/main/js/components/tutorials/types.ts
server/sonar-web/src/main/js/components/tutorials/utils.ts
sonar-core/src/main/resources/org/sonar/l10n/core.properties

index bdb521f43ec402d9c6f97c3e322d51158c7bd787..13b851236a720acdaea17d64cc98f9b303287ae8 100644 (file)
@@ -117,6 +117,10 @@ it('should render correctly and allow token generation', async () => {
   await user.click(getTutorialBuildButtons().macosButton.get());
   assertObjCStepIsCorrectlyRendered(OSs.MacOS);
 
+  // Analysis step: Dart
+  await user.click(getTutorialBuildButtons().dartBuildButton.get());
+  assertOtherStepIsCorrectlyRendered();
+
   // Analysis step: Other
   await user.click(getTutorialBuildButtons().otherBuildButton.get());
   assertOtherStepIsCorrectlyRendered();
index 32d77e59a0359e58e362a0e5d3cfb55de6494216..b28e92c5cc08647add7d738e10b30356eb997e49 100644 (file)
@@ -53,6 +53,7 @@ export default function AnalysisCommand(props: AnalysisCommandProps) {
     case BuildTools.ObjectiveC:
       return <ClangGCC config={config} projectKey={projectKey} />;
 
+    case BuildTools.Dart:
     case BuildTools.Other:
       return <Other projectKey={projectKey} />;
 
index fa956930e0bfdab3e1208c3065e23ca13e0cf858..bc0bfade9c94bc02b8b18a4b0ecfcf92957a1633 100644 (file)
@@ -30,6 +30,7 @@ import { Arch, BuildTools, TutorialConfig } from '../types';
 import { isCFamily } from '../utils';
 import { PreambuleYaml } from './PreambuleYaml';
 import cFamilyExample from './commands/CFamily';
+import dartExample from './commands/Dart';
 import dotNetExample from './commands/DotNet';
 import gradleExample from './commands/Gradle';
 import mavenExample from './commands/Maven';
@@ -57,6 +58,7 @@ const YamlTemplate: Dictionary<BuildToolExampleBuilder> = {
   [BuildTools.DotNet]: dotNetExample,
   [BuildTools.Cpp]: cFamilyExample,
   [BuildTools.ObjectiveC]: cFamilyExample,
+  [BuildTools.Dart]: dartExample,
   [BuildTools.Other]: othersExample,
 };
 
index 83222ccbe612fdb27f6bcff4dba09b548da9c644..c8d40198f578e3adbf0313c1901257226a284d58 100644 (file)
@@ -35,6 +35,7 @@ export function PreambuleYaml(props: PreambuleYamlProps) {
       return <GradleBuild component={component} />;
     case BuildTools.Cpp:
     case BuildTools.ObjectiveC:
+    case BuildTools.Dart:
     case BuildTools.Other:
       return <DefaultProjectKey component={component} />;
     default:
index 5efadd4646c56c74e3d83f0fa979d11314413d53..54ecf78154a08c89a15b650fd3ec32b3309d5317 100644 (file)
@@ -128,6 +128,11 @@ it('should follow and complete all steps', async () => {
     'C++ (manual arm64) and Objective-C: sonar-project.properties',
   );
 
+  // Dart
+  await user.click(ui.dartBuildButton.get());
+  expect(getCopyToClipboardValue(0, 'Copy')).toMatchSnapshot('Dart: sonar-project.properties');
+  expect(getCopyToClipboardValue(1, 'Copy')).toMatchSnapshot('Dart: bitbucket-pipelines.yml');
+
   // Other
   await user.click(ui.otherBuildButton.get());
   expect(getCopyToClipboardValue(0, 'Copy')).toMatchSnapshot(
index 8652ad9cb4109f534f4f218695f2097ceeea193f..47fabb0cee7872a368a464fc8a3ceb3543a2f3c3 100644 (file)
@@ -1,5 +1,38 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
+exports[`should follow and complete all steps: Dart: sonar-project.properties 1`] = `"sonar.projectKey=my-project"`;
+
+exports[`should follow and complete all steps: Dart: bitbucket-pipelines.yml 1`] = `
+"image: ghcr.io/cirruslabs/flutter:stable
+
+definitions:
+  steps:
+    - step: &build-step
+        name: Build the project, and run the SonarQube analysis
+        script:
+          - <commands to build your project>
+          - export SONAR_SCANNER_VERSION=6.1.0.4477
+          - mkdir $HOME/.sonar
+          - curl -sSLo $HOME/.sonar/sonar-scanner.zip https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-\${SONAR_SCANNER_VERSION}-linux-x64.zip
+          - unzip -o $HOME/.sonar/sonar-scanner.zip -d $HOME/.sonar/
+          - export PATH="$PATH:$HOME/.sonar/sonar-scanner-\${SONAR_SCANNER_VERSION}-linux-x64/bin"
+          - sonar-scanner
+  caches:
+    sonar: ~/.sonar
+
+clone:
+  depth: full
+
+pipelines:
+  branches:
+    '{main}':
+      - step: *build-step
+
+  pull-requests:
+    '**':
+      - step: *build-step"
+`;
+
 exports[`should follow and complete all steps: .NET: bitbucket-pipelines.yml 1`] = `
 "image: mcr.microsoft.com/dotnet/sdk:7.0
 
diff --git a/server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/commands/Dart.ts b/server/sonar-web/src/main/js/components/tutorials/bitbucket-pipelines/commands/Dart.ts
new file mode 100644 (file)
index 0000000..3bb69f1
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 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 { Arch, OSs } from '../../types';
+import { SONAR_SCANNER_CLI_LATEST_VERSION, getScannerUrlSuffix } from '../../utils';
+import { BuildToolExampleBuilder } from '../AnalysisCommand';
+
+const dartExample: BuildToolExampleBuilder = ({ branchesEnabled, mainBranchName }) => {
+  const scannerSuffix = getScannerUrlSuffix(OSs.Linux, Arch.X86_64);
+  return `image: ghcr.io/cirruslabs/flutter:stable
+
+definitions:
+  steps:
+    - step: &build-step
+        name: Build the project, and run the SonarQube analysis
+        script:
+          - <commands to build your project>
+          - export SONAR_SCANNER_VERSION=${SONAR_SCANNER_CLI_LATEST_VERSION}
+          - mkdir $HOME/.sonar
+          - curl -sSLo $HOME/.sonar/sonar-scanner.zip https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-\${SONAR_SCANNER_VERSION}${scannerSuffix}.zip
+          - unzip -o $HOME/.sonar/sonar-scanner.zip -d $HOME/.sonar/
+          - export PATH="$PATH:$HOME/.sonar/sonar-scanner-\${SONAR_SCANNER_VERSION}${scannerSuffix}/bin"
+          - sonar-scanner
+  caches:
+    sonar: ~/.sonar
+
+clone:
+  depth: full
+
+pipelines:
+  branches:
+    '{${mainBranchName}}':
+      - step: *build-step
+${
+  branchesEnabled
+    ? `
+  pull-requests:
+    '**':
+      - step: *build-step`
+    : ''
+}`;
+};
+
+export default dartExample;
index f58f9d0bae9dc57767af500011b3bf8c2ea5ad84..ddcfe5975642da47bc7e7a7de2e0dfc0097f1fc8 100644 (file)
@@ -25,6 +25,7 @@ import { Feature } from '../../../types/features';
 import { Component } from '../../../types/types';
 import { BuildTools, TutorialConfig } from '../types';
 import CFamily from './commands/CFamily';
+import Dart from './commands/Dart';
 import DotNet from './commands/DotNet';
 import Gradle from './commands/Gradle';
 import JavaMaven from './commands/JavaMaven';
@@ -80,6 +81,15 @@ export function AnalysisCommand(props: Readonly<AnalysisCommandProps>) {
           component={component}
         />
       );
+    case BuildTools.Dart:
+      return (
+        <Dart
+          branchesEnabled={branchSupportEnabled}
+          mainBranchName={mainBranchName}
+          monorepo={monorepo}
+          component={component}
+        />
+      );
     case BuildTools.Other:
       return (
         <Others
index e6553192e9f8a8479f12dce6bd40f0aff4c7cdf7..562ef915d5ebee7e15127705fbf9acef7185ba8d 100644 (file)
@@ -136,6 +136,10 @@ it('should follow and complete all steps', async () => {
     'Objective-C MacOS: .github/workflows/build.yml',
   );
 
+  // Dart
+  await user.click(ui.dartBuildButton.get());
+  expect(getCopyToClipboardValue(0, 'Copy')).toMatchSnapshot('Dart: .github/workflows/build.yml');
+
   // Other
   await user.click(ui.otherBuildButton.get());
   expect(getCopyToClipboardValue(0, 'Copy')).toMatchSnapshot(
index 98d789f4c4aeaa8cec9dc0fd3d0a42b392e8ebf4..90daec9363afd30e0230e740fca145ea303c6f98 100644 (file)
@@ -1,5 +1,35 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
+exports[`should follow and complete all steps: Dart: .github/workflows/build.yml 1`] = `
+"
+name: Build
+
+on:
+  push:
+    branches:
+      - main
+  pull_request:
+    types: [opened, synchronize, reopened]
+
+jobs:
+  build:
+    name: Build and analyze
+    runs-on: ubuntu-latest
+    steps:
+      - <commands to build your project>
+      - name: Download sonar-scanner
+        run: |
+          curl --create-dirs -sSLo $HOME/.sonar/sonar-scanner.zip https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-6.1.0.4477-linux-x64.zip
+          unzip $HOME/.sonar/sonar-scanner.zip -o -d $HOME/.sonar/
+      - name: Run sonar-scanner
+        env:
+          SONAR_TOKEN: \${{ secrets.SONAR_TOKEN }}
+          SONAR_HOST_URL: \${{ secrets.SONAR_HOST_URL }}
+        run: |
+          sonar-scanner-6.1.0.4477-linux-x64/bin/sonar-scanner \\
+            -Dsonar.projectKey=my-project"
+`;
+
 exports[`should follow and complete all steps: .NET: .github/workflows/build.yml 1`] = `
 "name: Build
 
diff --git a/server/sonar-web/src/main/js/components/tutorials/github-action/commands/Dart.tsx b/server/sonar-web/src/main/js/components/tutorials/github-action/commands/Dart.tsx
new file mode 100644 (file)
index 0000000..44c989c
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 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 { CodeSnippet, Link, NumberedListItem } from 'design-system';
+import * as React from 'react';
+import { FormattedMessage } from 'react-intl';
+import { DocLink } from '../../../../helpers/doc-links';
+import { useDocUrl } from '../../../../helpers/docs';
+import { translate } from '../../../../helpers/l10n';
+import { Component } from '../../../../types/types';
+import MonorepoDocLinkFallback from './MonorepoDocLinkFallback';
+
+export interface DartProps {
+  branchesEnabled?: boolean;
+  component: Component;
+  mainBranchName: string;
+  monorepo?: boolean;
+}
+
+export default function Dart(props: Readonly<DartProps>) {
+  const { component, branchesEnabled, mainBranchName, monorepo } = props;
+  const docUrl = useDocUrl(DocLink.SonarScanner);
+
+  if (monorepo) {
+    return <MonorepoDocLinkFallback />;
+  }
+
+  return (
+    <NumberedListItem>
+      <FormattedMessage
+        defaultMessage={translate('onboarding.tutorial.with.github_action.dart')}
+        id="onboarding.tutorial.with.github_action.dart"
+      />
+      <CodeSnippet
+        className="sw-p-6 sw-overflow-auto"
+        snippet={`
+name: Build
+
+on:
+  push:
+    branches:
+      - ${mainBranchName}
+${branchesEnabled ? '  pull_request:\n    types: [opened, synchronize, reopened]' : ''}
+
+jobs:
+  build:
+    name: Build and analyze
+    runs-on: ubuntu-latest
+    steps:
+      - <commands to build your project>
+      - name: Download sonar-scanner
+        run: |
+          curl --create-dirs -sSLo $HOME/.sonar/sonar-scanner.zip https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-6.1.0.4477-linux-x64.zip
+          unzip $HOME/.sonar/sonar-scanner.zip -o -d $HOME/.sonar/
+      - name: Run sonar-scanner
+        env:
+          SONAR_TOKEN: \${{ secrets.SONAR_TOKEN }}
+          SONAR_HOST_URL: \${{ secrets.SONAR_HOST_URL }}
+        run: |
+          sonar-scanner-6.1.0.4477-linux-x64/bin/sonar-scanner \\
+            -Dsonar.projectKey=${component.key}`}
+        language="yml"
+      />
+
+      <p className="sw-mt-4">
+        <FormattedMessage
+          defaultMessage={translate('onboarding.analysis.sq_scanner.docs')}
+          id="onboarding.analysis.sq_scanner.docs"
+          values={{
+            link: <Link to={docUrl}>{translate('onboarding.analysis.sq_scanner.docs_link')}</Link>,
+          }}
+        />
+      </p>
+    </NumberedListItem>
+  );
+}
index 992c09c3ca70f78e641671e3f1b41c50c3a3ae8f..6ca29e6a79300c9d712ac771c16d253f09bf747d 100644 (file)
@@ -92,6 +92,7 @@ const snippetForBuildTool = {
   [BuildTools.ObjectiveC]: otherSnippet,
   [BuildTools.Gradle]: gradleSnippet,
   [BuildTools.Maven]: mavenSnippet,
+  [BuildTools.Dart]: otherSnippet,
   [BuildTools.Other]: otherSnippet,
 };
 
@@ -100,6 +101,7 @@ const filenameForBuildTool = {
   [BuildTools.ObjectiveC]: 'sonar-project.properties',
   [BuildTools.Gradle]: GradleBuildDSL.Groovy,
   [BuildTools.Maven]: 'pom.xml',
+  [BuildTools.Dart]: 'sonar-project.properties',
   [BuildTools.Other]: 'sonar-project.properties',
 };
 
@@ -108,6 +110,7 @@ const snippetLanguageForBuildTool = {
   [BuildTools.ObjectiveC]: undefined,
   [BuildTools.Gradle]: undefined,
   [BuildTools.Maven]: 'xml',
+  [BuildTools.Dart]: undefined,
   [BuildTools.Other]: undefined,
 };
 
index 6ac323f6d0cc26e8db6ffbcb378d43506efddb79..26fec42cb080a8d3ac90ff44a9a46ece9c52d8ee 100644 (file)
@@ -88,6 +88,11 @@ it('should follow and complete all steps', async () => {
   await user.click(ui.autoConfigManual.get());
   expect(getCopyToClipboardValue(1, 'Copy')).toMatchSnapshot('CPP - manual: gitlab-ci.yml');
 
+  // Dart
+  await user.click(ui.dartBuildButton.get());
+  expect(getCopyToClipboardValue(0, 'Copy')).toMatchSnapshot('Dart: sonar-project.properties');
+  expect(getCopyToClipboardValue(1, 'Copy')).toMatchSnapshot('Dart: gitlab-ci.yml');
+
   // Other
   await user.click(ui.otherBuildButton.get());
   expect(getCopyToClipboardValue(0, 'Copy')).toMatchSnapshot('Other: sonar-project.properties');
index c2e41a10cbc2f54b4a4d01fa73b5a78c29a32a45..0dcb01b15f398749b2d41e49204ecb3cd1cd7e9e 100644 (file)
@@ -186,6 +186,74 @@ sonar.qualitygate.wait=true
 "
 `;
 
+exports[`should follow and complete all steps: Dart: gitlab-ci.yml 1`] = `
+"image: ghcr.io/cirruslabs/flutter:stable
+
+variables:
+  SONAR_USER_HOME: "\${CI_PROJECT_DIR}/.sonar"  # Defines the location of the analysis task cache
+  GIT_DEPTH: "0"  # Tells git to fetch all the branches of the project, required by the analysis task
+
+stages:
+  - get-binaries
+  - sonarqube-check
+  - sonarqube-vulnerability-report
+
+get-binaries:
+  stage: get-binaries
+  cache:
+    policy: push
+    key: "\${CI_COMMIT_SHORT_SHA}"
+    paths:
+      - sonar-scanner/
+      
+  script:
+    # Download sonar-scanner
+    - curl -sSLo ./sonar-scanner.zip 'https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-6.1.0.4477-linux-x64.zip'
+    - unzip -o sonar-scanner.zip
+    - mv sonar-scanner-6.1.0.4477-linux-x64 sonar-scanner
+    
+  rules:
+    - if: $CI_PIPELINE_SOURCE == 'merge_request_event'
+    - if: $CI_COMMIT_BRANCH == 'master'
+    - if: $CI_COMMIT_BRANCH == 'main'
+    - if: $CI_COMMIT_BRANCH == 'develop'
+
+sonarqube-check:
+  stage: sonarqube-check
+  
+  script: 
+    - <commands to build your project>
+    - sonar-scanner/bin/sonar-scanner --define sonar.host.url="\${SONAR_HOST_URL}"
+  allow_failure: true
+  rules:
+    - if: $CI_PIPELINE_SOURCE == 'merge_request_event'
+    - if: $CI_COMMIT_BRANCH == 'master'
+    - if: $CI_COMMIT_BRANCH == 'main'
+    - if: $CI_COMMIT_BRANCH == 'develop'
+
+sonarqube-vulnerability-report:
+  stage: sonarqube-vulnerability-report
+  script:
+    - 'curl -u "\${SONAR_TOKEN}:" "\${SONAR_HOST_URL}/api/issues/gitlab_sast_export?projectKey=my-project&branch=\${CI_COMMIT_BRANCH}&pullRequest=\${CI_MERGE_REQUEST_IID}" -o gl-sast-sonar-report.json'
+  allow_failure: true
+  rules:
+    - if: $CI_PIPELINE_SOURCE == 'merge_request_event'
+    - if: $CI_COMMIT_BRANCH == 'master'
+    - if: $CI_COMMIT_BRANCH == 'main'
+    - if: $CI_COMMIT_BRANCH == 'develop'
+  artifacts:
+    expire_in: 1 day
+    reports:
+      sast: gl-sast-sonar-report.json
+"
+`;
+
+exports[`should follow and complete all steps: Dart: sonar-project.properties 1`] = `
+"sonar.projectKey=my-project
+sonar.qualitygate.wait=true
+"
+`;
+
 exports[`should follow and complete all steps: Gradle: gitlab-ci.yml 1`] = `
 "image: gradle:8.2.0-jdk17-jammy
 
index 0e819d263f708a6aeb44d894a782272926a2ed19..2276988966c65349eb8cb09cabc99dc1cb2a1a98 100644 (file)
@@ -79,6 +79,12 @@ const BUILD_TOOL_SPECIFIC: {
       `sonar-scanner/bin/sonar-scanner --define sonar.host.url="\${SONAR_HOST_URL}" ` +
       `--define sonar.cfamily.compile-commands="\${BUILD_WRAPPER_OUT_DIR}/compile_commands.json"`,
   },
+  [BuildTools.Dart]: {
+    image: 'ghcr.io/cirruslabs/flutter:stable',
+    script: () => `
+    - <commands to build your project>
+    - sonar-scanner/bin/sonar-scanner --define sonar.host.url="\${SONAR_HOST_URL}"`,
+  },
   [BuildTools.Other]: {
     image: `
     name: sonarsource/sonar-scanner-cli:latest
@@ -187,7 +193,7 @@ export default function PipeCommand(props: Readonly<PipeCommandProps>) {
     stageDeclaration = ['sonarqube-check', ...stageDeclaration];
   }
 
-  if (isCFamily(buildTool)) {
+  if (isCFamily(buildTool) || buildTool === BuildTools.Dart) {
     stages = [getBinaries, ...stages];
     stageDeclaration = ['get-binaries', ...stageDeclaration];
   }
index 87ca0994688ad1cf5c3bb06c2f59ad7c81add4c3..079af4ae8493703f173c509d8b01d7a5af596d10 100644 (file)
@@ -38,6 +38,7 @@ const BUILDTOOL_COMPONENT_MAP: {
   [BuildTools.DotNet]: DotNet,
   [BuildTools.Cpp]: CFamily,
   [BuildTools.ObjectiveC]: CFamily,
+  [BuildTools.Dart]: Other,
   [BuildTools.Other]: Other,
 };
 
index 98dcb166e66140a31f956b8b84e097295fcf31f7..61ccedae4bd34965014a9312f3b886d2e4913f1d 100644 (file)
@@ -183,6 +183,11 @@ it.each([AlmKeys.BitbucketCloud, AlmKeys.BitbucketServer, AlmKeys.GitHub, AlmKey
     await user.click(ui.macosButton.get());
     expect(getCopyToClipboardValue(3, 'Copy')).toMatchSnapshot(`objectivec: macos jenkinsfile`);
 
+    // Dart
+    await user.click(ui.dartBuildButton.get());
+    expect(getCopyToClipboardValue(2, 'Copy')).toMatchSnapshot(`Dart: sonar-project.properties`);
+    expect(getCopyToClipboardValue(3, 'Copy')).toMatchSnapshot(`Dart: jenkinsfile`);
+
     // Other
     await user.click(ui.otherBuildButton.get());
     expect(getCopyToClipboardValue(2, 'Copy')).toMatchSnapshot(
index cb6312f809af89f09321b176a813644ac8f5c493..a0688444fe32d611b8f9b4e2895f3f7ceb9d922d 100644 (file)
@@ -1,5 +1,21 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
+exports[`bitbucket: can select devops platform and complete all the steps with copying code snippets: Dart: jenkinsfile 1`] = `
+"node {
+  stage('SCM') {
+    checkout scm
+  }
+  stage('SonarQube Analysis') {
+    def scannerHome = tool 'SonarScanner';
+    withSonarQubeEnv() {
+      sh "\${scannerHome}/bin/sonar-scanner"
+    }
+  }
+}"
+`;
+
+exports[`bitbucket: can select devops platform and complete all the steps with copying code snippets: Dart: sonar-project.properties 1`] = `"sonar.projectKey=my-project"`;
+
 exports[`bitbucket: can select devops platform and complete all the steps with copying code snippets: Groovy: build.gradle file 1`] = `
 "plugins {
   id "org.sonarqube" version "5.0.0.4638"
@@ -349,6 +365,22 @@ exports[`bitbucket: can select devops platform and complete all the steps with c
 "
 `;
 
+exports[`bitbucketcloud: can select devops platform and complete all the steps with copying code snippets: Dart: jenkinsfile 1`] = `
+"node {
+  stage('SCM') {
+    checkout scm
+  }
+  stage('SonarQube Analysis') {
+    def scannerHome = tool 'SonarScanner';
+    withSonarQubeEnv() {
+      sh "\${scannerHome}/bin/sonar-scanner"
+    }
+  }
+}"
+`;
+
+exports[`bitbucketcloud: can select devops platform and complete all the steps with copying code snippets: Dart: sonar-project.properties 1`] = `"sonar.projectKey=my-project"`;
+
 exports[`bitbucketcloud: can select devops platform and complete all the steps with copying code snippets: Groovy: build.gradle file 1`] = `
 "plugins {
   id "org.sonarqube" version "5.0.0.4638"
@@ -698,6 +730,22 @@ exports[`bitbucketcloud: can select devops platform and complete all the steps w
 "
 `;
 
+exports[`github: can select devops platform and complete all the steps with copying code snippets: Dart: jenkinsfile 1`] = `
+"node {
+  stage('SCM') {
+    checkout scm
+  }
+  stage('SonarQube Analysis') {
+    def scannerHome = tool 'SonarScanner';
+    withSonarQubeEnv() {
+      sh "\${scannerHome}/bin/sonar-scanner"
+    }
+  }
+}"
+`;
+
+exports[`github: can select devops platform and complete all the steps with copying code snippets: Dart: sonar-project.properties 1`] = `"sonar.projectKey=my-project"`;
+
 exports[`github: can select devops platform and complete all the steps with copying code snippets: Groovy: build.gradle file 1`] = `
 "plugins {
   id "org.sonarqube" version "5.0.0.4638"
@@ -1047,6 +1095,22 @@ exports[`github: can select devops platform and complete all the steps with copy
 "
 `;
 
+exports[`gitlab: can select devops platform and complete all the steps with copying code snippets: Dart: jenkinsfile 1`] = `
+"node {
+  stage('SCM') {
+    checkout scm
+  }
+  stage('SonarQube Analysis') {
+    def scannerHome = tool 'SonarScanner';
+    withSonarQubeEnv() {
+      sh "\${scannerHome}/bin/sonar-scanner"
+    }
+  }
+}"
+`;
+
+exports[`gitlab: can select devops platform and complete all the steps with copying code snippets: Dart: sonar-project.properties 1`] = `"sonar.projectKey=my-project"`;
+
 exports[`gitlab: can select devops platform and complete all the steps with copying code snippets: Groovy: build.gradle file 1`] = `
 "plugins {
   id "org.sonarqube" version "5.0.0.4638"
index 78d5bbf5531c2035670e117b494bdc108d2eac72..3cc9278e81860328b3e16a1a65b9b30cf0033180 100644 (file)
@@ -43,6 +43,7 @@ export function BuildToolForm(props: Readonly<Props>) {
   function handleConfigChange(newConfig: TutorialConfig) {
     const selectOsByDefault = (newConfig.buildTool === BuildTools.Cpp ||
       newConfig.buildTool === BuildTools.ObjectiveC ||
+      newConfig.buildTool === BuildTools.Dart ||
       newConfig.buildTool === BuildTools.Other) && {
       os: OSs.Linux,
     };
@@ -65,6 +66,7 @@ export function BuildToolForm(props: Readonly<Props>) {
         />
       )}
       {(config.buildTool === BuildTools.Other ||
+        config.buildTool === BuildTools.Dart ||
         config.buildTool === BuildTools.Cpp ||
         config.buildTool === BuildTools.ObjectiveC) && (
         <RenderOptions
index f99d456c3c8369e3774192a2b10474547988f7b2..905eb73b915add26a5322e77a93d10c5ff64c304 100644 (file)
@@ -259,6 +259,22 @@ it('can choose build tools and copy provided settings', async () => {
   );
   expect(getCopyToClipboardValue(3, 'Copy')).toMatchSnapshot('objective-c macos: execute scanner');
 
+  // Dart - Linux
+  await user.click(ui.dartBuildButton.get());
+  await user.click(ui.linuxButton.get());
+  expect(getCopyToClipboardValue(0, 'Copy')).toMatchSnapshot('Dart linux: download scanner');
+  expect(getCopyToClipboardValue(1, 'Copy')).toMatchSnapshot('Dart linux: execute scanner');
+
+  // Dart - Windows
+  await user.click(ui.windowsButton.get());
+  expect(getCopyToClipboardValue(0, 'Copy')).toMatchSnapshot('Dart windows: download scanner');
+  expect(getCopyToClipboardValue(1, 'Copy')).toMatchSnapshot('Dart windows: execute scanner');
+
+  // Dart - MacOS
+  await user.click(ui.macosButton.get());
+  expect(getCopyToClipboardValue(0, 'Copy')).toMatchSnapshot('Dart macos: download scanner');
+  expect(getCopyToClipboardValue(1, 'Copy')).toMatchSnapshot('Dart macos: execute scanner');
+
   // Other - Linux
   await user.click(ui.otherBuildButton.get());
   await user.click(ui.linuxButton.get());
index fce78d03bc7b8ff9d42423f1571e1c0d7d11c73c..c82a688c22cf36a4ab595fd44dae9c0203476dc8 100644 (file)
@@ -1,5 +1,56 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
+exports[`can choose build tools and copy provided settings: Dart linux: download scanner 1`] = `
+"export SONAR_SCANNER_VERSION=6.1.0.4477
+export SONAR_SCANNER_HOME=$HOME/.sonar/sonar-scanner-$SONAR_SCANNER_VERSION-linux-x64
+curl --create-dirs -sSLo $HOME/.sonar/sonar-scanner.zip https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-$SONAR_SCANNER_VERSION-linux-x64.zip
+unzip -o $HOME/.sonar/sonar-scanner.zip -d $HOME/.sonar/
+export PATH=$SONAR_SCANNER_HOME/bin:$PATH
+export SONAR_SCANNER_OPTS="-server"
+"
+`;
+
+exports[`can choose build tools and copy provided settings: Dart linux: execute scanner 1`] = `
+"sonar-scanner \\
+  -Dsonar.projectKey=my-project \\
+  -Dsonar.sources=. \\
+  -Dsonar.host.url=http://localhost:9000"
+`;
+
+exports[`can choose build tools and copy provided settings: Dart windows: download scanner 1`] = `
+"$env:SONAR_SCANNER_VERSION = "6.1.0.4477"
+$env:SONAR_DIRECTORY = [System.IO.Path]::Combine($(get-location).Path,".sonar")
+$env:SONAR_SCANNER_HOME = "$env:SONAR_DIRECTORY/sonar-scanner-$env:SONAR_SCANNER_VERSION-windows-x64"
+rm $env:SONAR_SCANNER_HOME -Force -Recurse -ErrorAction SilentlyContinue
+New-Item -path $env:SONAR_SCANNER_HOME -type directory
+(New-Object System.Net.WebClient).DownloadFile("https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-$env:SONAR_SCANNER_VERSION-windows-x64.zip", "$env:SONAR_DIRECTORY/sonar-scanner.zip")
+Add-Type -AssemblyName System.IO.Compression.FileSystem
+[System.IO.Compression.ZipFile]::ExtractToDirectory("$env:SONAR_DIRECTORY/sonar-scanner.zip", "$env:SONAR_DIRECTORY")
+rm ./.sonar/sonar-scanner.zip -Force -ErrorAction SilentlyContinue
+$env:Path += ";$env:SONAR_SCANNER_HOME/bin"
+$env:SONAR_SCANNER_OPTS="-server"
+"
+`;
+
+exports[`can choose build tools and copy provided settings: Dart windows: execute scanner 1`] = `"sonar-scanner.bat -D"sonar.projectKey=my-project" -D"sonar.sources=." -D"sonar.host.url=http://localhost:9000""`;
+
+exports[`can choose build tools and copy provided settings: Dart macos: download scanner 1`] = `
+"export SONAR_SCANNER_VERSION=6.1.0.4477
+export SONAR_SCANNER_HOME=$HOME/.sonar/sonar-scanner-$SONAR_SCANNER_VERSION-macosx-x64
+curl --create-dirs -sSLo $HOME/.sonar/sonar-scanner.zip https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-$SONAR_SCANNER_VERSION-macosx-x64.zip
+unzip -o $HOME/.sonar/sonar-scanner.zip -d $HOME/.sonar/
+export PATH=$SONAR_SCANNER_HOME/bin:$PATH
+export SONAR_SCANNER_OPTS="-server"
+"
+`;
+
+exports[`can choose build tools and copy provided settings: Dart macos: execute scanner 1`] = `
+"sonar-scanner \\
+  -Dsonar.projectKey=my-project \\
+  -Dsonar.sources=. \\
+  -Dsonar.host.url=http://localhost:9000"
+`;
+
 exports[`can choose build tools and copy provided settings: c++ (automatic) and other linux arm64: download scanner 1`] = `
 "export SONAR_SCANNER_VERSION=6.1.0.4477
 export SONAR_SCANNER_HOME=$HOME/.sonar/sonar-scanner-$SONAR_SCANNER_VERSION-linux-aarch64
index 846fdb0f14cb8dfbd6eac19d28224f9738c86064..2ad95448d8f4ece5e3bdbb6f5855507c6176ed39 100644 (file)
@@ -53,6 +53,7 @@ export default function AnalysisCommand(props: Readonly<AnalysisCommandProps>) {
     case BuildTools.DotNet:
       return <DotNet baseUrl={baseUrl} component={component} token={token} />;
 
+    case BuildTools.Dart:
     case BuildTools.Other:
       return (
         <Other
index c972a28c578ee3b81c6378f4a9fe4211a1905911..47069819ca88bc82b9ad7b3ffcbed46c10418dd5 100644 (file)
@@ -74,6 +74,7 @@ export function getTutorialBuildButtons() {
     dotnetBuildButton: byRole('radio', { name: `onboarding.build.${BuildTools.DotNet}` }),
     cppBuildButton: byRole('radio', { name: `onboarding.build.${BuildTools.Cpp}` }),
     objCBuildButton: byRole('radio', { name: `onboarding.build.${BuildTools.ObjectiveC}` }),
+    dartBuildButton: byRole('radio', { name: `onboarding.build.${BuildTools.Dart}` }),
     otherBuildButton: byRole('radio', { name: `onboarding.build.${BuildTools.Other}` }),
     windowsDotnetCoreButton: byRole('radio', {
       name: `onboarding.build.${BuildTools.DotNet}.win_core`,
index 06783c05fbdf9d9a13bf4bc70a849c05bb6d21dc..13f22602cc59d00ec11d48fb565373bd7106c1e5 100644 (file)
@@ -33,6 +33,7 @@ export enum BuildTools {
   Cpp = 'cpp',
   ObjectiveC = 'objectivec',
   DotNet = 'dotnet',
+  Dart = 'dart',
   Other = 'other',
 }
 
index fa62732d252130c068eeb629a85ee215d91c4145..58c66594bc4dd2ab7a70ecd213c58d74c200311f 100644 (file)
@@ -103,6 +103,8 @@ export function getBuildToolOptions(supportCFamily: boolean) {
   if (supportCFamily) {
     list.push(BuildTools.Cpp);
     list.push(BuildTools.ObjectiveC);
+    // Both Dart and CFamily are available in Developer Edition and above
+    list.push(BuildTools.Dart);
   }
   list.push(BuildTools.Other);
   return list;
index de88613b2c284fc1adfd0a3e8301a7889e6ed8dd..7adb8527d285afac9bb7ed72d3922240c4476a4d 100644 (file)
@@ -4847,6 +4847,7 @@ onboarding.build.dotnet.win_msbuild=Windows + .NET Framework
 onboarding.build.dotnet.linux_core=Linux + .NET Core
 onboarding.build.cpp=C or C++
 onboarding.build.objectivec=Objective-C
+onboarding.build.dart=Flutter or Dart
 onboarding.build.other=Other (for JS, TS, Go, Python, PHP, ...)
 
 onboarding.build.dotnet.variant=Which framework do you use?
@@ -4993,12 +4994,14 @@ 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.dart=Add the following steps to your GitHub Actions Workflow after build of your Flutter or Dart project:
 
 onboarding.tutorial.with.gitlab_ci.title=Analyze your project with GitLab CI
 onboarding.tutorial.with.gitlab_ci.project_key.title=Set your project key
 onboarding.tutorial.with.gitlab_ci.project_key.maven.step2=Add the following to your {file} file:
 onboarding.tutorial.with.gitlab_ci.project_key.gradle.step2=Add the following to your {file} or {file2} file:
 onboarding.tutorial.with.gitlab_ci.project_key.other.step2=Create a {file} file in your repository and paste the following code:
+onboarding.tutorial.with.gitlab_ci.project_key.dart.step2=Create a {file} file in your repository and paste the following code:
 onboarding.tutorial.with.gitlab_ci.project_key.dotnet.step2=Create a {file} file in your repository and paste the following code:
 onboarding.tutorial.with.gitlab_ci.project_key.cpp.step2=Create a {file} file in your repository and paste the following code:
 onboarding.tutorial.with.gitlab_ci.project_key.objectivec.step2=Create a {file} file in your repository and paste the following code: