finalize #79
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: finalize | |
| on: | |
| workflow_run: | |
| workflows: | |
| - CI | |
| types: | |
| - completed | |
| permissions: | |
| actions: read | |
| checks: write | |
| contents: read | |
| pull-requests: read | |
| statuses: write | |
| jobs: | |
| sonar: | |
| name: sonar | |
| if: | | |
| github.repository == 'redhat-developer/abbenay' && | |
| github.event.workflow_run.conclusion == 'success' && | |
| (github.event.workflow_run.event == 'pull_request' || | |
| (github.event.workflow_run.event == 'push' && github.event.workflow_run.head_branch == 'main')) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Create check run | |
| id: create-check | |
| uses: actions/github-script@d746ffe35508b1917358783b479e04febd2b8f71 # v9.0.0 | |
| with: | |
| result-encoding: string | |
| script: | | |
| const check = await github.rest.checks.create({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| name: 'sonar', | |
| head_sha: '${{ github.event.workflow_run.head_sha }}', | |
| status: 'in_progress', | |
| details_url: `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`, | |
| }); | |
| console.log(`In progress check created with ID: ${check.data.id}`); | |
| return check.data.id; | |
| - name: Checkout repository | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 | |
| with: | |
| ref: ${{ github.event.workflow_run.head_sha }} | |
| repository: ${{ github.event.workflow_run.head_repository.full_name }} | |
| fetch-depth: 0 | |
| show-progress: false | |
| persist-credentials: false | |
| allow-unsafe-pr-checkout: true | |
| - name: Download coverage artifact | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 | |
| with: | |
| name: sonar-coverage | |
| path: packages/daemon/coverage | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| run-id: ${{ github.event.workflow_run.id }} | |
| - name: Resolve PR metadata | |
| if: github.event.workflow_run.event == 'pull_request' | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| HEAD_SHA: ${{ github.event.workflow_run.head_sha }} | |
| HEAD_BRANCH: ${{ github.event.workflow_run.head_branch }} | |
| HEAD_REPOSITORY: ${{ github.event.workflow_run.head_repository.full_name }} | |
| REPO: ${{ github.repository }} | |
| # Trusted GitHub payload — not PR-controlled artifact content | |
| PR_NUMBER: ${{ github.event.workflow_run.pull_requests[0].number }} | |
| run: | | |
| set -euo pipefail | |
| if [[ -z "${PR_NUMBER}" ]]; then | |
| PR_NUMBER=$(gh api \ | |
| -H "Accept: application/vnd.github+json" \ | |
| "repos/${REPO}/commits/${HEAD_SHA}/pulls" \ | |
| --jq '.[0].number // empty') | |
| fi | |
| # Fork PR head SHAs are often missing from the commits/{sha}/pulls API | |
| # and workflow_run.pull_requests. Resolve via trusted head owner:branch, | |
| # then require an exact head OID match (fail if 0 or >1). | |
| if [[ ! "${PR_NUMBER}" =~ ^[0-9]+$ ]]; then | |
| if [[ -z "${HEAD_BRANCH}" || -z "${HEAD_REPOSITORY}" ]]; then | |
| echo "::error::Missing workflow_run head_branch/head_repository for SHA ${HEAD_SHA}" | |
| exit 1 | |
| fi | |
| HEAD_OWNER="${HEAD_REPOSITORY%%/*}" | |
| MATCHES=$(gh api \ | |
| -H "Accept: application/vnd.github+json" \ | |
| "repos/${REPO}/pulls?state=open&head=${HEAD_OWNER}:${HEAD_BRANCH}" \ | |
| --jq "[.[] | select(.head.sha == \"${HEAD_SHA}\") | .number]") | |
| MATCH_COUNT=$(jq 'length' <<< "${MATCHES}") | |
| if [[ "${MATCH_COUNT}" -ne 1 ]]; then | |
| echo "::error::Expected exactly one open PR for ${HEAD_OWNER}:${HEAD_BRANCH}@${HEAD_SHA}, found ${MATCH_COUNT}: ${MATCHES}" | |
| exit 1 | |
| fi | |
| PR_NUMBER=$(jq -r '.[0]' <<< "${MATCHES}") | |
| fi | |
| if [[ ! "${PR_NUMBER}" =~ ^[0-9]+$ ]]; then | |
| echo "::error::Unable to resolve a trusted PR number for head SHA ${HEAD_SHA}" | |
| exit 1 | |
| fi | |
| PR_DATA=$(gh api "repos/${REPO}/pulls/${PR_NUMBER}") | |
| PR_BASE=$(jq -r '.base.ref' <<< "${PR_DATA}") | |
| PR_HEAD=$(jq -r '.head.ref' <<< "${PR_DATA}") | |
| if [[ -z "${PR_BASE}" || "${PR_BASE}" == "null" || -z "${PR_HEAD}" || "${PR_HEAD}" == "null" ]]; then | |
| echo "::error::Unable to resolve PR branch metadata for PR ${PR_NUMBER}" | |
| exit 1 | |
| fi | |
| { | |
| echo "PR_NUMBER=${PR_NUMBER}" | |
| echo "PR_BASE=${PR_BASE}" | |
| echo "PR_HEAD=${PR_HEAD}" | |
| } >> "${GITHUB_ENV}" | |
| echo "Resolved PR #${PR_NUMBER} (${PR_HEAD} -> ${PR_BASE})" | |
| - name: Prepare SonarCloud args | |
| if: hashFiles('packages/daemon/coverage/lcov.info') != '' | |
| shell: bash | |
| env: | |
| WORKFLOW_EVENT: ${{ github.event.workflow_run.event }} | |
| COMMIT_SHA: ${{ github.event.workflow_run.head_sha }} | |
| REPO_NAME: ${{ github.repository }} | |
| run: | | |
| set -euo pipefail | |
| IFS="/" read -r REPO_OWNER REPO_NAME_ONLY <<< "${REPO_NAME}" | |
| # Pin endpoint; PRs must not override via sonar-project.properties | |
| SONAR_ARGS="-Dsonar.host.url=https://sonarcloud.io" | |
| SONAR_ARGS="${SONAR_ARGS} -Dsonar.projectKey=${REPO_OWNER}_${REPO_NAME_ONLY} -Dsonar.organization=${REPO_OWNER}" | |
| SONAR_ARGS="${SONAR_ARGS} -Dsonar.scm.revision=${COMMIT_SHA}" | |
| if [[ "${WORKFLOW_EVENT}" == "pull_request" ]]; then | |
| if [[ ! "${PR_NUMBER:-}" =~ ^[0-9]+$ ]]; then | |
| echo "::error::PR_NUMBER is missing or invalid" | |
| exit 1 | |
| fi | |
| SONAR_ARGS="${SONAR_ARGS} -Dsonar.pullrequest.key=${PR_NUMBER}" | |
| SONAR_ARGS="${SONAR_ARGS} -Dsonar.pullrequest.branch=${PR_HEAD}" | |
| SONAR_ARGS="${SONAR_ARGS} -Dsonar.pullrequest.base=${PR_BASE}" | |
| fi | |
| echo "SONAR_ARGS=${SONAR_ARGS}" >> "${GITHUB_ENV}" | |
| - name: Check for coverage files | |
| run: | | |
| if [ -f packages/daemon/coverage/lcov.info ]; then | |
| echo "Coverage Data: Available" | |
| ls -la packages/daemon/coverage/lcov.info | |
| else | |
| echo "Coverage Data: Not available - exiting" | |
| exit 1 | |
| fi | |
| echo "Running SonarCloud analysis..." | |
| - name: SonarCloud Scan | |
| if: env.SONAR_ARGS != '' | |
| uses: SonarSource/sonarqube-scan-action@22918119ff8e1ca75a623e15c8296b6ea4fbe28f # v8 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} | |
| with: | |
| args: ${{ env.SONAR_ARGS }} | |
| - name: Update check run (success) | |
| if: success() | |
| uses: actions/github-script@d746ffe35508b1917358783b479e04febd2b8f71 # v9.0.0 | |
| with: | |
| script: | | |
| const isPullRequest = '${{ github.event.workflow_run.event }}' === 'pull_request'; | |
| const prNumber = process.env.PR_NUMBER; | |
| const summary = isPullRequest && prNumber | |
| ? `SonarCloud analysis passed for PR #${prNumber}.` | |
| : 'SonarCloud analysis passed.'; | |
| await github.rest.checks.update({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| check_run_id: ${{ steps.create-check.outputs.result }}, | |
| status: 'completed', | |
| conclusion: 'success', | |
| completed_at: new Date().toISOString(), | |
| details_url: `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`, | |
| output: { | |
| title: 'SonarCloud analysis passed', | |
| summary, | |
| }, | |
| }); | |
| - name: Update check run (failure) | |
| if: failure() && steps.create-check.outcome == 'success' | |
| uses: actions/github-script@d746ffe35508b1917358783b479e04febd2b8f71 # v9.0.0 | |
| with: | |
| script: | | |
| const isPullRequest = '${{ github.event.workflow_run.event }}' === 'pull_request'; | |
| const prNumber = process.env.PR_NUMBER; | |
| const summary = isPullRequest && prNumber | |
| ? `SonarCloud analysis failed for PR #${prNumber}. Click Details for logs.` | |
| : 'SonarCloud analysis failed. Click Details for logs.'; | |
| await github.rest.checks.update({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| check_run_id: ${{ steps.create-check.outputs.result }}, | |
| status: 'completed', | |
| conclusion: 'failure', | |
| completed_at: new Date().toISOString(), | |
| details_url: `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`, | |
| output: { | |
| title: 'SonarCloud analysis failed', | |
| summary, | |
| text: `**Workflow run:** [View details](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId})`, | |
| }, | |
| }); |