From 69c1a75940dec6249b86dace6b630d3a2ae9d2a7 Mon Sep 17 00:00:00 2001 From: Matteo Mara Date: Fri, 25 Aug 2023 12:48:23 +0200 Subject: [PATCH 01/60] SQSCANGHA-13 Update base image --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 2e3dd7b..882c681 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ -FROM sonarsource/sonar-scanner-cli:5.0 +FROM sonarsource/sonar-scanner-cli:5.0.1 -LABEL version="2.0.0" \ +LABEL version="2.0.1" \ repository="https://github.com/sonarsource/sonarqube-scan-action" \ homepage="https://github.com/sonarsource/sonarqube-scan-action" \ maintainer="SonarSource" \ From ccaf9efb1129361bafd633eecd1223977b0f5876 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Sep 2023 13:02:51 +0200 Subject: [PATCH 02/60] NO-JIRA Bump actions/checkout from 3 to 4 --- .github/workflows/qa.yml | 2 +- .github/workflows/update-tags.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index 4f772de..c906724 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -6,7 +6,7 @@ jobs: run_qa: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: token: ${{ secrets.GITHUB_TOKEN }} - run: ./test/run-qa.sh diff --git a/.github/workflows/update-tags.yml b/.github/workflows/update-tags.yml index ed54f4d..e7e5a9e 100644 --- a/.github/workflows/update-tags.yml +++ b/.github/workflows/update-tags.yml @@ -13,7 +13,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Parse semver uses: madhead/semver-utils@latest From 1b9d398800bf807ad36901b351fff52deba642d6 Mon Sep 17 00:00:00 2001 From: David Cho-Lerat <117642976+david-cho-lerat-sonarsource@users.noreply.github.com> Date: Wed, 18 Oct 2023 16:31:00 +0200 Subject: [PATCH 03/60] Update README.md with Clean Code link (#86) https://docs.google.com/document/d/1XhLeIhXWOzyWGJlJYp9OqYbkP5KQ-Gvx1a0O5JHTQsY/edit --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 0926d26..e133687 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ # Scan your code with SonarQube [![QA](https://github.com/SonarSource/sonarqube-scan-action/actions/workflows/qa.yml/badge.svg)](https://github.com/SonarSource/sonarqube-scan-action/actions/workflows/qa.yml) -Using this GitHub Action, scan your code with [SonarQube](https://www.sonarqube.org/) to detects Bugs, Vulnerabilities and Code Smells in up to 27 programming languages! +Using this GitHub Action, achieve [Clean Code](https://www.sonarsource.com/solutions/clean-code/?utm_medium=referral&utm_source=github&utm_campaign=clean-code&utm_content=sonarqube-scan-action) with [SonarQube](https://www.sonarqube.org/) by scanning to detect Bugs, Vulnerabilities, and Code Smells in 30+ programming languages! -SonarQube is the leading product for Continuous Code Quality & Code Security. It supports most popular programming languages, including Java, JavaScript, TypeScript, C#, Python, C, C++, and many more. +SonarQube is the leading product for Continuous Code Quality and code Security. It supports most popular programming languages, including Java, JavaScript, TypeScript, C#, Python, C, C++, and many more. ## Requirements @@ -20,7 +20,7 @@ Project metadata, including the location to the sources to be analyzed, must be sonar.projectKey= # relative paths to source directories. More details and properties are described -# in https://docs.sonarqube.org/latest/project-administration/narrowing-the-focus/ +# at https://docs.sonarqube.org/latest/project-administration/narrowing-the-focus/ sonar.sources=. ``` @@ -45,7 +45,7 @@ jobs: steps: - uses: actions/checkout@v3 with: - # Disabling shallow clone is recommended for improving relevancy of reporting + # Disabling shallow clones is recommended for improving the relevancy of reporting fetch-depth: 0 - name: SonarQube Scan uses: sonarsource/sonarqube-scan-action@master @@ -65,7 +65,7 @@ If your source code file names contain special characters that are not covered b LC_ALL: "ru_RU.UTF-8" ``` -If your SonarQube server uses a self-signed certificate, you can pass a root certificate (in PEM format) to the java certificate store: +If your SonarQube server uses a self-signed certificate, you can pass a root certificate (in PEM format) to the Java certificate store: ```yaml - name: SonarQube Scan @@ -115,7 +115,7 @@ This GitHub Action will not work for all technologies. If you are in one of the * You want to analyze a .NET solution. Read the documentation about our [Scanner for .NET](https://redirect.sonarsource.com/doc/install-configure-scanner-msbuild.html). * You want to analyze C/C++ code. Read the documentation on [analyzing C/C++ code](https://docs.sonarqube.org/latest/analysis/languages/cfamily/). -## Have question or feedback? +## Have questions or feedback? To provide feedback (requesting a feature or reporting a bug) please post on the [SonarSource Community Forum](https://community.sonarsource.com/tags/c/help/sq/github-actions). @@ -123,4 +123,4 @@ To provide feedback (requesting a feature or reporting a bug) please post on the The Dockerfile and associated scripts and documentation in this project are released under the LGPLv3 License. -Container images built with this project include third party materials. +Container images built with this project include third-party materials. From 74e7b4f99815e8e6b836e3de04f85ff3ff7f612e Mon Sep 17 00:00:00 2001 From: ALX99 <46844683+ALX99@users.noreply.github.com> Date: Tue, 19 Mar 2024 00:48:50 +0900 Subject: [PATCH 04/60] docs: use actions/checkout@v4 as an example (#96) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e133687..3d58564 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ jobs: sonarqube: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: # Disabling shallow clones is recommended for improving the relevancy of reporting fetch-depth: 0 From 9ad16418d1dd6d28912bc0047ee387e90181ce1c Mon Sep 17 00:00:00 2001 From: Claire Villard <60586848+claire-villard-sonarsource@users.noreply.github.com> Date: Tue, 19 Mar 2024 09:12:46 -0600 Subject: [PATCH 05/60] SQSCANGHA-18 Improve the SonarQube intro in README.md --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3d58564..037b916 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,13 @@ # Scan your code with SonarQube [![QA](https://github.com/SonarSource/sonarqube-scan-action/actions/workflows/qa.yml/badge.svg)](https://github.com/SonarSource/sonarqube-scan-action/actions/workflows/qa.yml) -Using this GitHub Action, achieve [Clean Code](https://www.sonarsource.com/solutions/clean-code/?utm_medium=referral&utm_source=github&utm_campaign=clean-code&utm_content=sonarqube-scan-action) with [SonarQube](https://www.sonarqube.org/) by scanning to detect Bugs, Vulnerabilities, and Code Smells in 30+ programming languages! +This SonarSource project, available as a GitHub Action, scans your projects with SonarQube, and helps developers produce +[Clean Code](https://www.sonarsource.com/solutions/clean-code/?utm_medium=referral&utm_source=github&utm_campaign=clean-code&utm_content=sonarqube-scan-action). -SonarQube is the leading product for Continuous Code Quality and code Security. It supports most popular programming languages, including Java, JavaScript, TypeScript, C#, Python, C, C++, and many more. +[SonarQube](https://www.sonarsource.com/products/sonarqube/) is a widely used static analysis solution for continuous code quality and security inspection. +It helps developers identify and fix issues in their code that could lead to bugs, vulnerabilities, or decreased development velocity. +SonarQube supports the most popular programming languages, including Java, JavaScript, TypeScript, C#, Python, C, C++, and [many more](https://www.sonarsource.com/knowledge/languages/). ## Requirements From 53c3e3207fe4b8d52e2f1ac9d6eb1d2506f626c0 Mon Sep 17 00:00:00 2001 From: Claire Villard <60586848+claire-villard-sonarsource@users.noreply.github.com> Date: Thu, 28 Mar 2024 09:46:15 +0100 Subject: [PATCH 06/60] This repository is owned by the Analysis Experience squad --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 2a68a83..3f43f0d 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1 @@ -.github/CODEOWNERS @sonarsource/sonarqube-team +.github/CODEOWNERS @sonarsource/analysis-experience-squad From 6abcb2537c297b61a7310bada652d7ef3f71fc08 Mon Sep 17 00:00:00 2001 From: Geoffray Adde Date: Tue, 16 Apr 2024 17:14:09 +0200 Subject: [PATCH 07/60] point to C and C++ GH Action instead of C and C++ help page --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 037b916..eac06c2 100644 --- a/README.md +++ b/README.md @@ -116,7 +116,7 @@ This GitHub Action will not work for all technologies. If you are in one of the * Your code is built with Maven. Read the documentation about our [Scanner for Maven](https://redirect.sonarsource.com/doc/install-configure-scanner-maven.html). * Your code is built with Gradle. Read the documentation about our [Scanner for Gradle](https://redirect.sonarsource.com/doc/gradle.html). * You want to analyze a .NET solution. Read the documentation about our [Scanner for .NET](https://redirect.sonarsource.com/doc/install-configure-scanner-msbuild.html). -* You want to analyze C/C++ code. Read the documentation on [analyzing C/C++ code](https://docs.sonarqube.org/latest/analysis/languages/cfamily/). +* You want to analyze C/C++ code. Use the [SonarQube C and C++](https://github.com/SonarSource/sonarqube-github-c-cpp) GitHub Action. ## Have questions or feedback? From be64f357263a9a69c6488e9bdc6f666f9783049b Mon Sep 17 00:00:00 2001 From: Julien HENRY Date: Mon, 13 May 2024 17:07:56 +0200 Subject: [PATCH 08/60] SQSCANGHA-25 Rewrite tests using GitHub Actions --- .github/workflows/qa.yml | 121 +++++++++++++++++++++++++++++++++++++-- entrypoint.sh | 4 +- test/assertFileContains | 10 ++++ test/assertFileExists | 8 +++ test/run-qa.sh | 112 ------------------------------------ 5 files changed, 137 insertions(+), 118 deletions(-) create mode 100755 test/assertFileContains create mode 100755 test/assertFileExists delete mode 100755 test/run-qa.sh diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index c906724..ed9695a 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -3,16 +3,129 @@ name: QA on: [push, pull_request] jobs: - run_qa: + argsInputTest: + name: > + 'args' input runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: token: ${{ secrets.GITHUB_TOKEN }} - - run: ./test/run-qa.sh - timeout-minutes: 5 + - name: Run action with args + uses: ./ + with: + args: -Dsonar.someArg=aValue -Dsonar.scanner.dumpToFile=./output.properties + env: + SONAR_HOST_URL: http://not_actually_used + - name: Assert + run: | + ./test/assertFileContains ./output.properties "sonar.someArg=aValue" + projectBaseDirInputTest: + name: > + 'projectBaseDir' input + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + - run: mkdir -p ./baseDir + - name: Run action with projectBaseDir + uses: ./ + with: + args: -Dsonar.scanner.dumpToFile=./output.properties + projectBaseDir: ./baseDir + env: + SONAR_HOST_URL: http://not_actually_used + - name: Assert + run: | + ./test/assertFileContains ./output.properties "sonar.projectBaseDir=.*/baseDir" + sonarHostUrlRequiredTest: + name: > + 'SONAR_HOST_URL' is required + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + - name: Run action without SONAR_HOST_URL + id: runTest + uses: ./ + continue-on-error: true + - name: Previous should have failed + if: ${{ steps.runTest.outcome == 'success'}} + run: | + echo "Expected previous step to fail" + exit 1 + failFastGradleTest: + name: > + Fail fast on Gradle project + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + - name: Run action on Gradle project + id: runTest + uses: ./ + continue-on-error: true + env: + SONAR_HOST_URL: http://not_actually_used + with: + projectBaseDir: ./test/gradle-project + - name: Previous should have failed + if: ${{ steps.runTest.outcome == 'success'}} + run: | + echo "Expected previous step to fail" + exit 1 + failFastMavenTest: + name: > + Fail fast on Maven project + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + - name: Run action on Maven project + id: runTest + uses: ./ + continue-on-error: true + env: + SONAR_HOST_URL: http://not_actually_used + with: + projectBaseDir: ./test/maven-project + - name: Previous should have failed + if: ${{ steps.runTest.outcome == 'success'}} + run: | + echo "Expected previous step to fail" + exit 1 + runAnalysisTest: + runs-on: ubuntu-latest services: sonarqube: - image: sonarqube:8.9-community + image: sonarqube:lts-community ports: - 9000:9000 + volumes: + - sonarqube_data:/opt/sonarqube/data + - sonarqube_logs:/opt/sonarqube/logs + - sonarqube_extensions:/opt/sonarqube/extensions + options: >- + --health-cmd "grep -Fq \"SonarQube is operational\" /opt/sonarqube/logs/sonar.log" + --health-interval 10s + --health-timeout 5s + --health-retries 10 + steps: + - uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + - name: Run action on sample project + id: runTest + uses: ./ + env: + SONAR_HOST_URL: http://sonarqube:9000 + with: + args: -Dsonar.login=admin -Dsonar.password=admin + projectBaseDir: ./test/example-project + - name: Assert + run: | + ./test/assertFileExists ./test/example-project/.scannerwork/report-task.txt \ No newline at end of file diff --git a/entrypoint.sh b/entrypoint.sh index 36873d1..d0b4e1e 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -20,12 +20,12 @@ if [[ -n "${SONAR_ROOT_CERT}" ]]; then keytool -keystore /etc/ssl/certs/java/cacerts -storepass changeit -noprompt -trustcacerts -importcert -alias sonarqube -file /tmp/tmpcert.pem fi -if [[ -f "${INPUT_PROJECTBASEDIR%/}pom.xml" ]]; then +if [[ -f "${INPUT_PROJECTBASEDIR%/}/pom.xml" ]]; then echo "Maven project detected. You should run the goal 'org.sonarsource.scanner.maven:sonar' during build rather than using this GitHub Action." exit 1 fi -if [[ -f "${INPUT_PROJECTBASEDIR%/}build.gradle" ]]; then +if [[ -f "${INPUT_PROJECTBASEDIR%/}/build.gradle" ]]; then echo "Gradle project detected. You should use the SonarQube plugin for Gradle during build rather than using this GitHub Action." exit 1 fi diff --git a/test/assertFileContains b/test/assertFileContains new file mode 100755 index 0000000..69380e1 --- /dev/null +++ b/test/assertFileContains @@ -0,0 +1,10 @@ +#!/bin/bash + +error() { echo -e "\\e[31m✗ $*\\e[0m"; } + +assertFileExists $1 + +if ! grep -q $2 $1; then + error "'$2' not found in '$1'" + exit 1 +fi \ No newline at end of file diff --git a/test/assertFileExists b/test/assertFileExists new file mode 100755 index 0000000..8f04686 --- /dev/null +++ b/test/assertFileExists @@ -0,0 +1,8 @@ +#!/bin/bash + +error() { echo -e "\\e[31m✗ $*\\e[0m"; } + +if [ ! -f $1 ]; then + error "File '$1' not found" + exit 1 +fi \ No newline at end of file diff --git a/test/run-qa.sh b/test/run-qa.sh deleted file mode 100755 index 397d3ba..0000000 --- a/test/run-qa.sh +++ /dev/null @@ -1,112 +0,0 @@ -#!/bin/bash - -# Helper functions for coloring output. -info() { echo -e "\\e[36m$*\\e[0m"; } -error() { echo -e "\\e[31m✗ $*\\e[0m"; } -success() { echo -e "\\e[32m✔ $*\\e[0m"; } - -# Helper function to check if SonarQube is up and running. -check_sq_is_up() { - local statusCall="$(curl --silent --user admin:admin http://127.0.0.1:9000/api/system/status)" - local status="$(jq -r '.status' <<< "$statusCall")" - if [[ ! $? -eq 0 ]]; then - error "Failed to check if SonarQube is up and running." - exit 1 - fi - echo $status; -} - -_current_perm=$(stat -c "%u:%g" $(pwd)) - -info "Build scanner action..." -docker build --no-cache -t sonarsource/sonarqube-scan-action . -if [[ ! $? -eq 0 ]]; then - error "Failed to build the scanner action." - exit 1 -fi -success "Scanner action built." - -info "Find the network SonarQube is running on..." -network=$(docker network ls -f 'name=github_network' --format "{{.Name}}") -if [[ $network != "github_network_"* ]]; then - error "Failed to find the local Docker network." - exit 1 -fi -success "Found the network ($network)." - -info "Wait until SonarQube is up..." -sleep 10 -isUp=$(check_sq_is_up) -until [[ "$isUp" == "UP" ]]; do - sleep 1 - isUp=$(check_sq_is_up) -done -success "SonarQube is up and running." - -info "Generate a new token..." -tokenCall=$(curl --silent --user admin:admin -d "name=token" http://127.0.0.1:9000/api/user_tokens/generate) -token="$(jq -r '.token' <<< "$tokenCall")" -if [[ -z "$token" ]]; then - error "Failed to generate a new token." - exit 1 -fi -success "New token generated." - -info "Test fail-fast if SONAR_TOKEN is omitted..." -docker run -v `pwd`:/github/workspace/ --workdir /github/workspace --network $network sonarsource/sonarqube-scan-action -if [[ $? -eq 0 ]]; then - error "Should have failed fast." - exit 1 -fi -success "Correctly failed fast." - -info "Test fail-fast if SONAR_HOST_URL is omitted..." -docker run -v `pwd`:/github/workspace/ --workdir /github/workspace --network $network --env SONAR_TOKEN=$token sonarsource/sonarqube-scan-action -if [[ $? -eq 0 ]]; then - error "Should have failed fast." - exit 1 -fi -success "Correctly failed fast." - -info "Test fail-fast on Gradle project..." -pushd test/gradle-project/ -docker run -v `pwd`:/github/workspace/ --workdir /github/workspace --network $network --env SONAR_TOKEN=$token --env SONAR_HOST_URL='http://sonarqube:9000' sonarsource/sonarqube-scan-action -if [[ $? -eq 0 ]]; then - error "Should have failed fast." - exit 1 -fi -popd -success "Correctly failed fast." - -info "Test fail-fast on Maven project..." -pushd test/maven-project/ -docker run -v `pwd`:/github/workspace/ --workdir /github/workspace --network $network --env SONAR_TOKEN=$token --env SONAR_HOST_URL='http://sonarqube:9000' sonarsource/sonarqube-scan-action -if [[ $? -eq 0 ]]; then - error "Should have failed fast." - exit 1 -fi -popd -success "Correctly failed fast." - -info "Analyze project..." -cd test/example-project/ -docker run -v `pwd`:/github/workspace/ --workdir /github/workspace --network $network --env INPUT_PROJECTBASEDIR=/github/workspace --env SONAR_TOKEN=$token --env SONAR_HOST_URL='http://sonarqube:9000' sonarsource/sonarqube-scan-action -docker run -v `pwd`:/github/workspace/ --workdir /github/workspace --network $network --env INPUT_PROJECTBASEDIR=/github/workspace --entrypoint /cleanup.sh sonarsource/sonarqube-scan-action -if [[ ! $? -eq 0 ]]; then - error "Couldn't run the analysis." - exit 1 -elif [[ ! -f ".scannerwork/report-task.txt" ]]; then - error "Couldn't find the report task file. Analysis failed." - exit 1 -elif [ ! "$(stat -c "%u:%g" ".scannerwork/report-task.txt")" == "$_current_perm" ]; then - error "File permissions differ from desired once" - error "desired: $_current_perm" - error "actual: $(stat -c "%u:%g" ".scannerwork/report-task.txt")" - exit 1 -fi -success "Analysis successful." - -echo "" # new line -echo "============================" -echo "" # new line -success "QA successful!" From 04623c1cb13f5b60b8ac82f537af0ff19c4bb519 Mon Sep 17 00:00:00 2001 From: Ni Jannasch Date: Fri, 10 May 2024 16:15:54 +0200 Subject: [PATCH 09/60] SQSCANGHA-22 Show pinned action version SQSCANGHA-22 Pin Github Action Version --- .github/workflows/update-tags.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-tags.yml b/.github/workflows/update-tags.yml index e7e5a9e..a07d193 100644 --- a/.github/workflows/update-tags.yml +++ b/.github/workflows/update-tags.yml @@ -16,7 +16,7 @@ jobs: uses: actions/checkout@v4 - name: Parse semver - uses: madhead/semver-utils@latest + uses: madhead/semver-utils@40bbdc6e50b258c09f35f574e83c51f60d2ce3a2 # v4.0.0 id: version with: version: ${{ github.ref_name }} From f8003d5a3a5acbdf440230b4a98d79dffb7c73a9 Mon Sep 17 00:00:00 2001 From: "antoine.vinot" Date: Thu, 16 May 2024 09:17:55 +0200 Subject: [PATCH 10/60] SQSCANGHA-25 Adapt events that trigger the qa workflow --- .github/workflows/qa.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index ed9695a..4bb5ccc 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -1,6 +1,11 @@ name: QA -on: [push, pull_request] +on: + push: + branches: + - main + pull_request: + types: [opened, synchronize, reopened] jobs: argsInputTest: @@ -128,4 +133,4 @@ jobs: projectBaseDir: ./test/example-project - name: Assert run: | - ./test/assertFileExists ./test/example-project/.scannerwork/report-task.txt \ No newline at end of file + ./test/assertFileExists ./test/example-project/.scannerwork/report-task.txt From 0c14a18753f306c616b305d03e7d4b39aa822e31 Mon Sep 17 00:00:00 2001 From: "antoine.vinot" Date: Thu, 16 May 2024 13:12:16 +0200 Subject: [PATCH 11/60] SQSCANGHA-25 Fix main branch name in GitHub workflow --- .github/workflows/qa.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index 4bb5ccc..70d3a00 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -3,7 +3,7 @@ name: QA on: push: branches: - - main + - master pull_request: types: [opened, synchronize, reopened] From d3ca1743de4293fc030a2e1ded1fb44088b80b76 Mon Sep 17 00:00:00 2001 From: Julien HENRY Date: Thu, 16 May 2024 11:35:45 +0200 Subject: [PATCH 12/60] SQSCANGHA-24 Enable Mend scan --- .cirrus.star | 4 ++++ .cirrus.yml | 38 ++++++++++++++++++++++++++++++++ .cirrus/wss-unified-agent.config | 4 ++++ 3 files changed, 46 insertions(+) create mode 100644 .cirrus.star create mode 100644 .cirrus.yml create mode 100644 .cirrus/wss-unified-agent.config diff --git a/.cirrus.star b/.cirrus.star new file mode 100644 index 0000000..28b17b7 --- /dev/null +++ b/.cirrus.star @@ -0,0 +1,4 @@ +load("github.com/SonarSource/cirrus-modules@v2", "load_features") + +def main(ctx): + return load_features(ctx) diff --git a/.cirrus.yml b/.cirrus.yml new file mode 100644 index 0000000..358472c --- /dev/null +++ b/.cirrus.yml @@ -0,0 +1,38 @@ +env: + CIRRUS_VAULT_URL: https://vault.sonar.build:8200 + CIRRUS_VAULT_AUTH_PATH: jwt-cirrusci + CIRRUS_VAULT_ROLE: cirrusci-${CIRRUS_REPO_OWNER}-${CIRRUS_REPO_NAME} + + # Mend scan global configuration + MEND_API_KEY: VAULT[development/kv/data/mend data.apikey] + + # Staging image configuration + STAGING_IMAGE_NAME: sonarsource/sonarqube-scan-action + CURRENT_TAG: master + +vm_instance_template: &VM_TEMPLATE + experimental: true # see https://github.com/cirruslabs/cirrus-ci-docs/issues/1051 + image: docker-builder-v* + type: t2.small + region: eu-central-1 + subnet_id: ${CIRRUS_AWS_SUBNET} + disk: 10 + cpu: 4 + memory: 16G + +mend_task: + ec2_instance: + <<: *VM_TEMPLATE + # run only on master and long-term branches + only_if: $CIRRUS_USER_COLLABORATOR == 'true' && ($CIRRUS_BRANCH == "master" || $CIRRUS_BRANCH =~ "branch-.*") + setup_script: + - docker build --tag "${STAGING_IMAGE_NAME}:${CURRENT_TAG}" . + - apt-get remove -y unattended-upgrades + - apt-get update && apt-get install -y --no-install-recommends openjdk-17-jre + - curl -sSL https://unified-agent.s3.amazonaws.com/wss-unified-agent.jar -o wss-unified-agent.jar + - echo "docker.includes=${CURRENT_TAG}" >> .cirrus/wss-unified-agent.config + scan_script: + - echo "Scan the ${STAGING_IMAGE_NAME}:${CURRENT_TAG} image" + - java -jar wss-unified-agent.jar -c .cirrus/wss-unified-agent.config -apiKey $MEND_API_KEY + + diff --git a/.cirrus/wss-unified-agent.config b/.cirrus/wss-unified-agent.config new file mode 100644 index 0000000..8ce1b83 --- /dev/null +++ b/.cirrus/wss-unified-agent.config @@ -0,0 +1,4 @@ +docker.projectNameFormat=repositoryNameAndTag +docker.scanImages=true +wss.url=https://saas-eu.whitesourcesoftware.com/agent +productName=GitHubAction/SonarQubeScanAction From 9bea6a46af788d59fc88f335fd752da4860b10cc Mon Sep 17 00:00:00 2001 From: istvan-bodo-sonarsource Date: Tue, 21 May 2024 14:11:19 +0200 Subject: [PATCH 13/60] SQSCANGHA-27 Use GHA debug logging with scanner --- .github/workflows/qa.yml | 18 ++++++++++++++++++ entrypoint.sh | 7 ++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index 70d3a00..f4a7be3 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -134,3 +134,21 @@ jobs: - name: Assert run: | ./test/assertFileExists ./test/example-project/.scannerwork/report-task.txt + runnerDebugUsedTest: + name: > + 'RUNNER_DEBUG' is used + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + - name: Run action with debug mode + uses: ./ + with: + args: -Dsonar.scanner.dumpToFile=./output.properties + env: + RUNNER_DEBUG: 1 + SONAR_HOST_URL: http://not_actually_used + - name: Assert + run: | + ./test/assertFileContains ./output.properties "sonar.verbose=true" diff --git a/entrypoint.sh b/entrypoint.sh index d0b4e1e..0d0ef25 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -30,7 +30,12 @@ if [[ -f "${INPUT_PROJECTBASEDIR%/}/build.gradle" ]]; then exit 1 fi +debug_flag='' +if [[ "$RUNNER_DEBUG" == '1' ]]; then + debug_flag='--debug' +fi + unset JAVA_HOME -sonar-scanner -Dsonar.projectBaseDir=${INPUT_PROJECTBASEDIR} ${INPUT_ARGS} +sonar-scanner $debug_flag -Dsonar.projectBaseDir=${INPUT_PROJECTBASEDIR} ${INPUT_ARGS} From fed3555e670e7a40c48412ac4e981fd772ce847e Mon Sep 17 00:00:00 2001 From: Julien HENRY Date: Tue, 14 May 2024 14:38:18 +0200 Subject: [PATCH 14/60] SQSCANGHA-21 Update the base image --- Dockerfile | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 882c681..a38bed0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ -FROM sonarsource/sonar-scanner-cli:5.0.1 +FROM sonarsource/sonar-scanner-cli:10.0 -LABEL version="2.0.1" \ +LABEL version="2.1.0" \ repository="https://github.com/sonarsource/sonarqube-scan-action" \ homepage="https://github.com/sonarsource/sonarqube-scan-action" \ maintainer="SonarSource" \ @@ -9,9 +9,13 @@ LABEL version="2.0.1" \ com.github.actions.icon="check" \ com.github.actions.color="green" +# GitHub actions should be run under ROOT +# https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners#docker-container-filesystem +USER 0 COPY entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh COPY cleanup.sh /cleanup.sh RUN chmod +x /cleanup.sh + ENTRYPOINT ["/entrypoint.sh"] From 320b72385a2f8f88fb55ffc43ba4d56406a836b6 Mon Sep 17 00:00:00 2001 From: "antoine.vinot" Date: Mon, 20 May 2024 16:17:53 +0200 Subject: [PATCH 15/60] SQSCANGHA-26 Warning instead of failure for Maven/Gradle projects --- .github/workflows/qa.yml | 22 ++++++++++------------ entrypoint.sh | 8 ++++---- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index f4a7be3..b632014 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -61,9 +61,9 @@ jobs: run: | echo "Expected previous step to fail" exit 1 - failFastGradleTest: + dontFailGradleTest: name: > - Fail fast on Gradle project + Don't fail on Gradle project runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -77,14 +77,13 @@ jobs: SONAR_HOST_URL: http://not_actually_used with: projectBaseDir: ./test/gradle-project - - name: Previous should have failed - if: ${{ steps.runTest.outcome == 'success'}} + args: -Dsonar.scanner.dumpToFile=./output.properties + - name: Assert run: | - echo "Expected previous step to fail" - exit 1 - failFastMavenTest: + ./test/assertFileExists ./output.properties + dontFailMavenTest: name: > - Fail fast on Maven project + Don't fail on Maven project runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -98,11 +97,10 @@ jobs: SONAR_HOST_URL: http://not_actually_used with: projectBaseDir: ./test/maven-project - - name: Previous should have failed - if: ${{ steps.runTest.outcome == 'success'}} + args: -Dsonar.scanner.dumpToFile=./output.properties + - name: Assert run: | - echo "Expected previous step to fail" - exit 1 + ./test/assertFileExists ./output.properties runAnalysisTest: runs-on: ubuntu-latest services: diff --git a/entrypoint.sh b/entrypoint.sh index 0d0ef25..24911d0 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -21,13 +21,13 @@ if [[ -n "${SONAR_ROOT_CERT}" ]]; then fi if [[ -f "${INPUT_PROJECTBASEDIR%/}/pom.xml" ]]; then - echo "Maven project detected. You should run the goal 'org.sonarsource.scanner.maven:sonar' during build rather than using this GitHub Action." - exit 1 + echo "WARNING! Maven project detected. Sonar recommends running the 'org.sonarsource.scanner.maven:sonar-maven-plugin:sonar' goal during the build process instead of using this GitHub Action + to get more accurate results." fi if [[ -f "${INPUT_PROJECTBASEDIR%/}/build.gradle" ]]; then - echo "Gradle project detected. You should use the SonarQube plugin for Gradle during build rather than using this GitHub Action." - exit 1 + echo "WARNING! Gradle project detected. Sonar recommends using the SonarQube plugin for Gradle during the build process instead of using this GitHub Action + to get more accurate results." fi debug_flag='' From 968b486245c5c71cb245a3070ab7d3113eac9859 Mon Sep 17 00:00:00 2001 From: "antoine.vinot" Date: Tue, 21 May 2024 10:45:32 +0200 Subject: [PATCH 16/60] SQSCANGHA-20 Add detection of Kotlin Gradle configuration --- .github/workflows/qa.yml | 20 ++++++++++++++++++++ entrypoint.sh | 2 +- test/gradle-project-kotlin/build.gradle.kts | 0 3 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 test/gradle-project-kotlin/build.gradle.kts diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index b632014..5d0f337 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -81,6 +81,26 @@ jobs: - name: Assert run: | ./test/assertFileExists ./output.properties + dontFailGradleKotlinTest: + name: > + Don't fail on Kotlin Gradle project + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + - name: Run action on Kotlin Gradle project + id: runTest + uses: ./ + continue-on-error: true + env: + SONAR_HOST_URL: http://not_actually_used + with: + projectBaseDir: ./test/gradle-project + args: -Dsonar.scanner.dumpToFile=./output.properties + - name: Assert + run: | + ./test/assertFileExists ./output.properties dontFailMavenTest: name: > Don't fail on Maven project diff --git a/entrypoint.sh b/entrypoint.sh index 24911d0..2bdd5d5 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -25,7 +25,7 @@ if [[ -f "${INPUT_PROJECTBASEDIR%/}/pom.xml" ]]; then to get more accurate results." fi -if [[ -f "${INPUT_PROJECTBASEDIR%/}/build.gradle" ]]; then +if [[ -f "${INPUT_PROJECTBASEDIR%/}/build.gradle" || -f "${INPUT_PROJECTBASEDIR%/}/build.gradle.kts" ]]; then echo "WARNING! Gradle project detected. Sonar recommends using the SonarQube plugin for Gradle during the build process instead of using this GitHub Action to get more accurate results." fi diff --git a/test/gradle-project-kotlin/build.gradle.kts b/test/gradle-project-kotlin/build.gradle.kts new file mode 100644 index 0000000..e69de29 From 16be80a08001cc68072c0b1eafb58f7abafc4a10 Mon Sep 17 00:00:00 2001 From: Julien HENRY Date: Wed, 22 May 2024 10:21:00 +0200 Subject: [PATCH 17/60] SQSCANGHA-28 Support passing args with spaces --- .github/workflows/qa.yml | 5 +++-- entrypoint.sh | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index 5d0f337..eec67a7 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -19,12 +19,13 @@ jobs: - name: Run action with args uses: ./ with: - args: -Dsonar.someArg=aValue -Dsonar.scanner.dumpToFile=./output.properties + args: >- + "-Dsonar.someArg=a value with spaces" -Dsonar.scanner.dumpToFile=./output.properties env: SONAR_HOST_URL: http://not_actually_used - name: Assert run: | - ./test/assertFileContains ./output.properties "sonar.someArg=aValue" + ./test/assertFileContains ./output.properties "sonar.someArg=a value with spaces" projectBaseDirInputTest: name: > 'projectBaseDir' input diff --git a/entrypoint.sh b/entrypoint.sh index 2bdd5d5..205251c 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -37,5 +37,6 @@ fi unset JAVA_HOME -sonar-scanner $debug_flag -Dsonar.projectBaseDir=${INPUT_PROJECTBASEDIR} ${INPUT_ARGS} +eval "args=(${INPUT_ARGS})" +sonar-scanner $debug_flag "-Dsonar.projectBaseDir=${INPUT_PROJECTBASEDIR}" "${args[@]}" From e4c4bdc17f34738d2343a3f09077a0186c0842f0 Mon Sep 17 00:00:00 2001 From: Julien HENRY Date: Wed, 22 May 2024 12:14:15 +0200 Subject: [PATCH 18/60] Don't recomend to use master as a version --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index eac06c2..5afadab 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Read more information on how to analyze your code [here](https://docs.sonarqube. ## Usage -Project metadata, including the location to the sources to be analyzed, must be declared in the file `sonar-project.properties` in the base directory: +Project metadata, including the location of the sources to be analyzed, must be declared in the file `sonar-project.properties` in the base directory: ```properties sonar.projectKey= @@ -51,7 +51,7 @@ jobs: # Disabling shallow clones is recommended for improving the relevancy of reporting fetch-depth: 0 - name: SonarQube Scan - uses: sonarsource/sonarqube-scan-action@master + uses: sonarsource/sonarqube-scan-action@v2.0.2 env: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} @@ -61,7 +61,7 @@ If your source code file names contain special characters that are not covered b ```yaml - name: SonarQube Scan - uses: sonarsource/sonarqube-scan-action@master + uses: sonarsource/sonarqube-scan-action@v2.0.2 env: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} @@ -72,7 +72,7 @@ If your SonarQube server uses a self-signed certificate, you can pass a root cer ```yaml - name: SonarQube Scan - uses: sonarsource/sonarqube-scan-action@master + uses: sonarsource/sonarqube-scan-action@v2.0.2 env: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} @@ -83,7 +83,7 @@ You can change the analysis base directory by using the optional input `projectB ```yaml - name: SonarQube Scan - uses: sonarsource/sonarqube-scan-action@master + uses: sonarsource/sonarqube-scan-action@v2.0.2 with: projectBaseDir: app/src ``` @@ -92,7 +92,7 @@ In case you need to add additional analysis parameters, and you do not wish to s ```yaml - name: SonarQube Scan - uses: sonarsource/sonarqube-scan-action@master + uses: sonarsource/sonarqube-scan-action@v2.0.2 with: projectBaseDir: app/src args: > From 8c56bc3994f1fa0736f991d3c5093886e01019a7 Mon Sep 17 00:00:00 2001 From: istvan-bodo-sonarsource Date: Thu, 23 May 2024 08:10:06 +0200 Subject: [PATCH 19/60] SQSCANGHA-29 Update .scannerwork cleanup --- README.md | 13 +++++++++++++ cleanup.sh | 11 ++++++++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5afadab..e3b9ebb 100644 --- a/README.md +++ b/README.md @@ -118,6 +118,19 @@ This GitHub Action will not work for all technologies. If you are in one of the * You want to analyze a .NET solution. Read the documentation about our [Scanner for .NET](https://redirect.sonarsource.com/doc/install-configure-scanner-msbuild.html). * You want to analyze C/C++ code. Use the [SonarQube C and C++](https://github.com/SonarSource/sonarqube-github-c-cpp) GitHub Action. +## Error cleaning up workspace + +In some cases, the checkout action may fail to clean up the workspace. This is a known problem for GitHub actions implemented as a docker container (such as `sonarqube-scan-action`) when self-hosted runners are used. +Example of the error message: `File was unable to be removed Error: EACCES: permission denied, unlink '/actions-runner/_work//project/.scannerwork/.sonar_lock'` +To work around the problem, `sonarqube-scan-action` attempts to fix the permission of the temporary files that it creates. If that doesn't work, you can manually clean up the workspace by running the following action: +``` +- name: Clean the workspace + uses: docker://alpine + with: + args: /bin/sh -c "find \"${GITHUB_WORKSPACE}\" -mindepth 1 ! -name . -prune -exec rm -rf {} +" +``` +You can find more info [here](https://github.com/actions/runner/issues/434). + ## Have questions or feedback? To provide feedback (requesting a feature or reporting a bug) please post on the [SonarSource Community Forum](https://community.sonarsource.com/tags/c/help/sq/github-actions). diff --git a/cleanup.sh b/cleanup.sh index e499d4a..2a435a7 100755 --- a/cleanup.sh +++ b/cleanup.sh @@ -2,7 +2,12 @@ set -e -_tmp_file=$(ls "${INPUT_PROJECTBASEDIR}/" | head -1) -PERM=$(stat -c "%u:%g" "${INPUT_PROJECTBASEDIR}/$_tmp_file") +if [ ! -d "${INPUT_PROJECTBASEDIR%/}/.scannerwork" ]; then + echo ".scannerwork directory not found; nothing to clean up." + exit +fi -chown -R $PERM "${INPUT_PROJECTBASEDIR}/" \ No newline at end of file +_tmp_file=$(ls "${INPUT_PROJECTBASEDIR%/}/" | head -1) +PERM=$(stat -c "%u:%g" "${INPUT_PROJECTBASEDIR%/}/$_tmp_file") + +chown -R $PERM "${INPUT_PROJECTBASEDIR%/}/.scannerwork/" \ No newline at end of file From 44de84c3e812ce86b4d57c78b4670cd9e2e9baee Mon Sep 17 00:00:00 2001 From: Julien HENRY Date: Thu, 23 May 2024 08:40:45 +0200 Subject: [PATCH 20/60] SQSCANGHA-31 Stop making SONAR_HOST_URL mandatory --- .github/workflows/qa.yml | 17 ----------------- entrypoint.sh | 5 ----- 2 files changed, 22 deletions(-) diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index eec67a7..3e17d55 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -45,23 +45,6 @@ jobs: - name: Assert run: | ./test/assertFileContains ./output.properties "sonar.projectBaseDir=.*/baseDir" - sonarHostUrlRequiredTest: - name: > - 'SONAR_HOST_URL' is required - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GITHUB_TOKEN }} - - name: Run action without SONAR_HOST_URL - id: runTest - uses: ./ - continue-on-error: true - - name: Previous should have failed - if: ${{ steps.runTest.outcome == 'success'}} - run: | - echo "Expected previous step to fail" - exit 1 dontFailGradleTest: name: > Don't fail on Gradle project diff --git a/entrypoint.sh b/entrypoint.sh index 205251c..5bca08c 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -8,11 +8,6 @@ if [[ -z "${SONAR_TOKEN}" ]]; then echo "============================ WARNING ============================" fi -if [[ -z "${SONAR_HOST_URL}" ]]; then - echo "This GitHub Action requires the SONAR_HOST_URL env variable." - exit 1 -fi - if [[ -n "${SONAR_ROOT_CERT}" ]]; then echo "Adding custom root certificate to java certificate store" rm -f /tmp/tmpcert.pem From 86fe81775628f1c6349c28baab87881a2170f495 Mon Sep 17 00:00:00 2001 From: Julien HENRY Date: Thu, 23 May 2024 10:15:18 +0200 Subject: [PATCH 21/60] Use a placeholder for the action version in README --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index e3b9ebb..c7a8e82 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ jobs: # Disabling shallow clones is recommended for improving the relevancy of reporting fetch-depth: 0 - name: SonarQube Scan - uses: sonarsource/sonarqube-scan-action@v2.0.2 + uses: sonarsource/sonarqube-scan-action@ # Ex: v2.1.0, See the latest version at https://github.com/marketplace/actions/official-sonarqube-scan env: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} @@ -61,7 +61,7 @@ If your source code file names contain special characters that are not covered b ```yaml - name: SonarQube Scan - uses: sonarsource/sonarqube-scan-action@v2.0.2 + uses: sonarsource/sonarqube-scan-action@ # Ex: v2.1.0, See the latest version at https://github.com/marketplace/actions/official-sonarqube-scan env: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} @@ -72,7 +72,7 @@ If your SonarQube server uses a self-signed certificate, you can pass a root cer ```yaml - name: SonarQube Scan - uses: sonarsource/sonarqube-scan-action@v2.0.2 + uses: sonarsource/sonarqube-scan-action@ # Ex: v2.1.0, See the latest version at https://github.com/marketplace/actions/official-sonarqube-scan env: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} @@ -83,7 +83,7 @@ You can change the analysis base directory by using the optional input `projectB ```yaml - name: SonarQube Scan - uses: sonarsource/sonarqube-scan-action@v2.0.2 + uses: sonarsource/sonarqube-scan-action@ # Ex: v2.1.0, See the latest version at https://github.com/marketplace/actions/official-sonarqube-scan with: projectBaseDir: app/src ``` @@ -92,7 +92,7 @@ In case you need to add additional analysis parameters, and you do not wish to s ```yaml - name: SonarQube Scan - uses: sonarsource/sonarqube-scan-action@v2.0.2 + uses: sonarsource/sonarqube-scan-action@ # Ex: v2.1.0, See the latest version at https://github.com/marketplace/actions/official-sonarqube-scan with: projectBaseDir: app/src args: > From 94ac847096eeed8621e842984de12b68db76a95b Mon Sep 17 00:00:00 2001 From: Csaba Feher Date: Thu, 23 May 2024 11:29:14 +0200 Subject: [PATCH 22/60] SQSCANGHA-30 Replace secrets.SONAR_HOST_URL with vars.SONAR_HOST_URL --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index c7a8e82..241cce8 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ jobs: uses: sonarsource/sonarqube-scan-action@ # Ex: v2.1.0, See the latest version at https://github.com/marketplace/actions/official-sonarqube-scan env: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} + SONAR_HOST_URL: ${{ vars.SONAR_HOST_URL }} ``` If your source code file names contain special characters that are not covered by the locale range of `en_US.UTF-8`, you can configure your desired locale like this: @@ -64,7 +64,7 @@ If your source code file names contain special characters that are not covered b uses: sonarsource/sonarqube-scan-action@ # Ex: v2.1.0, See the latest version at https://github.com/marketplace/actions/official-sonarqube-scan env: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} + SONAR_HOST_URL: ${{ vars.SONAR_HOST_URL }} LC_ALL: "ru_RU.UTF-8" ``` @@ -75,7 +75,7 @@ If your SonarQube server uses a self-signed certificate, you can pass a root cer uses: sonarsource/sonarqube-scan-action@ # Ex: v2.1.0, See the latest version at https://github.com/marketplace/actions/official-sonarqube-scan env: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} + SONAR_HOST_URL: ${{ vars.SONAR_HOST_URL }} SONAR_ROOT_CERT: ${{ secrets.SONAR_ROOT_CERT }} ``` @@ -106,7 +106,7 @@ More information about possible analysis parameters can be found in [the documen ### Environment variables - `SONAR_TOKEN` – **Required** this is the token used to authenticate access to SonarQube. You can read more about security tokens [here](https://docs.sonarqube.org/latest/user-guide/user-token/). You can set the `SONAR_TOKEN` environment variable in the "Secrets" settings page of your repository, or you can add them at the level of your GitHub organization (recommended). -- `SONAR_HOST_URL` – **Required** this tells the scanner where SonarQube is hosted. You can set the `SONAR_HOST_URL` environment variable in the "Secrets" settings page of your repository, or you can add them at the level of your GitHub organization (recommended). +- `SONAR_HOST_URL` – **Required** this tells the scanner where SonarQube is hosted. You can set the `SONAR_HOST_URL` environment variable in the "Variables" settings page of your repository, or you can add them at the level of your GitHub organization (recommended). - `SONAR_ROOT_CERT` – Holds an additional root certificate (in PEM format) that is used to validate the SonarQube server certificate. You can set the `SONAR_ROOT_CERT` environment variable in the "Secrets" settings page of your repository, or you can add them at the level of your GitHub organization (recommended). ## Alternatives for Java, .NET, and C/C++ projects From e56fc172a4296390592cebc68554510e3a1ea74d Mon Sep 17 00:00:00 2001 From: Benjamin Raymond <31401273+7PH@users.noreply.github.com> Date: Thu, 6 Jun 2024 17:11:09 +0200 Subject: [PATCH 23/60] SQSCANGHA-37 Update C++/C recommendation adding AutoScan recommendation --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 241cce8..edc6836 100644 --- a/README.md +++ b/README.md @@ -116,7 +116,7 @@ This GitHub Action will not work for all technologies. If you are in one of the * Your code is built with Maven. Read the documentation about our [Scanner for Maven](https://redirect.sonarsource.com/doc/install-configure-scanner-maven.html). * Your code is built with Gradle. Read the documentation about our [Scanner for Gradle](https://redirect.sonarsource.com/doc/gradle.html). * You want to analyze a .NET solution. Read the documentation about our [Scanner for .NET](https://redirect.sonarsource.com/doc/install-configure-scanner-msbuild.html). -* You want to analyze C/C++ code. Use the [SonarQube C and C++](https://github.com/SonarSource/sonarqube-github-c-cpp) GitHub Action. +* You want to analyze C or C++ code. Starting from SonarQube 10.6, this GitHub Action will scan C and C++ out of the box. If you want to have better control over the scan configuration/setup, you can switch to the [SonarQube C and C++](https://github.com/SonarSource/sonarqube-github-c-cpp) GitHub Action. ## Error cleaning up workspace From 540792c588b5c2740ad2bb4667db5cd46ae678f2 Mon Sep 17 00:00:00 2001 From: Csaba Feher Date: Thu, 13 Jun 2024 11:47:45 +0200 Subject: [PATCH 24/60] Revert "SQSCANGHA-28 Support passing args with spaces" This reverts commit 16be80a08001cc68072c0b1eafb58f7abafc4a10. --- .github/workflows/qa.yml | 5 ++--- entrypoint.sh | 3 +-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index 3e17d55..61a418e 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -19,13 +19,12 @@ jobs: - name: Run action with args uses: ./ with: - args: >- - "-Dsonar.someArg=a value with spaces" -Dsonar.scanner.dumpToFile=./output.properties + args: -Dsonar.someArg=aValue -Dsonar.scanner.dumpToFile=./output.properties env: SONAR_HOST_URL: http://not_actually_used - name: Assert run: | - ./test/assertFileContains ./output.properties "sonar.someArg=a value with spaces" + ./test/assertFileContains ./output.properties "sonar.someArg=aValue" projectBaseDirInputTest: name: > 'projectBaseDir' input diff --git a/entrypoint.sh b/entrypoint.sh index 5bca08c..a687be7 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -32,6 +32,5 @@ fi unset JAVA_HOME -eval "args=(${INPUT_ARGS})" -sonar-scanner $debug_flag "-Dsonar.projectBaseDir=${INPUT_PROJECTBASEDIR}" "${args[@]}" +sonar-scanner $debug_flag -Dsonar.projectBaseDir=${INPUT_PROJECTBASEDIR} ${INPUT_ARGS} From aecaf43ae57e412bd97d70ef9ce6076e672fe0a9 Mon Sep 17 00:00:00 2001 From: Julien HENRY Date: Tue, 2 Jul 2024 09:56:02 +0200 Subject: [PATCH 25/60] SQSCANGHA-40 Restore permission fix for files in the project basedir --- .github/workflows/qa.yml | 37 +++++++++++++++++++++++++++++++++++++ cleanup.sh | 10 +++++----- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index 61a418e..350a7b1 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -153,3 +153,40 @@ jobs: - name: Assert run: | ./test/assertFileContains ./output.properties "sonar.verbose=true" + runAnalysisWithCacheTest: + runs-on: ubuntu-latest + services: + sonarqube: + image: sonarqube:lts-community + ports: + - 9000:9000 + volumes: + - sonarqube_data:/opt/sonarqube/data + - sonarqube_logs:/opt/sonarqube/logs + - sonarqube_extensions:/opt/sonarqube/extensions + options: >- + --health-cmd "grep -Fq \"SonarQube is operational\" /opt/sonarqube/logs/sonar.log" + --health-interval 10s + --health-timeout 5s + --health-retries 10 + steps: + - uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + - name: SonarQube Cache + uses: actions/cache@v4 + with: + path: ${{ github.workspace }}/.sonar/cache + key: ${{ runner.os }}-sonar + - name: Run action on sample project + id: runTest + uses: ./ + env: + SONAR_HOST_URL: http://sonarqube:9000 + SONAR_USER_HOME: ${{ github.workspace }}/.sonar + with: + args: -Dsonar.login=admin -Dsonar.password=admin + projectBaseDir: ./test/example-project + - name: Assert + run: | + ./test/assertFileExists ./test/example-project/.scannerwork/report-task.txt diff --git a/cleanup.sh b/cleanup.sh index 2a435a7..f1d32a4 100755 --- a/cleanup.sh +++ b/cleanup.sh @@ -2,12 +2,12 @@ set -e -if [ ! -d "${INPUT_PROJECTBASEDIR%/}/.scannerwork" ]; then - echo ".scannerwork directory not found; nothing to clean up." - exit -fi +# Reset all files permissions to the default Runner user and group to allow the follow up steps (mainly cache) to access all files. +# Assume that the first (non-hidden) file in the project directory is one from the project, and not one written by the scanner _tmp_file=$(ls "${INPUT_PROJECTBASEDIR%/}/" | head -1) +echo "Reading permissions from $_tmp_file" PERM=$(stat -c "%u:%g" "${INPUT_PROJECTBASEDIR%/}/$_tmp_file") -chown -R $PERM "${INPUT_PROJECTBASEDIR%/}/.scannerwork/" \ No newline at end of file +echo "Applying permissions $PERM to all files in the project base directory" +chown -R $PERM "${INPUT_PROJECTBASEDIR%/}/" \ No newline at end of file From bfafdf2896c713c5d4172ee174843c7207810bc8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 5 Jun 2024 12:34:24 +0000 Subject: [PATCH 26/60] NO-JIRA Bump madhead/semver-utils Bumps [madhead/semver-utils](https://github.com/madhead/semver-utils) from 40bbdc6e50b258c09f35f574e83c51f60d2ce3a2 to ed58b1e544d13426a67fea39cb19638b3c5623d4. - [Release notes](https://github.com/madhead/semver-utils/releases) - [Commits](https://github.com/madhead/semver-utils/compare/40bbdc6e50b258c09f35f574e83c51f60d2ce3a2...ed58b1e544d13426a67fea39cb19638b3c5623d4) --- updated-dependencies: - dependency-name: madhead/semver-utils dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: Benjamin Raymond <31401273+7PH@users.noreply.github.com> --- .github/workflows/update-tags.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/update-tags.yml b/.github/workflows/update-tags.yml index a07d193..13953b7 100644 --- a/.github/workflows/update-tags.yml +++ b/.github/workflows/update-tags.yml @@ -16,7 +16,7 @@ jobs: uses: actions/checkout@v4 - name: Parse semver - uses: madhead/semver-utils@40bbdc6e50b258c09f35f574e83c51f60d2ce3a2 # v4.0.0 + uses: madhead/semver-utils@v4 id: version with: version: ${{ github.ref_name }} @@ -24,7 +24,7 @@ jobs: - name: Update tags run: | TAGS='v${{ steps.version.outputs.major }} v${{ steps.version.outputs.major }}.${{ steps.version.outputs.minor }}' - + for t in $TAGS; do git tag -f "$t" git push origin ":$t" 2>/dev/null || true From 8c8682dac7c144ee82da08feadfd0b169522397e Mon Sep 17 00:00:00 2001 From: vil02 Date: Fri, 12 Jul 2024 21:24:55 +0200 Subject: [PATCH 27/60] Prevent globbing and word splitting in `cleanup.sh` --- cleanup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cleanup.sh b/cleanup.sh index f1d32a4..bdc3316 100755 --- a/cleanup.sh +++ b/cleanup.sh @@ -10,4 +10,4 @@ echo "Reading permissions from $_tmp_file" PERM=$(stat -c "%u:%g" "${INPUT_PROJECTBASEDIR%/}/$_tmp_file") echo "Applying permissions $PERM to all files in the project base directory" -chown -R $PERM "${INPUT_PROJECTBASEDIR%/}/" \ No newline at end of file +chown -R "$PERM" "${INPUT_PROJECTBASEDIR%/}/" From 0c0f3958d90fc466625f1d1af1f47bddd4cc6bd1 Mon Sep 17 00:00:00 2001 From: istvan-bodo-sonarsource Date: Tue, 13 Aug 2024 10:47:43 +0200 Subject: [PATCH 28/60] SQSCANGHA-42 Update scanner cli to v11.0 --- .github/workflows/qa.yml | 12 ++++++------ Dockerfile | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index 350a7b1..4e80c49 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -19,7 +19,7 @@ jobs: - name: Run action with args uses: ./ with: - args: -Dsonar.someArg=aValue -Dsonar.scanner.dumpToFile=./output.properties + args: -Dsonar.someArg=aValue -Dsonar.scanner.internal.dumpToFile=./output.properties env: SONAR_HOST_URL: http://not_actually_used - name: Assert @@ -37,7 +37,7 @@ jobs: - name: Run action with projectBaseDir uses: ./ with: - args: -Dsonar.scanner.dumpToFile=./output.properties + args: -Dsonar.scanner.internal.dumpToFile=./output.properties projectBaseDir: ./baseDir env: SONAR_HOST_URL: http://not_actually_used @@ -60,7 +60,7 @@ jobs: SONAR_HOST_URL: http://not_actually_used with: projectBaseDir: ./test/gradle-project - args: -Dsonar.scanner.dumpToFile=./output.properties + args: -Dsonar.scanner.internal.dumpToFile=./output.properties - name: Assert run: | ./test/assertFileExists ./output.properties @@ -80,7 +80,7 @@ jobs: SONAR_HOST_URL: http://not_actually_used with: projectBaseDir: ./test/gradle-project - args: -Dsonar.scanner.dumpToFile=./output.properties + args: -Dsonar.scanner.internal.dumpToFile=./output.properties - name: Assert run: | ./test/assertFileExists ./output.properties @@ -100,7 +100,7 @@ jobs: SONAR_HOST_URL: http://not_actually_used with: projectBaseDir: ./test/maven-project - args: -Dsonar.scanner.dumpToFile=./output.properties + args: -Dsonar.scanner.internal.dumpToFile=./output.properties - name: Assert run: | ./test/assertFileExists ./output.properties @@ -146,7 +146,7 @@ jobs: - name: Run action with debug mode uses: ./ with: - args: -Dsonar.scanner.dumpToFile=./output.properties + args: -Dsonar.scanner.internal.dumpToFile=./output.properties env: RUNNER_DEBUG: 1 SONAR_HOST_URL: http://not_actually_used diff --git a/Dockerfile b/Dockerfile index a38bed0..f86af93 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ -FROM sonarsource/sonar-scanner-cli:10.0 +FROM sonarsource/sonar-scanner-cli:11.0 -LABEL version="2.1.0" \ +LABEL version="3.0.0" \ repository="https://github.com/sonarsource/sonarqube-scan-action" \ homepage="https://github.com/sonarsource/sonarqube-scan-action" \ maintainer="SonarSource" \ From 2af7c4bea3abd8c236b5edb80998f31374896f09 Mon Sep 17 00:00:00 2001 From: istvan-bodo-sonarsource Date: Wed, 14 Aug 2024 13:15:47 +0200 Subject: [PATCH 29/60] Revert "SQSCANGHA-42 Update scanner cli to v11.0" This reverts commit 0c0f3958d90fc466625f1d1af1f47bddd4cc6bd1. --- .github/workflows/qa.yml | 12 ++++++------ Dockerfile | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index 4e80c49..350a7b1 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -19,7 +19,7 @@ jobs: - name: Run action with args uses: ./ with: - args: -Dsonar.someArg=aValue -Dsonar.scanner.internal.dumpToFile=./output.properties + args: -Dsonar.someArg=aValue -Dsonar.scanner.dumpToFile=./output.properties env: SONAR_HOST_URL: http://not_actually_used - name: Assert @@ -37,7 +37,7 @@ jobs: - name: Run action with projectBaseDir uses: ./ with: - args: -Dsonar.scanner.internal.dumpToFile=./output.properties + args: -Dsonar.scanner.dumpToFile=./output.properties projectBaseDir: ./baseDir env: SONAR_HOST_URL: http://not_actually_used @@ -60,7 +60,7 @@ jobs: SONAR_HOST_URL: http://not_actually_used with: projectBaseDir: ./test/gradle-project - args: -Dsonar.scanner.internal.dumpToFile=./output.properties + args: -Dsonar.scanner.dumpToFile=./output.properties - name: Assert run: | ./test/assertFileExists ./output.properties @@ -80,7 +80,7 @@ jobs: SONAR_HOST_URL: http://not_actually_used with: projectBaseDir: ./test/gradle-project - args: -Dsonar.scanner.internal.dumpToFile=./output.properties + args: -Dsonar.scanner.dumpToFile=./output.properties - name: Assert run: | ./test/assertFileExists ./output.properties @@ -100,7 +100,7 @@ jobs: SONAR_HOST_URL: http://not_actually_used with: projectBaseDir: ./test/maven-project - args: -Dsonar.scanner.internal.dumpToFile=./output.properties + args: -Dsonar.scanner.dumpToFile=./output.properties - name: Assert run: | ./test/assertFileExists ./output.properties @@ -146,7 +146,7 @@ jobs: - name: Run action with debug mode uses: ./ with: - args: -Dsonar.scanner.internal.dumpToFile=./output.properties + args: -Dsonar.scanner.dumpToFile=./output.properties env: RUNNER_DEBUG: 1 SONAR_HOST_URL: http://not_actually_used diff --git a/Dockerfile b/Dockerfile index f86af93..a38bed0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ -FROM sonarsource/sonar-scanner-cli:11.0 +FROM sonarsource/sonar-scanner-cli:10.0 -LABEL version="3.0.0" \ +LABEL version="2.1.0" \ repository="https://github.com/sonarsource/sonarqube-scan-action" \ homepage="https://github.com/sonarsource/sonarqube-scan-action" \ maintainer="SonarSource" \ From f885e52a7572cf7943f28637e75730227df2dbf2 Mon Sep 17 00:00:00 2001 From: Samir M Date: Thu, 22 Aug 2024 16:14:22 +0200 Subject: [PATCH 30/60] BUILD-6088 Create SECURITY.md --- SECURITY.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..3989705 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,13 @@ +# Reporting Security Issues + +A mature software vulnerability treatment process is a cornerstone of a robust information security management system. Contributions from the community play an important role in the evolution and security of our products, and in safeguarding the security and privacy of our users. + +If you believe you have discovered a security vulnerability in Sonar's products, we encourage you to report it immediately. + +To responsibly report a security issue, please email us at [security@sonarsource.com](mailto:security@sonarsource.com). Sonar’s security team will acknowledge your report, guide you through the next steps, or request additional information if necessary. Customers with a support contract can also report the vulnerability directly through the support channel. + +For security vulnerabilities found in third-party libraries, please also contact the library's owner or maintainer directly. + +## Responsible Disclosure Policy + +For more information about disclosing a security vulnerability to Sonar, please refer to our community post: [Responsible Vulnerability Disclosure](https://community.sonarsource.com/t/responsible-vulnerability-disclosure/9317). \ No newline at end of file From 884b79409bbd464b2a59edc326a4b77dc56b2195 Mon Sep 17 00:00:00 2001 From: Julien HENRY Date: Tue, 24 Sep 2024 11:59:38 +0200 Subject: [PATCH 31/60] SQSCANGHA-42 Update Scanner CLI Docker to 11.1 --- .github/workflows/qa.yml | 80 ++++++++++++++++++++++++++++++++++++---- Dockerfile | 4 +- entrypoint.sh | 21 ++++++++--- 3 files changed, 90 insertions(+), 15 deletions(-) diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index 350a7b1..f2be5a2 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -8,6 +8,22 @@ on: types: [opened, synchronize, reopened] jobs: + noInputsTest: + name: > + No inputs + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + - name: Run action with args + uses: ./ + env: + SONAR_HOST_URL: http://not_actually_used + SONAR_SCANNER_JSON_PARAMS: '{"sonar.scanner.internal.dumpToFile": "./output.properties"}' + - name: Assert + run: | + ./test/assertFileContains ./output.properties "sonar.projectBaseDir=." argsInputTest: name: > 'args' input @@ -19,9 +35,10 @@ jobs: - name: Run action with args uses: ./ with: - args: -Dsonar.someArg=aValue -Dsonar.scanner.dumpToFile=./output.properties + args: -Dsonar.someArg=aValue env: SONAR_HOST_URL: http://not_actually_used + SONAR_SCANNER_JSON_PARAMS: '{"sonar.scanner.internal.dumpToFile": "./output.properties"}' - name: Assert run: | ./test/assertFileContains ./output.properties "sonar.someArg=aValue" @@ -37,10 +54,10 @@ jobs: - name: Run action with projectBaseDir uses: ./ with: - args: -Dsonar.scanner.dumpToFile=./output.properties projectBaseDir: ./baseDir env: SONAR_HOST_URL: http://not_actually_used + SONAR_SCANNER_JSON_PARAMS: '{"sonar.scanner.internal.dumpToFile": "./output.properties"}' - name: Assert run: | ./test/assertFileContains ./output.properties "sonar.projectBaseDir=.*/baseDir" @@ -58,9 +75,9 @@ jobs: continue-on-error: true env: SONAR_HOST_URL: http://not_actually_used + SONAR_SCANNER_JSON_PARAMS: '{"sonar.scanner.internal.dumpToFile": "./output.properties"}' with: projectBaseDir: ./test/gradle-project - args: -Dsonar.scanner.dumpToFile=./output.properties - name: Assert run: | ./test/assertFileExists ./output.properties @@ -78,9 +95,9 @@ jobs: continue-on-error: true env: SONAR_HOST_URL: http://not_actually_used + SONAR_SCANNER_JSON_PARAMS: '{"sonar.scanner.internal.dumpToFile": "./output.properties"}' with: projectBaseDir: ./test/gradle-project - args: -Dsonar.scanner.dumpToFile=./output.properties - name: Assert run: | ./test/assertFileExists ./output.properties @@ -98,9 +115,9 @@ jobs: continue-on-error: true env: SONAR_HOST_URL: http://not_actually_used + SONAR_SCANNER_JSON_PARAMS: '{"sonar.scanner.internal.dumpToFile": "./output.properties"}' with: projectBaseDir: ./test/maven-project - args: -Dsonar.scanner.dumpToFile=./output.properties - name: Assert run: | ./test/assertFileExists ./output.properties @@ -145,11 +162,10 @@ jobs: token: ${{ secrets.GITHUB_TOKEN }} - name: Run action with debug mode uses: ./ - with: - args: -Dsonar.scanner.dumpToFile=./output.properties env: RUNNER_DEBUG: 1 SONAR_HOST_URL: http://not_actually_used + SONAR_SCANNER_JSON_PARAMS: '{"sonar.scanner.internal.dumpToFile": "./output.properties"}' - name: Assert run: | ./test/assertFileContains ./output.properties "sonar.verbose=true" @@ -190,3 +206,53 @@ jobs: - name: Assert run: | ./test/assertFileExists ./test/example-project/.scannerwork/report-task.txt + useSslCertificate: + name: > + 'SONAR_ROOT_CERT' is converted to truststore + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + - name: Run action with SSL certificate + uses: ./ + env: + SONAR_ROOT_CERT: | + -----BEGIN CERTIFICATE----- + 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 + Fct6d1S08JAosVnZcP2P7Yz+TbmDRtsqCgk= + -----END CERTIFICATE----- + SONAR_HOST_URL: http://not_actually_used + SONAR_SCANNER_JSON_PARAMS: '{"sonar.scanner.internal.dumpToFile": "./output.properties"}' + - name: Assert + run: | + ./test/assertFileContains ./output.properties "sonar.scanner.truststorePassword=changeit" diff --git a/Dockerfile b/Dockerfile index a38bed0..cf151b3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ -FROM sonarsource/sonar-scanner-cli:10.0 +FROM sonarsource/sonar-scanner-cli:11.1 -LABEL version="2.1.0" \ +LABEL version="3.0.0" \ repository="https://github.com/sonarsource/sonarqube-scan-action" \ homepage="https://github.com/sonarsource/sonarqube-scan-action" \ maintainer="SonarSource" \ diff --git a/entrypoint.sh b/entrypoint.sh index a687be7..790ab2a 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -1,6 +1,8 @@ #!/bin/bash -set -e +set -eo pipefail + +declare -a args=() if [[ -z "${SONAR_TOKEN}" ]]; then echo "============================ WARNING ============================" @@ -9,10 +11,15 @@ if [[ -z "${SONAR_TOKEN}" ]]; then fi if [[ -n "${SONAR_ROOT_CERT}" ]]; then - echo "Adding custom root certificate to java certificate store" + echo "Adding custom root certificate to the scanner truststore" rm -f /tmp/tmpcert.pem echo "${SONAR_ROOT_CERT}" > /tmp/tmpcert.pem - keytool -keystore /etc/ssl/certs/java/cacerts -storepass changeit -noprompt -trustcacerts -importcert -alias sonarqube -file /tmp/tmpcert.pem + # we can't use the default "sonar" password as keytool requires a password with at least 6 characters + args+=("-Dsonar.scanner.truststorePassword=changeit") + mkdir -p $SONAR_USER_HOME/ssl + keytool -storetype PKCS12 -keystore $SONAR_USER_HOME/ssl/truststore.p12 -storepass changeit -noprompt -trustcacerts -importcert -alias sonarqube -file /tmp/tmpcert.pem + # for older SQ versions < 10.6 + export SONAR_SCANNER_OPTS="${SONAR_SCANNER_OPTS:-} -Djavax.net.ssl.trustStore=$SONAR_USER_HOME/ssl/truststore.p12 -Djavax.net.ssl.trustStorePassword=changeit" fi if [[ -f "${INPUT_PROJECTBASEDIR%/}/pom.xml" ]]; then @@ -25,12 +32,14 @@ if [[ -f "${INPUT_PROJECTBASEDIR%/}/build.gradle" || -f "${INPUT_PROJECTBASEDIR to get more accurate results." fi -debug_flag='' + if [[ "$RUNNER_DEBUG" == '1' ]]; then - debug_flag='--debug' + args+=("--debug") fi unset JAVA_HOME -sonar-scanner $debug_flag -Dsonar.projectBaseDir=${INPUT_PROJECTBASEDIR} ${INPUT_ARGS} +args+=("-Dsonar.projectBaseDir=${INPUT_PROJECTBASEDIR}") + +sonar-scanner "${args[@]}" ${INPUT_ARGS} From 66a0baa492c7732d783f7c7174560f99482410bf Mon Sep 17 00:00:00 2001 From: Julien HENRY Date: Wed, 6 Nov 2024 12:22:05 +0100 Subject: [PATCH 32/60] SQSCANGHA-48 Migrating cirrus-modules v2 to v3 --- .cirrus.star | 2 +- .cirrus.yml | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.cirrus.star b/.cirrus.star index 28b17b7..9f91e15 100644 --- a/.cirrus.star +++ b/.cirrus.star @@ -1,4 +1,4 @@ -load("github.com/SonarSource/cirrus-modules@v2", "load_features") +load("github.com/SonarSource/cirrus-modules@v3", "load_features") def main(ctx): return load_features(ctx) diff --git a/.cirrus.yml b/.cirrus.yml index 358472c..97cdd3a 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -15,7 +15,6 @@ vm_instance_template: &VM_TEMPLATE image: docker-builder-v* type: t2.small region: eu-central-1 - subnet_id: ${CIRRUS_AWS_SUBNET} disk: 10 cpu: 4 memory: 16G From 13990a695682794b53148ff9f6a8b6e22e43955e Mon Sep 17 00:00:00 2001 From: Antonio Aversa Date: Thu, 7 Nov 2024 14:13:56 +0100 Subject: [PATCH 33/60] Add warning in v3 about upcoming Docker removal in v4 --- Dockerfile | 2 +- entrypoint.sh | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index cf151b3..dd81624 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ FROM sonarsource/sonar-scanner-cli:11.1 -LABEL version="3.0.0" \ +LABEL version="3.1.0" \ repository="https://github.com/sonarsource/sonarqube-scan-action" \ homepage="https://github.com/sonarsource/sonarqube-scan-action" \ maintainer="SonarSource" \ diff --git a/entrypoint.sh b/entrypoint.sh index 790ab2a..d40ba60 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -2,6 +2,8 @@ set -eo pipefail +echo "::warning title=Docker removed in the next major version::Users on the master branch of this GitHub action will be upgraded automatically on December 9th to its next major version, which replaces Docker with a composite action, executing in the runner environment. Self-hosted runners analyzing JS/TS code against SonarQube 10.2 and below will need to have Node JS installed." + declare -a args=() if [[ -z "${SONAR_TOKEN}" ]]; then From 94d4f8ac4aaefccd7fb84bff00b0aeb2d65fcd49 Mon Sep 17 00:00:00 2001 From: Antonio Aversa Date: Tue, 12 Nov 2024 14:16:39 +0100 Subject: [PATCH 34/60] SQSCANGHA-46 Replace the Docker action by a composite action --- .cirrus.star | 4 --- .cirrus.yml | 37 ---------------------------- .github/workflows/qa.yml | 41 ++++++++++++++++++++++--------- Dockerfile | 21 ---------------- README.md | 15 ------------ action.yml | 38 ++++++++++++++++++++++++----- cleanup.sh | 13 ---------- entrypoint.sh | 47 ------------------------------------ install-sonar-scanner-cli.sh | 34 ++++++++++++++++++++++++++ run-sonar-scanner.sh | 41 +++++++++++++++++++++++++++++++ sanity-checks.sh | 18 ++++++++++++++ 11 files changed, 155 insertions(+), 154 deletions(-) delete mode 100644 .cirrus.star delete mode 100644 .cirrus.yml delete mode 100644 Dockerfile delete mode 100755 cleanup.sh delete mode 100755 entrypoint.sh create mode 100755 install-sonar-scanner-cli.sh create mode 100755 run-sonar-scanner.sh create mode 100755 sanity-checks.sh diff --git a/.cirrus.star b/.cirrus.star deleted file mode 100644 index 9f91e15..0000000 --- a/.cirrus.star +++ /dev/null @@ -1,4 +0,0 @@ -load("github.com/SonarSource/cirrus-modules@v3", "load_features") - -def main(ctx): - return load_features(ctx) diff --git a/.cirrus.yml b/.cirrus.yml deleted file mode 100644 index 97cdd3a..0000000 --- a/.cirrus.yml +++ /dev/null @@ -1,37 +0,0 @@ -env: - CIRRUS_VAULT_URL: https://vault.sonar.build:8200 - CIRRUS_VAULT_AUTH_PATH: jwt-cirrusci - CIRRUS_VAULT_ROLE: cirrusci-${CIRRUS_REPO_OWNER}-${CIRRUS_REPO_NAME} - - # Mend scan global configuration - MEND_API_KEY: VAULT[development/kv/data/mend data.apikey] - - # Staging image configuration - STAGING_IMAGE_NAME: sonarsource/sonarqube-scan-action - CURRENT_TAG: master - -vm_instance_template: &VM_TEMPLATE - experimental: true # see https://github.com/cirruslabs/cirrus-ci-docs/issues/1051 - image: docker-builder-v* - type: t2.small - region: eu-central-1 - disk: 10 - cpu: 4 - memory: 16G - -mend_task: - ec2_instance: - <<: *VM_TEMPLATE - # run only on master and long-term branches - only_if: $CIRRUS_USER_COLLABORATOR == 'true' && ($CIRRUS_BRANCH == "master" || $CIRRUS_BRANCH =~ "branch-.*") - setup_script: - - docker build --tag "${STAGING_IMAGE_NAME}:${CURRENT_TAG}" . - - apt-get remove -y unattended-upgrades - - apt-get update && apt-get install -y --no-install-recommends openjdk-17-jre - - curl -sSL https://unified-agent.s3.amazonaws.com/wss-unified-agent.jar -o wss-unified-agent.jar - - echo "docker.includes=${CURRENT_TAG}" >> .cirrus/wss-unified-agent.config - scan_script: - - echo "Scan the ${STAGING_IMAGE_NAME}:${CURRENT_TAG} image" - - java -jar wss-unified-agent.jar -c .cirrus/wss-unified-agent.config -apiKey $MEND_API_KEY - - diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index f2be5a2..f4bd70c 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -27,7 +27,10 @@ jobs: argsInputTest: name: > 'args' input - runs-on: ubuntu-latest + strategy: + matrix: + os: [ ubuntu-latest, windows-latest, macos-latest ] + runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 with: @@ -35,7 +38,7 @@ jobs: - name: Run action with args uses: ./ with: - args: -Dsonar.someArg=aValue + args: -Dsonar.someArg=aValue -Dsonar.scanner.internal.dumpToFile=./output.properties env: SONAR_HOST_URL: http://not_actually_used SONAR_SCANNER_JSON_PARAMS: '{"sonar.scanner.internal.dumpToFile": "./output.properties"}' @@ -45,7 +48,10 @@ jobs: projectBaseDirInputTest: name: > 'projectBaseDir' input - runs-on: ubuntu-latest + strategy: + matrix: + os: [ ubuntu-latest, windows-latest, macos-latest ] + runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 with: @@ -54,6 +60,7 @@ jobs: - name: Run action with projectBaseDir uses: ./ with: + args: -Dsonar.scanner.internal.dumpToFile=./output.properties projectBaseDir: ./baseDir env: SONAR_HOST_URL: http://not_actually_used @@ -78,6 +85,7 @@ jobs: SONAR_SCANNER_JSON_PARAMS: '{"sonar.scanner.internal.dumpToFile": "./output.properties"}' with: projectBaseDir: ./test/gradle-project + args: -Dsonar.scanner.internal.dumpToFile=./output.properties - name: Assert run: | ./test/assertFileExists ./output.properties @@ -98,6 +106,7 @@ jobs: SONAR_SCANNER_JSON_PARAMS: '{"sonar.scanner.internal.dumpToFile": "./output.properties"}' with: projectBaseDir: ./test/gradle-project + args: -Dsonar.scanner.internal.dumpToFile=./output.properties - name: Assert run: | ./test/assertFileExists ./output.properties @@ -118,6 +127,7 @@ jobs: SONAR_SCANNER_JSON_PARAMS: '{"sonar.scanner.internal.dumpToFile": "./output.properties"}' with: projectBaseDir: ./test/maven-project + args: -Dsonar.scanner.internal.dumpToFile=./output.properties - name: Assert run: | ./test/assertFileExists ./output.properties @@ -145,7 +155,7 @@ jobs: id: runTest uses: ./ env: - SONAR_HOST_URL: http://sonarqube:9000 + SONAR_HOST_URL: http://localhost:9000 with: args: -Dsonar.login=admin -Dsonar.password=admin projectBaseDir: ./test/example-project @@ -155,13 +165,18 @@ jobs: runnerDebugUsedTest: name: > 'RUNNER_DEBUG' is used - runs-on: ubuntu-latest + strategy: + matrix: + os: [ ubuntu-latest, windows-latest, macos-latest ] + runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 with: token: ${{ secrets.GITHUB_TOKEN }} - name: Run action with debug mode uses: ./ + with: + args: -Dsonar.scanner.internal.dumpToFile=./output.properties env: RUNNER_DEBUG: 1 SONAR_HOST_URL: http://not_actually_used @@ -193,29 +208,34 @@ jobs: uses: actions/cache@v4 with: path: ${{ github.workspace }}/.sonar/cache - key: ${{ runner.os }}-sonar + key: ${{ runner.os }}-${{ runner.arch }}-sonar - name: Run action on sample project id: runTest uses: ./ env: - SONAR_HOST_URL: http://sonarqube:9000 + SONAR_HOST_URL: http://localhost:9000 SONAR_USER_HOME: ${{ github.workspace }}/.sonar with: args: -Dsonar.login=admin -Dsonar.password=admin projectBaseDir: ./test/example-project - name: Assert run: | - ./test/assertFileExists ./test/example-project/.scannerwork/report-task.txt + ./test/assertFileExists ./test/example-project/.scannerwork/report-task.txt useSslCertificate: name: > 'SONAR_ROOT_CERT' is converted to truststore - runs-on: ubuntu-latest + strategy: + matrix: + os: [ ubuntu-latest, windows-latest, macos-latest ] + runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 with: token: ${{ secrets.GITHUB_TOKEN }} - name: Run action with SSL certificate uses: ./ + with: + args: -Dsonar.scanner.internal.dumpToFile=./output.properties env: SONAR_ROOT_CERT: | -----BEGIN CERTIFICATE----- @@ -252,7 +272,6 @@ jobs: Fct6d1S08JAosVnZcP2P7Yz+TbmDRtsqCgk= -----END CERTIFICATE----- SONAR_HOST_URL: http://not_actually_used - SONAR_SCANNER_JSON_PARAMS: '{"sonar.scanner.internal.dumpToFile": "./output.properties"}' - name: Assert run: | - ./test/assertFileContains ./output.properties "sonar.scanner.truststorePassword=changeit" + ./test/assertFileExists ~/.sonar/ssl/truststore.p12 \ No newline at end of file diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index dd81624..0000000 --- a/Dockerfile +++ /dev/null @@ -1,21 +0,0 @@ -FROM sonarsource/sonar-scanner-cli:11.1 - -LABEL version="3.1.0" \ - repository="https://github.com/sonarsource/sonarqube-scan-action" \ - homepage="https://github.com/sonarsource/sonarqube-scan-action" \ - maintainer="SonarSource" \ - com.github.actions.name="SonarQube Scan" \ - com.github.actions.description="Scan your code with SonarQube to detect Bugs, Vulnerabilities and Code Smells in up to 27 programming languages!" \ - com.github.actions.icon="check" \ - com.github.actions.color="green" - -# GitHub actions should be run under ROOT -# https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners#docker-container-filesystem -USER 0 - -COPY entrypoint.sh /entrypoint.sh -RUN chmod +x /entrypoint.sh -COPY cleanup.sh /cleanup.sh -RUN chmod +x /cleanup.sh - -ENTRYPOINT ["/entrypoint.sh"] diff --git a/README.md b/README.md index edc6836..1d83d6d 100644 --- a/README.md +++ b/README.md @@ -118,25 +118,10 @@ This GitHub Action will not work for all technologies. If you are in one of the * You want to analyze a .NET solution. Read the documentation about our [Scanner for .NET](https://redirect.sonarsource.com/doc/install-configure-scanner-msbuild.html). * You want to analyze C or C++ code. Starting from SonarQube 10.6, this GitHub Action will scan C and C++ out of the box. If you want to have better control over the scan configuration/setup, you can switch to the [SonarQube C and C++](https://github.com/SonarSource/sonarqube-github-c-cpp) GitHub Action. -## Error cleaning up workspace - -In some cases, the checkout action may fail to clean up the workspace. This is a known problem for GitHub actions implemented as a docker container (such as `sonarqube-scan-action`) when self-hosted runners are used. -Example of the error message: `File was unable to be removed Error: EACCES: permission denied, unlink '/actions-runner/_work//project/.scannerwork/.sonar_lock'` -To work around the problem, `sonarqube-scan-action` attempts to fix the permission of the temporary files that it creates. If that doesn't work, you can manually clean up the workspace by running the following action: -``` -- name: Clean the workspace - uses: docker://alpine - with: - args: /bin/sh -c "find \"${GITHUB_WORKSPACE}\" -mindepth 1 ! -name . -prune -exec rm -rf {} +" -``` -You can find more info [here](https://github.com/actions/runner/issues/434). - ## Have questions or feedback? To provide feedback (requesting a feature or reporting a bug) please post on the [SonarSource Community Forum](https://community.sonarsource.com/tags/c/help/sq/github-actions). ## License -The Dockerfile and associated scripts and documentation in this project are released under the LGPLv3 License. - Container images built with this project include third-party materials. diff --git a/action.yml b/action.yml index b2baff6..14854e5 100644 --- a/action.yml +++ b/action.yml @@ -4,11 +4,6 @@ description: > branding: icon: check color: green -runs: - using: docker - image: Dockerfile - entrypoint: "/entrypoint.sh" - post-entrypoint: "/cleanup.sh" inputs: args: description: Additional arguments to the sonar-scanner @@ -16,4 +11,35 @@ inputs: projectBaseDir: description: Set the sonar.projectBaseDir analysis property required: false - default: . + scannerVersion: + description: Version of the Sonar Scanner CLI to use + required: false + default: 6.2.1.4610 +runs: + using: "composite" + steps: + - name: Sanity checks + run: ${GITHUB_ACTION_PATH}/sanity-checks.sh + shell: bash + env: + INPUT_PROJECTBASEDIR: ${{ inputs.projectBaseDir }} + - name: Load Sonar Scanner CLI from cache + id: sonar-scanner-cli + uses: actions/cache@v4.0.2 + with: + path: ${{ runner.temp }}/sonar-scanner-cli-${{ inputs.scannerVersion }}-${{ runner.os }}-${{ runner.arch }} + key: sonar-scanner-cli-${{ inputs.scannerVersion }}-${{ runner.os }}-${{ runner.arch }} + - name: Install Sonar Scanner CLI + if: steps.sonar-scanner-cli.outputs.cache-hit != 'true' + run: ${GITHUB_ACTION_PATH}/install-sonar-scanner-cli.sh + shell: bash + env: + INPUT_SCANNERVERSION: ${{ inputs.scannerVersion }} + - name: Add SonarScanner CLI to the PATH + run: echo "${RUNNER_TEMP}/sonar-scanner-cli-${{ inputs.scannerVersion }}-${{ runner.os }}-${{ runner.arch }}/bin" >> $GITHUB_PATH + shell: bash + - name: Run SonarScanner + run: ${GITHUB_ACTION_PATH}/run-sonar-scanner.sh ${{ inputs.args }} + shell: bash + env: + INPUT_PROJECTBASEDIR: ${{ inputs.projectBaseDir }} \ No newline at end of file diff --git a/cleanup.sh b/cleanup.sh deleted file mode 100755 index bdc3316..0000000 --- a/cleanup.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash - -set -e - -# Reset all files permissions to the default Runner user and group to allow the follow up steps (mainly cache) to access all files. - -# Assume that the first (non-hidden) file in the project directory is one from the project, and not one written by the scanner -_tmp_file=$(ls "${INPUT_PROJECTBASEDIR%/}/" | head -1) -echo "Reading permissions from $_tmp_file" -PERM=$(stat -c "%u:%g" "${INPUT_PROJECTBASEDIR%/}/$_tmp_file") - -echo "Applying permissions $PERM to all files in the project base directory" -chown -R "$PERM" "${INPUT_PROJECTBASEDIR%/}/" diff --git a/entrypoint.sh b/entrypoint.sh deleted file mode 100755 index d40ba60..0000000 --- a/entrypoint.sh +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/bash - -set -eo pipefail - -echo "::warning title=Docker removed in the next major version::Users on the master branch of this GitHub action will be upgraded automatically on December 9th to its next major version, which replaces Docker with a composite action, executing in the runner environment. Self-hosted runners analyzing JS/TS code against SonarQube 10.2 and below will need to have Node JS installed." - -declare -a args=() - -if [[ -z "${SONAR_TOKEN}" ]]; then - echo "============================ WARNING ============================" - echo "Running this GitHub Action without SONAR_TOKEN is not recommended" - echo "============================ WARNING ============================" -fi - -if [[ -n "${SONAR_ROOT_CERT}" ]]; then - echo "Adding custom root certificate to the scanner truststore" - rm -f /tmp/tmpcert.pem - echo "${SONAR_ROOT_CERT}" > /tmp/tmpcert.pem - # we can't use the default "sonar" password as keytool requires a password with at least 6 characters - args+=("-Dsonar.scanner.truststorePassword=changeit") - mkdir -p $SONAR_USER_HOME/ssl - keytool -storetype PKCS12 -keystore $SONAR_USER_HOME/ssl/truststore.p12 -storepass changeit -noprompt -trustcacerts -importcert -alias sonarqube -file /tmp/tmpcert.pem - # for older SQ versions < 10.6 - export SONAR_SCANNER_OPTS="${SONAR_SCANNER_OPTS:-} -Djavax.net.ssl.trustStore=$SONAR_USER_HOME/ssl/truststore.p12 -Djavax.net.ssl.trustStorePassword=changeit" -fi - -if [[ -f "${INPUT_PROJECTBASEDIR%/}/pom.xml" ]]; then - echo "WARNING! Maven project detected. Sonar recommends running the 'org.sonarsource.scanner.maven:sonar-maven-plugin:sonar' goal during the build process instead of using this GitHub Action - to get more accurate results." -fi - -if [[ -f "${INPUT_PROJECTBASEDIR%/}/build.gradle" || -f "${INPUT_PROJECTBASEDIR%/}/build.gradle.kts" ]]; then - echo "WARNING! Gradle project detected. Sonar recommends using the SonarQube plugin for Gradle during the build process instead of using this GitHub Action - to get more accurate results." -fi - - -if [[ "$RUNNER_DEBUG" == '1' ]]; then - args+=("--debug") -fi - -unset JAVA_HOME - -args+=("-Dsonar.projectBaseDir=${INPUT_PROJECTBASEDIR}") - -sonar-scanner "${args[@]}" ${INPUT_ARGS} - diff --git a/install-sonar-scanner-cli.sh b/install-sonar-scanner-cli.sh new file mode 100755 index 0000000..7509d74 --- /dev/null +++ b/install-sonar-scanner-cli.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +set -eou pipefail + +#See https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/store-information-in-variables#default-environment-variables + +WGET=wget +if [[ "$RUNNER_OS" == "Linux" && "$RUNNER_ARCH" == "X64" ]]; then + FLAVOR="linux-x64" +elif [[ "$RUNNER_OS" == "Linux" && "$RUNNER_ARCH" == "ARM64" ]]; then + FLAVOR="linux-aarch64" +elif [[ "$RUNNER_OS" == "Windows" && "$RUNNER_ARCH" == "X64" ]]; then + FLAVOR="windows-x64" + WGET="C:\\msys64\\usr\\bin\\wget.exe" +elif [[ "$RUNNER_OS" == "macOS" && "$RUNNER_ARCH" == "X64" ]]; then + FLAVOR="macosx-x64" +elif [[ "$RUNNER_OS" == "macOS" && "$RUNNER_ARCH" == "ARM64" ]]; then + FLAVOR="macosx-aarch64" +else + echo "$RUNNER_OS $RUNNER_ARCH not supported" + exit 1 +fi + +set -x + +mkdir -p $RUNNER_TEMP/sonarscanner +cd $RUNNER_TEMP/sonarscanner + +$WGET --no-verbose --user-agent="sonarqube-scan-action" https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-$INPUT_SCANNERVERSION-$FLAVOR.zip + +unzip -q sonar-scanner-cli-$INPUT_SCANNERVERSION-$FLAVOR.zip + +# Folder name should correspond to the directory cached by the actions/cache +mv sonar-scanner-$INPUT_SCANNERVERSION-$FLAVOR $RUNNER_TEMP/sonar-scanner-cli-$INPUT_SCANNERVERSION-$RUNNER_OS-$RUNNER_ARCH diff --git a/run-sonar-scanner.sh b/run-sonar-scanner.sh new file mode 100755 index 0000000..13c2f69 --- /dev/null +++ b/run-sonar-scanner.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +set -eo pipefail + +if [[ "$RUNNER_OS" == "Windows" ]]; then + SCANNER_BIN="sonar-scanner.bat" +else + SCANNER_BIN="sonar-scanner" +fi + +scanner_args=() +if [[ ${SONARCLOUD_URL} ]]; then + scanner_args+=("-Dsonar.scanner.sonarcloudUrl=${SONARCLOUD_URL}") +fi + +if [[ "$RUNNER_DEBUG" == '1' ]]; then + scanner_args+=('--debug') +fi + +if [[ -n "${INPUT_PROJECTBASEDIR}" ]]; then + scanner_args+=("-Dsonar.projectBaseDir=${INPUT_PROJECTBASEDIR}") +fi + +if [[ -n "${SONAR_ROOT_CERT}" ]]; then + echo "Adding SSL certificate to the Scanner truststore" + rm -f $RUNNER_TEMP/tmpcert.pem + echo "${SONAR_ROOT_CERT}" > $RUNNER_TEMP/tmpcert.pem + # Use keytool for now, as SonarQube 11.6 won't support openssl generated keystores + # keytool require a password > 6 characters, so we wan't use the default password 'sonar' + store_pass=changeit + mkdir -p ~/.sonar/ssl + keytool -storetype PKCS12 -keystore ~/.sonar/ssl/truststore.p12 -storepass $store_pass -noprompt -trustcacerts -importcert -alias sonar -file $RUNNER_TEMP/tmpcert.pem + scanner_args+=("-Dsonar.scanner.truststorePassword=$store_pass") +fi + +scanner_args+=("$@") + +set -ux + +$SCANNER_BIN "${scanner_args[@]}" + diff --git a/sanity-checks.sh b/sanity-checks.sh new file mode 100755 index 0000000..6fd8b97 --- /dev/null +++ b/sanity-checks.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +set -eo pipefail + +if [[ -z "${SONAR_TOKEN}" ]]; then + echo "::warning title=SonarScanner::Running this GitHub Action without SONAR_TOKEN is not recommended" +fi + +if [[ -f "${INPUT_PROJECTBASEDIR%/}/pom.xml" ]]; then + echo "::warning title=SonarScanner::Maven project detected. Sonar recommends running the 'org.sonarsource.scanner.maven:sonar-maven-plugin:sonar' goal during the build process instead of using this GitHub Action + to get more accurate results." +fi + +if [[ -f "${INPUT_PROJECTBASEDIR%/}/build.gradle" || -f "${INPUT_PROJECTBASEDIR%/}/build.gradle.kts" ]]; then + echo "::warning title=SonarScanner::Gradle project detected. Sonar recommends using the SonarQube plugin for Gradle during the build process instead of using this GitHub Action + to get more accurate results." +fi + From 6440c7398239864bf06dd65f6800d5beefe34ba2 Mon Sep 17 00:00:00 2001 From: Antonio Aversa Date: Thu, 28 Nov 2024 07:36:28 +0100 Subject: [PATCH 35/60] SQSCANGHA-56 Support GitHub self-hosted runners without keytool --- .github/qa-sq-behind-ngix/compose.yml | 26 ++++++ .github/qa-sq-behind-ngix/nginx.conf | 54 +++++++++++++ .github/workflows/qa.yml | 110 +++++++++++++++++++++++++- action.yml | 3 +- run-sonar-scanner.sh | 4 +- 5 files changed, 193 insertions(+), 4 deletions(-) create mode 100644 .github/qa-sq-behind-ngix/compose.yml create mode 100644 .github/qa-sq-behind-ngix/nginx.conf diff --git a/.github/qa-sq-behind-ngix/compose.yml b/.github/qa-sq-behind-ngix/compose.yml new file mode 100644 index 0000000..0c35001 --- /dev/null +++ b/.github/qa-sq-behind-ngix/compose.yml @@ -0,0 +1,26 @@ +services: + sonarqube: + image: sonarqube:lts-community + ports: + - 9000:9000 + healthcheck: + test: 'grep -Fq "SonarQube is operational" /opt/sonarqube/logs/sonar.log' + interval: 10s + timeout: 5s + retries: 20 + start_period: 2m + + https-proxy: + image: nginx + ports: + - 4443:4443 + volumes: + - $GITHUB_WORKSPACE/.github/qa-sq-behind-ngix/nginx.conf:/etc/nginx/nginx.conf:ro + - $GITHUB_WORKSPACE/.github/qa-sq-behind-ngix/server.crt:/etc/nginx/server.crt:ro + - $GITHUB_WORKSPACE/.github/qa-sq-behind-ngix/server.key:/etc/nginx/server.key:ro + healthcheck: + test: ["CMD", "curl", "--fail", "localhost:8080/health"] + interval: 10s + timeout: 5s + retries: 20 + start_period: 2m \ No newline at end of file diff --git a/.github/qa-sq-behind-ngix/nginx.conf b/.github/qa-sq-behind-ngix/nginx.conf new file mode 100644 index 0000000..fd588d6 --- /dev/null +++ b/.github/qa-sq-behind-ngix/nginx.conf @@ -0,0 +1,54 @@ +user nginx; +worker_processes auto; + +error_log /var/log/nginx/error.log notice; +pid /var/run/nginx.pid; + +events { + worker_connections 1024; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log main; + + sendfile on; + + keepalive_timeout 65; + + include /etc/nginx/conf.d/*.conf; + + server { + listen 8080; + + location /health { + access_log off; + add_header 'Content-Type' 'text/plain'; + return 200 "healthy\n"; + } + } + + server { + listen 4443 ssl; + + ssl_protocols TLSv1.1 TLSv1.2; + ssl_certificate /etc/nginx/server.crt; + ssl_certificate_key /etc/nginx/server.key; + + access_log /var/log/nginx/localhost; + error_log /var/log/nginx/localhost.error debug; + + location / { + proxy_pass http://sonarqube:9000; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header X-Forwarded-Proto https; + } + } +} diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index f4bd70c..e85a913 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -274,4 +274,112 @@ jobs: SONAR_HOST_URL: http://not_actually_used - name: Assert run: | - ./test/assertFileExists ~/.sonar/ssl/truststore.p12 \ No newline at end of file + ./test/assertFileExists ~/.sonar/ssl/truststore.p12 + analysisWithSslCertificate: + name: > + Analysis takes into account 'SONAR_ROOT_CERT' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + - name: Generate server certificate + run: | + openssl req \ + -newkey rsa:4096 \ + -x509 \ + -sha256 \ + -addext "subjectAltName = DNS:localhost" \ + -days 3650 \ + -nodes \ + -out server.crt \ + -subj "/C=CH/ST=Geneva/L=Geneva/O=Server/OU=Dept" \ + -keyout server.key + working-directory: .github/qa-sq-behind-ngix + - name: Start nginx and SonarQube via Docker Compose + run: docker compose up -d --wait + working-directory: .github/qa-sq-behind-ngix + - name: Read correct server certificate + run: | + # read server.crt from .github/qa-sq-behind-ngix/ and store into the SONAR_ROOT_CERT_VALID + # environment variable, to be able to read it in the next step + { + echo 'SONAR_ROOT_CERT_VALID<<==========' + cat .github/qa-sq-behind-ngix/server.crt + echo ========== + } >> $GITHUB_ENV + - name: Run action with the correct SSL certificate + uses: ./ + env: + SONAR_ROOT_CERT: ${{ env.SONAR_ROOT_CERT_VALID }} + SONAR_HOST_URL: https://localhost:4443 + with: + args: -Dsonar.login=admin -Dsonar.password=admin + projectBaseDir: ./test/example-project + - name: Clear imported SSL certificates + run: | + rm -f ~/.sonar/ssl/truststore.p12 + - name: Run action with an invalid SSL certificate + id: invalid_ssl_certificate + continue-on-error: true + uses: ./ + env: + SONAR_ROOT_CERT: | + -----BEGIN CERTIFICATE----- + INVALID + -----END CERTIFICATE----- + SONAR_HOST_URL: https://localhost:4443 + with: + args: -Dsonar.login=admin -Dsonar.password=admin + projectBaseDir: ./test/example-project + - name: Assert failure of previous step + if: steps.invalid_ssl_certificate.outcome == 'success' + run: exit 1 + - name: Clear imported SSL certificates + run: | + rm -f ~/.sonar/ssl/truststore.p12 + - name: Run action with the wrong SSL certificate + id: wrong_ssl_certificate + continue-on-error: true + uses: ./ + env: + SONAR_ROOT_CERT: | + -----BEGIN CERTIFICATE----- + MIIFlTCCA32gAwIBAgIUXK4LyGUFe4ZVL93StPXCoJzmnLMwDQYJKoZIhvcNAQEL + BQAwTzELMAkGA1UEBhMCQ0gxDzANBgNVBAgMBkdlbmV2YTEPMA0GA1UEBwwGR2Vu + ZXZhMQ8wDQYDVQQKDAZTZXJ2ZXIxDTALBgNVBAsMBERlcHQwHhcNMjQxMTAxMDgx + MzM3WhcNMzQxMDMwMDgxMzM3WjBPMQswCQYDVQQGEwJDSDEPMA0GA1UECAwGR2Vu + ZXZhMQ8wDQYDVQQHDAZHZW5ldmExDzANBgNVBAoMBlNlcnZlcjENMAsGA1UECwwE + RGVwdDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK5m0V6IFFykib77 + nmlN7weS9q3D6YGEj+8hRNQViL9KduUoLjoKpONIihU5kfIg+5SkGygjHRkBvIp3 + b0HQqhkwtGln3/FxxaSfGEguLHgzXR8JDQSyJ8UKIGOPCH93n1rUip5Ok1iExVup + HtkiVDRoCC9cRjZXbGOKrO6VBT4RvakpkaqCdXYikV244B5ElM7kdFdz8fso78Aq + xekb9dM0f21uUaDBKCIhRcxWeafp0CJIoejTq0+PF7qA2qIY5UHqWElWO5NsvQ8+ + MqKkIdsOa1pYNuH/5eQ59k9KSE92ps1xTKweW000GfPqxx8IQ/e4aAd2SaMTKvN6 + aac6piWBeJ7AssgWwkg/3rnZB5seQIrWjIUePmxJ4c0g0eL9cnVpYF0K/Dldle/G + wg0zi1g709rBI1TYj9xwrivxSwEQupz8OdKqOmgqrKHJJ/CCLl+JdFYjgwl3NWLH + wsU639H1bMXIJoQujg9U47e9fXbwiqdkMQzt7rPGkOBBaAkSctAReiXnWy+CbVEM + QFHDrnD5YUJRd5t/DUuWuqhR2QhfUvRClPUKoVqB/iOu2IumlgDEDA8jb1dxEW+W + iaYokQCS94OpxOJ8aeReSt9bghT0vc9ifCLWvuE1iBjujdK32ekKSY9DCZyBHXsG + J9N1nt1qd/k7QqWOkuPjr1JrTIMbAgMBAAGjaTBnMB0GA1UdDgQWBBQw4ESReEk+ + AIxwjHRqPkESzMv1bTAfBgNVHSMEGDAWgBQw4ESReEk+AIxwjHRqPkESzMv1bTAP + BgNVHRMBAf8EBTADAQH/MBQGA1UdEQQNMAuCCWxvY2FsaG9zdDANBgkqhkiG9w0B + AQsFAAOCAgEAE8WefoZN23aOSe79ZN7zRBWP8DdPgFAqg5XUhfc9bCIVfJ4XMpEe + 3lzRhgjwDm4naEs35QWOhPZH2vx8XrEKnZNI6vKO8JzaCsivgngk8bsWnvhwSXy5 + eFdc99K+FOmOHevDmeiimoQnikffnSULRhQYzE2Qwyo9iky8703/+D3IKEC/8exC + rlyGMUV/Nqj+4M+57DiZ6OXeFuunfoFB7vmcDZygqDhKoHhVRyu8qN6PeK2fvUFK + EjeRtvA0GkdlOtLIF2g5yBTK2ykkt/oLUoAolfYUTKcoV2/FS0gVR5ovmEpKyBcP + H9hzr16a8dtrEqOf/oKHQSLwxn8afmS354HJ75sq9SujOtIWpHfyH5IgqtUpiBN/ + bzvKs/QZjtGlqvquOTkdh9L4oxTXqG7zEStZyo/v9g5jf1Tq195b2DNFwVUZIcbb + u2d4CvAZ1yNr+8ax/kTwBSY8WU+mCtmvowFstdvsJXVXJKnUO6EZOdbg0GxTBVyE + zMsnPcnkOwV5TJIKKhonrgrwmPmQ9IOV9BrThVxujjjEbAdA6jM9PMiXzuDukldm + QBRwNbczGbdsHkMKHmQnrTqOyQyI4KCXF08kcOm4C1P+Whrvi0DXkqHnyKvBE0td + dciInBoeHwUs2eclz7gP7pMBJUlFUkKfQxwxGLIqZSXnlAFBfW6hHLI= + -----END CERTIFICATE----- + SONAR_HOST_URL: https://localhost:4443 + with: + args: -Dsonar.login=admin -Dsonar.password=admin + projectBaseDir: ./test/example-project + - name: Assert failure of previous step + if: steps.wrong_ssl_certificate.outcome == 'success' + run: exit 1 \ No newline at end of file diff --git a/action.yml b/action.yml index 14854e5..743c81c 100644 --- a/action.yml +++ b/action.yml @@ -42,4 +42,5 @@ runs: run: ${GITHUB_ACTION_PATH}/run-sonar-scanner.sh ${{ inputs.args }} shell: bash env: - INPUT_PROJECTBASEDIR: ${{ inputs.projectBaseDir }} \ No newline at end of file + INPUT_PROJECTBASEDIR: ${{ inputs.projectBaseDir }} + SONAR_SCANNER_JRE: ${{ runner.temp }}/sonar-scanner-cli-${{ inputs.scannerVersion }}-${{ runner.os }}-${{ runner.arch }}/jre \ No newline at end of file diff --git a/run-sonar-scanner.sh b/run-sonar-scanner.sh index 13c2f69..14caadc 100755 --- a/run-sonar-scanner.sh +++ b/run-sonar-scanner.sh @@ -25,11 +25,11 @@ if [[ -n "${SONAR_ROOT_CERT}" ]]; then echo "Adding SSL certificate to the Scanner truststore" rm -f $RUNNER_TEMP/tmpcert.pem echo "${SONAR_ROOT_CERT}" > $RUNNER_TEMP/tmpcert.pem - # Use keytool for now, as SonarQube 11.6 won't support openssl generated keystores + # Use keytool for now, as SonarQube 10.6 and below doesn't support openssl generated keystores # keytool require a password > 6 characters, so we wan't use the default password 'sonar' store_pass=changeit mkdir -p ~/.sonar/ssl - keytool -storetype PKCS12 -keystore ~/.sonar/ssl/truststore.p12 -storepass $store_pass -noprompt -trustcacerts -importcert -alias sonar -file $RUNNER_TEMP/tmpcert.pem + $SONAR_SCANNER_JRE/bin/java sun.security.tools.keytool.Main -storetype PKCS12 -keystore ~/.sonar/ssl/truststore.p12 -storepass $store_pass -noprompt -trustcacerts -importcert -alias sonar -file $RUNNER_TEMP/tmpcert.pem scanner_args+=("-Dsonar.scanner.truststorePassword=$store_pass") fi From 05ca09c2daab27b485543a2f645b7702d4f47df2 Mon Sep 17 00:00:00 2001 From: Antonio Aversa Date: Thu, 28 Nov 2024 08:06:29 +0100 Subject: [PATCH 36/60] SQSCANGHA-51 Make Scanner CLI binaries URL customizable --- .github/workflows/qa.yml | 48 ++++++++++++++++++++++++++++++++++++ action.yml | 7 +++++- install-sonar-scanner-cli.sh | 2 +- test/assertFileDoesntExist | 8 ++++++ 4 files changed, 63 insertions(+), 2 deletions(-) create mode 100755 test/assertFileDoesntExist diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index e85a913..d0610f2 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -68,6 +68,54 @@ jobs: - name: Assert run: | ./test/assertFileContains ./output.properties "sonar.projectBaseDir=.*/baseDir" + scannerVersionTest: + name: > + 'scannerVersion' input + runs-on: ubuntu-latest # assumes default RUNNER_ARCH for linux is X64 + steps: + - uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + - name: Run action with scannerVersion + uses: ./ + with: + scannerVersion: 6.1.0.4477 + args: -Dsonar.scanner.internal.dumpToFile=./output.properties + env: + NO_CACHE: true # force install-sonar-scanner-cli.sh execution + SONAR_HOST_URL: http://not_actually_used + SONAR_SCANNER_JSON_PARAMS: '{"sonar.scanner.internal.dumpToFile": "./output.properties"}' + - name: Assert + run: | + ./test/assertFileExists "$RUNNER_TEMP/sonarscanner/sonar-scanner-cli-6.1.0.4477-linux-x64.zip" + scannerBinariesUrlTest: + name: > + 'scannerBinariesUrl' input with invalid URL + runs-on: ubuntu-latest # assumes default RUNNER_ARCH for linux is X64 + steps: + - uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + - name: Run action with scannerBinariesUrl + id: runTest + uses: ./ + continue-on-error: true + with: + scannerVersion: 6.2.1.4610 + scannerBinariesUrl: https://invalid_uri/Distribution/sonar-scanner-cli + env: + NO_CACHE: true # force install-sonar-scanner-cli.sh execution + SONAR_HOST_URL: http://not_actually_used + SONAR_SCANNER_JSON_PARAMS: '{"sonar.scanner.internal.dumpToFile": "./output.properties"}' + - name: Fail if action succeeded + if: steps.runTest.outcome == 'success' + run: exit 1 + - name: Assert Sonar Scanner CLI was not downloaded + run: | + ./test/assertFileDoesntExist "$RUNNER_TEMP/sonarscanner/sonar-scanner-cli-6.2.1.4610-linux-x64.zip" + - name: Assert Sonar Scanner CLI was not executed + run: | + ./test/assertFileDoesntExist ./output.properties dontFailGradleTest: name: > Don't fail on Gradle project diff --git a/action.yml b/action.yml index 743c81c..ea5cd96 100644 --- a/action.yml +++ b/action.yml @@ -15,6 +15,10 @@ inputs: description: Version of the Sonar Scanner CLI to use required: false default: 6.2.1.4610 + scannerBinariesUrl: + description: URL to download the Sonar Scanner CLI binaries from + required: false + default: https://binaries.sonarsource.com/Distribution/sonar-scanner-cli runs: using: "composite" steps: @@ -30,11 +34,12 @@ runs: path: ${{ runner.temp }}/sonar-scanner-cli-${{ inputs.scannerVersion }}-${{ runner.os }}-${{ runner.arch }} key: sonar-scanner-cli-${{ inputs.scannerVersion }}-${{ runner.os }}-${{ runner.arch }} - name: Install Sonar Scanner CLI - if: steps.sonar-scanner-cli.outputs.cache-hit != 'true' + if: ${{ env.NO_CACHE == 'true' || steps.sonar-scanner-cli.outputs.cache-hit != 'true' }} run: ${GITHUB_ACTION_PATH}/install-sonar-scanner-cli.sh shell: bash env: INPUT_SCANNERVERSION: ${{ inputs.scannerVersion }} + INPUT_SCANNERBINARIESURL: ${{ inputs.scannerBinariesUrl }} - name: Add SonarScanner CLI to the PATH run: echo "${RUNNER_TEMP}/sonar-scanner-cli-${{ inputs.scannerVersion }}-${{ runner.os }}-${{ runner.arch }}/bin" >> $GITHUB_PATH shell: bash diff --git a/install-sonar-scanner-cli.sh b/install-sonar-scanner-cli.sh index 7509d74..5cdbedb 100755 --- a/install-sonar-scanner-cli.sh +++ b/install-sonar-scanner-cli.sh @@ -26,7 +26,7 @@ set -x mkdir -p $RUNNER_TEMP/sonarscanner cd $RUNNER_TEMP/sonarscanner -$WGET --no-verbose --user-agent="sonarqube-scan-action" https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-$INPUT_SCANNERVERSION-$FLAVOR.zip +$WGET --no-verbose --user-agent="sonarqube-scan-action" "${INPUT_SCANNERBINARIESURL%/}/sonar-scanner-cli-$INPUT_SCANNERVERSION-$FLAVOR.zip" unzip -q sonar-scanner-cli-$INPUT_SCANNERVERSION-$FLAVOR.zip diff --git a/test/assertFileDoesntExist b/test/assertFileDoesntExist new file mode 100755 index 0000000..032a07c --- /dev/null +++ b/test/assertFileDoesntExist @@ -0,0 +1,8 @@ +#!/bin/bash + +error() { echo -e "\\e[31m✗ $*\\e[0m"; } + +if [ -f $1 ]; then + error "File '$1' found" + exit 1 +fi \ No newline at end of file From 1f659fabd34caab2421fa2769cb5d94fa3bbf6f4 Mon Sep 17 00:00:00 2001 From: Antonio Aversa Date: Thu, 28 Nov 2024 10:32:04 +0100 Subject: [PATCH 37/60] SQSCANGHA-55 Support GitHub self-hosted runners without wget --- .github/workflows/qa.yml | 85 ++++++++++++++++++++++++++++++++++++ install-sonar-scanner-cli.sh | 44 ++++++++++++++----- 2 files changed, 118 insertions(+), 11 deletions(-) diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index d0610f2..8b4240a 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -269,6 +269,91 @@ jobs: - name: Assert run: | ./test/assertFileExists ./test/example-project/.scannerwork/report-task.txt + dontFailWhenMissingWgetButCurlAvailable: + name: Don't fail when missing wget but curl available + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + - name: Remove wget + run: sudo apt-get remove -y wget + - name: Assert wget is not available + run: | + if command -v wget 2>&1 >/dev/null + then + exit 1 + fi + - name: Run action + uses: ./ + env: + NO_CACHE: true + SONAR_HOST_URL: http://not_actually_used + SONAR_SCANNER_JSON_PARAMS: '{"sonar.scanner.internal.dumpToFile": "./output.properties"}' + with: + args: -Dsonar.scanner.internal.dumpToFile=./output.properties + - name: Assert + run: | + ./test/assertFileExists ./output.properties + dontFailWhenMissingCurlButWgetAvailable: + name: Don't fail when missing curl but wget available + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + - name: Remove curl + run: sudo apt-get remove -y curl + - name: Assert curl is not available + run: | + if command -v curl 2>&1 >/dev/null + then + exit 1 + fi + - name: Run action + id: runTest + uses: ./ + env: + NO_CACHE: true + SONAR_HOST_URL: http://not_actually_used + SONAR_SCANNER_JSON_PARAMS: '{"sonar.scanner.internal.dumpToFile": "./output.properties"}' + with: + args: -Dsonar.scanner.internal.dumpToFile=./output.properties + - name: Assert + run: | + ./test/assertFileExists ./output.properties + failWhenBothWgetAndCurlMissing: + name: Fail when both wget and curl are missing + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + - name: Remove wget and curl + run: sudo apt-get remove -y wget curl + - name: Assert wget and curl are not available + run: | + if command -v wget 2>&1 >/dev/null + then + exit 1 + fi + if command -v curl 2>&1 >/dev/null + then + exit 1 + fi + - name: Run action + id: runTest + uses: ./ + continue-on-error: true + env: + NO_CACHE: true + SONAR_HOST_URL: http://not_actually_used + SONAR_SCANNER_JSON_PARAMS: '{"sonar.scanner.internal.dumpToFile": "./output.properties"}' + with: + args: -Dsonar.scanner.internal.dumpToFile=./output.properties + - name: Assert failure of previous step + if: steps.runTest.outcome == 'success' + run: exit 1 useSslCertificate: name: > 'SONAR_ROOT_CERT' is converted to truststore diff --git a/install-sonar-scanner-cli.sh b/install-sonar-scanner-cli.sh index 5cdbedb..d87c8e4 100755 --- a/install-sonar-scanner-cli.sh +++ b/install-sonar-scanner-cli.sh @@ -2,33 +2,55 @@ set -eou pipefail -#See https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/store-information-in-variables#default-environment-variables +# See https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/store-information-in-variables#default-environment-variables +# +# Script-specific variables required: +# - INPUT_SCANNERVERSION: e.g. 6.2.1.4610 +# - INPUT_SCANNERBINARIESURL: e.g. https://github.com/me/my-repo/raw/refs/heads/main/binaries -WGET=wget -if [[ "$RUNNER_OS" == "Linux" && "$RUNNER_ARCH" == "X64" ]]; then +if [[ "$RUNNER_OS" == "Linux" && "$RUNNER_ARCH" == "X64" ]]; then FLAVOR="linux-x64" -elif [[ "$RUNNER_OS" == "Linux" && "$RUNNER_ARCH" == "ARM64" ]]; then +elif [[ "$RUNNER_OS" == "Linux" && "$RUNNER_ARCH" == "ARM64" ]]; then FLAVOR="linux-aarch64" -elif [[ "$RUNNER_OS" == "Windows" && "$RUNNER_ARCH" == "X64" ]]; then +elif [[ "$RUNNER_OS" == "Windows" && "$RUNNER_ARCH" == "X64" ]]; then FLAVOR="windows-x64" - WGET="C:\\msys64\\usr\\bin\\wget.exe" -elif [[ "$RUNNER_OS" == "macOS" && "$RUNNER_ARCH" == "X64" ]]; then +elif [[ "$RUNNER_OS" == "macOS" && "$RUNNER_ARCH" == "X64" ]]; then FLAVOR="macosx-x64" -elif [[ "$RUNNER_OS" == "macOS" && "$RUNNER_ARCH" == "ARM64" ]]; then +elif [[ "$RUNNER_OS" == "macOS" && "$RUNNER_ARCH" == "ARM64" ]]; then FLAVOR="macosx-aarch64" else - echo "$RUNNER_OS $RUNNER_ARCH not supported" + echo "::error title=SonarScanner::$RUNNER_OS $RUNNER_ARCH not supported" exit 1 fi +SCANNER_FILE_NAME="sonar-scanner-cli-$INPUT_SCANNERVERSION-$FLAVOR.zip" +SCANNER_URI="${INPUT_SCANNERBINARIESURL%/}/$SCANNER_FILE_NAME" + +if command -v wget &> /dev/null; then + DOWNLOAD_COMMAND="wget" + DOWNLOAD_ARGS="--no-verbose --user-agent=sonarqube-scan-action $SCANNER_URI" +elif command -v curl &> /dev/null; then + DOWNLOAD_COMMAND="curl" + DOWNLOAD_ARGS="--silent --show-error --user-agent sonarqube-scan-action --output $SCANNER_FILE_NAME $SCANNER_URI" +elif [ "$RUNNER_OS" == "Windows" ] && [ -t "C:\\msys64\\usr\\bin\\wget.exe" ]; then + DOWNLOAD_COMMAND="C:\\msys64\\usr\\bin\\wget.exe" + DOWNLOAD_ARGS="--no-verbose --user-agent=sonarqube-scan-action $SCANNER_URI" +elif [ "$RUNNER_OS" == "Windows" ] && [ -t "C:\\msys64\\usr\\bin\\curl.exe" ]; then + DOWNLOAD_COMMAND="C:\\msys64\\usr\\bin\\curl.exe" + DOWNLOAD_ARGS="--silent --show-error --user-agent sonarqube-scan-action --output $SCANNER_FILE_NAME $SCANNER_URI" +else + echo "::error title=SonarScanner::Neither wget nor curl found on the machine" + exit 1 +fi + set -x mkdir -p $RUNNER_TEMP/sonarscanner cd $RUNNER_TEMP/sonarscanner -$WGET --no-verbose --user-agent="sonarqube-scan-action" "${INPUT_SCANNERBINARIESURL%/}/sonar-scanner-cli-$INPUT_SCANNERVERSION-$FLAVOR.zip" +$DOWNLOAD_COMMAND $DOWNLOAD_ARGS -unzip -q sonar-scanner-cli-$INPUT_SCANNERVERSION-$FLAVOR.zip +unzip -q $SCANNER_FILE_NAME # Folder name should correspond to the directory cached by the actions/cache mv sonar-scanner-$INPUT_SCANNERVERSION-$FLAVOR $RUNNER_TEMP/sonar-scanner-cli-$INPUT_SCANNERVERSION-$RUNNER_OS-$RUNNER_ARCH From 7b13cfe1951a233d6406c96b24d31771d68eba1d Mon Sep 17 00:00:00 2001 From: Antonio Aversa Date: Thu, 28 Nov 2024 10:41:20 +0100 Subject: [PATCH 38/60] SQSCANGHA-54 Rebranding --- .github/workflows/qa.yml | 22 +++ README.md | 143 +++++++++++++----- action.yml | 9 +- .../SQ_Logo_Server_Cloud_Dark_Backgrounds.png | Bin 0 -> 24476 bytes ...SQ_Logo_Server_Cloud_Light_Backgrounds.png | Bin 0 -> 25864 bytes images/SonarQube-72px.png | Bin 9894 -> 0 bytes 6 files changed, 133 insertions(+), 41 deletions(-) create mode 100644 images/SQ_Logo_Server_Cloud_Dark_Backgrounds.png create mode 100644 images/SQ_Logo_Server_Cloud_Light_Backgrounds.png delete mode 100644 images/SonarQube-72px.png diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index 8b4240a..d06fb58 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -269,6 +269,28 @@ jobs: - name: Assert run: | ./test/assertFileExists ./test/example-project/.scannerwork/report-task.txt + overrideSonarcloudUrlTest: + name: > + 'SONARCLOUD_URL' is used + strategy: + matrix: + os: [ ubuntu-latest, windows-latest, macos-latest ] + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + - name: Run action with SONARCLOUD_URL + uses: ./ + with: + args: -Dsonar.scanner.internal.dumpToFile=./output.properties + env: + SONARCLOUD_URL: mirror.sonarcloud.io + SONAR_TOKEN: FAKE_TOKEN + - name: Assert + run: | + ./test/assertFileContains ./output.properties "sonar.host.url=mirror.sonarcloud.io" + ./test/assertFileContains ./output.properties "sonar.scanner.sonarcloudUrl=mirror.sonarcloud.io" dontFailWhenMissingWgetButCurlAvailable: name: Don't fail when missing wget but curl available runs-on: ubuntu-latest diff --git a/README.md b/README.md index 1d83d6d..0e12d94 100644 --- a/README.md +++ b/README.md @@ -1,33 +1,44 @@ # Scan your code with SonarQube [![QA](https://github.com/SonarSource/sonarqube-scan-action/actions/workflows/qa.yml/badge.svg)](https://github.com/SonarSource/sonarqube-scan-action/actions/workflows/qa.yml) -This SonarSource project, available as a GitHub Action, scans your projects with SonarQube, and helps developers produce -[Clean Code](https://www.sonarsource.com/solutions/clean-code/?utm_medium=referral&utm_source=github&utm_campaign=clean-code&utm_content=sonarqube-scan-action). +This SonarSource project, available as a GitHub Action, scans your projects with SonarQube [Server](https://www.sonarsource.com/products/sonarqube/) or [Cloud](https://www.sonarsource.com/products/sonarcloud/). - +![Logo](./images/SQ_Logo_Server_Cloud_Dark_Backgrounds.png#gh-dark-mode-only) +![Logo](./images/SQ_Logo_Server_Cloud_Light_Backgrounds.png#gh-light-mode-only) -[SonarQube](https://www.sonarsource.com/products/sonarqube/) is a widely used static analysis solution for continuous code quality and security inspection. -It helps developers identify and fix issues in their code that could lead to bugs, vulnerabilities, or decreased development velocity. -SonarQube supports the most popular programming languages, including Java, JavaScript, TypeScript, C#, Python, C, C++, and [many more](https://www.sonarsource.com/knowledge/languages/). +SonarQube [Server](https://www.sonarsource.com/products/sonarqube/) and [Cloud](https://www.sonarsource.com/products/sonarcloud/) (formerly SonarQube and SonarCloud) is a widely used static analysis solution for continuous code quality and security inspection. + +It helps developers detect coding issues in 30+ languages, frameworks, and IaC platforms, including Java, JavaScript, TypeScript, C#, Python, C, C++, and [many more](https://www.sonarsource.com/knowledge/languages/). + +The solution also provides fix recommendations leveraging AI with Sonar's AI CodeFix capability. ## Requirements -To run an analysis on your code, you first need to set up your project on SonarQube. Your SonarQube instance must be accessible from GitHub, and you will need an access token to run the analysis (more information below under **Environment variables**). +### Server -Read more information on how to analyze your code [here](https://docs.sonarqube.org/latest/analysis/github-integration/). +To run an analysis on your code, you first need to set up your project on SonarQube Server. Your SonarQube Server instance must be accessible from GitHub, and you will need an access token to run the analysis (more information below under **Environment variables**). + +Read more information on how to analyze your code [here](https://docs.sonarsource.com/sonarqube-server/latest/devops-platform-integration/github-integration/introduction/). + +### Cloud + +* Create your account on SonarQube Cloud. [Sign up for free](https://www.sonarsource.com/products/sonarcloud/signup/?utm_medium=referral&utm_source=github&utm_campaign=sc-signup&utm_content=signup-sonarcloud-listing-x-x&utm_term=ww-psp-x) now if it's not already the case! +* The repository to analyze is set up on SonarQube Cloud. [Set it up](https://sonarcloud.io/projects/create) in just one click. ## Usage Project metadata, including the location of the sources to be analyzed, must be declared in the file `sonar-project.properties` in the base directory: +### Server + ```properties -sonar.projectKey= +sonar.projectKey= # relative paths to source directories. More details and properties are described -# at https://docs.sonarqube.org/latest/project-administration/narrowing-the-focus/ +# at https://docs.sonarsource.com/sonarqube-server/latest/project-administration/analysis-scope/ sonar.sources=. ``` -The workflow YAML file will usually look something like this: +The workflow, usually declared under `.github/workflows`, looks like: ```yaml on: @@ -51,72 +62,128 @@ jobs: # Disabling shallow clones is recommended for improving the relevancy of reporting fetch-depth: 0 - name: SonarQube Scan - uses: sonarsource/sonarqube-scan-action@ # Ex: v2.1.0, See the latest version at https://github.com/marketplace/actions/official-sonarqube-scan + uses: sonarsource/sonarqube-scan-action@ # Ex: v4.1.0, See the latest version at https://github.com/marketplace/actions/official-sonarqube-scan env: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} SONAR_HOST_URL: ${{ vars.SONAR_HOST_URL }} ``` -If your source code file names contain special characters that are not covered by the locale range of `en_US.UTF-8`, you can configure your desired locale like this: +### Cloud + +```properties +sonar.organization= +sonar.projectKey= + +# relative paths to source directories. More details and properties are described +# at https://docs.sonarsource.com/sonarqube-cloud/advanced-setup/analysis-scope/ +sonar.sources=. +``` + +The workflow, usually declared under `.github/workflows`, looks like: ```yaml +on: + # Trigger analysis when pushing to your main branches, and when creating a pull request. + push: + branches: + - main + - master + - develop + - 'releases/**' + pull_request: + types: [opened, synchronize, reopened] + +name: Main Workflow +jobs: + sonarqube: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + # Disabling shallow clones is recommended for improving the relevancy of reporting + fetch-depth: 0 - name: SonarQube Scan - uses: sonarsource/sonarqube-scan-action@ # Ex: v2.1.0, See the latest version at https://github.com/marketplace/actions/official-sonarqube-scan + uses: sonarsource/sonarqube-scan-action@ # Ex: v4.1.0, See the latest version at https://github.com/marketplace/actions/official-sonarqube-scan env: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - SONAR_HOST_URL: ${{ vars.SONAR_HOST_URL }} - LC_ALL: "ru_RU.UTF-8" + SONAR_HOST_URL: https://sonarcloud.io ``` -If your SonarQube server uses a self-signed certificate, you can pass a root certificate (in PEM format) to the Java certificate store: - -```yaml - - name: SonarQube Scan - uses: sonarsource/sonarqube-scan-action@ # Ex: v2.1.0, See the latest version at https://github.com/marketplace/actions/official-sonarqube-scan - env: - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - SONAR_HOST_URL: ${{ vars.SONAR_HOST_URL }} - SONAR_ROOT_CERT: ${{ secrets.SONAR_ROOT_CERT }} -``` +## Action parameters You can change the analysis base directory by using the optional input `projectBaseDir` like this: ```yaml -- name: SonarQube Scan - uses: sonarsource/sonarqube-scan-action@ # Ex: v2.1.0, See the latest version at https://github.com/marketplace/actions/official-sonarqube-scan +- uses: sonarsource/sonarqube-scan-action@ with: projectBaseDir: app/src ``` +In case you need to specify the version of the Sonar Scanner, you can use the `scannerVersion` option: + +```yaml +- uses: sonarsource/sonarqube-scan-action@ + with: + scannerVersion: 6.2.0.4584 +``` + In case you need to add additional analysis parameters, and you do not wish to set them in the `sonar-project.properties` file, you can use the `args` option: ```yaml -- name: SonarQube Scan - uses: sonarsource/sonarqube-scan-action@ # Ex: v2.1.0, See the latest version at https://github.com/marketplace/actions/official-sonarqube-scan +- uses: sonarsource/sonarqube-scan-action@ with: projectBaseDir: app/src args: > + -Dsonar.organization=my-organization # For SonarQube Cloud only + -Dsonar.projectKey=my-projectkey -Dsonar.python.coverage.reportPaths=coverage.xml + -Dsonar.sources=lib/ -Dsonar.tests=tests/ + -Dsonar.test.exclusions=tests/** -Dsonar.verbose=true ``` -More information about possible analysis parameters can be found in [the documentation](https://redirect.sonarsource.com/doc/analysis-parameters.html). +More information about possible analysis parameters can be found: +* in the [Analysis parameters page](https://docs.sonarsource.com/sonarqube-server/latest/analyzing-source-code/analysis-parameters/) of the SonarQube Server documentation +* in the [Analysis parameters page](https://docs.sonarsource.com/sonarqube-cloud/advanced-setup/analysis-parameters/) of the SonarQube Cloud documentation ### Environment variables -- `SONAR_TOKEN` – **Required** this is the token used to authenticate access to SonarQube. You can read more about security tokens [here](https://docs.sonarqube.org/latest/user-guide/user-token/). You can set the `SONAR_TOKEN` environment variable in the "Secrets" settings page of your repository, or you can add them at the level of your GitHub organization (recommended). -- `SONAR_HOST_URL` – **Required** this tells the scanner where SonarQube is hosted. You can set the `SONAR_HOST_URL` environment variable in the "Variables" settings page of your repository, or you can add them at the level of your GitHub organization (recommended). -- `SONAR_ROOT_CERT` – Holds an additional root certificate (in PEM format) that is used to validate the SonarQube server certificate. You can set the `SONAR_ROOT_CERT` environment variable in the "Secrets" settings page of your repository, or you can add them at the level of your GitHub organization (recommended). +- `SONAR_TOKEN` – **Required** this is the token used to authenticate access to SonarQube. You can read more about security tokens in the documentation of SonarQube [Server](https://docs.sonarsource.com/sonarqube-server/latest/user-guide/managing-tokens/) and [Cloud](https://docs.sonarsource.com/sonarqube-cloud/managing-your-account/managing-tokens/). You can set the `SONAR_TOKEN` environment variable in the "Secrets" settings page of your repository, or you can add them at the level of your GitHub organization (recommended). +- *`GITHUB_TOKEN` – Provided by Github (see [Authenticating with the GITHUB_TOKEN](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/authenticating-with-the-github_token)).* +- `SONAR_HOST_URL` – this tells the scanner where SonarQube Server is hosted. You can set the `SONAR_HOST_URL` environment variable in the "Variables" settings page of your repository, or you can add them at the level of your GitHub organization (recommended). Not needed for SonarQube Cloud. +- `SONAR_ROOT_CERT` – Holds an additional root certificate (in PEM format) that is used to validate the certificate of SonarQube Server or of a secured proxy to SonarQube (Server or Cloud). You can set the `SONAR_ROOT_CERT` environment variable in the "Secrets" settings page of your repository, or you can add them at the level of your GitHub organization (recommended). + +Here is an example of how you can pass a root certificate (in PEM format) to the Java certificate store, when your SonarQube Server uses a self-signed certificate: + +```yaml +- uses: sonarsource/sonarqube-scan-action@ + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + SONAR_HOST_URL: ${{ vars.SONAR_HOST_URL }} + SONAR_ROOT_CERT: ${{ secrets.SONAR_ROOT_CERT }} +``` + +If your source code file names contain special characters that are not covered by the locale range of `en_US.UTF-8`, you can configure your desired locale like this: + +```yaml +- uses: sonarsource/sonarqube-scan-action@ + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + SONAR_HOST_URL: ${{ vars.SONAR_HOST_URL }} # or https://sonarcloud.io + LC_ALL: "ru_RU.UTF-8" +``` ## Alternatives for Java, .NET, and C/C++ projects This GitHub Action will not work for all technologies. If you are in one of the following situations, you should use the following alternatives: -* Your code is built with Maven. Read the documentation about our [Scanner for Maven](https://redirect.sonarsource.com/doc/install-configure-scanner-maven.html). -* Your code is built with Gradle. Read the documentation about our [Scanner for Gradle](https://redirect.sonarsource.com/doc/gradle.html). -* You want to analyze a .NET solution. Read the documentation about our [Scanner for .NET](https://redirect.sonarsource.com/doc/install-configure-scanner-msbuild.html). -* You want to analyze C or C++ code. Starting from SonarQube 10.6, this GitHub Action will scan C and C++ out of the box. If you want to have better control over the scan configuration/setup, you can switch to the [SonarQube C and C++](https://github.com/SonarSource/sonarqube-github-c-cpp) GitHub Action. +* Your code is built with Maven. Read the documentation about our SonarScanner for Maven in SonarQube [Server](https://docs.sonarsource.com/sonarqube-server/latest/analyzing-source-code/scanners/sonarscanner-for-maven/) and [Cloud](https://docs.sonarsource.com/sonarqube-cloud/advanced-setup/ci-based-analysis/sonarscanner-for-maven/). +* Your code is built with Gradle. Read the documentation about our SonarScanner for Gradle in SonarQube [Server](https://docs.sonarsource.com/sonarqube-server/latest/analyzing-source-code/scanners/sonarscanner-for-gradle/) and [Cloud](https://docs.sonarsource.com/sonarqube-cloud/advanced-setup/ci-based-analysis/sonarscanner-for-gradle/). +* You want to analyze a .NET solution. Read the documentation about our SonarScanner for .NET in SonarQube [Server](https://docs.sonarsource.com/sonarqube-server/latest/analyzing-source-code/scanners/dotnet/introduction/) and [Cloud](https://docs.sonarsource.com/sonarqube-cloud/advanced-setup/ci-based-analysis/sonarscanner-for-dotnet/introduction/). +* You want to analyze C or C++ code. Starting from SonarQube 10.6, this GitHub Action will scan C and C++ out of the box. If you want to have better control over the scan configuration/setup, you can switch to: + * the [SonarQube Server Scan for C and C++](https://github.com/marketplace/actions/sonarqube-scan-for-c-and-c) GitHub Action, for projects on SonarQube Server + * the [SonarQube Cloud Scan for C and C++](https://github.com/marketplace/actions/sonarcloud-scan-for-c-and-c) GitHub Action, for projects on SonarQube Cloud - look at [our sample C and C++ project](https://github.com/sonarsource-cfamily-examples?q=gh-actions-sc&type=all&language=&sort=). ## Have questions or feedback? diff --git a/action.yml b/action.yml index ea5cd96..dbbcdd5 100644 --- a/action.yml +++ b/action.yml @@ -1,12 +1,15 @@ -name: Official SonarQube Scan +name: Official SonarQube (Server, Cloud) Scan description: > - Scan your code with SonarQube to detect Bugs, Vulnerabilities and Code Smells in up to 27 programming languages! + Scan your code with SonarQube Server and Cloud to detect coding + issues in 30+ languages, frameworks, and IaC platforms. + The solution also provides fix recommendations leveraging AI with + Sonar's AI CodeFix capability. (Formerly SonarQube and SonarCloud) branding: icon: check color: green inputs: args: - description: Additional arguments to the sonar-scanner + description: Additional arguments to the Sonar Scanner CLI required: false projectBaseDir: description: Set the sonar.projectBaseDir analysis property diff --git a/images/SQ_Logo_Server_Cloud_Dark_Backgrounds.png b/images/SQ_Logo_Server_Cloud_Dark_Backgrounds.png new file mode 100644 index 0000000000000000000000000000000000000000..6f019d5fe9fd5938a52c05804032eace8a0e8c71 GIT binary patch literal 24476 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 literal 0 HcmV?d00001 diff --git a/images/SQ_Logo_Server_Cloud_Light_Backgrounds.png b/images/SQ_Logo_Server_Cloud_Light_Backgrounds.png new file mode 100644 index 0000000000000000000000000000000000000000..e57423172815268da7f4b60e8cbe22bc21fc98c3 GIT binary patch literal 25864 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 bkgFS}?8`H|PiwLNN>q8F`Mgx#^4 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 Date: Fri, 29 Nov 2024 10:45:49 +0100 Subject: [PATCH 39/60] SQSCANGHA-54 Improve the README Co-authored-by: Julien HENRY --- README.md | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 0e12d94..dc75636 100644 --- a/README.md +++ b/README.md @@ -106,7 +106,6 @@ jobs: uses: sonarsource/sonarqube-scan-action@ # Ex: v4.1.0, See the latest version at https://github.com/marketplace/actions/official-sonarqube-scan env: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - SONAR_HOST_URL: https://sonarcloud.io ``` ## Action parameters @@ -143,6 +142,16 @@ In case you need to add additional analysis parameters, and you do not wish to s -Dsonar.verbose=true ``` +You can also specify the URL where to retrieve the SonarScanner CLI from. +The specified URL overrides the default address: `https://binaries.sonarsource.com/Distribution/sonar-scanner-cli`. +This can be useful when the runner executing the action is self-hosted and has regulated or no access to the Internet: + +```yaml +- uses: sonarsource/sonarqube-scan-action@ + with: + scannerBinariesUrl: https://my.custom.binaries.url.com/Distribution/sonar-scanner-cli/ +``` + More information about possible analysis parameters can be found: * in the [Analysis parameters page](https://docs.sonarsource.com/sonarqube-server/latest/analyzing-source-code/analysis-parameters/) of the SonarQube Server documentation * in the [Analysis parameters page](https://docs.sonarsource.com/sonarqube-cloud/advanced-setup/analysis-parameters/) of the SonarQube Cloud documentation @@ -152,9 +161,9 @@ More information about possible analysis parameters can be found: - `SONAR_TOKEN` – **Required** this is the token used to authenticate access to SonarQube. You can read more about security tokens in the documentation of SonarQube [Server](https://docs.sonarsource.com/sonarqube-server/latest/user-guide/managing-tokens/) and [Cloud](https://docs.sonarsource.com/sonarqube-cloud/managing-your-account/managing-tokens/). You can set the `SONAR_TOKEN` environment variable in the "Secrets" settings page of your repository, or you can add them at the level of your GitHub organization (recommended). - *`GITHUB_TOKEN` – Provided by Github (see [Authenticating with the GITHUB_TOKEN](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/authenticating-with-the-github_token)).* - `SONAR_HOST_URL` – this tells the scanner where SonarQube Server is hosted. You can set the `SONAR_HOST_URL` environment variable in the "Variables" settings page of your repository, or you can add them at the level of your GitHub organization (recommended). Not needed for SonarQube Cloud. -- `SONAR_ROOT_CERT` – Holds an additional root certificate (in PEM format) that is used to validate the certificate of SonarQube Server or of a secured proxy to SonarQube (Server or Cloud). You can set the `SONAR_ROOT_CERT` environment variable in the "Secrets" settings page of your repository, or you can add them at the level of your GitHub organization (recommended). +- `SONAR_ROOT_CERT` – Holds an additional certificate (in PEM format) that is used to validate the certificate of SonarQube Server or of a secured proxy to SonarQube (Server or Cloud). You can set the `SONAR_ROOT_CERT` environment variable in the "Secrets" settings page of your repository, or you can add them at the level of your GitHub organization (recommended). -Here is an example of how you can pass a root certificate (in PEM format) to the Java certificate store, when your SonarQube Server uses a self-signed certificate: +Here is an example of how you can pass a certificate (in PEM format) to the Scanner truststore: ```yaml - uses: sonarsource/sonarqube-scan-action@ @@ -187,7 +196,7 @@ This GitHub Action will not work for all technologies. If you are in one of the ## Have questions or feedback? -To provide feedback (requesting a feature or reporting a bug) please post on the [SonarSource Community Forum](https://community.sonarsource.com/tags/c/help/sq/github-actions). +To provide feedback (requesting a feature or reporting a bug) please post on the SonarSource Community Forum page for SonarQube [Server](https://community.sonarsource.com/tags/c/help/sq/github-actions) or [Cloud](https://community.sonarsource.com/tags/c/help/sc/9/github-actions). ## License From 1b442ee39ac3fa7c2acdd410208dcb2bcfaae6c4 Mon Sep 17 00:00:00 2001 From: Antonio Aversa Date: Fri, 29 Nov 2024 13:13:18 +0100 Subject: [PATCH 40/60] SQSCANGHA-55 Add curl redirect and fix splatting of URL with special chars --- .github/qa-nginx-redirecting/compose.yml | 13 ++++ .github/qa-nginx-redirecting/nginx.conf | 32 ++++++++++ .github/qa-sq-behind-ngix/nginx.conf | 11 ---- .github/workflows/qa.yml | 81 ++++++++++++++++++++++++ install-sonar-scanner-cli.sh | 38 +++++------ 5 files changed, 143 insertions(+), 32 deletions(-) create mode 100644 .github/qa-nginx-redirecting/compose.yml create mode 100644 .github/qa-nginx-redirecting/nginx.conf diff --git a/.github/qa-nginx-redirecting/compose.yml b/.github/qa-nginx-redirecting/compose.yml new file mode 100644 index 0000000..1b2a919 --- /dev/null +++ b/.github/qa-nginx-redirecting/compose.yml @@ -0,0 +1,13 @@ +services: + https-proxy: + image: nginx + ports: + - 8080:8080 + volumes: + - $GITHUB_WORKSPACE/.github/qa-nginx-redirecting/nginx.conf:/etc/nginx/nginx.conf:ro + healthcheck: + test: ["CMD", "curl", "--fail", "localhost:8080/health"] + interval: 10s + timeout: 5s + retries: 20 + start_period: 2m \ No newline at end of file diff --git a/.github/qa-nginx-redirecting/nginx.conf b/.github/qa-nginx-redirecting/nginx.conf new file mode 100644 index 0000000..d1df2e6 --- /dev/null +++ b/.github/qa-nginx-redirecting/nginx.conf @@ -0,0 +1,32 @@ +user nginx; +worker_processes auto; + +error_log /var/log/nginx/error.log notice; + +events { + worker_connections 1024; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + sendfile on; + + keepalive_timeout 65; + + include /etc/nginx/conf.d/*.conf; + + server { + listen 8080; + + location /health { + add_header 'Content-Type' 'text/plain'; + return 200 "healthy\n"; + } + + location ~ /clientRedirectToSonarBinaries/(.*) { + return 301 "https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/$1"; + } + } +} diff --git a/.github/qa-sq-behind-ngix/nginx.conf b/.github/qa-sq-behind-ngix/nginx.conf index fd588d6..893ac04 100644 --- a/.github/qa-sq-behind-ngix/nginx.conf +++ b/.github/qa-sq-behind-ngix/nginx.conf @@ -2,7 +2,6 @@ user nginx; worker_processes auto; error_log /var/log/nginx/error.log notice; -pid /var/run/nginx.pid; events { worker_connections 1024; @@ -12,12 +11,6 @@ http { include /etc/nginx/mime.types; default_type application/octet-stream; - log_format main '$remote_addr - $remote_user [$time_local] "$request" ' - '$status $body_bytes_sent "$http_referer" ' - '"$http_user_agent" "$http_x_forwarded_for"'; - - access_log /var/log/nginx/access.log main; - sendfile on; keepalive_timeout 65; @@ -28,7 +21,6 @@ http { listen 8080; location /health { - access_log off; add_header 'Content-Type' 'text/plain'; return 200 "healthy\n"; } @@ -40,9 +32,6 @@ http { ssl_protocols TLSv1.1 TLSv1.2; ssl_certificate /etc/nginx/server.crt; ssl_certificate_key /etc/nginx/server.key; - - access_log /var/log/nginx/localhost; - error_log /var/log/nginx/localhost.error debug; location / { proxy_pass http://sonarqube:9000; diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index d06fb58..bd375c1 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -116,6 +116,56 @@ jobs: - name: Assert Sonar Scanner CLI was not executed run: | ./test/assertFileDoesntExist ./output.properties + scannerBinariesUrlIsEscapedWithWget: + name: > + 'scannerBinariesUrl' is escaped with wget so special chars are not injected in the download command + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + - name: Run action with scannerBinariesUrl + id: runTest + uses: ./ + continue-on-error: true + with: + scannerBinariesUrl: 'http://some_uri;touch file.txt;' + env: + NO_CACHE: true + SONAR_HOST_URL: http://not_actually_used + SONAR_SCANNER_JSON_PARAMS: '{"sonar.scanner.internal.dumpToFile": "./output1.properties"}' + - name: Assert file.txt does not exist + run: | + ./test/assertFileDoesntExist "$RUNNER_TEMP/sonarscanner/file.txt" + scannerBinariesUrlIsEscapedWithCurl: + name: > + 'scannerBinariesUrl' is escaped with curl so special chars are not injected in the download command + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + - name: Remove wget + run: sudo apt-get remove -y wget + - name: Assert wget is not available + run: | + if command -v wget 2>&1 >/dev/null + then + exit 1 + fi + - name: Run action with scannerBinariesUrl + id: runTest + uses: ./ + continue-on-error: true + with: + scannerBinariesUrl: 'http://some_uri http://another_uri''; touch file.txt;' + env: + NO_CACHE: true + SONAR_HOST_URL: http://not_actually_used + SONAR_SCANNER_JSON_PARAMS: '{"sonar.scanner.internal.dumpToFile": "./output1.properties"}' + - name: Assert file.txt does not exist + run: | + ./test/assertFileDoesntExist "$RUNNER_TEMP/sonarscanner/file.txt" dontFailGradleTest: name: > Don't fail on Gradle project @@ -376,6 +426,37 @@ jobs: - name: Assert failure of previous step if: steps.runTest.outcome == 'success' run: exit 1 + curlPerformsRedirect: + name: > + curl performs redirect when scannerBinariesUrl returns 3xx + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + - name: Remove wget + run: sudo apt-get remove -y wget + - name: Assert wget is not available + run: | + if command -v wget 2>&1 >/dev/null + then + exit 1 + fi + - name: Start nginx via Docker Compose + run: docker compose up -d --wait + working-directory: .github/qa-nginx-redirecting + - name: Run action with scannerBinariesUrl + id: runTest + uses: ./ + with: + scannerBinariesUrl: http://localhost:8080/clientRedirectToSonarBinaries + env: + NO_CACHE: true + SONAR_HOST_URL: http://not_actually_used + SONAR_SCANNER_JSON_PARAMS: '{"sonar.scanner.internal.dumpToFile": "./output1.properties"}' + - name: Assert Sonar Scanner CLI was downloaded + run: | + ./test/assertFileExists "$RUNNER_TEMP/sonarscanner/sonar-scanner-cli-6.2.1.4610-linux-x64.zip" useSslCertificate: name: > 'SONAR_ROOT_CERT' is converted to truststore diff --git a/install-sonar-scanner-cli.sh b/install-sonar-scanner-cli.sh index d87c8e4..daf6ef8 100755 --- a/install-sonar-scanner-cli.sh +++ b/install-sonar-scanner-cli.sh @@ -23,32 +23,28 @@ else exit 1 fi -SCANNER_FILE_NAME="sonar-scanner-cli-$INPUT_SCANNERVERSION-$FLAVOR.zip" -SCANNER_URI="${INPUT_SCANNERBINARIESURL%/}/$SCANNER_FILE_NAME" - -if command -v wget &> /dev/null; then - DOWNLOAD_COMMAND="wget" - DOWNLOAD_ARGS="--no-verbose --user-agent=sonarqube-scan-action $SCANNER_URI" -elif command -v curl &> /dev/null; then - DOWNLOAD_COMMAND="curl" - DOWNLOAD_ARGS="--silent --show-error --user-agent sonarqube-scan-action --output $SCANNER_FILE_NAME $SCANNER_URI" -elif [ "$RUNNER_OS" == "Windows" ] && [ -t "C:\\msys64\\usr\\bin\\wget.exe" ]; then - DOWNLOAD_COMMAND="C:\\msys64\\usr\\bin\\wget.exe" - DOWNLOAD_ARGS="--no-verbose --user-agent=sonarqube-scan-action $SCANNER_URI" -elif [ "$RUNNER_OS" == "Windows" ] && [ -t "C:\\msys64\\usr\\bin\\curl.exe" ]; then - DOWNLOAD_COMMAND="C:\\msys64\\usr\\bin\\curl.exe" - DOWNLOAD_ARGS="--silent --show-error --user-agent sonarqube-scan-action --output $SCANNER_FILE_NAME $SCANNER_URI" -else - echo "::error title=SonarScanner::Neither wget nor curl found on the machine" - exit 1 -fi - set -x mkdir -p $RUNNER_TEMP/sonarscanner cd $RUNNER_TEMP/sonarscanner -$DOWNLOAD_COMMAND $DOWNLOAD_ARGS +SCANNER_FILE_NAME="sonar-scanner-cli-$INPUT_SCANNERVERSION-$FLAVOR.zip" +SCANNER_URI="${INPUT_SCANNERBINARIESURL%/}/$SCANNER_FILE_NAME" + +if command -v wget &> /dev/null; then + wget --no-verbose --user-agent=sonarqube-scan-action "$SCANNER_URI" +elif command -v curl &> /dev/null; then + curl --fail --silent --show-error --user-agent sonarqube-scan-action \ + --location --output "$SCANNER_FILE_NAME" "$SCANNER_URI" +elif [ "$RUNNER_OS" == "Windows" ] && [ -t "C:\\msys64\\usr\\bin\\wget.exe" ]; then + "C:\\msys64\\usr\\bin\\wget.exe" --no-verbose --user-agent=sonarqube-scan-action "$SCANNER_URI" +elif [ "$RUNNER_OS" == "Windows" ] && [ -t "C:\\msys64\\usr\\bin\\curl.exe" ]; then + "C:\\msys64\\usr\\bin\\curl.exe" --fail --silent --show-error --user-agent sonarqube-scan-action \ + --location --output "$SCANNER_FILE_NAME" "$SCANNER_URI" +else + echo "::error title=SonarScanner::Neither wget nor curl found on the machine" + exit 1 +fi unzip -q $SCANNER_FILE_NAME From a36db763ac8d69398c0bf7d6f6fafe853fc16029 Mon Sep 17 00:00:00 2001 From: Antonio Aversa Date: Mon, 9 Dec 2024 10:56:27 +0100 Subject: [PATCH 41/60] SQSCANGHA-64 Shorten action description to respect 125 chars limit (#157) --- action.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/action.yml b/action.yml index dbbcdd5..5b0c4ca 100644 --- a/action.yml +++ b/action.yml @@ -1,9 +1,7 @@ name: Official SonarQube (Server, Cloud) Scan description: > - Scan your code with SonarQube Server and Cloud to detect coding - issues in 30+ languages, frameworks, and IaC platforms. - The solution also provides fix recommendations leveraging AI with - Sonar's AI CodeFix capability. (Formerly SonarQube and SonarCloud) + Scan your code with SonarQube Server and Cloud to detect + issues in 30+ languages. (Formerly SonarQube and SonarCloud) branding: icon: check color: green From 844ce2710b50b043b790ffc12eff424c7427d9e0 Mon Sep 17 00:00:00 2001 From: Pavel Mikula Date: Wed, 27 Nov 2024 14:31:03 +0100 Subject: [PATCH 42/60] Add Jira integration --- .github/PULL_REQUEST_TEMPLATE.md | 7 ++++++ .github/workflows/PullRequestClosed.yml | 29 +++++++++++++++++++++++ .github/workflows/PullRequestCreated.yml | 29 +++++++++++++++++++++++ .github/workflows/RequestReview.yml | 28 ++++++++++++++++++++++ .github/workflows/SubmitReview.yml | 30 ++++++++++++++++++++++++ 5 files changed, 123 insertions(+) create mode 100644 .github/workflows/PullRequestClosed.yml create mode 100644 .github/workflows/PullRequestCreated.yml create mode 100644 .github/workflows/RequestReview.yml create mode 100644 .github/workflows/SubmitReview.yml diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 70e857e..198d22d 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,3 +1,10 @@ + + Please be aware that we are not actively looking for feature contributions. The truth is that it's extremely difficult for someone outside SonarSource to comply with our roadmap and expectations. Therefore, we typically only accept minor cosmetic changes and typo fixes. If you would like to see a new feature, please create a new thread in the forum ["Suggest new features"](https://community.sonarsource.com/c/suggestions/features). With that in mind, if you would like to submit a code contribution, make sure that you adhere to the following guidelines and all tests are passing: diff --git a/.github/workflows/PullRequestClosed.yml b/.github/workflows/PullRequestClosed.yml new file mode 100644 index 0000000..b50896e --- /dev/null +++ b/.github/workflows/PullRequestClosed.yml @@ -0,0 +1,29 @@ +name: Pull Request Closed + +on: + pull_request: + types: [closed] + +jobs: + PullRequestMerged_job: + name: Pull Request Merged + runs-on: ubuntu-latest + permissions: + id-token: write + pull-requests: read + # For external PR, ticket should be moved manually + if: | + github.event.pull_request.head.repo.full_name == github.repository + && github.event.pull_request.merged + steps: + - id: secrets + uses: SonarSource/vault-action-wrapper@v3 + with: + secrets: | + development/kv/data/jira user | JIRA_USER; + development/kv/data/jira token | JIRA_TOKEN; + - uses: sonarsource/gh-action-lt-backlog/PullRequestClosed@v2 + with: + github-token: ${{secrets.GITHUB_TOKEN}} + jira-user: ${{ fromJSON(steps.secrets.outputs.vault).JIRA_USER }} + jira-token: ${{ fromJSON(steps.secrets.outputs.vault).JIRA_TOKEN }} diff --git a/.github/workflows/PullRequestCreated.yml b/.github/workflows/PullRequestCreated.yml new file mode 100644 index 0000000..895ba78 --- /dev/null +++ b/.github/workflows/PullRequestCreated.yml @@ -0,0 +1,29 @@ +name: Pull Request Created + +on: + pull_request: + types: ["opened"] + +jobs: + PullRequestCreated_job: + name: Pull Request Created + runs-on: ubuntu-latest + permissions: + id-token: write + # For external PR, ticket should be created manually + if: | + github.event.pull_request.head.repo.full_name == github.repository + steps: + - id: secrets + uses: SonarSource/vault-action-wrapper@v3 + with: + secrets: | + development/github/token/{REPO_OWNER_NAME_DASH}-jira token | GITHUB_TOKEN; + development/kv/data/jira user | JIRA_USER; + development/kv/data/jira token | JIRA_TOKEN; + - uses: sonarsource/gh-action-lt-backlog/PullRequestCreated@v2 + with: + github-token: ${{ fromJSON(steps.secrets.outputs.vault).GITHUB_TOKEN }} + jira-user: ${{ fromJSON(steps.secrets.outputs.vault).JIRA_USER }} + jira-token: ${{ fromJSON(steps.secrets.outputs.vault).JIRA_TOKEN }} + jira-project: SQSCANGHA diff --git a/.github/workflows/RequestReview.yml b/.github/workflows/RequestReview.yml new file mode 100644 index 0000000..5eac0d5 --- /dev/null +++ b/.github/workflows/RequestReview.yml @@ -0,0 +1,28 @@ +name: Request review + +on: + pull_request: + types: ["review_requested"] + +jobs: + RequestReview_job: + name: Request review + runs-on: ubuntu-latest + permissions: + id-token: write + # For external PR, ticket should be moved manually + if: | + github.event.pull_request.head.repo.full_name == github.repository + steps: + - id: secrets + uses: SonarSource/vault-action-wrapper@v3 + with: + secrets: | + development/github/token/{REPO_OWNER_NAME_DASH}-jira token | GITHUB_TOKEN; + development/kv/data/jira user | JIRA_USER; + development/kv/data/jira token | JIRA_TOKEN; + - uses: sonarsource/gh-action-lt-backlog/RequestReview@v2 + with: + github-token: ${{ fromJSON(steps.secrets.outputs.vault).GITHUB_TOKEN }} + jira-user: ${{ fromJSON(steps.secrets.outputs.vault).JIRA_USER }} + jira-token: ${{ fromJSON(steps.secrets.outputs.vault).JIRA_TOKEN }} diff --git a/.github/workflows/SubmitReview.yml b/.github/workflows/SubmitReview.yml new file mode 100644 index 0000000..d5f22e6 --- /dev/null +++ b/.github/workflows/SubmitReview.yml @@ -0,0 +1,30 @@ +name: Submit Review + +on: + pull_request_review: + types: [submitted] + +jobs: + SubmitReview_job: + name: Submit Review + runs-on: ubuntu-latest + permissions: + id-token: write + pull-requests: read + # For external PR, ticket should be moved manually + if: | + github.event.pull_request.head.repo.full_name == github.repository + && (github.event.review.state == 'changes_requested' + || github.event.review.state == 'approved') + steps: + - id: secrets + uses: SonarSource/vault-action-wrapper@v3 + with: + secrets: | + development/kv/data/jira user | JIRA_USER; + development/kv/data/jira token | JIRA_TOKEN; + - uses: sonarsource/gh-action-lt-backlog/SubmitReview@v2 + with: + github-token: ${{secrets.GITHUB_TOKEN}} + jira-user: ${{ fromJSON(steps.secrets.outputs.vault).JIRA_USER }} + jira-token: ${{ fromJSON(steps.secrets.outputs.vault).JIRA_TOKEN }} From 00e62e119083df8c4315d967fb0fcfb4a1895444 Mon Sep 17 00:00:00 2001 From: Antonio Aversa Date: Mon, 16 Dec 2024 10:24:14 +0100 Subject: [PATCH 43/60] SQCPPGHA-9 Extend action to support C, C++, and Objective-C projects (#161) --- .github/workflows/qa-deprecated-c-cpp.yml | 87 +++++ .../workflows/qa-install-build-wrapper.yml | 69 ++++ .github/workflows/{qa.yml => qa-main.yml} | 2 +- .github/workflows/qa-scripts.yml | 351 ++++++++++++++++++ .github/workflows/version_update.yml | 50 +++ README.md | 146 +++++++- action.yml | 15 +- deprecated-c-cpp/action.yml | 134 +++++++ install-build-wrapper/action.yml | 62 ++++ scripts/cert.sh | 8 + scripts/configure_paths.sh | 71 ++++ scripts/create_install_path.sh | 26 ++ scripts/download.sh | 58 +++ scripts/fetch_latest_version.sh | 25 ++ .../install-sonar-scanner-cli.sh | 0 .../run-sonar-scanner-cli.sh | 0 sanity-checks.sh => scripts/sanity-checks.sh | 0 scripts/utils.sh | 25 ++ sonar-scanner-version | 11 + 19 files changed, 1118 insertions(+), 22 deletions(-) create mode 100644 .github/workflows/qa-deprecated-c-cpp.yml create mode 100644 .github/workflows/qa-install-build-wrapper.yml rename .github/workflows/{qa.yml => qa-main.yml} (99%) create mode 100644 .github/workflows/qa-scripts.yml create mode 100644 .github/workflows/version_update.yml create mode 100644 deprecated-c-cpp/action.yml create mode 100644 install-build-wrapper/action.yml create mode 100755 scripts/cert.sh create mode 100755 scripts/configure_paths.sh create mode 100755 scripts/create_install_path.sh create mode 100755 scripts/download.sh create mode 100755 scripts/fetch_latest_version.sh rename install-sonar-scanner-cli.sh => scripts/install-sonar-scanner-cli.sh (100%) rename run-sonar-scanner.sh => scripts/run-sonar-scanner-cli.sh (100%) rename sanity-checks.sh => scripts/sanity-checks.sh (100%) create mode 100755 scripts/utils.sh create mode 100644 sonar-scanner-version diff --git a/.github/workflows/qa-deprecated-c-cpp.yml b/.github/workflows/qa-deprecated-c-cpp.yml new file mode 100644 index 0000000..8ab16d5 --- /dev/null +++ b/.github/workflows/qa-deprecated-c-cpp.yml @@ -0,0 +1,87 @@ +name: QA Deprecated C and C++ action + +on: + push: + branches: + - master + pull_request: + types: [opened, synchronize, reopened] + +jobs: + output-test: + name: Action outputs + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macos-latest, macos-13] + cache: [true, false] + include: + - arch: X64 + - os: macos-latest + arch: ARM64 + runs-on: ${{ matrix.os }} + steps: + # Specifying a specific architecture of the runner is not possible for Github hosted runners + # We can only check if the runner architecture matches the expected one + - name: check_runner_arch + shell: bash + run: | + echo "Runner architecture: ${{ runner.arch }}" + if [[ "${{ runner.arch }}" != "${{ matrix.arch }}" ]]; then + echo "##[error]Runner architecture does not match the expected one" + exit 1 + fi + + - uses: actions/checkout@v4 + with: + fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis + + - name: Run SonarQube C/C++ action + id: run-action + uses: ./deprecated-c-cpp + env: + SONAR_HOST_URL: 'https://next.sonarqube.com/sonarqube/' + with: + cache-binaries: ${{ matrix.cache }} + + - name: SONAR_HOST_URL is set + shell: bash + run: | + [[ $SONAR_HOST_URL == "https://next.sonarqube.com/sonarqube/" ]] + + - name: sonar-scanner is installed and in PATH + run: | + sonar-scanner --help | grep "usage: sonar-scanner " + + - name: sonar-scanner-binary output is correct + shell: bash + env: + BINARY: ${{ steps.run-action.outputs.sonar-scanner-binary }} + run: | + "$BINARY" --help | grep "usage: sonar-scanner " + + # build-wrapper does not have --help or equivalent option. + # Pass to few arguments and ignore error code + - name: build-wrapper is installed and in PATH on Windows + if: runner.os == 'Windows' + shell: bash + run: | + (build-wrapper-win-x86-64.exe || true) | grep "build-wrapper, version " + + - name: build-wrapper is installed and in PATH on Linux + if: runner.os == 'Linux' + shell: bash + run: | + (build-wrapper-linux-x86-64 || true) | grep "build-wrapper, version " + + - name: build-wrapper is installed and in PATH on macOS + if: runner.os == 'macOs' + shell: bash + run: | + (build-wrapper-macosx-x86 || true) | grep "build-wrapper, version " + + - name: build-wrapper-binary output is correct + shell: bash + env: + BINARY: ${{ steps.run-action.outputs.build-wrapper-binary }} + run: | + ("$BINARY" || true) | grep "build-wrapper, version " diff --git a/.github/workflows/qa-install-build-wrapper.yml b/.github/workflows/qa-install-build-wrapper.yml new file mode 100644 index 0000000..793ae05 --- /dev/null +++ b/.github/workflows/qa-install-build-wrapper.yml @@ -0,0 +1,69 @@ +name: QA Install Build Wrapper action + +on: + push: + branches: + - master + pull_request: + types: [opened, synchronize, reopened] + +jobs: + output-test: + name: Action outputs + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macos-latest, macos-13] + cache: [true, false] + include: + - arch: X64 + - os: macos-latest + arch: ARM64 + runs-on: ${{ matrix.os }} + steps: + # Specifying a specific architecture of the runner is not possible for Github hosted runners + # We can only check if the runner architecture matches the expected one + - name: check_runner_arch + shell: bash + run: | + echo "Runner architecture: ${{ runner.arch }}" + if [[ "${{ runner.arch }}" != "${{ matrix.arch }}" ]]; then + echo "##[error]Runner architecture does not match the expected one" + exit 1 + fi + + - uses: actions/checkout@v4 + with: + fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis + + - name: Run SonarQube C/C++ action + id: run-action + uses: ./install-build-wrapper + env: + SONAR_HOST_URL: 'https://next.sonarqube.com/sonarqube/' + + # build-wrapper does not have --help or equivalent option. + # Pass to few arguments and ignore error code + - name: build-wrapper is installed and in PATH on Windows + if: runner.os == 'Windows' + shell: bash + run: | + (build-wrapper-win-x86-64.exe || true) | grep "build-wrapper, version " + + - name: build-wrapper is installed and in PATH on Linux + if: runner.os == 'Linux' + shell: bash + run: | + (build-wrapper-linux-x86-64 || true) | grep "build-wrapper, version " + + - name: build-wrapper is installed and in PATH on macOS + if: runner.os == 'macOs' + shell: bash + run: | + (build-wrapper-macosx-x86 || true) | grep "build-wrapper, version " + + - name: build-wrapper-binary output is correct + shell: bash + env: + BINARY: ${{ steps.run-action.outputs.build-wrapper-binary }} + run: | + ("$BINARY" || true) | grep "build-wrapper, version " diff --git a/.github/workflows/qa.yml b/.github/workflows/qa-main.yml similarity index 99% rename from .github/workflows/qa.yml rename to .github/workflows/qa-main.yml index bd375c1..44d432f 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa-main.yml @@ -1,4 +1,4 @@ -name: QA +name: QA Main action on: push: diff --git a/.github/workflows/qa-scripts.yml b/.github/workflows/qa-scripts.yml new file mode 100644 index 0000000..74d8691 --- /dev/null +++ b/.github/workflows/qa-scripts.yml @@ -0,0 +1,351 @@ +name: QA Scripts + +on: + push: + branches: + - master + pull_request: + types: [opened, synchronize, reopened] + +jobs: + create-install-dir-test: + name: create_install_path.sh + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis + + - name: Existing + shell: bash + env: + INSTALL_PATH: '.sonar' + run: | + echo "- Create dir" + mkdir -p "${INSTALL_PATH}" + + echo "- Test script behavior" + ./scripts/create_install_path.sh > output + grep -v "::error::" output + + - name: Non-existing nested in current dir + shell: bash + env: + INSTALL_PATH: '.sonar' + run: | + ./scripts/create_install_path.sh > output + grep -v "::error::" output + test -d "${INSTALL_PATH}" + + - name: Nonexisting nested in home + shell: bash + env: + INSTALL_PATH: '~/third_party/.sonar' + run: | + ./scripts/create_install_path.sh > output + grep -v "::error::" output + test -d "${INSTALL_PATH}" + + - name: Empty install dir specified + shell: bash + env: + INSTALL_PATH: '' + run: | + (./scripts/create_install_path.sh || echo "=== Script failed ===") > output + grep "::error::Empty installation path specified" output + grep "=== Script failed ===" output + + - name: No permission to create directory + shell: bash + env: + INSTALL_PATH: '/non_creatable' + run: | + (./scripts/create_install_path.sh || echo "=== Script failed ===") > output + grep "::error::Failed to create non-existing installation path '/non_creatable'" output + grep "=== Script failed ===" output + + - name: Existing but not directory + shell: bash + env: + INSTALL_PATH: 'not_directory' + run: | + echo "- Create normal file" + echo "content" > "${INSTALL_PATH}" + + echo "- Test script behavior" + (./scripts/create_install_path.sh || echo "=== Script failed ===") > output + grep "::error::Installation path 'not_directory' is not a directory" output + grep "=== Script failed ===" output + + + - name: Existing but not readable + shell: bash + env: + INSTALL_PATH: 'not_readable' + run: | + echo "- Create dir and make it not readable" + mkdir -p "${INSTALL_PATH}" + chmod -r "${INSTALL_PATH}" + + echo "- Test script behavior" + (./scripts/create_install_path.sh || echo "=== Script failed ===") > output + grep "::error::Installation path 'not_readable' is not readable" output + grep "=== Script failed ===" output + + - name: Existing but not writeable + shell: bash + env: + INSTALL_PATH: 'not_writeable' + run: | + echo "- Create dir and make it not writeable" + mkdir -p "${INSTALL_PATH}" + chmod -w "${INSTALL_PATH}" + + echo "- Test script behavior" + (./scripts/create_install_path.sh || echo "=== Script failed ===") > output + grep "::error::Installation path 'not_writeable' is not writeable" output + grep "=== Script failed ===" output + setup-script-test: + name: configure_paths.sh + runs-on: ubuntu-latest + env: + INSTALL_PATH: 'install-directory' + SONAR_HOST_URL: 'http://sonar-host.com' + SONAR_SCANNER_VERSION: 'vX.Y.Z.MMMM' + SONAR_SCANNER_URL_WINDOWS_X64: 'https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-vX.Y.Z.MMMM-windows-x64.zip' + SONAR_SCANNER_SHA_WINDOWS_X64: 'DOWNLOAD-SHA-WINDOWS-X64' + SONAR_SCANNER_URL_LINUX_X64: 'https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-vX.Y.Z.MMMM-linux-x64.zip' + SONAR_SCANNER_SHA_LINUX_X64: 'DOWNLOAD-SHA-LINUX-X64' + SONAR_SCANNER_URL_LINUX_AARCH64: 'https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-vX.Y.Z.MMMM-linux-aarch64.zip' + SONAR_SCANNER_SHA_LINUX_AARCH64: 'DOWNLOAD-SHA-LINUX-AARCH64' + SONAR_SCANNER_URL_MACOSX_X64: 'https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-vX.Y.Z.MMMM-macosx-x64.zip' + SONAR_SCANNER_SHA_MACOSX_X64: 'DOWNLOAD-SHA-MACOSX-X64' + SONAR_SCANNER_URL_MACOSX_AARCH64: 'https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-vX.Y.Z.MMMM-macosx-aarch64.zip' + SONAR_SCANNER_SHA_MACOSX_AARCH64: 'DOWNLOAD-SHA-MACOSX-AARCH64' + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis + + - name: Windows + shell: bash + env: + OS: 'Windows' + ARCH: 'X64' + run: | + ./scripts/configure_paths.sh > output + grep -v "::error::" output + + echo "- Check sonar-scanner:" + grep "sonar-scanner-url=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-vX.Y.Z.MMMM-windows-x64.zip" output + grep "sonar-scanner-sha=DOWNLOAD-SHA-WINDOWS-X64" output + grep "sonar-scanner-dir=install-directory/sonar-scanner-vX.Y.Z.MMMM-windows-x64" output + grep "sonar-scanner-bin=install-directory/sonar-scanner-vX.Y.Z.MMMM-windows-x64/bin/sonar-scanner.bat" output + + echo "- Check build-wrapper:" + grep "build-wrapper-url=http://sonar-host.com/static/cpp/build-wrapper-win-x86.zip" output + grep "build-wrapper-dir=install-directory/build-wrapper-win-x86" output + grep "build-wrapper-bin=install-directory/build-wrapper-win-x86/build-wrapper-win-x86-64.exe" output + + - name: Linux X64 + shell: bash + env: + OS: 'Linux' + ARCH: 'X64' + run: | + ./scripts/configure_paths.sh > output + grep -v "::error::" output + + echo "- Check sonar-scanner:" + grep "sonar-scanner-url=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-vX.Y.Z.MMMM-linux-x64.zip" output + grep "sonar-scanner-sha=DOWNLOAD-SHA-LINUX-X64" output + grep "sonar-scanner-dir=install-directory/sonar-scanner-vX.Y.Z.MMMM-linux-x64" output + grep "sonar-scanner-bin=install-directory/sonar-scanner-vX.Y.Z.MMMM-linux-x64/bin/sonar-scanner" output + + echo "- Check build-wrapper:" + grep "build-wrapper-url=http://sonar-host.com/static/cpp/build-wrapper-linux-x86.zip" output + grep "build-wrapper-dir=install-directory/build-wrapper-linux-x86" output + grep "build-wrapper-bin=install-directory/build-wrapper-linux-x86/build-wrapper-linux-x86-64" output + + - name: Linux ARM64 + shell: bash + env: + OS: 'Linux' + ARCH: 'ARM64' + run: | + ./scripts/configure_paths.sh > output + grep -v "::error::" output + echo "- Check sonar-scanner:" + grep "sonar-scanner-url=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-vX.Y.Z.MMMM-linux-aarch64.zip" output + grep "sonar-scanner-sha=DOWNLOAD-SHA-LINUX-AARCH64" output + grep "sonar-scanner-dir=install-directory/sonar-scanner-vX.Y.Z.MMMM-linux-aarch64" output + grep "sonar-scanner-bin=install-directory/sonar-scanner-vX.Y.Z.MMMM-linux-aarch64/bin/sonar-scanner" output + echo "- Check build-wrapper:" + grep "build-wrapper-url=http://sonar-host.com/static/cpp/build-wrapper-linux-aarch64.zip" output + grep "build-wrapper-dir=install-directory/build-wrapper-linux-aarch64" output + grep "build-wrapper-bin=install-directory/build-wrapper-linux-aarch64/build-wrapper-linux-aarch64" output + + - name: macOSX_X64 + shell: bash + env: + OS: 'macOS' + ARCH: 'X64' + run: | + ./scripts/configure_paths.sh > output + grep -v "::error::" output + + echo "- Check sonar-scanner:" + grep "sonar-scanner-url=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-vX.Y.Z.MMMM-macosx-x64.zip" output + grep "sonar-scanner-sha=DOWNLOAD-SHA-MACOSX-X64" output + grep "sonar-scanner-dir=install-directory/sonar-scanner-vX.Y.Z.MMMM-macosx-x64" output + grep "sonar-scanner-bin=install-directory/sonar-scanner-vX.Y.Z.MMMM-macosx-x64/bin/sonar-scanner" output + + echo "- Check build-wrapper:" + grep "build-wrapper-url=http://sonar-host.com/static/cpp/build-wrapper-macosx-x86.zip" output + grep "build-wrapper-dir=install-directory/build-wrapper-macosx-x86" output + grep "build-wrapper-bin=install-directory/build-wrapper-macosx-x86/build-wrapper-macosx-x86" output + + - name: macOSX_ARM64 + shell: bash + env: + OS: 'macOS' + ARCH: 'ARM64' + run: | + ./scripts/configure_paths.sh > output + grep -v "::error::" output + + echo "- Check sonar-scanner:" + grep "sonar-scanner-url=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-vX.Y.Z.MMMM-macosx-aarch64.zip" output + grep "sonar-scanner-sha=DOWNLOAD-SHA-MACOSX-AARCH64" output + grep "sonar-scanner-dir=install-directory/sonar-scanner-vX.Y.Z.MMMM-macosx-aarch64" output + grep "sonar-scanner-bin=install-directory/sonar-scanner-vX.Y.Z.MMMM-macosx-aarch64/bin/sonar-scanner" output + + echo "- Check build-wrapper:" + grep "build-wrapper-url=http://sonar-host.com/static/cpp/build-wrapper-macosx-x86.zip" output + grep "build-wrapper-dir=install-directory/build-wrapper-macosx-x86" output + grep "build-wrapper-bin=install-directory/build-wrapper-macosx-x86/build-wrapper-macosx-x86" output + + - name: Unsupported OS + shell: bash + env: + OS: 'unsupportedOS' + ARCH: 'X64' + run: | + (./scripts/configure_paths.sh || echo "=== Script failed ===") > output + + echo "- Check errors:" + grep "::error::Unsupported runner OS 'unsupportedOS'" output + grep "=== Script failed ===" output + + - name: Unsupported architecture + shell: bash + env: + OS: 'Linux' + ARCH: 'X86' + run: | + (./scripts/configure_paths.sh || echo "=== Script failed ===") > output + + echo "- Check errors:" + grep "::error::Architecture 'X86' is unsupported by build-wrapper" output + grep "=== Script failed ===" output + download-script-test: + name: download.sh + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis + + - name: Download test without validation + shell: bash + env: + INSTALL_PATH: 'install-directory-no-sha-validation' + DOWNLOAD_URL: 'https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-4.6.2.2472-linux.zip' + EXPECTED_SHA: 'incorrect-sha-not-validated' + TMP_ZIP_PATH: ${{ runner.temp }}/sonar-scanner.zip + run: | + ./scripts/download.sh > output + test -f "$TMP_ZIP_PATH" + grep -v "::error::" output + - name: Download test with validation + shell: bash + env: + INSTALL_PATH: 'install-directory-sha-validation' + DOWNLOAD_URL: 'https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-4.6.2.2472-linux.zip' + EXPECTED_SHA: '9411331814c1d002bd65d37758b872918b7602e7cf3ca5b83a3e19a729b2be05' + TMP_ZIP_PATH: ${{ runner.temp }}/sonar-scanner.zip + run: | + ./scripts/download.sh -v > output + test -f "$TMP_ZIP_PATH" + grep -v "::error::" output + - name: Incorrect install dir + shell: bash + env: + INSTALL_PATH: '' + run: | + (./scripts/download.sh || echo "=== Script failed ===") > output + grep "::error::Failed to create" output + grep "=== Script failed ===" output + - name: Incorrect download url + shell: bash + env: + INSTALL_PATH: 'install-directory-incorrect-url' + DOWNLOAD_URL: 'incorrect-url' + run: | + (./scripts/download.sh || echo "=== Script failed ===") > output + grep "::error::Failed to download 'incorrect-url'" output + grep "=== Script failed ===" output + - name: Incorrect SHA256 + shell: bash + env: + INSTALL_PATH: 'install-directory-incorrect-sha' + DOWNLOAD_URL: 'https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-4.6.2.2472-linux.zip' + EXPECTED_SHA: 'incorrect-sha256' + TMP_ZIP_PATH: ${{ runner.temp }}/sonar-scanner.zip + run: | + (./scripts/download.sh -v || echo "=== Script failed ===") > output + grep "::error::Checking sha256 failed" output + grep "=== Script failed ===" output + - name: Mismatching SHA256 + shell: bash + env: + INSTALL_PATH: 'install-directory-mismtaching-sha' + DOWNLOAD_URL: 'https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-4.6.2.2472-linux.zip' + EXPECTED_SHA: '3e121d85a4adb1f30b917d5f3eb897966b59e02c3d6d313a78dcd964193dc963' + TMP_ZIP_PATH: ${{ runner.temp }}/sonar-scanner.zip + run: | + (./scripts/download.sh -v || echo "=== Script failed ===") > output + grep "::error::Checking sha256 failed" output + grep "=== Script failed ===" output + fetch-latest-version-test: + name: fetch_latest_version.sh + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis + - name: Test script + shell: bash + run: | + ./scripts/fetch_latest_version.sh > output + + echo "- Check sonar-scanner version:" + grep "sonar-scanner-version=" output + SONAR_SCANNER_VERSION=$(cat output | cut -d= -f 2) + test ! -z "${SONAR_SCANNER_VERSION}" + + echo "- Check windows sonar-scanner URLs:" + grep "sonar-scanner-url-windows-x64=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-${SONAR_SCANNER_VERSION}-windows-x64.zip" output + grep -e "^sonar-scanner-sha-windows-x64=[0-9A-Fa-f]\+$" output + + echo "- Check linux sonar-scanner URLs:" + grep "sonar-scanner-url-linux-x64=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-${SONAR_SCANNER_VERSION}-linux-x64.zip" output + grep -e "^sonar-scanner-sha-linux-x64=[0-9A-Fa-f]\+$" output + grep "sonar-scanner-url-linux-aarch64=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-${SONAR_SCANNER_VERSION}-linux-aarch64.zip" output + grep -e "^sonar-scanner-sha-linux-aarch64=[0-9A-Fa-f]\+$" output + + echo "- Check macosx sonar-scanner URLs:" + grep "sonar-scanner-url-linux-x64=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-${SONAR_SCANNER_VERSION}-linux-x64.zip" output + grep -e "^sonar-scanner-sha-linux-x64=[0-9A-Fa-f]\+$" output + grep "sonar-scanner-url-linux-aarch64=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-${SONAR_SCANNER_VERSION}-linux-aarch64.zip" output + grep -e "^sonar-scanner-sha-linux-aarch64=[0-9A-Fa-f]\+$" output diff --git a/.github/workflows/version_update.yml b/.github/workflows/version_update.yml new file mode 100644 index 0000000..aeec0bd --- /dev/null +++ b/.github/workflows/version_update.yml @@ -0,0 +1,50 @@ +name: sonar-scanner version check +on: + workflow_dispatch: + schedule: + - cron: '15 10 * * *' + +jobs: + update-version: + name: Prepare pull request for sonar-scanner version update + runs-on: ubuntu-latest + steps: + - run: sudo apt install -y jq + + - uses: actions/checkout@v4 + with: + ref: master + persist-credentials: true + fetch-depth: 0 + + - name: "Fetch currently used sonar-scanner version" + id: tagged-version + shell: bash + run: cat sonar-scanner-version >> $GITHUB_OUTPUT + + - name: "Fetch lastest sonar-scanner version" + id: latest-version + shell: bash + run: | + ./scripts/fetch_latest_version.sh > sonar-scanner-version + cat sonar-scanner-version >> $GITHUB_OUTPUT + + - name: "Create Pull Request for version update" + if: steps.tagged-version.outputs.sonar-scanner-version != steps.latest-version.outputs.sonar-scanner-version + shell: bash + env: + UPDATE_BRANCH: update-to-sonar-scanner-${{ steps.latest-version.outputs.sonar-scanner-version }} + TITLE: "Update sonar-scanner-version to ${{ steps.latest-version.outputs.sonar-scanner-version }}" + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + git config --global user.name "SonarTech" + git config --global user.email "sonartech@sonarsource.com" + git checkout -b ${UPDATE_BRANCH} + git add sonar-scanner-version + git commit -m "${TITLE}" + git push --force-with-lease origin ${UPDATE_BRANCH} + gh pr list + + if [[ $(gh pr list -H "${UPDATE_BRANCH}" | grep "${UPDATE_BRANCH}" | wc -l) -eq 0 ]]; then + gh pr create -B master -H ${UPDATE_BRANCH} --title "${TITLE}" --body "Automatic updated of sonar-scanner version value. Needs to be tagged for release." + fi diff --git a/README.md b/README.md index dc75636..bea3deb 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Scan your code with SonarQube [![QA](https://github.com/SonarSource/sonarqube-scan-action/actions/workflows/qa.yml/badge.svg)](https://github.com/SonarSource/sonarqube-scan-action/actions/workflows/qa.yml) +# Scan your code with SonarQube [![QA Main](https://github.com/SonarSource/sonarqube-scan-action/actions/workflows/qa-main.yml/badge.svg)](https://github.com/SonarSource/sonarqube-scan-action/actions/workflows/qa-main.yml) [![QA Install Build Wrapper](https://github.com/SonarSource/sonarqube-scan-action/actions/workflows/qa-install-build-wrapper.yml/badge.svg)](https://github.com/SonarSource/sonarqube-scan-action/actions/workflows/qa-install-build-wrapper.yml) [![QA Scripts](https://github.com/SonarSource/sonarqube-scan-action/actions/workflows/qa-scripts.yml/badge.svg)](https://github.com/SonarSource/sonarqube-scan-action/actions/workflows/qa-scripts.yml) [![QA Deprecated C and C++ Action](https://github.com/SonarSource/sonarqube-scan-action/actions/workflows/qa-deprecated-c-cpp.yml/badge.svg)](https://github.com/SonarSource/sonarqube-scan-action/actions/workflows/qa-deprecated-c-cpp.yml) This SonarSource project, available as a GitHub Action, scans your projects with SonarQube [Server](https://www.sonarsource.com/products/sonarqube/) or [Cloud](https://www.sonarsource.com/products/sonarcloud/). @@ -11,6 +11,9 @@ It helps developers detect coding issues in 30+ languages, frameworks, and IaC p The solution also provides fix recommendations leveraging AI with Sonar's AI CodeFix capability. +> [!NOTE] +> This action now supports and is the official entrypoint for scanning C, C++, Objective-C and Dart projects via GitHub actions. + ## Requirements ### Server @@ -38,7 +41,11 @@ sonar.projectKey= # Ex: v4.1.0, See the latest version at https://github.com/marketplace/actions/official-sonarqube-scan + uses: SonarSource/sonarqube-scan-action@ # Ex: v4.1.0, See the latest version at https://github.com/marketplace/actions/official-sonarqube-scan env: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} SONAR_HOST_URL: ${{ vars.SONAR_HOST_URL }} ``` +For C, C++, and Objective-C projects relying on [Build Wrapper](https://docs.sonarsource.com/sonarqube-server/latest/analyzing-source-code/languages/c-family/prerequisites/#using-buildwrapper) to generate the compilation database, the workflow requires additional steps to download the Build Wrapper and invoke it: + +```yaml +# Trigger analysis when pushing to your main branches, and when creating a pull request. + push: + branches: + - main + - master + - develop + - 'releases/**' + pull_request: + types: [opened, synchronize, reopened] + +name: Main Workflow +jobs: + sonarqube: + runs-on: ubuntu-latest + env: + BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory # Directory where build-wrapper output will be placed + steps: + - uses: actions/checkout@v4 + with: + # Disabling shallow clone is recommended for improving relevancy of reporting + fetch-depth: 0 + - name: Install Build Wrapper + uses: SonarSource/sonarqube-scan-action/install-build-wrapper@ + env: + SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} + - name: Run Build Wrapper + run: | + # here goes your compilation wrapped with build-wrapper; See https://docs.sonarsource.com/sonarqube/latest/ analyzing-source-code/languages/c-family/#using-build-wrapper for more information + # build-preparation steps + # build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} build-command + - name: SonarQube Scan + uses: SonarSource/sonarqube-scan-action@ + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} + SONAR_ROOT_CERT: ${{ secrets.SONAR_ROOT_CERT }} + with: + # Consult https://docs.sonarsource.com/sonarqube/latest/analyzing-source-code/scanners/sonarscanner/ for more information and options + args: > + --define sonar.cfamily.compile-commands="${{ env.BUILD_WRAPPER_OUT_DIR }}/compile_commands.json" +``` + +If you are using SonarQube Server 10.5 or earlier, use `sonar.cfamily.build-wrapper-output` instead of `sonar.cfamily.compile-commands` in the `args` property of the last step, as Build Wrapper does not generate a `compile_commands.json` file before SonarQube Server 10.6. + +It should look like this: + +```yaml +with: + args: > + --define sonar.cfamily.build-wrapper-output="${{ env.BUILD_WRAPPER_OUT_DIR }}" +``` + +See also [example configurations of C++ projects for SonarQube Server](https://github.com/search?q=org%3Asonarsource-cfamily-examples+gh-actions-sq&type=repositories). + ### Cloud ```properties @@ -79,7 +143,11 @@ sonar.projectKey= # Ex: v4.1.0, See the latest version at https://github.com/marketplace/actions/official-sonarqube-scan + uses: SonarSource/sonarqube-scan-action@ # Ex: v4.1.0, See the latest version at https://github.com/marketplace/actions/official-sonarqube-scan env: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} ``` +For C, C++, and Objective-C projects relying on [Build Wrapper](https://docs.sonarsource.com/sonarqube-cloud/advanced-setup/languages/c-family/prerequisites/#using-build-wrapper) to generate the compilation database, the workflow requires additional steps to download the Build Wrapper and invoke it: + +```yaml +# Trigger analysis when pushing to your main branches, and when creating a pull request. + push: + branches: + - main + - master + - develop + - 'releases/**' + pull_request: + types: [opened, synchronize, reopened] + +name: Main Workflow +jobs: + sonarqube: + runs-on: ubuntu-latest + env: + BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory # Directory where build-wrapper output will be placed + steps: + - uses: actions/checkout@v4 + with: + # Disabling shallow clone is recommended for improving relevancy of reporting + fetch-depth: 0 + - name: Install Build Wrapper + uses: SonarSource/sonarqube-scan-action/install-build-wrapper@ + - name: Run Build Wrapper + run: | + # here goes your compilation wrapped with build-wrapper; See https://docs.sonarsource.com/sonarqube/latest/ analyzing-source-code/languages/c-family/#using-build-wrapper for more information + # build-preparation steps + # build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} build-command + - name: SonarQube Scan + uses: SonarSource/sonarqube-scan-action@ + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + SONAR_ROOT_CERT: ${{ secrets.SONAR_ROOT_CERT }} + with: + # Consult https://docs.sonarsource.com/sonarqube/latest/analyzing-source-code/scanners/sonarscanner/ for more information and options + args: > + --define sonar.cfamily.compile-commands="${{ env.BUILD_WRAPPER_OUT_DIR }}/compile_commands.json" +``` + +See also [example configurations of C++ projects for SonarQube Cloud](https://github.com/search?q=org%3Asonarsource-cfamily-examples+gh-actions-sc&type=repositories). + ## Action parameters You can change the analysis base directory by using the optional input `projectBaseDir` like this: ```yaml -- uses: sonarsource/sonarqube-scan-action@ +- uses: SonarSource/sonarqube-scan-action@ with: projectBaseDir: app/src ``` @@ -121,7 +233,7 @@ You can change the analysis base directory by using the optional input `projectB In case you need to specify the version of the Sonar Scanner, you can use the `scannerVersion` option: ```yaml -- uses: sonarsource/sonarqube-scan-action@ +- uses: SonarSource/sonarqube-scan-action@ with: scannerVersion: 6.2.0.4584 ``` @@ -129,7 +241,7 @@ In case you need to specify the version of the Sonar Scanner, you can use the `s In case you need to add additional analysis parameters, and you do not wish to set them in the `sonar-project.properties` file, you can use the `args` option: ```yaml -- uses: sonarsource/sonarqube-scan-action@ +- uses: SonarSource/sonarqube-scan-action@ with: projectBaseDir: app/src args: > @@ -147,7 +259,7 @@ The specified URL overrides the default address: `https://binaries.sonarsource.c This can be useful when the runner executing the action is self-hosted and has regulated or no access to the Internet: ```yaml -- uses: sonarsource/sonarqube-scan-action@ +- uses: SonarSource/sonarqube-scan-action@ with: scannerBinariesUrl: https://my.custom.binaries.url.com/Distribution/sonar-scanner-cli/ ``` @@ -159,14 +271,13 @@ More information about possible analysis parameters can be found: ### Environment variables - `SONAR_TOKEN` – **Required** this is the token used to authenticate access to SonarQube. You can read more about security tokens in the documentation of SonarQube [Server](https://docs.sonarsource.com/sonarqube-server/latest/user-guide/managing-tokens/) and [Cloud](https://docs.sonarsource.com/sonarqube-cloud/managing-your-account/managing-tokens/). You can set the `SONAR_TOKEN` environment variable in the "Secrets" settings page of your repository, or you can add them at the level of your GitHub organization (recommended). -- *`GITHUB_TOKEN` – Provided by Github (see [Authenticating with the GITHUB_TOKEN](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/authenticating-with-the-github_token)).* - `SONAR_HOST_URL` – this tells the scanner where SonarQube Server is hosted. You can set the `SONAR_HOST_URL` environment variable in the "Variables" settings page of your repository, or you can add them at the level of your GitHub organization (recommended). Not needed for SonarQube Cloud. - `SONAR_ROOT_CERT` – Holds an additional certificate (in PEM format) that is used to validate the certificate of SonarQube Server or of a secured proxy to SonarQube (Server or Cloud). You can set the `SONAR_ROOT_CERT` environment variable in the "Secrets" settings page of your repository, or you can add them at the level of your GitHub organization (recommended). Here is an example of how you can pass a certificate (in PEM format) to the Scanner truststore: ```yaml -- uses: sonarsource/sonarqube-scan-action@ +- uses: SonarSource/sonarqube-scan-action@ env: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} SONAR_HOST_URL: ${{ vars.SONAR_HOST_URL }} @@ -176,7 +287,7 @@ Here is an example of how you can pass a certificate (in PEM format) to the Scan If your source code file names contain special characters that are not covered by the locale range of `en_US.UTF-8`, you can configure your desired locale like this: ```yaml -- uses: sonarsource/sonarqube-scan-action@ +- uses: SonarSource/sonarqube-scan-action@ env: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} SONAR_HOST_URL: ${{ vars.SONAR_HOST_URL }} # or https://sonarcloud.io @@ -190,9 +301,14 @@ This GitHub Action will not work for all technologies. If you are in one of the * Your code is built with Maven. Read the documentation about our SonarScanner for Maven in SonarQube [Server](https://docs.sonarsource.com/sonarqube-server/latest/analyzing-source-code/scanners/sonarscanner-for-maven/) and [Cloud](https://docs.sonarsource.com/sonarqube-cloud/advanced-setup/ci-based-analysis/sonarscanner-for-maven/). * Your code is built with Gradle. Read the documentation about our SonarScanner for Gradle in SonarQube [Server](https://docs.sonarsource.com/sonarqube-server/latest/analyzing-source-code/scanners/sonarscanner-for-gradle/) and [Cloud](https://docs.sonarsource.com/sonarqube-cloud/advanced-setup/ci-based-analysis/sonarscanner-for-gradle/). * You want to analyze a .NET solution. Read the documentation about our SonarScanner for .NET in SonarQube [Server](https://docs.sonarsource.com/sonarqube-server/latest/analyzing-source-code/scanners/dotnet/introduction/) and [Cloud](https://docs.sonarsource.com/sonarqube-cloud/advanced-setup/ci-based-analysis/sonarscanner-for-dotnet/introduction/). -* You want to analyze C or C++ code. Starting from SonarQube 10.6, this GitHub Action will scan C and C++ out of the box. If you want to have better control over the scan configuration/setup, you can switch to: - * the [SonarQube Server Scan for C and C++](https://github.com/marketplace/actions/sonarqube-scan-for-c-and-c) GitHub Action, for projects on SonarQube Server - * the [SonarQube Cloud Scan for C and C++](https://github.com/marketplace/actions/sonarcloud-scan-for-c-and-c) GitHub Action, for projects on SonarQube Cloud - look at [our sample C and C++ project](https://github.com/sonarsource-cfamily-examples?q=gh-actions-sc&type=all&language=&sort=). + +## Do not use this GitHub action if you are in the following situations + +* You want to run the action on C, C++, or Objective-C projects on a 32-bits system - build wrappers support only 64-bits OS. + +## Additional information + +The `sonarqube-scan-action/install-build-wrapper` action installs `coreutils` if run on macOS. ## Have questions or feedback? diff --git a/action.yml b/action.yml index 5b0c4ca..9e8ce9e 100644 --- a/action.yml +++ b/action.yml @@ -15,7 +15,7 @@ inputs: scannerVersion: description: Version of the Sonar Scanner CLI to use required: false - default: 6.2.1.4610 + default: 6.2.1.4610 # to be kept in sync with sonar-scanner-version scannerBinariesUrl: description: URL to download the Sonar Scanner CLI binaries from required: false @@ -24,19 +24,22 @@ runs: using: "composite" steps: - name: Sanity checks - run: ${GITHUB_ACTION_PATH}/sanity-checks.sh + run: ${GITHUB_ACTION_PATH}/scripts/sanity-checks.sh shell: bash env: INPUT_PROJECTBASEDIR: ${{ inputs.projectBaseDir }} - name: Load Sonar Scanner CLI from cache id: sonar-scanner-cli - uses: actions/cache@v4.0.2 + uses: actions/cache@v4 + env: + # The default value is 60mins. Reaching timeout is treated the same as a cache miss. + SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1 with: path: ${{ runner.temp }}/sonar-scanner-cli-${{ inputs.scannerVersion }}-${{ runner.os }}-${{ runner.arch }} key: sonar-scanner-cli-${{ inputs.scannerVersion }}-${{ runner.os }}-${{ runner.arch }} - name: Install Sonar Scanner CLI if: ${{ env.NO_CACHE == 'true' || steps.sonar-scanner-cli.outputs.cache-hit != 'true' }} - run: ${GITHUB_ACTION_PATH}/install-sonar-scanner-cli.sh + run: ${GITHUB_ACTION_PATH}/scripts/install-sonar-scanner-cli.sh shell: bash env: INPUT_SCANNERVERSION: ${{ inputs.scannerVersion }} @@ -45,8 +48,8 @@ runs: run: echo "${RUNNER_TEMP}/sonar-scanner-cli-${{ inputs.scannerVersion }}-${{ runner.os }}-${{ runner.arch }}/bin" >> $GITHUB_PATH shell: bash - name: Run SonarScanner - run: ${GITHUB_ACTION_PATH}/run-sonar-scanner.sh ${{ inputs.args }} + run: ${GITHUB_ACTION_PATH}/scripts/run-sonar-scanner-cli.sh ${{ inputs.args }} shell: bash env: INPUT_PROJECTBASEDIR: ${{ inputs.projectBaseDir }} - SONAR_SCANNER_JRE: ${{ runner.temp }}/sonar-scanner-cli-${{ inputs.scannerVersion }}-${{ runner.os }}-${{ runner.arch }}/jre \ No newline at end of file + SONAR_SCANNER_JRE: ${{ runner.temp }}/sonar-scanner-cli-${{ inputs.scannerVersion }}-${{ runner.os }}-${{ runner.arch }}/jre diff --git a/deprecated-c-cpp/action.yml b/deprecated-c-cpp/action.yml new file mode 100644 index 0000000..a1e420f --- /dev/null +++ b/deprecated-c-cpp/action.yml @@ -0,0 +1,134 @@ +name: 'SonarQube Scan for C and C++' +description: 'Scan your C and C++ code with SonarQube to detect bugs, vulnerabilities and code smells.' +branding: + icon: check + color: green +inputs: + installation-path: + description: 'Directory where the sonar-scanner and build wrapper will be installed. Created if does not exists.' + required: false + default: '.sonar' + cache-binaries: + description: 'Controls if installed binaries are cached using GitHub cache.' + required: false + default: 'true' + +outputs: + sonar-scanner-binary: + description: "Absolute path to sonar-scanner binary." + value: ${{ steps.setup-outputs.outputs.sonar-scanner-binary }} + build-wrapper-binary: + description: "Absolute path to build-wrapper binary." + value: ${{ steps.setup-outputs.outputs.build-wrapper-binary }} + +runs: + using: "composite" + steps: + # install packaged required for greadlink and sha256sum command on macOS + - name: Install required packages for macOS + if: runner.os == 'macOS' + shell: bash + run: brew install coreutils + + - name: Set SONAR_HOST_URL to 'https://sonarcloud.io' + if: env.SONAR_HOST_URL == '' + shell: bash + run: | + echo "Setting SONAR_HOST_URL to 'https://sonarcloud.io'" + echo "SONAR_HOST_URL=https://sonarcloud.io" >> $GITHUB_ENV + + - name: Verify and create installation path + shell: bash + env: + INSTALL_PATH: ${{ inputs.installation-path }} + run: ${GITHUB_ACTION_PATH}/../scripts/create_install_path.sh + + - name: Set version of sonar-scanner + id: sonar-scanner-version + shell: bash + run: cat ${GITHUB_ACTION_PATH}/../sonar-scanner-version >> $GITHUB_OUTPUT + + - name: Configure paths + id: configure_paths + shell: bash + env: + OS: ${{ runner.os }} + ARCH: ${{ runner.arch }} + INSTALL_PATH: ${{ inputs.installation-path }} + SONAR_SCANNER_VERSION: ${{ steps.sonar-scanner-version.outputs.sonar-scanner-version }} + SONAR_SCANNER_URL_WINDOWS_X64: ${{ steps.sonar-scanner-version.outputs.sonar-scanner-url-windows-x64 }} + SONAR_SCANNER_SHA_WINDOWS_X64: ${{ steps.sonar-scanner-version.outputs.sonar-scanner-sha-windows-x64 }} + SONAR_SCANNER_URL_LINUX_X64: ${{ steps.sonar-scanner-version.outputs.sonar-scanner-url-linux-x64 }} + SONAR_SCANNER_SHA_LINUX_X64: ${{ steps.sonar-scanner-version.outputs.sonar-scanner-sha-linux-x64 }} + SONAR_SCANNER_URL_LINUX_AARCH64: ${{ steps.sonar-scanner-version.outputs.sonar-scanner-url-linux-aarch64 }} + SONAR_SCANNER_SHA_LINUX_AARCH64: ${{ steps.sonar-scanner-version.outputs.sonar-scanner-sha-linux-aarch64 }} + SONAR_SCANNER_URL_MACOSX_X64: ${{ steps.sonar-scanner-version.outputs.sonar-scanner-url-macosx-x64 }} + SONAR_SCANNER_SHA_MACOSX_X64: ${{ steps.sonar-scanner-version.outputs.sonar-scanner-sha-macosx-x64 }} + SONAR_SCANNER_URL_MACOSX_AARCH64: ${{ steps.sonar-scanner-version.outputs.sonar-scanner-url-macosx-aarch64 }} + SONAR_SCANNER_SHA_MACOSX_AARCH64: ${{ steps.sonar-scanner-version.outputs.sonar-scanner-sha-macosx-aarch64 }} + run: ${GITHUB_ACTION_PATH}/../scripts/configure_paths.sh >> $GITHUB_OUTPUT + + - name: Cache sonar-scanner installation + id: cache-sonar-tools + if: inputs.cache-binaries == 'true' + uses: actions/cache@v4 + env: + # The default value is 60mins. Reaching timeout is treated the same as a cache miss. + SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1 + with: + key: sonar-scanner-${{ runner.os }}-${{ runner.arch }}-${{ steps.sonar-scanner-version.outputs.sonar-scanner-version }} + path: ${{ steps.configure_paths.outputs.sonar-scanner-dir }} + + - name: Download and install sonar-scanner + if: steps.cache-sonar-tools.outputs.cache-hit != 'true' + shell: bash + env: + DOWNLOAD_URL: ${{ steps.configure_paths.outputs.sonar-scanner-url }} + EXPECTED_SHA: ${{ steps.configure_paths.outputs.sonar-scanner-sha }} + INSTALL_PATH: ${{ inputs.installation-path }} + TMP_ZIP_PATH: ${{ runner.temp }}/sonar-scanner.zip + run: ${GITHUB_ACTION_PATH}/../scripts/download.sh -v + + - name: Add the custom root certificate to java certificate store + shell: bash + run: ${GITHUB_ACTION_PATH}/../scripts/cert.sh + + - name: Download and install build-wrapper + shell: bash + env: + DOWNLOAD_URL: ${{ steps.configure_paths.outputs.build-wrapper-url }} + INSTALL_PATH: ${{ inputs.installation-path }} + TMP_ZIP_PATH: ${{ runner.temp }}/build-wrapper.zip + run: ${GITHUB_ACTION_PATH}/../scripts/download.sh + + - name: Setup action outputs + id: setup-outputs + shell: bash + env: + SONAR_SCANNER_DIR: ${{ steps.configure_paths.outputs.sonar-scanner-dir }} + SONAR_SCANNER_BIN: ${{ steps.configure_paths.outputs.sonar-scanner-bin }} + BUILD_WRAPPER_DIR: ${{ steps.configure_paths.outputs.build-wrapper-dir }} + BUILD_WRAPPER_BIN: ${{ steps.configure_paths.outputs.build-wrapper-bin }} + run: | + source ${GITHUB_ACTION_PATH}/../scripts/utils.sh + + echo "::group::Action outputs" + echo "SONAR_HOST_URL=${SONAR_HOST_URL}" >> $GITHUB_ENV + echo "'SONAR_HOST_URL' environment variable set to '${SONAR_HOST_URL}'" + + SONAR_SCANNER_BIN_DIR=$(realpath "${SONAR_SCANNER_DIR}/bin") + echo "${SONAR_SCANNER_BIN_DIR}" >> $GITHUB_PATH + echo "'${SONAR_SCANNER_BIN_DIR}' added to the path" + + SONAR_SCANNER_BIN=$(realpath "${SONAR_SCANNER_BIN}") + echo "sonar-scanner-binary=${SONAR_SCANNER_BIN}" >> $GITHUB_OUTPUT + echo "'sonar-scanner-binary' output set to '${SONAR_SCANNER_BIN}'" + + BUILD_WRAPPER_BIN_DIR=$(realpath "${BUILD_WRAPPER_DIR}") + echo "${BUILD_WRAPPER_BIN_DIR}" >> $GITHUB_PATH + echo "'${BUILD_WRAPPER_BIN_DIR}' added to the path" + + BUILD_WRAPPER_BIN=$(realpath "${BUILD_WRAPPER_BIN}") + echo "build-wrapper-binary=${BUILD_WRAPPER_BIN}" >> $GITHUB_OUTPUT + echo "'build-wrapper-binary' output set to '${BUILD_WRAPPER_BIN}'" + echo "::endgroup::" diff --git a/install-build-wrapper/action.yml b/install-build-wrapper/action.yml new file mode 100644 index 0000000..65a457b --- /dev/null +++ b/install-build-wrapper/action.yml @@ -0,0 +1,62 @@ +name: 'Install Build Wrapper for C and C++' +description: > + Download and install the Build Wrapper for C, C++, and Objective-C + projects analyzed with manual config. +branding: + icon: check + color: green +outputs: + build-wrapper-binary: + description: "Absolute path to Build Wrapper binary." + value: ${{ steps.setup-outputs.outputs.build-wrapper-binary }} +runs: + using: "composite" + + steps: + # install packaged required for greadlink and sha256sum command on macOS + - name: Install required packages for macOS + if: runner.os == 'macOS' + shell: bash + run: brew install coreutils + + - name: Set SONAR_HOST_URL to 'https://sonarcloud.io' + if: env.SONAR_HOST_URL == '' + shell: bash + run: | + echo "Setting SONAR_HOST_URL to 'https://sonarcloud.io'" + echo "SONAR_HOST_URL=https://sonarcloud.io" >> $GITHUB_ENV + + - name: Configure paths + id: configure_paths + shell: bash + env: + OS: ${{ runner.os }} + ARCH: ${{ runner.arch }} + INSTALL_PATH: ${{ runner.temp }} # TODO: or .sonar, if RUNNER_TEMP creates problem with caching and self-hosted runners + run: ${GITHUB_ACTION_PATH}/../scripts/configure_paths.sh >> $GITHUB_OUTPUT + + - name: Download and install Build Wrapper + shell: bash + env: + DOWNLOAD_URL: ${{ steps.configure_paths.outputs.build-wrapper-url }} + TMP_ZIP_PATH: ${{ runner.temp }}/build-wrapper-${{ inputs.configure_paths.sonar-scanner-version }}-${{ runner.os }}-${{ runner.arch }}.zip + INSTALL_PATH: ${{ runner.temp }} # TODO: or .sonar, if RUNNER_TEMP creates problem with caching and self-hosted runners + run: ${GITHUB_ACTION_PATH}/../scripts/download.sh + + - name: Setup action outputs + id: setup-outputs + shell: bash + env: + BUILD_WRAPPER_DIR: ${{ steps.configure_paths.outputs.build-wrapper-dir }} + BUILD_WRAPPER_BIN: ${{ steps.configure_paths.outputs.build-wrapper-bin }} + run: | + source ${GITHUB_ACTION_PATH}/../scripts/utils.sh + + BUILD_WRAPPER_BIN_DIR=$(realpath "${BUILD_WRAPPER_DIR}") + echo "${BUILD_WRAPPER_BIN_DIR}" >> $GITHUB_PATH + echo "'${BUILD_WRAPPER_BIN_DIR}' added to the path" + + BUILD_WRAPPER_BIN=$(realpath "${BUILD_WRAPPER_BIN}") + echo "build-wrapper-binary=${BUILD_WRAPPER_BIN}" >> $GITHUB_OUTPUT + echo "'build-wrapper-binary' output set to '${BUILD_WRAPPER_BIN}'" + echo "::endgroup::" diff --git a/scripts/cert.sh b/scripts/cert.sh new file mode 100755 index 0000000..2c2a2a5 --- /dev/null +++ b/scripts/cert.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +if [[ -n "${SONAR_ROOT_CERT}" ]]; then + echo "Adding custom root certificate to java certificate store" + rm -f /tmp/tmpcert.pem + echo "${SONAR_ROOT_CERT}" > /tmp/tmpcert.pem + keytool -keystore /etc/ssl/certs/java/cacerts -storepass changeit -noprompt -trustcacerts -importcert -alias sonarqube -file /tmp/tmpcert.pem +fi diff --git a/scripts/configure_paths.sh b/scripts/configure_paths.sh new file mode 100755 index 0000000..d1bbfe1 --- /dev/null +++ b/scripts/configure_paths.sh @@ -0,0 +1,71 @@ +#!/bin/bash + +if [[ ${ARCH} != "X64" && ! (${ARCH} == "ARM64" && (${OS} == "macOS" || ${OS} == "Linux")) ]]; then + echo "::error::Architecture '${ARCH}' is unsupported by build-wrapper" + exit 1 +fi + +case ${OS} in + Windows) + SONAR_SCANNER_SUFFIX="windows-x64" + BUILD_WRAPPER_SUFFIX="win-x86" + SONAR_SCANNER_NAME="sonar-scanner.bat" + BUILD_WRAPPER_NAME="build-wrapper-win-x86-64.exe" + SONAR_SCANNER_URL="${SONAR_SCANNER_URL_WINDOWS_X64}" + SONAR_SCANNER_SHA="${SONAR_SCANNER_SHA_WINDOWS_X64}" + ;; + Linux) + case ${ARCH} in + X64) + SONAR_SCANNER_SUFFIX="linux-x64" + BUILD_WRAPPER_SUFFIX="linux-x86" + BUILD_WRAPPER_NAME="build-wrapper-linux-x86-64" + SONAR_SCANNER_URL="${SONAR_SCANNER_URL_LINUX_X64}" + SONAR_SCANNER_SHA="${SONAR_SCANNER_SHA_LINUX_X64}" + ;; + ARM64) + SONAR_SCANNER_SUFFIX="linux-aarch64" + BUILD_WRAPPER_SUFFIX="linux-aarch64" + BUILD_WRAPPER_NAME="build-wrapper-linux-aarch64" + SONAR_SCANNER_URL="${SONAR_SCANNER_URL_LINUX_AARCH64}" + SONAR_SCANNER_SHA="${SONAR_SCANNER_SHA_LINUX_AARCH64}" + ;; + esac + SONAR_SCANNER_NAME="sonar-scanner" + ;; + macOS) + case ${ARCH} in + X64) + SONAR_SCANNER_SUFFIX="macosx-x64" + SONAR_SCANNER_URL="${SONAR_SCANNER_URL_MACOSX_X64}" + SONAR_SCANNER_SHA="${SONAR_SCANNER_SHA_MACOSX_X64}" + ;; + ARM64) + SONAR_SCANNER_SUFFIX="macosx-aarch64" + SONAR_SCANNER_URL="${SONAR_SCANNER_URL_MACOSX_AARCH64}" + SONAR_SCANNER_SHA="${SONAR_SCANNER_SHA_MACOSX_AARCH64}" + ;; + esac + BUILD_WRAPPER_SUFFIX="macosx-x86" + SONAR_SCANNER_NAME="sonar-scanner" + BUILD_WRAPPER_NAME="build-wrapper-macosx-x86" + ;; + *) + echo "::error::Unsupported runner OS '${OS}'" + exit 1 + ;; +esac + + +echo "sonar-scanner-url=${SONAR_SCANNER_URL}" +echo "sonar-scanner-sha=${SONAR_SCANNER_SHA}" + +SONAR_SCANNER_DIR="${INSTALL_PATH}/sonar-scanner-${SONAR_SCANNER_VERSION}-${SONAR_SCANNER_SUFFIX}" +echo "sonar-scanner-dir=${SONAR_SCANNER_DIR}" +echo "sonar-scanner-bin=${SONAR_SCANNER_DIR}/bin/${SONAR_SCANNER_NAME}" + +BUILD_WRAPPER_DIR="${INSTALL_PATH}/build-wrapper-${BUILD_WRAPPER_SUFFIX}" +echo "build-wrapper-url=${SONAR_HOST_URL%/}/static/cpp/build-wrapper-${BUILD_WRAPPER_SUFFIX}.zip" +echo "build-wrapper-dir=${BUILD_WRAPPER_DIR}" +echo "build-wrapper-bin=${BUILD_WRAPPER_DIR}/${BUILD_WRAPPER_NAME}" + diff --git a/scripts/create_install_path.sh b/scripts/create_install_path.sh new file mode 100755 index 0000000..7e35571 --- /dev/null +++ b/scripts/create_install_path.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +source "$(dirname -- "$0")/utils.sh" + +echo "Installation path is '${INSTALL_PATH}'" + +test ! -z "${INSTALL_PATH}" +check_status "Empty installation path specified" + +if [[ ! -e "${INSTALL_PATH}" ]]; then + mkdir -p "${INSTALL_PATH}" + check_status "Failed to create non-existing installation path '${INSTALL_PATH}'" +fi + +ABSOLUTE_INSTALL_PATH=$(realpath "${INSTALL_PATH}") +echo "Absolute installation path is '${ABSOLUTE_INSTALL_PATH}'" + +test -d "${INSTALL_PATH}" +check_status "Installation path '${INSTALL_PATH}' is not a directory (absolute path is '${ABSOLUTE_INSTALL_PATH}')" + +test -r "${INSTALL_PATH}" +check_status "Installation path '${INSTALL_PATH}' is not readable (absolute path is '${ABSOLUTE_INSTALL_PATH}')" + +test -w "${INSTALL_PATH}" +check_status "Installation path '${INSTALL_PATH}' is not writeable (absolute path is '${ABSOLUTE_INSTALL_PATH}')" + diff --git a/scripts/download.sh b/scripts/download.sh new file mode 100755 index 0000000..9e1aefa --- /dev/null +++ b/scripts/download.sh @@ -0,0 +1,58 @@ +#!/bin/bash + +source "$(dirname -- "$0")/utils.sh" + +VERIFY_CORRECTNESS=false + +help() { + cat < Date: Mon, 16 Dec 2024 06:32:38 -0300 Subject: [PATCH 44/60] README: required programs for self-hosted and container (#162) Co-authored-by: Antonio Aversa --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index bea3deb..7ac12c6 100644 --- a/README.md +++ b/README.md @@ -306,6 +306,13 @@ This GitHub Action will not work for all technologies. If you are in one of the * You want to run the action on C, C++, or Objective-C projects on a 32-bits system - build wrappers support only 64-bits OS. +## Self-hosted runner or container + +When running the action in a self-hosted runner or container, please ensure that the following programs are installed: + +* **curl** or **wget** +* **unzip** + ## Additional information The `sonarqube-scan-action/install-build-wrapper` action installs `coreutils` if run on macOS. From ea0362bf7b35097068b985d005f8c0887f251063 Mon Sep 17 00:00:00 2001 From: Bilgin Aksoy Date: Mon, 16 Dec 2024 10:40:37 +0100 Subject: [PATCH 45/60] Force unzip without prompt in sonar scanner installation when files already exist (#163) --- scripts/install-sonar-scanner-cli.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/install-sonar-scanner-cli.sh b/scripts/install-sonar-scanner-cli.sh index daf6ef8..f08a78e 100755 --- a/scripts/install-sonar-scanner-cli.sh +++ b/scripts/install-sonar-scanner-cli.sh @@ -46,7 +46,7 @@ else exit 1 fi -unzip -q $SCANNER_FILE_NAME +unzip -q -o $SCANNER_FILE_NAME # Folder name should correspond to the directory cached by the actions/cache mv sonar-scanner-$INPUT_SCANNERVERSION-$FLAVOR $RUNNER_TEMP/sonar-scanner-cli-$INPUT_SCANNERVERSION-$RUNNER_OS-$RUNNER_ARCH From 0ab314b63d8b8578bc90420663b12835ed33ecf4 Mon Sep 17 00:00:00 2001 From: Antonio Aversa Date: Mon, 16 Dec 2024 10:45:31 +0100 Subject: [PATCH 46/60] SQSCANGHA-75 Support self-hosted runners not clearing temp after run (#164) --- .github/workflows/qa-main.yml | 37 +++++++++++++++++++++++++++- scripts/install-sonar-scanner-cli.sh | 10 +++++++- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/.github/workflows/qa-main.yml b/.github/workflows/qa-main.yml index 44d432f..6427f00 100644 --- a/.github/workflows/qa-main.yml +++ b/.github/workflows/qa-main.yml @@ -618,4 +618,39 @@ jobs: projectBaseDir: ./test/example-project - name: Assert failure of previous step if: steps.wrong_ssl_certificate.outcome == 'success' - run: exit 1 \ No newline at end of file + run: exit 1 + overridesScannerLocalFolderWhenPresent: + name: > + 'SCANNER_LOCAL_FOLDER' is overridden with warning when present + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + - name: Create a dummy SCANNER_LOCAL_FOLDER with dummy content in it + run: | + SCANNER_VERSION="6.2.1.4610" + SCANNER_LOCAL_FOLDER="$RUNNER_TEMP/sonar-scanner-cli-$SCANNER_VERSION-$RUNNER_OS-$RUNNER_ARCH" + # emit SCANNER_VERSION and SCANNER_LOCAL_FOLDER to be able to read them in the next steps + echo "SCANNER_VERSION=$SCANNER_VERSION" >> $GITHUB_ENV + echo "SCANNER_LOCAL_FOLDER=$SCANNER_LOCAL_FOLDER" >> $GITHUB_ENV + mkdir -p "$SCANNER_LOCAL_FOLDER" + touch "$SCANNER_LOCAL_FOLDER/some_content.txt" + - name: Assert SCANNER_LOCAL_FOLDER exists and dummy file is in it + run: | + [ -d "$SCANNER_LOCAL_FOLDER" ] || exit 1 + [ -f "$SCANNER_LOCAL_FOLDER/some_content.txt" ] || exit 1 + - name: Run action with SONAR_SCANNER_TEMP + uses: ./ + env: + SONAR_SCANNER_TEMP: /tmp/sonar-scanner + SONAR_HOST_URL: http://not_actually_used + NO_CACHE: true # force install-sonar-scanner-cli.sh execution + with: + args: -Dsonar.scanner.internal.dumpToFile=./output.properties + scannerVersion: ${{ env.SCANNER_VERSION }} + - name: Assert SCANNER_LOCAL_FOLDER exists and dummy file is not in it + run: | + [ -d "$SCANNER_LOCAL_FOLDER" ] || exit 1 + [ ! -f "$SCANNER_LOCAL_FOLDER/some_content.txt" ] || exit 1 + diff --git a/scripts/install-sonar-scanner-cli.sh b/scripts/install-sonar-scanner-cli.sh index f08a78e..6d810e3 100755 --- a/scripts/install-sonar-scanner-cli.sh +++ b/scripts/install-sonar-scanner-cli.sh @@ -48,5 +48,13 @@ fi unzip -q -o $SCANNER_FILE_NAME +SCANNER_UNZIP_FOLDER="sonar-scanner-$INPUT_SCANNERVERSION-$FLAVOR" # Folder name should correspond to the directory cached by the actions/cache -mv sonar-scanner-$INPUT_SCANNERVERSION-$FLAVOR $RUNNER_TEMP/sonar-scanner-cli-$INPUT_SCANNERVERSION-$RUNNER_OS-$RUNNER_ARCH +SCANNER_LOCAL_FOLDER="$RUNNER_TEMP/sonar-scanner-cli-$INPUT_SCANNERVERSION-$RUNNER_OS-$RUNNER_ARCH" + +if [ -d "$SCANNER_LOCAL_FOLDER" ]; then + echo "::warning title=SonarScanner::Cleaning existing scanner folder: $SCANNER_LOCAL_FOLDER" + rm -rf "$SCANNER_LOCAL_FOLDER" +fi + +mv -f "$SCANNER_UNZIP_FOLDER" "$SCANNER_LOCAL_FOLDER" From 26c51824c8330b026f261a3205f94958d4b1bc5c Mon Sep 17 00:00:00 2001 From: Antonio Aversa Date: Tue, 17 Dec 2024 09:19:42 +0100 Subject: [PATCH 47/60] SQSCANGHA-76 Support self-hosted runners not clearing truststore after run (#165) --- .github/workflows/qa-main.yml | 136 ++++++++++++++++++++++++++++++- README.md | 2 +- scripts/run-sonar-scanner-cli.sh | 52 ++++++++++-- 3 files changed, 179 insertions(+), 11 deletions(-) diff --git a/.github/workflows/qa-main.yml b/.github/workflows/qa-main.yml index 6427f00..65f3558 100644 --- a/.github/workflows/qa-main.yml +++ b/.github/workflows/qa-main.yml @@ -619,9 +619,9 @@ jobs: - name: Assert failure of previous step if: steps.wrong_ssl_certificate.outcome == 'success' run: exit 1 - overridesScannerLocalFolderWhenPresent: + overridesScannerLocalFolderWhenPresent: # can happen in uncleaned self-hosted runners name: > - 'SCANNER_LOCAL_FOLDER' is overridden with warning when present + 'SCANNER_LOCAL_FOLDER' is cleaned with warning when present runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -643,9 +643,9 @@ jobs: - name: Run action with SONAR_SCANNER_TEMP uses: ./ env: + NO_CACHE: true # force install-sonar-scanner-cli.sh execution SONAR_SCANNER_TEMP: /tmp/sonar-scanner SONAR_HOST_URL: http://not_actually_used - NO_CACHE: true # force install-sonar-scanner-cli.sh execution with: args: -Dsonar.scanner.internal.dumpToFile=./output.properties scannerVersion: ${{ env.SCANNER_VERSION }} @@ -653,4 +653,132 @@ jobs: run: | [ -d "$SCANNER_LOCAL_FOLDER" ] || exit 1 [ ! -f "$SCANNER_LOCAL_FOLDER/some_content.txt" ] || exit 1 - + updateTruststoreWhenPresent: # can happen in uncleaned self-hosted runners + name: > + truststore.p12 is updated when present + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + - name: Create SONAR_SSL_FOLDER with a file in it (not-truststore.p12) + run: | + SONAR_SSL_FOLDER=~/.sonar/ssl + mkdir -p "$SONAR_SSL_FOLDER" + touch "$SONAR_SSL_FOLDER/not-truststore.p12" + # emit SONAR_SSL_FOLDER to be able to read it in the next steps + echo "SONAR_SSL_FOLDER=$SONAR_SSL_FOLDER" >> $GITHUB_ENV + - name: Assert truststore.p12 does not file exists + run: | + [ ! -f "$SONAR_SSL_FOLDER/truststore.p12" ] || exit 1 + - name: Run action with SONAR_ROOT_CERT + uses: ./ + env: + # NO_CACHE not needed, as SONAR_SSL_FOLDER is setup when the Sonar Scanner is run, not installed + SONAR_HOST_URL: http://not_actually_used + SONAR_ROOT_CERT: | + -----BEGIN CERTIFICATE----- + MIIFlTCCA32gAwIBAgIUXK4LyGUFe4ZVL93StPXCoJzmnLMwDQYJKoZIhvcNAQEL + BQAwTzELMAkGA1UEBhMCQ0gxDzANBgNVBAgMBkdlbmV2YTEPMA0GA1UEBwwGR2Vu + ZXZhMQ8wDQYDVQQKDAZTZXJ2ZXIxDTALBgNVBAsMBERlcHQwHhcNMjQxMTAxMDgx + MzM3WhcNMzQxMDMwMDgxMzM3WjBPMQswCQYDVQQGEwJDSDEPMA0GA1UECAwGR2Vu + ZXZhMQ8wDQYDVQQHDAZHZW5ldmExDzANBgNVBAoMBlNlcnZlcjENMAsGA1UECwwE + RGVwdDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK5m0V6IFFykib77 + nmlN7weS9q3D6YGEj+8hRNQViL9KduUoLjoKpONIihU5kfIg+5SkGygjHRkBvIp3 + b0HQqhkwtGln3/FxxaSfGEguLHgzXR8JDQSyJ8UKIGOPCH93n1rUip5Ok1iExVup + HtkiVDRoCC9cRjZXbGOKrO6VBT4RvakpkaqCdXYikV244B5ElM7kdFdz8fso78Aq + xekb9dM0f21uUaDBKCIhRcxWeafp0CJIoejTq0+PF7qA2qIY5UHqWElWO5NsvQ8+ + MqKkIdsOa1pYNuH/5eQ59k9KSE92ps1xTKweW000GfPqxx8IQ/e4aAd2SaMTKvN6 + aac6piWBeJ7AssgWwkg/3rnZB5seQIrWjIUePmxJ4c0g0eL9cnVpYF0K/Dldle/G + wg0zi1g709rBI1TYj9xwrivxSwEQupz8OdKqOmgqrKHJJ/CCLl+JdFYjgwl3NWLH + wsU639H1bMXIJoQujg9U47e9fXbwiqdkMQzt7rPGkOBBaAkSctAReiXnWy+CbVEM + QFHDrnD5YUJRd5t/DUuWuqhR2QhfUvRClPUKoVqB/iOu2IumlgDEDA8jb1dxEW+W + iaYokQCS94OpxOJ8aeReSt9bghT0vc9ifCLWvuE1iBjujdK32ekKSY9DCZyBHXsG + J9N1nt1qd/k7QqWOkuPjr1JrTIMbAgMBAAGjaTBnMB0GA1UdDgQWBBQw4ESReEk+ + AIxwjHRqPkESzMv1bTAfBgNVHSMEGDAWgBQw4ESReEk+AIxwjHRqPkESzMv1bTAP + BgNVHRMBAf8EBTADAQH/MBQGA1UdEQQNMAuCCWxvY2FsaG9zdDANBgkqhkiG9w0B + AQsFAAOCAgEAE8WefoZN23aOSe79ZN7zRBWP8DdPgFAqg5XUhfc9bCIVfJ4XMpEe + 3lzRhgjwDm4naEs35QWOhPZH2vx8XrEKnZNI6vKO8JzaCsivgngk8bsWnvhwSXy5 + eFdc99K+FOmOHevDmeiimoQnikffnSULRhQYzE2Qwyo9iky8703/+D3IKEC/8exC + rlyGMUV/Nqj+4M+57DiZ6OXeFuunfoFB7vmcDZygqDhKoHhVRyu8qN6PeK2fvUFK + EjeRtvA0GkdlOtLIF2g5yBTK2ykkt/oLUoAolfYUTKcoV2/FS0gVR5ovmEpKyBcP + H9hzr16a8dtrEqOf/oKHQSLwxn8afmS354HJ75sq9SujOtIWpHfyH5IgqtUpiBN/ + bzvKs/QZjtGlqvquOTkdh9L4oxTXqG7zEStZyo/v9g5jf1Tq195b2DNFwVUZIcbb + u2d4CvAZ1yNr+8ax/kTwBSY8WU+mCtmvowFstdvsJXVXJKnUO6EZOdbg0GxTBVyE + zMsnPcnkOwV5TJIKKhonrgrwmPmQ9IOV9BrThVxujjjEbAdA6jM9PMiXzuDukldm + QBRwNbczGbdsHkMKHmQnrTqOyQyI4KCXF08kcOm4C1P+Whrvi0DXkqHnyKvBE0td + dciInBoeHwUs2eclz7gP7pMBJUlFUkKfQxwxGLIqZSXnlAFBfW6hHLI= + -----END CERTIFICATE----- + with: + args: -Dsonar.scanner.internal.dumpToFile=./output.properties + - name: Assert not-truststore.p12 file still exists + run: | + [ -f "$SONAR_SSL_FOLDER/not-truststore.p12" ] || exit 1 + - name: Assert truststore.p12 file now exists and take note of modification time + run: | + [ -f "$SONAR_SSL_FOLDER/truststore.p12" ] || exit 1 + # emit the modification time of the truststore.p12 file to be able to read it in the next steps + TRUSTSTORE_P12_MOD_TIME_T1=$(stat -c %Y "$SONAR_SSL_FOLDER/truststore.p12") + echo "TRUSTSTORE_P12_MOD_TIME_T1=$TRUSTSTORE_P12_MOD_TIME_T1" >> $GITHUB_ENV + - name: Run action a second time with a different SONAR_ROOT_CERT + uses: ./ + env: + # NO_CACHE not needed, as SONAR_SSL_FOLDER is setup when the Sonar Scanner is run, not installed + SONAR_HOST_URL: http://not_actually_used + SONAR_ROOT_CERT: | + -----BEGIN CERTIFICATE----- + MIICgTCCAeoCCQCbOlrWDdX7FTANBgkqhkiG9w0BAQUFADCBhDELMAkGA1UEBhMC + Tk8xGDAWBgNVBAgTD0FuZHJlYXMgU29sYmVyZzEMMAoGA1UEBxMDRm9vMRAwDgYD + VQQKEwdVTklORVRUMRgwFgYDVQQDEw9mZWlkZS5lcmxhbmcubm8xITAfBgkqhkiG + 9w0BCQEWEmFuZHJlYXNAdW5pbmV0dC5ubzAeFw0wNzA2MTUxMjAxMzVaFw0wNzA4 + MTQxMjAxMzVaMIGEMQswCQYDVQQGEwJOTzEYMBYGA1UECBMPQW5kcmVhcyBTb2xi + ZXJnMQwwCgYDVQQHEwNGb28xEDAOBgNVBAoTB1VOSU5FVFQxGDAWBgNVBAMTD2Zl + aWRlLmVybGFuZy5ubzEhMB8GCSqGSIb3DQEJARYSYW5kcmVhc0B1bmluZXR0Lm5v + MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDivbhR7P516x/S3BqKxupQe0LO + NoliupiBOesCO3SHbDrl3+q9IbfnfmE04rNuMcPsIxB161TdDpIesLCn7c8aPHIS + KOtPlAeTZSnb8QAu7aRjZq3+PbrP5uW3TcfCGPtKTytHOge/OlJbo078dVhXQ14d + 1EDwXJW1rRXuUt4C8QIDAQABMA0GCSqGSIb3DQEBBQUAA4GBACDVfp86HObqY+e8 + BUoWQ9+VMQx1ASDohBjwOsg2WykUqRXF+dLfcUH9dWR63CtZIKFDbStNomPnQz7n + bK+onygwBspVEbnHuUihZq3ZUdmumQqCw4Uvs/1Uvq3orOo/WJVhTyvLgFVK2Qar + Q4/67OZfHd7R+POBXhophSMv1ZOo + -----END CERTIFICATE----- + with: + args: -Dsonar.scanner.internal.dumpToFile=./output.properties + - name: Assert truststore.p12 still exists, but it has been updated, and take note of modification time + run: | + [ -f "$SONAR_SSL_FOLDER/truststore.p12" ] || exit 1 + TRUSTSTORE_P12_MOD_TIME_T2=$(stat -c %Y "$SONAR_SSL_FOLDER/truststore.p12") + [ "$TRUSTSTORE_P12_MOD_TIME_T1" != "$TRUSTSTORE_P12_MOD_TIME_T2" ] || exit 1 + # emit the modification time of the truststore.p12 file to be able to read it in the next steps + echo "TRUSTSTORE_P12_MOD_TIME_T2=$TRUSTSTORE_P12_MOD_TIME_T2" >> $GITHUB_ENV + - name: Remove sonar alias from truststore.p12 + run: keytool -delete -alias sonar -keystore "$SONAR_SSL_FOLDER/truststore.p12" -storepass changeit + - name: Run action a third time + uses: ./ + env: + # NO_CACHE not needed, as SONAR_SSL_FOLDER is setup when the Sonar Scanner is run, not installed + SONAR_HOST_URL: http://not_actually_used + SONAR_ROOT_CERT: | + -----BEGIN CERTIFICATE----- + MIICgTCCAeoCCQCbOlrWDdX7FTANBgkqhkiG9w0BAQUFADCBhDELMAkGA1UEBhMC + Tk8xGDAWBgNVBAgTD0FuZHJlYXMgU29sYmVyZzEMMAoGA1UEBxMDRm9vMRAwDgYD + VQQKEwdVTklORVRUMRgwFgYDVQQDEw9mZWlkZS5lcmxhbmcubm8xITAfBgkqhkiG + 9w0BCQEWEmFuZHJlYXNAdW5pbmV0dC5ubzAeFw0wNzA2MTUxMjAxMzVaFw0wNzA4 + MTQxMjAxMzVaMIGEMQswCQYDVQQGEwJOTzEYMBYGA1UECBMPQW5kcmVhcyBTb2xi + ZXJnMQwwCgYDVQQHEwNGb28xEDAOBgNVBAoTB1VOSU5FVFQxGDAWBgNVBAMTD2Zl + aWRlLmVybGFuZy5ubzEhMB8GCSqGSIb3DQEJARYSYW5kcmVhc0B1bmluZXR0Lm5v + MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDivbhR7P516x/S3BqKxupQe0LO + NoliupiBOesCO3SHbDrl3+q9IbfnfmE04rNuMcPsIxB161TdDpIesLCn7c8aPHIS + KOtPlAeTZSnb8QAu7aRjZq3+PbrP5uW3TcfCGPtKTytHOge/OlJbo078dVhXQ14d + 1EDwXJW1rRXuUt4C8QIDAQABMA0GCSqGSIb3DQEBBQUAA4GBACDVfp86HObqY+e8 + BUoWQ9+VMQx1ASDohBjwOsg2WykUqRXF+dLfcUH9dWR63CtZIKFDbStNomPnQz7n + bK+onygwBspVEbnHuUihZq3ZUdmumQqCw4Uvs/1Uvq3orOo/WJVhTyvLgFVK2Qar + Q4/67OZfHd7R+POBXhophSMv1ZOo + -----END CERTIFICATE----- + with: + args: -Dsonar.scanner.internal.dumpToFile=./output.properties + - name: Assert truststore.p12 still exists, and it has been updated again + run: | + [ -f "$SONAR_SSL_FOLDER/truststore.p12" ] || exit 1 + TRUSTSTORE_P12_MOD_TIME_T3=$(stat -c %Y "$SONAR_SSL_FOLDER/truststore.p12") + [ "$TRUSTSTORE_P12_MOD_TIME_T2" != "$TRUSTSTORE_P12_MOD_TIME_T3" ] || exit 1 diff --git a/README.md b/README.md index 7ac12c6..b568645 100644 --- a/README.md +++ b/README.md @@ -294,7 +294,7 @@ If your source code file names contain special characters that are not covered b LC_ALL: "ru_RU.UTF-8" ``` -## Alternatives for Java, .NET, and C/C++ projects +## Alternatives for Java and .NET This GitHub Action will not work for all technologies. If you are in one of the following situations, you should use the following alternatives: diff --git a/scripts/run-sonar-scanner-cli.sh b/scripts/run-sonar-scanner-cli.sh index 14caadc..1a77f07 100755 --- a/scripts/run-sonar-scanner-cli.sh +++ b/scripts/run-sonar-scanner-cli.sh @@ -21,16 +21,56 @@ if [[ -n "${INPUT_PROJECTBASEDIR}" ]]; then scanner_args+=("-Dsonar.projectBaseDir=${INPUT_PROJECTBASEDIR}") fi +# The SSL folder may exist on an uncleaned self-hosted runner +SONAR_SSL_FOLDER=~/.sonar/ssl +# Use keytool for now, as SonarQube 10.6 and below doesn't support openssl generated keystores +# keytool requires a password > 6 characters, so we won't use the default password 'sonar' +KEYTOOL_MAIN_CLASS=sun.security.tools.keytool.Main +SONAR_SSL_TRUSTSTORE_FILE="$SONAR_SSL_FOLDER/truststore.p12" +SONAR_SSL_TRUSTSTORE_PASSWORD=changeit + +if [ -f "$SONAR_SSL_TRUSTSTORE_FILE" ]; then + ALIAS_SONAR_IS_PRESENT=true + + "$SONAR_SCANNER_JRE/bin/java" "$KEYTOOL_MAIN_CLASS" \ + -storetype PKCS12 \ + -keystore "$SONAR_SSL_TRUSTSTORE_FILE" \ + -storepass "$SONAR_SSL_TRUSTSTORE_PASSWORD" \ + -noprompt \ + -trustcacerts \ + -list -v -alias sonar > /dev/null 2>&1 || { + ALIAS_SONAR_IS_PRESENT=false + echo "Existing Scanner truststore $SONAR_SSL_TRUSTSTORE_FILE does not contain 'sonar' alias" + } + + if [[ $ALIAS_SONAR_IS_PRESENT == "true" ]]; then + echo "Removing 'sonar' alias from already existing Scanner truststore: $SONAR_SSL_TRUSTSTORE_FILE" + "$SONAR_SCANNER_JRE/bin/java" "$KEYTOOL_MAIN_CLASS" \ + -storetype PKCS12 \ + -keystore "$SONAR_SSL_TRUSTSTORE_FILE" \ + -storepass "$SONAR_SSL_TRUSTSTORE_PASSWORD" \ + -noprompt \ + -trustcacerts \ + -delete \ + -alias sonar + fi +fi + if [[ -n "${SONAR_ROOT_CERT}" ]]; then echo "Adding SSL certificate to the Scanner truststore" rm -f $RUNNER_TEMP/tmpcert.pem echo "${SONAR_ROOT_CERT}" > $RUNNER_TEMP/tmpcert.pem - # Use keytool for now, as SonarQube 10.6 and below doesn't support openssl generated keystores - # keytool require a password > 6 characters, so we wan't use the default password 'sonar' - store_pass=changeit - mkdir -p ~/.sonar/ssl - $SONAR_SCANNER_JRE/bin/java sun.security.tools.keytool.Main -storetype PKCS12 -keystore ~/.sonar/ssl/truststore.p12 -storepass $store_pass -noprompt -trustcacerts -importcert -alias sonar -file $RUNNER_TEMP/tmpcert.pem - scanner_args+=("-Dsonar.scanner.truststorePassword=$store_pass") + mkdir -p "$SONAR_SSL_FOLDER" + "$SONAR_SCANNER_JRE/bin/java" "$KEYTOOL_MAIN_CLASS" \ + -storetype PKCS12 \ + -keystore "$SONAR_SSL_TRUSTSTORE_FILE" \ + -storepass "$SONAR_SSL_TRUSTSTORE_PASSWORD" \ + -noprompt \ + -trustcacerts \ + -importcert \ + -alias sonar \ + -file "$RUNNER_TEMP/tmpcert.pem" + scanner_args+=("-Dsonar.scanner.truststorePassword=$SONAR_SSL_TRUSTSTORE_PASSWORD") fi scanner_args+=("$@") From bfd4e558cda28cda6b5defafb9232d191be8c203 Mon Sep 17 00:00:00 2001 From: Antonio Aversa Date: Tue, 17 Dec 2024 10:59:50 +0100 Subject: [PATCH 48/60] SQSCANGHA-77 Change title back to SonarQube Scan Action (#166) --- action.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/action.yml b/action.yml index 9e8ce9e..642e1c3 100644 --- a/action.yml +++ b/action.yml @@ -1,4 +1,5 @@ -name: Official SonarQube (Server, Cloud) Scan +name: Official SonarQube Scan +# Warning: changing name would change URL in the marketplace description: > Scan your code with SonarQube Server and Cloud to detect issues in 30+ languages. (Formerly SonarQube and SonarCloud) From d6b87b0febe175825faabc65211aea46da0de19a Mon Sep 17 00:00:00 2001 From: Przemek Date: Wed, 8 Jan 2025 15:22:30 +0100 Subject: [PATCH 49/60] DOC-403 Update links in the README.md file to the documentation (#167) Co-authored-by: Antonio Aversa --- README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index b568645..f4c20ed 100644 --- a/README.md +++ b/README.md @@ -105,7 +105,8 @@ jobs: SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} - name: Run Build Wrapper run: | - # here goes your compilation wrapped with build-wrapper; See https://docs.sonarsource.com/sonarqube/latest/ analyzing-source-code/languages/c-family/#using-build-wrapper for more information + # Here goes your compilation wrapped with Build Wrapper + # For more information, see https://docs.sonarsource.com/sonarqube-server/latest/analyzing-source-code/languages/c-family/prerequisites/#using-buildwrapper # build-preparation steps # build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} build-command - name: SonarQube Scan @@ -115,7 +116,7 @@ jobs: SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} SONAR_ROOT_CERT: ${{ secrets.SONAR_ROOT_CERT }} with: - # Consult https://docs.sonarsource.com/sonarqube/latest/analyzing-source-code/scanners/sonarscanner/ for more information and options + # Consult https://docs.sonarsource.com/sonarqube-server/latest/analyzing-source-code/scanners/sonarscanner/ for more information and options args: > --define sonar.cfamily.compile-commands="${{ env.BUILD_WRAPPER_OUT_DIR }}/compile_commands.json" ``` @@ -204,7 +205,8 @@ jobs: uses: SonarSource/sonarqube-scan-action/install-build-wrapper@ - name: Run Build Wrapper run: | - # here goes your compilation wrapped with build-wrapper; See https://docs.sonarsource.com/sonarqube/latest/ analyzing-source-code/languages/c-family/#using-build-wrapper for more information + # Here goes your compilation wrapped with Build Wrapper + # For more information, see https://docs.sonarsource.com/sonarqube-cloud/advanced-setup/languages/c-family/prerequisites/#using-build-wrapper # build-preparation steps # build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} build-command - name: SonarQube Scan @@ -213,7 +215,7 @@ jobs: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} SONAR_ROOT_CERT: ${{ secrets.SONAR_ROOT_CERT }} with: - # Consult https://docs.sonarsource.com/sonarqube/latest/analyzing-source-code/scanners/sonarscanner/ for more information and options + # Consult https://docs.sonarsource.com/sonarqube-server/latest/analyzing-source-code/scanners/sonarscanner/ for more information and options args: > --define sonar.cfamily.compile-commands="${{ env.BUILD_WRAPPER_OUT_DIR }}/compile_commands.json" ``` From 6bbc1364b808d558e21b9e63eefb12bfa8518194 Mon Sep 17 00:00:00 2001 From: Julien HENRY Date: Tue, 21 Jan 2025 15:25:30 +0100 Subject: [PATCH 50/60] SQSCANGHA-59 Use the new way of having theme sensitive images. --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f4c20ed..9c5756d 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,10 @@ This SonarSource project, available as a GitHub Action, scans your projects with SonarQube [Server](https://www.sonarsource.com/products/sonarqube/) or [Cloud](https://www.sonarsource.com/products/sonarcloud/). -![Logo](./images/SQ_Logo_Server_Cloud_Dark_Backgrounds.png#gh-dark-mode-only) -![Logo](./images/SQ_Logo_Server_Cloud_Light_Backgrounds.png#gh-light-mode-only) + + + SonarQube Logo + SonarQube [Server](https://www.sonarsource.com/products/sonarqube/) and [Cloud](https://www.sonarsource.com/products/sonarcloud/) (formerly SonarQube and SonarCloud) is a widely used static analysis solution for continuous code quality and security inspection. From 7622374390f1d39d4e18e945a12e0afb52e6eb7c Mon Sep 17 00:00:00 2001 From: Pierre Date: Fri, 7 Feb 2025 16:44:54 +0100 Subject: [PATCH 51/60] SQSCANGHA-79 Update CODEOWNERS (#170) --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 3f43f0d..e182dab 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1 @@ -.github/CODEOWNERS @sonarsource/analysis-experience-squad +.github/CODEOWNERS @sonarsource/orchestration-processing-squad From 994c850d7abc29e4de895f15cf8d39cb51188317 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 10 Feb 2025 14:25:57 +0100 Subject: [PATCH 52/60] SQSCANGHA-81 Update SonarScanner CLI to 7.0.1.4817 (#171) Co-authored-by: SonarTech --- sonar-scanner-version | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/sonar-scanner-version b/sonar-scanner-version index 7f6d3d9..f73fbf6 100644 --- a/sonar-scanner-version +++ b/sonar-scanner-version @@ -1,11 +1,11 @@ -sonar-scanner-version=6.2.1.4610 -sonar-scanner-url-windows-x64=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-6.2.1.4610-windows-x64.zip -sonar-scanner-sha-windows-x64=b7de8d75c43093e0353e6a3147c3720cafac1c38da96bc61123657197086a1c9 -sonar-scanner-url-linux-x64=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-6.2.1.4610-linux-x64.zip -sonar-scanner-sha-linux-x64=0b8a3049f0bd5de7abc1582c78c233960d3d4ed7cc983a1d1635e8552f8bb439 -sonar-scanner-url-linux-aarch64=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-6.2.1.4610-linux-aarch64.zip -sonar-scanner-sha-linux-aarch64=f67819e7a52ed4c28b541baa5bca0621446314de148f889d7d2d7ff239808f0c -sonar-scanner-url-macosx-x64=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-6.2.1.4610-macosx-x64.zip -sonar-scanner-sha-macosx-x64=471348fcb912584f093cebf28114322455979d2cceb1654e0a7990da50add94f -sonar-scanner-url-macosx-aarch64=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-6.2.1.4610-macosx-aarch64.zip -sonar-scanner-sha-macosx-aarch64=583b1ed386b6f61ddfbb39c0ae169355e96a8e1852b0210a5a5ca4f7487347c1 +sonar-scanner-version=7.0.1.4817 +sonar-scanner-url-windows-x64=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-7.0.1.4817-windows-x64.zip +sonar-scanner-sha-windows-x64=6b523587567af4170a4e0e0d02053d4a3f117e6612a11a4382ae45211b82383f +sonar-scanner-url-linux-x64=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-7.0.1.4817-linux-x64.zip +sonar-scanner-sha-linux-x64=b0643348eed1ec808d8c9b35b34bdf953ed9788978c38b32c577960bbef0a7f8 +sonar-scanner-url-linux-aarch64=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-7.0.1.4817-linux-aarch64.zip +sonar-scanner-sha-linux-aarch64=f1def4b7f8fe5839ab185eee7e493551ed1bd5534707f8e02933579e2315ffaa +sonar-scanner-url-macosx-x64=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-7.0.1.4817-macosx-x64.zip +sonar-scanner-sha-macosx-x64=820100498148433db0674da3156eca5974e1b4f7dfc073d41df1f3ff49cd9b33 +sonar-scanner-url-macosx-aarch64=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-7.0.1.4817-macosx-aarch64.zip +sonar-scanner-sha-macosx-aarch64=4903800165c59890b9859a212054bd55d0eb2a5682ce377fad70560be4b833f0 From 73cb22d49a457b7fc2ba581a30e5b9263161d38c Mon Sep 17 00:00:00 2001 From: Julien HENRY Date: Mon, 10 Feb 2025 14:12:02 +0100 Subject: [PATCH 53/60] Fix permission of the version_update workflow --- .github/workflows/version_update.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/version_update.yml b/.github/workflows/version_update.yml index aeec0bd..c0deda7 100644 --- a/.github/workflows/version_update.yml +++ b/.github/workflows/version_update.yml @@ -8,6 +8,9 @@ jobs: update-version: name: Prepare pull request for sonar-scanner version update runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write steps: - run: sudo apt install -y jq @@ -34,7 +37,7 @@ jobs: shell: bash env: UPDATE_BRANCH: update-to-sonar-scanner-${{ steps.latest-version.outputs.sonar-scanner-version }} - TITLE: "Update sonar-scanner-version to ${{ steps.latest-version.outputs.sonar-scanner-version }}" + TITLE: "Update SonarScanner CLI to ${{ steps.latest-version.outputs.sonar-scanner-version }}" GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | git config --global user.name "SonarTech" From 3ed756013884aab36deebbaf6137d78e6533a664 Mon Sep 17 00:00:00 2001 From: Julien HENRY Date: Mon, 10 Feb 2025 14:44:54 +0100 Subject: [PATCH 54/60] SQSCANGHA-82 Automate the update of the Scanner CLI version --- .github/workflows/version_update.yml | 11 +++++++++-- action.yml | 3 ++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/.github/workflows/version_update.yml b/.github/workflows/version_update.yml index c0deda7..248d94f 100644 --- a/.github/workflows/version_update.yml +++ b/.github/workflows/version_update.yml @@ -13,7 +13,7 @@ jobs: pull-requests: write steps: - run: sudo apt install -y jq - + - run: sudo snap install yq - uses: actions/checkout@v4 with: ref: master @@ -31,7 +31,13 @@ jobs: run: | ./scripts/fetch_latest_version.sh > sonar-scanner-version cat sonar-scanner-version >> $GITHUB_OUTPUT - + - name: "Update default version" + if: steps.tagged-version.outputs.sonar-scanner-version != steps.latest-version.outputs.sonar-scanner-version + shell: bash + env: + NEW_VERSION: ${{ steps.latest-version.outputs.sonar-scanner-version }} + run: | + yq -i '.inputs.scannerVersion.default = "${NEW_VERSION}"' action.yml - name: "Create Pull Request for version update" if: steps.tagged-version.outputs.sonar-scanner-version != steps.latest-version.outputs.sonar-scanner-version shell: bash @@ -44,6 +50,7 @@ jobs: git config --global user.email "sonartech@sonarsource.com" git checkout -b ${UPDATE_BRANCH} git add sonar-scanner-version + git add action.yml git commit -m "${TITLE}" git push --force-with-lease origin ${UPDATE_BRANCH} gh pr list diff --git a/action.yml b/action.yml index 642e1c3..410ef16 100644 --- a/action.yml +++ b/action.yml @@ -16,7 +16,8 @@ inputs: scannerVersion: description: Version of the Sonar Scanner CLI to use required: false - default: 6.2.1.4610 # to be kept in sync with sonar-scanner-version + # to be kept in sync with sonar-scanner-version + default: 6.2.1.4610 scannerBinariesUrl: description: URL to download the Sonar Scanner CLI binaries from required: false From 0303d6b62e310685c0e34d0b9cde218036885c4d Mon Sep 17 00:00:00 2001 From: SonarTech Date: Fri, 14 Feb 2025 11:34:24 +0000 Subject: [PATCH 55/60] Update SonarScanner CLI to 7.0.2.4839 --- .github/workflows/qa-main.yml | 1 + .github/workflows/version_update.yml | 2 +- action.yml | 6 +++--- sonar-scanner-version | 22 +++++++++++----------- 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/.github/workflows/qa-main.yml b/.github/workflows/qa-main.yml index 65f3558..35a799d 100644 --- a/.github/workflows/qa-main.yml +++ b/.github/workflows/qa-main.yml @@ -449,6 +449,7 @@ jobs: id: runTest uses: ./ with: + scannerVersion: 6.2.1.4610 scannerBinariesUrl: http://localhost:8080/clientRedirectToSonarBinaries env: NO_CACHE: true diff --git a/.github/workflows/version_update.yml b/.github/workflows/version_update.yml index 248d94f..ae454b9 100644 --- a/.github/workflows/version_update.yml +++ b/.github/workflows/version_update.yml @@ -37,7 +37,7 @@ jobs: env: NEW_VERSION: ${{ steps.latest-version.outputs.sonar-scanner-version }} run: | - yq -i '.inputs.scannerVersion.default = "${NEW_VERSION}"' action.yml + yq -i '.inputs.scannerVersion.default = "$NEW_VERSION"' action.yml - name: "Create Pull Request for version update" if: steps.tagged-version.outputs.sonar-scanner-version != steps.latest-version.outputs.sonar-scanner-version shell: bash diff --git a/action.yml b/action.yml index 410ef16..776327a 100644 --- a/action.yml +++ b/action.yml @@ -1,8 +1,8 @@ name: Official SonarQube Scan # Warning: changing name would change URL in the marketplace description: > - Scan your code with SonarQube Server and Cloud to detect - issues in 30+ languages. (Formerly SonarQube and SonarCloud) + Scan your code with SonarQube Server and Cloud to detect issues in 30+ languages. (Formerly SonarQube and SonarCloud) + branding: icon: check color: green @@ -17,7 +17,7 @@ inputs: description: Version of the Sonar Scanner CLI to use required: false # to be kept in sync with sonar-scanner-version - default: 6.2.1.4610 + default: 7.0.2.4839 scannerBinariesUrl: description: URL to download the Sonar Scanner CLI binaries from required: false diff --git a/sonar-scanner-version b/sonar-scanner-version index f73fbf6..4b2c599 100644 --- a/sonar-scanner-version +++ b/sonar-scanner-version @@ -1,11 +1,11 @@ -sonar-scanner-version=7.0.1.4817 -sonar-scanner-url-windows-x64=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-7.0.1.4817-windows-x64.zip -sonar-scanner-sha-windows-x64=6b523587567af4170a4e0e0d02053d4a3f117e6612a11a4382ae45211b82383f -sonar-scanner-url-linux-x64=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-7.0.1.4817-linux-x64.zip -sonar-scanner-sha-linux-x64=b0643348eed1ec808d8c9b35b34bdf953ed9788978c38b32c577960bbef0a7f8 -sonar-scanner-url-linux-aarch64=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-7.0.1.4817-linux-aarch64.zip -sonar-scanner-sha-linux-aarch64=f1def4b7f8fe5839ab185eee7e493551ed1bd5534707f8e02933579e2315ffaa -sonar-scanner-url-macosx-x64=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-7.0.1.4817-macosx-x64.zip -sonar-scanner-sha-macosx-x64=820100498148433db0674da3156eca5974e1b4f7dfc073d41df1f3ff49cd9b33 -sonar-scanner-url-macosx-aarch64=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-7.0.1.4817-macosx-aarch64.zip -sonar-scanner-sha-macosx-aarch64=4903800165c59890b9859a212054bd55d0eb2a5682ce377fad70560be4b833f0 +sonar-scanner-version=7.0.2.4839 +sonar-scanner-url-windows-x64=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-7.0.2.4839-windows-x64.zip +sonar-scanner-sha-windows-x64=ecb5410e607e171fc43be4246f31e5432d796ac85372a5e68d6a8210197f5ca1 +sonar-scanner-url-linux-x64=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-7.0.2.4839-linux-x64.zip +sonar-scanner-sha-linux-x64=87f80a41ad861c3d0eb2c00a1268e77ab5f93b83c17c816318ddecb0911baeb0 +sonar-scanner-url-linux-aarch64=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-7.0.2.4839-linux-aarch64.zip +sonar-scanner-sha-linux-aarch64=567b391cb0e94c16fef558de909851a1a5b332f337f09ce12f863d7b3c633908 +sonar-scanner-url-macosx-x64=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-7.0.2.4839-macosx-x64.zip +sonar-scanner-sha-macosx-x64=221be67f88f4fcbc464a7946879062a82f392a6c9a676d3a7eaa5c299df3894c +sonar-scanner-url-macosx-aarch64=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-7.0.2.4839-macosx-aarch64.zip +sonar-scanner-sha-macosx-aarch64=4106d482c00935817feda88466b64d2c02718277c31a5323f1984f8610f3ac45 From 550777f6ebb446ca3e8f143099e04c5c7059dd8a Mon Sep 17 00:00:00 2001 From: Adam Setch Date: Thu, 20 Feb 2025 05:02:15 -0600 Subject: [PATCH 56/60] NO-JIRA Remove superfluous space from action description --- action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/action.yml b/action.yml index 776327a..3fc2bf5 100644 --- a/action.yml +++ b/action.yml @@ -1,7 +1,7 @@ name: Official SonarQube Scan # Warning: changing name would change URL in the marketplace description: > - Scan your code with SonarQube Server and Cloud to detect issues in 30+ languages. (Formerly SonarQube and SonarCloud) + Scan your code with SonarQube Server and Cloud to detect issues in 30+ languages. (Formerly SonarQube and SonarCloud) branding: icon: check From f932b663acf3c4b8b27c673927b5ac744638b17b Mon Sep 17 00:00:00 2001 From: Maikel van den Hurk Date: Thu, 20 Feb 2025 14:56:24 +0100 Subject: [PATCH 57/60] NO-JIRA docs(readme): use consistently vars.SONAR_HOST_URL --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9c5756d..5edcc96 100644 --- a/README.md +++ b/README.md @@ -104,7 +104,7 @@ jobs: - name: Install Build Wrapper uses: SonarSource/sonarqube-scan-action/install-build-wrapper@ env: - SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} + SONAR_HOST_URL: ${{ vars.SONAR_HOST_URL }} - name: Run Build Wrapper run: | # Here goes your compilation wrapped with Build Wrapper @@ -115,7 +115,7 @@ jobs: uses: SonarSource/sonarqube-scan-action@ env: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} + SONAR_HOST_URL: ${{ vars.SONAR_HOST_URL }} SONAR_ROOT_CERT: ${{ secrets.SONAR_ROOT_CERT }} with: # Consult https://docs.sonarsource.com/sonarqube-server/latest/analyzing-source-code/scanners/sonarscanner/ for more information and options From 961628671dd1017f26f7f0b1ff7bb6236182cc71 Mon Sep 17 00:00:00 2001 From: Pavel Mikula <57188685+pavel-mikula-sonarsource@users.noreply.github.com> Date: Mon, 10 Mar 2025 10:47:13 +0100 Subject: [PATCH 58/60] SQSCANGHA-86 Autoclose issues created by Jira integration (#179) --- .github/workflows/PullRequestClosed.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/PullRequestClosed.yml b/.github/workflows/PullRequestClosed.yml index b50896e..77bf0e1 100644 --- a/.github/workflows/PullRequestClosed.yml +++ b/.github/workflows/PullRequestClosed.yml @@ -5,8 +5,8 @@ on: types: [closed] jobs: - PullRequestMerged_job: - name: Pull Request Merged + PullRequestClosed_job: + name: Pull Request Closed runs-on: ubuntu-latest permissions: id-token: write @@ -14,7 +14,6 @@ jobs: # For external PR, ticket should be moved manually if: | github.event.pull_request.head.repo.full_name == github.repository - && github.event.pull_request.merged steps: - id: secrets uses: SonarSource/vault-action-wrapper@v3 From 1474b34972468dc4c34f9aabfce581cff023bcca Mon Sep 17 00:00:00 2001 From: Aleksandra Bozhinoska Date: Mon, 24 Mar 2025 14:31:44 +0100 Subject: [PATCH 59/60] SQSCANGHA-87 Fix the new version in version update (#182) --- .github/workflows/version_update.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/version_update.yml b/.github/workflows/version_update.yml index ae454b9..87f2019 100644 --- a/.github/workflows/version_update.yml +++ b/.github/workflows/version_update.yml @@ -37,7 +37,7 @@ jobs: env: NEW_VERSION: ${{ steps.latest-version.outputs.sonar-scanner-version }} run: | - yq -i '.inputs.scannerVersion.default = "$NEW_VERSION"' action.yml + yq -i '.inputs.scannerVersion.default = strenv(NEW_VERSION)' action.yml - name: "Create Pull Request for version update" if: steps.tagged-version.outputs.sonar-scanner-version != steps.latest-version.outputs.sonar-scanner-version shell: bash From aa494459d7c39c106cc77b166de8b4250a32bb97 Mon Sep 17 00:00:00 2001 From: SonarTech Date: Mon, 24 Mar 2025 13:40:49 +0000 Subject: [PATCH 60/60] SQSCANGHA-85 Update SonarScanner CLI to 7.1.0.4889 to support sonar.region=us --- .github/workflows/qa-main.yml | 2 +- action.yml | 2 +- sonar-scanner-version | 22 +++++++++++----------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/qa-main.yml b/.github/workflows/qa-main.yml index 35a799d..f49e853 100644 --- a/.github/workflows/qa-main.yml +++ b/.github/workflows/qa-main.yml @@ -333,7 +333,7 @@ jobs: - name: Run action with SONARCLOUD_URL uses: ./ with: - args: -Dsonar.scanner.internal.dumpToFile=./output.properties + args: -Dsonar.scanner.apiBaseUrl=api.mirror.sonarcloud.io -Dsonar.scanner.internal.dumpToFile=./output.properties env: SONARCLOUD_URL: mirror.sonarcloud.io SONAR_TOKEN: FAKE_TOKEN diff --git a/action.yml b/action.yml index 3fc2bf5..847cec8 100644 --- a/action.yml +++ b/action.yml @@ -17,7 +17,7 @@ inputs: description: Version of the Sonar Scanner CLI to use required: false # to be kept in sync with sonar-scanner-version - default: 7.0.2.4839 + default: 7.1.0.4889 scannerBinariesUrl: description: URL to download the Sonar Scanner CLI binaries from required: false diff --git a/sonar-scanner-version b/sonar-scanner-version index 4b2c599..b52ab0b 100644 --- a/sonar-scanner-version +++ b/sonar-scanner-version @@ -1,11 +1,11 @@ -sonar-scanner-version=7.0.2.4839 -sonar-scanner-url-windows-x64=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-7.0.2.4839-windows-x64.zip -sonar-scanner-sha-windows-x64=ecb5410e607e171fc43be4246f31e5432d796ac85372a5e68d6a8210197f5ca1 -sonar-scanner-url-linux-x64=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-7.0.2.4839-linux-x64.zip -sonar-scanner-sha-linux-x64=87f80a41ad861c3d0eb2c00a1268e77ab5f93b83c17c816318ddecb0911baeb0 -sonar-scanner-url-linux-aarch64=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-7.0.2.4839-linux-aarch64.zip -sonar-scanner-sha-linux-aarch64=567b391cb0e94c16fef558de909851a1a5b332f337f09ce12f863d7b3c633908 -sonar-scanner-url-macosx-x64=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-7.0.2.4839-macosx-x64.zip -sonar-scanner-sha-macosx-x64=221be67f88f4fcbc464a7946879062a82f392a6c9a676d3a7eaa5c299df3894c -sonar-scanner-url-macosx-aarch64=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-7.0.2.4839-macosx-aarch64.zip -sonar-scanner-sha-macosx-aarch64=4106d482c00935817feda88466b64d2c02718277c31a5323f1984f8610f3ac45 +sonar-scanner-version=7.1.0.4889 +sonar-scanner-url-windows-x64=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-7.1.0.4889-windows-x64.zip +sonar-scanner-sha-windows-x64=64c5154d3d924eb2e03386f10eecb3ec4132298e2c1bf0b60a0d0195cd51a555 +sonar-scanner-url-linux-x64=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-7.1.0.4889-linux-x64.zip +sonar-scanner-sha-linux-x64=b4d2a001d65b489f9effe1ea8a78495db1b152f124d7f7b058aad8651c7e1484 +sonar-scanner-url-linux-aarch64=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-7.1.0.4889-linux-aarch64.zip +sonar-scanner-sha-linux-aarch64=7948ccde77843829b87d41815ead669486f681cd38b0b0893006083a9b6f6b5c +sonar-scanner-url-macosx-x64=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-7.1.0.4889-macosx-x64.zip +sonar-scanner-sha-macosx-x64=08ad1e75994d91a17016ce55248d0827b62a757b263917234ea2d89bee8f136d +sonar-scanner-url-macosx-aarch64=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-7.1.0.4889-macosx-aarch64.zip +sonar-scanner-sha-macosx-aarch64=9ad8c5da9e9665c065328b86adb3f33ef43801347ecb3ff1ec27d598ac37b449