From 8696ea5eff74258d2838ea44056ebe32f2e8b0a9 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Mon, 30 Mar 2026 23:08:12 +0200 Subject: [PATCH 1/2] CAMEL-22752: Add SonarCloud PR analysis workflows Add two-workflow pattern for secure SonarCloud analysis on pull requests, including PRs from forks: - sonar-build.yml: triggered on pull_request, builds the project and uploads compiled classes + PR metadata as artifacts (no secrets needed) - sonar-scan.yml: triggered on workflow_run completion, downloads artifacts and runs sonar:sonar with access to SONARCLOUD_TOKEN secret This follows the same pattern used by Apache Ignite (IGNITE-20466) and Apache Kvrocks for safe SonarCloud analysis on fork PRs. Co-Authored-By: Claude Opus 4.6 --- .github/workflows/sonar-build.yml | 89 ++++++++++++++++ .github/workflows/sonar-scan.yml | 164 ++++++++++++++++++++++++++++++ 2 files changed, 253 insertions(+) create mode 100644 .github/workflows/sonar-build.yml create mode 100644 .github/workflows/sonar-scan.yml diff --git a/.github/workflows/sonar-build.yml b/.github/workflows/sonar-build.yml new file mode 100644 index 0000000000000..bbff7b1ebfae9 --- /dev/null +++ b/.github/workflows/sonar-build.yml @@ -0,0 +1,89 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +name: SonarBuild + +on: + pull_request: + branches: + - main + paths-ignore: + - README.md + - SECURITY.md + - Jenkinsfile + - Jenkinsfile.* + - NOTICE.txt + +permissions: + contents: read + +concurrency: + group: sonar-pr-${{ github.event.pull_request.head.repo.full_name }}-${{ github.event.pull_request.head.ref }} + cancel-in-progress: true + +jobs: + build: + if: github.repository == 'apache/camel' + name: Build for Sonar Analysis + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + + - id: install-packages + uses: ./.github/actions/install-packages + + - name: Set up JDK 21 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 + with: + distribution: 'temurin' + java-version: '21' + cache: 'maven' + + - name: Build with Maven + run: ./mvnw install -B -Dquickly + + - name: Prepare compiled classes artifact + shell: bash + run: find . -name "target" -type d | tar -czf target.tar.gz -T - + + - name: Upload compiled classes artifact + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + id: target-upload + with: + name: sonar-target + path: target.tar.gz + if-no-files-found: error + retention-days: 1 + + - name: Prepare pull request metadata + shell: bash + run: | + echo "${{ github.event.pull_request.number }}" > pr-event.txt + echo "${{ github.event.pull_request.head.ref }}" >> pr-event.txt + echo "${{ github.event.pull_request.base.ref }}" >> pr-event.txt + echo "${{ github.event.pull_request.head.sha }}" >> pr-event.txt + echo "${{ steps.target-upload.outputs.artifact-id }}" >> pr-event.txt + + - name: Upload pull request metadata + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + with: + name: sonar-pr-event + path: pr-event.txt + if-no-files-found: error + retention-days: 1 diff --git a/.github/workflows/sonar-scan.yml b/.github/workflows/sonar-scan.yml new file mode 100644 index 0000000000000..acfd4da7e1ed0 --- /dev/null +++ b/.github/workflows/sonar-scan.yml @@ -0,0 +1,164 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +name: Sonar Quality Pull Request Analysis + +on: + workflow_run: + workflows: [SonarBuild] + types: [completed] + +concurrency: + group: sonar-pr-${{ github.event.workflow_run.head_repository.full_name }}-${{ github.event.workflow_run.head_branch }} + cancel-in-progress: true + +jobs: + sonar: + if: > + github.event.workflow_run.conclusion == 'success' && + github.repository == 'apache/camel' + name: Sonar Analysis + runs-on: ubuntu-latest + permissions: + contents: read + actions: write + checks: write + steps: + - name: Download pull request metadata + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 + with: + name: sonar-pr-event + run-id: ${{ github.event.workflow_run.id }} + github-token: ${{ secrets.GITHUB_TOKEN }} + + - name: Read pull request metadata + shell: bash + run: | + echo "pr_number=$(sed '1q;d' pr-event.txt)" >> "$GITHUB_ENV" + echo "pr_head_ref=$(sed '2q;d' pr-event.txt)" >> "$GITHUB_ENV" + echo "pr_base_ref=$(sed '3q;d' pr-event.txt)" >> "$GITHUB_ENV" + echo "pr_head_sha=$(sed '4q;d' pr-event.txt)" >> "$GITHUB_ENV" + echo "target_artifact_id=$(sed '5q;d' pr-event.txt)" >> "$GITHUB_ENV" + + - name: Create PR check + uses: actions/github-script@v7 + id: check + with: + script: | + const jobs_response = await github.rest.actions.listJobsForWorkflowRunAttempt({ + ...context.repo, + run_id: context.runId, + attempt_number: process.env.GITHUB_RUN_ATTEMPT, + }); + const job_url = jobs_response.data.jobs[0].html_url; + const check_response = await github.rest.checks.create({ + ...context.repo, + name: 'Sonar Quality Pull Request Analysis', + head_sha: process.env.pr_head_sha, + status: 'in_progress', + output: { + title: 'Sonar Quality Pull Request Analysis', + summary: '[Details](' + job_url + ')' + } + }); + return check_response.data.id; + result-encoding: string + + - name: Checkout PR source + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + repository: ${{ github.event.workflow_run.head_repository.full_name }} + ref: ${{ github.event.workflow_run.head_sha }} + fetch-depth: 0 + # fetch-depth: 0 is needed for Sonar's new code detection, blame information and issue backdating + + - name: Fetch base branch + run: | + git remote add upstream https://github.com/apache/camel || true + git fetch upstream + git checkout -B ${{ env.pr_base_ref }} upstream/${{ env.pr_base_ref }} + git checkout ${{ github.event.workflow_run.head_sha }} + + - name: Download compiled classes artifact + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 + with: + name: sonar-target + run-id: ${{ github.event.workflow_run.id }} + github-token: ${{ secrets.GITHUB_TOKEN }} + + - name: Delete compiled classes artifact + if: always() + uses: actions/github-script@v7 + with: + script: | + await github.rest.actions.deleteArtifact({ + ...context.repo, + artifact_id: process.env.target_artifact_id + }); + + - name: Extract compiled classes + shell: bash + run: tar -xzf target.tar.gz + + - name: Set up JDK 21 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 + with: + distribution: 'temurin' + java-version: '21' + cache: 'maven' + + - name: Cache SonarCloud packages + uses: actions/cache@v4 + with: + path: ~/.sonar/cache + key: ${{ runner.os }}-sonar + + - id: install-packages + uses: ./.github/actions/install-packages + + - name: Run Sonar Analysis + shell: bash + run: > + ./mvnw org.sonarsource.scanner.maven:sonar-maven-plugin:sonar + -Dsonar.scm.revision=${{ github.event.workflow_run.head_sha }} + -Dsonar.pullrequest.branch=${{ env.pr_head_ref }} + -Dsonar.pullrequest.base=${{ env.pr_base_ref }} + -Dsonar.pullrequest.key=${{ env.pr_number }} + -Dsonar.pullrequest.github.repository=apache/camel + -Dsonar.pullrequest.provider=GitHub + -Dsonar.pullrequest.github.summary_comment=true + -Dsonar.projectKey=apache_camel + -Dsonar.organization=apache + -Dsonar.token=${{ secrets.SONARCLOUD_TOKEN }} + -B -V + env: + MAVEN_OPTS: "-XX:+UseG1GC -XX:InitialHeapSize=2g -XX:MaxHeapSize=6g -XX:+UseStringDeduplication" + + - name: Update PR check status + uses: actions/github-script@v7 + if: always() + env: + CHECK_ID: ${{ steps.check.outputs.result }} + JOB_STATUS: ${{ job.status }} + with: + script: | + await github.rest.checks.update({ + ...context.repo, + check_run_id: process.env.CHECK_ID, + status: 'completed', + conclusion: process.env.JOB_STATUS + }); From 91e0352e7d01c03d3aab691a425d26c99ce4e3f9 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Mon, 30 Mar 2026 23:16:05 +0200 Subject: [PATCH 2/2] Fix SONAR_TOKEN secret name to match existing repository secret --- .github/workflows/sonar-scan.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/sonar-scan.yml b/.github/workflows/sonar-scan.yml index acfd4da7e1ed0..8a3d508cfb000 100644 --- a/.github/workflows/sonar-scan.yml +++ b/.github/workflows/sonar-scan.yml @@ -143,7 +143,7 @@ jobs: -Dsonar.pullrequest.github.summary_comment=true -Dsonar.projectKey=apache_camel -Dsonar.organization=apache - -Dsonar.token=${{ secrets.SONARCLOUD_TOKEN }} + -Dsonar.token=${{ secrets.SONAR_TOKEN }} -B -V env: MAVEN_OPTS: "-XX:+UseG1GC -XX:InitialHeapSize=2g -XX:MaxHeapSize=6g -XX:+UseStringDeduplication"