name: sonar on: workflow_run: workflows: - ci types: - completed permissions: contents: read actions: read pull-requests: read checks: write statuses: write jobs: sonar: if: | github.event.workflow_run.conclusion == 'success' && (github.event.workflow_run.event == 'pull_request' || github.event.workflow_run.event == 'push') runs-on: ubuntu-24.04 steps: - name: Collect workflow context id: metadata uses: actions/github-script@v7 with: script: | const run = context.payload.workflow_run; const result = { event: run.event, should_run: 'false', is_pr: 'false', pr_number: '', head_branch: run.head_branch || '', base_branch: '', head_sha: run.head_sha, checkout_repo: (run.head_repository && run.head_repository.full_name) || `${context.repo.owner}/${context.repo.repo}`, }; if (run.event === 'pull_request' && run.pull_requests && run.pull_requests.length > 0) { const pr = run.pull_requests[0]; result.should_run = 'true'; result.is_pr = 'true'; result.pr_number = pr.number.toString(); result.head_branch = pr.head.ref; result.base_branch = pr.base.ref; } else if (run.event === 'push' && result.head_branch) { result.should_run = 'true'; } Object.entries(result).forEach(([key, value]) => core.setOutput(key, value)); - name: Checkout repository if: steps.metadata.outputs.should_run == 'true' uses: actions/checkout@v5 with: repository: ${{ steps.metadata.outputs.checkout_repo }} ref: ${{ steps.metadata.outputs.head_sha }} fetch-depth: 0 - name: Align GitHub context with upstream run if: steps.metadata.outputs.should_run == 'true' run: | echo "GITHUB_SHA=${{ steps.metadata.outputs.head_sha }}" >> $GITHUB_ENV if [ -n "${{ steps.metadata.outputs.head_branch }}" ]; then echo "GITHUB_REF_NAME=${{ steps.metadata.outputs.head_branch }}" >> $GITHUB_ENV fi if [ "${{ steps.metadata.outputs.is_pr }}" = "true" ]; then echo "GITHUB_HEAD_REF=${{ steps.metadata.outputs.head_branch }}" >> $GITHUB_ENV echo "GITHUB_BASE_REF=${{ steps.metadata.outputs.base_branch }}" >> $GITHUB_ENV fi - name: Download merged coverage artifact if: steps.metadata.outputs.should_run == 'true' id: download-coverage uses: actions/github-script@v7 with: result-encoding: string script: | const { owner, repo } = context.repo; const runId = context.payload.workflow_run.id; const artifactName = 'merged-coverage'; const artifacts = await github.paginate(github.rest.actions.listWorkflowRunArtifacts, { owner, repo, run_id: runId, per_page: 100, }); const artifact = artifacts.find((entry) => entry.name === artifactName); if (!artifact) { core.setFailed(`Unable to locate artifact '${artifactName}' for workflow run ${runId}.`); return; } const download = await github.rest.actions.downloadArtifact({ owner, repo, artifact_id: artifact.id, archive_format: 'zip', }); const fs = require('fs'); const path = require('path'); const artifactDir = path.join(process.cwd(), 'coverage-artifacts'); fs.mkdirSync(artifactDir, { recursive: true }); const filePath = path.join(artifactDir, `${artifactName}.zip`); fs.writeFileSync(filePath, Buffer.from(download.data)); core.setOutput('zip-path', filePath); - name: Extract coverage files if: steps.metadata.outputs.should_run == 'true' run: | unzip -o "${{ steps.download-coverage.outputs.zip-path }}" -d coverage-artifacts/unpacked shopt -s dotglob cp -r coverage-artifacts/unpacked/* ./ - name: Configure Sonar scanner parameters if: steps.metadata.outputs.should_run == 'true' run: | if [ "${{ steps.metadata.outputs.is_pr }}" = "true" ]; then echo "SONAR_SCANNER_ARGS=-Dsonar.pullrequest.key=${{ steps.metadata.outputs.pr_number }} -Dsonar.pullrequest.branch=${{ steps.metadata.outputs.head_branch }} -Dsonar.pullrequest.base=${{ steps.metadata.outputs.base_branch }}" >> $GITHUB_ENV else echo "SONAR_SCANNER_ARGS=-Dsonar.branch.name=${{ steps.metadata.outputs.head_branch }}" >> $GITHUB_ENV fi - name: SonarQube Analysis if: steps.metadata.outputs.should_run == 'true' uses: SonarSource/sonarqube-scan-action@v5 env: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} with: args: ${{ env.SONAR_SCANNER_ARGS }}