SonarCloud #17315
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: SonarCloud | |
| on: | |
| # workflow_run is required to run analysis on PRs from forks with access to | |
| # secrets; the job recreates the merge state from trusted metadata and does | |
| # not execute untrusted PR code. | |
| workflow_run: # zizmor: ignore[dangerous-triggers] | |
| workflows: [Analysis] | |
| types: [completed] | |
| permissions: | |
| actions: read | |
| contents: read | |
| pull-requests: read | |
| jobs: | |
| sonarcloud: | |
| name: SonarCloud | |
| runs-on: ubuntu-latest | |
| container: ghcr.io/acts-project/ubuntu2404:87 | |
| if: github.event.workflow_run.conclusion == 'success' | |
| steps: | |
| - name: Install APT packages | |
| run: | | |
| apt-get update | |
| apt-get install -y unzip | |
| - name: "Checkout repository" | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| fetch-depth: 0 # To prevent shallow clone | |
| persist-credentials: false | |
| - name: Install dependencies | |
| uses: ./.github/actions/dependencies | |
| with: | |
| compiler: g++ | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| env_file: .env | |
| - name: 'Download artifact' | |
| uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 | |
| id: dl-af | |
| with: | |
| script: | | |
| console.log(`Getting artifacts for workflow run id: ${context.payload.workflow_run.id}`); | |
| let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| run_id: context.payload.workflow_run.id, | |
| }); | |
| for (artifact of allArtifacts.data.artifacts) { | |
| console.log(`Artifact #${artifact.id} ${artifact.name}`); | |
| let download = await github.rest.actions.downloadArtifact({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| artifact_id: artifact.id, | |
| archive_format: 'zip', | |
| }); | |
| let fs = require('fs'); | |
| fs.writeFileSync(`${process.env.GITHUB_WORKSPACE}/${artifact.name}.zip`, Buffer.from(download.data)); | |
| } | |
| return true; | |
| - name: Unzip coverage build | |
| run: unzip coverage-build.zip -d build | |
| - name: Unzip PR metadata | |
| if: github.event.workflow_run.event == 'pull_request' | |
| run: unzip PR_metadata.zip | |
| - name: Read PR metadata | |
| if: github.event.workflow_run.event == 'pull_request' | |
| id: pr_metadata | |
| uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 | |
| with: | |
| script: | | |
| const fs = require('fs'); | |
| const metadata = JSON.parse(fs.readFileSync('PR_metadata.json', 'utf8')); | |
| console.log('PR metadata:', JSON.stringify(metadata, null, 2)); | |
| core.setOutput('pr_number', metadata.pr_number); | |
| core.setOutput('pr_sha', metadata.pr_sha); | |
| core.setOutput('base_sha', metadata.base_sha); | |
| core.setOutput('merge_sha', metadata.merge_sha); | |
| - name: Request GitHub API for PR data | |
| if: github.event.workflow_run.event == 'pull_request' | |
| uses: octokit/request-action@b91aabaa861c777dcdb14e2387e30eddf04619ae # v3.0.0 | |
| id: get_pr_data | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| with: | |
| route: GET /repos/{full_name}/pulls/{number} | |
| number: ${{ steps.pr_metadata.outputs.pr_number }} | |
| full_name: ${{ github.event.repository.full_name }} | |
| - name: Validate PR branch names | |
| if: github.event.workflow_run.event == 'pull_request' | |
| env: | |
| HEAD_REF: ${{ fromJson(steps.get_pr_data.outputs.data).head.ref }} | |
| BASE_REF: ${{ fromJson(steps.get_pr_data.outputs.data).base.ref }} | |
| run: | | |
| # These values are attacker-controlled (the PR branch name) and are | |
| # passed to sonar-scanner as CLI arguments below. Reject anything that | |
| # isn't a well-formed git ref to prevent argument injection. | |
| for ref in "$HEAD_REF" "$BASE_REF"; do | |
| case "$ref" in | |
| ""|*[!A-Za-z0-9._/-]*) | |
| echo "Refusing to proceed: unexpected branch name '$ref'" >&2 | |
| exit 1 | |
| ;; | |
| esac | |
| done | |
| - name: Get upcoming version from milestones | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| GH_REPO: acts-project/acts | |
| run: | | |
| CI/get_next_milestone.py | tee next_version.txt | |
| - name: Read next_version.txt | |
| id: next_version | |
| uses: juliangruber/read-file-action@271ff311a4947af354c6abcd696a306553b9ec18 # v1.1.8 | |
| with: | |
| path: ./next_version.txt | |
| - name: Recreate merge commit state | |
| if: github.event.workflow_run.event == 'pull_request' | |
| env: | |
| PR_CLONE_URL: ${{ fromJson(steps.get_pr_data.outputs.data).head.repo.clone_url }} | |
| BASE_SHA: ${{ steps.pr_metadata.outputs.base_sha }} | |
| PR_SHA: ${{ steps.pr_metadata.outputs.pr_sha }} | |
| MERGE_SHA: ${{ steps.pr_metadata.outputs.merge_sha }} | |
| run: | | |
| git config --global --add safe.directory $PWD | |
| git config user.email "ci@acts-project.org" | |
| git config user.name "CI" | |
| # upstream: main branch, origin: PR branch | |
| git remote rename origin upstream | |
| git remote add origin "$PR_CLONE_URL" | |
| git fetch origin | |
| # Check out the exact base commit that was used in the original merge | |
| git checkout "$BASE_SHA" | |
| # Merge the PR commit to recreate the same merge state as the analysis run | |
| git merge --no-edit "$PR_SHA" | |
| # Restore the trusted scanner configuration: the merged tree contains | |
| # attacker-controlled files, and sonar-scanner reads | |
| # sonar-project.properties from the working directory. Reset it to the | |
| # base commit so the PR cannot override scanner settings. | |
| git checkout "$BASE_SHA" -- sonar-project.properties | |
| echo "Recreated merge state:" | |
| echo " Base SHA: $BASE_SHA" | |
| echo " PR SHA: $PR_SHA" | |
| echo " Current HEAD: $(git rev-parse HEAD)" | |
| echo " Original merge SHA: $MERGE_SHA" | |
| git remote -v | |
| git status | |
| - name: Run sonar-scanner (PR mode) | |
| uses: SonarSource/sonarqube-scan-action@713881670b6b3676cda39549040e2d88c70d582e # v8.2.0 | |
| if: github.event.workflow_run.event == 'pull_request' | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} | |
| with: | |
| args: > | |
| --define sonar.verbose=true | |
| --define sonar.cfamily.compile-commands=build/compile_commands.json | |
| --define sonar.projectVersion=${{ steps.next_version.outputs.content }} | |
| --define sonar.scm.revision=${{ steps.pr_metadata.outputs.merge_sha }} | |
| --define sonar.pullrequest.key=${{ steps.pr_metadata.outputs.pr_number }} | |
| --define sonar.pullrequest.branch=${{ fromJson(steps.get_pr_data.outputs.data).head.ref }} | |
| --define sonar.pullrequest.base=${{ fromJson(steps.get_pr_data.outputs.data).base.ref }} | |
| - name: Run sonar-scanner (push mode) | |
| uses: SonarSource/sonarqube-scan-action@713881670b6b3676cda39549040e2d88c70d582e # v8.2.0 | |
| if: github.event.workflow_run.event == 'push' && github.ref == 'refs/heads/main' | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} | |
| with: | |
| args: > | |
| --define sonar.verbose=true | |
| --define sonar.cfamily.compile-commands=build/compile_commands.json | |
| --define sonar.coverageReportPaths=build/coverage/cov.xml | |
| --define sonar.projectVersion=${{ steps.next_version.outputs.content }} | |
| --define sonar.branch.name=main |