Update docker/build-push-action digest to 53b7df9 #638
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: SonarQube PR insights comment | |
| # Posts a sticky, advisory PR comment summarising the current Sonar | |
| # smells / bugs / vulnerabilities for the project. This is intentionally | |
| # a soft signal: the workflow never sets a failing check and never | |
| # blocks merge. The Sonar scan itself runs on push to main via | |
| # sonar-scan.yml; this comment is the operator-facing surface so a PR | |
| # author can see "we currently sit at N smells" without leaving the PR | |
| # tab. | |
| # | |
| # Skipped on fork PRs (no secret access) and when SONAR_HOST_URL is | |
| # unset (host not configured for this repo). Both cases degrade | |
| # silently rather than failing the workflow. | |
| on: | |
| pull_request: | |
| types: [opened, synchronize, reopened] | |
| permissions: | |
| contents: read | |
| issues: write | |
| pull-requests: write | |
| concurrency: | |
| group: sonar-pr-comment-${{ github.event.pull_request.number }} | |
| cancel-in-progress: true | |
| jobs: | |
| comment: | |
| name: Sonar smells delta comment | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| # Skip on forks (no secret access) and when the Sonar host is | |
| # unconfigured for this repo. Both checks keep this advisory and | |
| # avoid noisy failures. | |
| if: >- | |
| ${{ vars.SONAR_HOST_URL != '' && | |
| github.event.pull_request.head.repo.full_name == github.repository }} | |
| steps: | |
| - name: Harden runner | |
| uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 | |
| with: | |
| egress-policy: audit | |
| disable-sudo: true | |
| - name: Query Sonar measures | |
| id: query | |
| env: | |
| SONAR_HOST_URL: ${{ vars.SONAR_HOST_URL }} | |
| SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} | |
| run: | | |
| set -euo pipefail | |
| # Tolerate the case where the project has not been scanned | |
| # yet: this workflow stays advisory either way. | |
| http_code=$(curl -sS -o response.json -w '%{http_code}' \ | |
| -u "${SONAR_TOKEN}:" \ | |
| "${SONAR_HOST_URL%/}/api/measures/component?component=bernstein&metricKeys=code_smells,bugs,vulnerabilities,security_hotspots,coverage") | |
| echo "status=${http_code}" >> "$GITHUB_OUTPUT" | |
| if [ "${http_code}" != "200" ]; then | |
| echo "Sonar returned ${http_code}; will post a placeholder comment." | |
| echo '{"component":{"measures":[]}}' > response.json | |
| fi | |
| # Extract metrics defensively. ``jq -r`` returns ``null`` when | |
| # absent; we coerce to ``-`` so the comment table never breaks. | |
| extract() { | |
| jq -r --arg k "$1" ' | |
| .component.measures | |
| | map(select(.metric == $k)) | |
| | .[0].value // "-" | |
| ' response.json | |
| } | |
| { | |
| echo "code_smells=$(extract code_smells)" | |
| echo "bugs=$(extract bugs)" | |
| echo "vulnerabilities=$(extract vulnerabilities)" | |
| echo "security_hotspots=$(extract security_hotspots)" | |
| echo "coverage=$(extract coverage)" | |
| } >> "$GITHUB_OUTPUT" | |
| - name: Post or update sticky comment | |
| uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 | |
| env: | |
| PR_NUMBER: ${{ github.event.pull_request.number }} | |
| SONAR_STATUS: ${{ steps.query.outputs.status }} | |
| CODE_SMELLS: ${{ steps.query.outputs.code_smells }} | |
| BUGS: ${{ steps.query.outputs.bugs }} | |
| VULNS: ${{ steps.query.outputs.vulnerabilities }} | |
| HOTSPOTS: ${{ steps.query.outputs.security_hotspots }} | |
| COVERAGE: ${{ steps.query.outputs.coverage }} | |
| with: | |
| github-token: ${{ github.token }} | |
| script: | | |
| const marker = '<!-- sonar-pr-comment:smells -->'; | |
| const prNumber = Number(process.env.PR_NUMBER); | |
| const status = process.env.SONAR_STATUS || ''; | |
| const lines = [ | |
| marker, | |
| '## Sonar insights (advisory, no merge-block)', | |
| '', | |
| status === '200' | |
| ? 'Snapshot of `bernstein` on the configured Sonar instance:' | |
| : `Sonar query returned status ${status || 'unknown'}; this is advisory only.`, | |
| '', | |
| '| Metric | Value |', | |
| '|---|---|', | |
| `| Coverage | ${process.env.COVERAGE || '-'} |`, | |
| `| Code smells | ${process.env.CODE_SMELLS || '-'} |`, | |
| `| Bugs | ${process.env.BUGS || '-'} |`, | |
| `| Vulnerabilities | ${process.env.VULNS || '-'} |`, | |
| `| Security hotspots | ${process.env.HOTSPOTS || '-'} |`, | |
| '', | |
| 'Run `bernstein doctor sonar` locally for the full surface.', | |
| '', | |
| '_This comment is a soft signal. The Sonar scan runs on push to `main`; the PR check itself never fails on smells._', | |
| ]; | |
| const body = lines.join('\n'); | |
| const { data: comments } = await github.rest.issues.listComments({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: prNumber, | |
| per_page: 100, | |
| }); | |
| const existing = comments.find((c) => c.body && c.body.includes(marker)); | |
| if (existing) { | |
| await github.rest.issues.updateComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| comment_id: existing.id, | |
| body, | |
| }); | |
| core.info(`Updated sticky sonar comment #${existing.id}.`); | |
| } else { | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: prNumber, | |
| body, | |
| }); | |
| core.info('Posted sticky sonar comment.'); | |
| } |