From 300bcc230bcc8fb0ab425cea3ee31b4bee8c0598 Mon Sep 17 00:00:00 2001 From: Eric Schneider <37347760+eric-schneider@users.noreply.github.com> Date: Wed, 26 Aug 2026 11:15:41 -0500 Subject: [PATCH 1/4] Add SonarQube workflow --- .github/workflows/ibm-sonar.yml | 58 +++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 .github/workflows/ibm-sonar.yml diff --git a/.github/workflows/ibm-sonar.yml b/.github/workflows/ibm-sonar.yml new file mode 100644 index 0000000..2560283 --- /dev/null +++ b/.github/workflows/ibm-sonar.yml @@ -0,0 +1,58 @@ +name: IBM SonarQube Scan + +on: + push: + branches: [main] + pull_request: + branches: [main] + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: sonarqube-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + +jobs: + sonarqube: + name: Scan + runs-on: ubuntu-latest + timeout-minutes: 30 + # Fork PRs don't receive secrets, so the scan can't authenticate. Skip cleanly. + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository + + steps: + - name: Checkout Repository + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Decode Trust Store Certificate + env: + TRUSTSTORE_B64: ${{ secrets.IBM_SONARQUBE_CERT_TRUSTSTORE_BASE64 }} + run: | + set -euo pipefail + umask 077 + printf '%s' "$TRUSTSTORE_B64" | base64 -d > "$RUNNER_TEMP/ibm_castorevpcprod" + [ -s "$RUNNER_TEMP/ibm_castorevpcprod" ] || { + echo "::error::Truststore decoded empty — check IBM_SONARQUBE_CERT_TRUSTSTORE_BASE64"; exit 1; } + + - name: SonarQube Scan + uses: SonarSource/sonarqube-scan-action@v5.2.0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SONAR_TOKEN: ${{ secrets.IBM_SONARQUBE_API_TOKEN }} + SONAR_HOST_URL: ${{ vars.SONAR_HOST_URL }} + with: + # The `projectKey` and `projectName` values are repo-specific - update them if copying this workflow. + args: > + -D sonar.projectKey=544478-685614324 + -D sonar.projectName=riptano/docs-ui + -D sonar.sources=. + -D sonar.scanner.truststorePath=${{ runner.temp }}/ibm_castorevpcprod + -D sonar.scanner.truststorePassword=${{ secrets.IBM_SONARQUBE_CERT_PASSWORD }} + + - name: Clean Up Trust Store Certificate + if: always() + run: rm -f "$RUNNER_TEMP/ibm_castorevpcprod" From d76cd30a0d65748cbc5e80d3be97647b0892e1b6 Mon Sep 17 00:00:00 2001 From: Eric Schneider <37347760+eric-schneider@users.noreply.github.com> Date: Wed, 26 Aug 2026 19:16:09 -0500 Subject: [PATCH 2/4] Update workflow --- .github/workflows/ibm-sonar.yml | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ibm-sonar.yml b/.github/workflows/ibm-sonar.yml index 2560283..3e486d4 100644 --- a/.github/workflows/ibm-sonar.yml +++ b/.github/workflows/ibm-sonar.yml @@ -22,6 +22,17 @@ jobs: # Fork PRs don't receive secrets, so the scan can't authenticate. Skip cleanly. if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository + # Per-repo Sonar configuration. You must update SONAR_PROJECT_KEY and + # SONAR_PROJECT_NAME when copying this workflow to another repository, along + # with the branch filters above (i.e. if the repository uses `master` + # instead of `main`). Project key format is -. Only + # update SONAR_SOURCES if only a portion of the repository should be + # scanned. + env: + SONAR_PROJECT_KEY: 544478-685614324 + SONAR_PROJECT_NAME: riptano/docs-ui + SONAR_SOURCES: "." + steps: - name: Checkout Repository uses: actions/checkout@v6 @@ -45,14 +56,26 @@ jobs: SONAR_TOKEN: ${{ secrets.IBM_SONARQUBE_API_TOKEN }} SONAR_HOST_URL: ${{ vars.SONAR_HOST_URL }} with: - # The `projectKey` and `projectName` values are repo-specific - update them if copying this workflow. args: > - -D sonar.projectKey=544478-685614324 - -D sonar.projectName=riptano/docs-ui - -D sonar.sources=. + -D sonar.projectKey=${{ env.SONAR_PROJECT_KEY }} + -D sonar.projectName=${{ env.SONAR_PROJECT_NAME }} + -D sonar.sources=${{ env.SONAR_SOURCES }} -D sonar.scanner.truststorePath=${{ runner.temp }}/ibm_castorevpcprod -D sonar.scanner.truststorePassword=${{ secrets.IBM_SONARQUBE_CERT_PASSWORD }} - name: Clean Up Trust Store Certificate if: always() run: rm -f "$RUNNER_TEMP/ibm_castorevpcprod" + + - name: Link to Results + if: always() + env: + DASHBOARD_URL: https://sonarqube-prod.apps.wdc-sonarqube-prod.core.cirrus.ibm.com + PR_NUMBER: ${{ github.event.pull_request.number }} + run: | + set -euo pipefail + url="${DASHBOARD_URL}/dashboard?id=${SONAR_PROJECT_KEY}" + if [ -n "$PR_NUMBER" ]; then + url="${url}&pullRequest=${PR_NUMBER}" + fi + echo "[See analysis details on SonarQube]($url)" >> "$GITHUB_STEP_SUMMARY" From 5e91cc557a8f24e9f6ce3233551dd59a4a933433 Mon Sep 17 00:00:00 2001 From: Eric Schneider <37347760+eric-schneider@users.noreply.github.com> Date: Wed, 26 Aug 2026 20:05:09 -0500 Subject: [PATCH 3/4] Add preflight check --- .github/workflows/ibm-sonar.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/.github/workflows/ibm-sonar.yml b/.github/workflows/ibm-sonar.yml index 3e486d4..b9b3809 100644 --- a/.github/workflows/ibm-sonar.yml +++ b/.github/workflows/ibm-sonar.yml @@ -34,6 +34,25 @@ jobs: SONAR_SOURCES: "." steps: + - name: Verify Configuration + env: + SONAR_HOST_URL: ${{ vars.SONAR_HOST_URL }} + SONAR_TOKEN: ${{ secrets.IBM_SONARQUBE_API_TOKEN }} + TRUSTSTORE_B64: ${{ secrets.IBM_SONARQUBE_CERT_TRUSTSTORE_BASE64 }} + CERT_PASSWORD: ${{ secrets.IBM_SONARQUBE_CERT_PASSWORD }} + run: | + set -uo pipefail + missing=() + [ -n "${SONAR_HOST_URL:-}" ] || missing+=("vars.SONAR_HOST_URL") + [ -n "${SONAR_TOKEN:-}" ] || missing+=("secrets.IBM_SONARQUBE_API_TOKEN") + [ -n "${TRUSTSTORE_B64:-}" ] || missing+=("secrets.IBM_SONARQUBE_CERT_TRUSTSTORE_BASE64") + [ -n "${CERT_PASSWORD:-}" ] || missing+=("secrets.IBM_SONARQUBE_CERT_PASSWORD") + if [ ${#missing[@]} -gt 0 ]; then + echo "::error::Missing required configuration: ${missing[*]}" + echo "Set at the org level. Check Settings > Secrets and variables > Actions, including each item's repository-access scope — org secrets can be limited to private repos or a selected list." + exit 1 + fi + - name: Checkout Repository uses: actions/checkout@v6 with: From 39a911ad0431a885845293de5d8a9a8dd06858fc Mon Sep 17 00:00:00 2001 From: Eric Schneider <37347760+eric-schneider@users.noreply.github.com> Date: Thu, 27 Aug 2026 12:21:23 -0500 Subject: [PATCH 4/4] Update workflow --- .github/workflows/ibm-sonar.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/workflows/ibm-sonar.yml b/.github/workflows/ibm-sonar.yml index b9b3809..7b0859e 100644 --- a/.github/workflows/ibm-sonar.yml +++ b/.github/workflows/ibm-sonar.yml @@ -28,10 +28,18 @@ jobs: # instead of `main`). Project key format is -. Only # update SONAR_SOURCES if only a portion of the repository should be # scanned. + # + # SONAR_EXCLUSIONS drops the Antora examples tree. Those snippets are not + # production code, and the .java ones can't be compiled, which aborts the scan. + # + # Setting this replaces the IBM instance's *overridable* exclusions (for + # example, `packages/**`) but not its forced-global ones — node_modules, + # venv, **/test/**, *.md and others still apply. env: SONAR_PROJECT_KEY: 544478-685614324 SONAR_PROJECT_NAME: riptano/docs-ui SONAR_SOURCES: "." + SONAR_EXCLUSIONS: "**/modules/*/examples/**" steps: - name: Verify Configuration @@ -79,6 +87,7 @@ jobs: -D sonar.projectKey=${{ env.SONAR_PROJECT_KEY }} -D sonar.projectName=${{ env.SONAR_PROJECT_NAME }} -D sonar.sources=${{ env.SONAR_SOURCES }} + -D sonar.exclusions=${{ env.SONAR_EXCLUSIONS }} -D sonar.scanner.truststorePath=${{ runner.temp }}/ibm_castorevpcprod -D sonar.scanner.truststorePassword=${{ secrets.IBM_SONARQUBE_CERT_PASSWORD }} @@ -91,10 +100,13 @@ jobs: env: DASHBOARD_URL: https://sonarqube-prod.apps.wdc-sonarqube-prod.core.cirrus.ibm.com PR_NUMBER: ${{ github.event.pull_request.number }} + REF_NAME: ${{ github.ref_name }} run: | set -euo pipefail url="${DASHBOARD_URL}/dashboard?id=${SONAR_PROJECT_KEY}" if [ -n "$PR_NUMBER" ]; then url="${url}&pullRequest=${PR_NUMBER}" + else + url="${url}&branch=${REF_NAME//\//%2F}" fi echo "[See analysis details on SonarQube]($url)" >> "$GITHUB_STEP_SUMMARY"