From 599b142512c3f09f9e3da80bf608e2cb9689deac Mon Sep 17 00:00:00 2001 From: Julien HENRY Date: Tue, 17 Sep 2024 16:32:47 +0200 Subject: [PATCH] SQSCANGHA-46 Replace the Docker action by a composite action --- .cirrus.star | 4 -- .cirrus.yml | 38 ---------------- .github/workflows/qa.yml | 87 +++++++++++++++++++++++++++++++----- Dockerfile | 21 --------- action.yml | 38 +++++++++++++--- cleanup.sh | 13 ------ entrypoint.sh | 36 --------------- install-sonar-scanner-cli.sh | 34 ++++++++++++++ run-sonar-scanner.sh | 37 +++++++++++++++ sanity-checks.sh | 18 ++++++++ 10 files changed, 196 insertions(+), 130 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 28b17b7..0000000 --- a/.cirrus.star +++ /dev/null @@ -1,4 +0,0 @@ -load("github.com/SonarSource/cirrus-modules@v2", "load_features") - -def main(ctx): - return load_features(ctx) diff --git a/.cirrus.yml b/.cirrus.yml deleted file mode 100644 index 358472c..0000000 --- a/.cirrus.yml +++ /dev/null @@ -1,38 +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 - 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/.github/workflows/qa.yml b/.github/workflows/qa.yml index 350a7b1..596534b 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -11,7 +11,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: @@ -19,7 +22,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 @@ -28,7 +31,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: @@ -37,7 +43,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 +66,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 +86,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 +106,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 @@ -128,7 +134,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 @@ -138,7 +144,10 @@ 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: @@ -146,13 +155,67 @@ 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 - name: Assert run: | ./test/assertFileContains ./output.properties "sonar.verbose=true" + useSslCertificate: + name: > + 'SONAR_ROOT_CERT' is converted to truststore + 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----- + 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 + Fct6d1S08JAosVnZcP2P7Yz+TbmDRtsqCgk= + -----END CERTIFICATE----- + SONAR_HOST_URL: http://not_actually_used + - name: Assert + run: | + ./test/assertFileExists ~/.sonar/ssl/truststore.p12 runAnalysisWithCacheTest: runs-on: ubuntu-latest services: @@ -177,12 +240,12 @@ 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 diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index a38bed0..0000000 --- a/Dockerfile +++ /dev/null @@ -1,21 +0,0 @@ -FROM sonarsource/sonar-scanner-cli:10.0 - -LABEL version="2.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/action.yml b/action.yml index b2baff6..1d91ca8 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.0.4584 +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 a687be7..0000000 --- a/entrypoint.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/bash - -set -e - -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 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 - -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 - -debug_flag='' -if [[ "$RUNNER_DEBUG" == '1' ]]; then - debug_flag='--debug' -fi - -unset JAVA_HOME - -sonar-scanner $debug_flag -Dsonar.projectBaseDir=${INPUT_PROJECTBASEDIR} ${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..087abcb --- /dev/null +++ b/run-sonar-scanner.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +set -eo pipefail + +if [[ "$RUNNER_OS" == "Windows" ]]; then + SCANNER_BIN="sonar-scanner.bat" +else + SCANNER_BIN="sonar-scanner" +fi + +scanner_args=() +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 +