Skip to content

Commit ad83e52

Browse files
zaniebzaniebot
andauthored
Add a shared pull request report publisher (astral-sh#29603)
Add `publish-pull-request-report.yml` as a shared publisher for automation reports, using STS for GitHub writes and the KV actions for comment IDs. Store IDs in `pull-request` scope so later runs can update the same report. Look up each stored ID directly and verify the bot, PR, marker, and run metadata. When a report is published, missing or expired keys create a new comment without scanning existing comments; deleted comments are replaced. Malformed IDs, IDs belonging to another comment, and KV errors fail the job. The publisher verifies the source run and current PR head before writing; report workflows enable it separately. --------- Co-authored-by: zaniebot <242828183+zaniebot@users.noreply.github.com>
1 parent e5de1bd commit ad83e52

4 files changed

Lines changed: 432 additions & 0 deletions

File tree

‎.github/actionlint.yaml‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@ paths:
2525
ignore:
2626
# actionlint doesn't yet support concurrency queues. The schema hook validates them.
2727
- '^unexpected key "queue" for "concurrency" section\.'
28+
".github/workflows/publish-pull-request-report.yml":
29+
ignore:
30+
# actionlint doesn't yet support concurrency queues. The schema hook validates them.
31+
- '^unexpected key "queue" for "concurrency" section\.'
32+
# actionlint doesn't yet recognize the reusable workflow's own revision context.
33+
- 'property "workflow_(repository|sha)" is not defined in object type'
2834
".github/workflows/{ty-ecosystem-report,ty-ecosystem-analyzer,memory_report,sync_typeshed}.yaml":
2935
ignore:
3036
# actionlint doesn't yet support the cache-mode feature.
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
name: Publish a pull request report
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
report:
7+
type: string
8+
required: true
9+
artifact:
10+
type: string
11+
required: true
12+
filename:
13+
type: string
14+
required: true
15+
title:
16+
type: string
17+
default: ""
18+
full-report-artifact:
19+
type: string
20+
default: ""
21+
secrets:
22+
KV_API_URL:
23+
required: true
24+
STS_API_URL:
25+
required: true
26+
27+
permissions: {}
28+
29+
env:
30+
UV_LOCKED: 1
31+
32+
jobs:
33+
publish:
34+
if: >-
35+
github.repository == 'astral-sh/ruff' &&
36+
github.event_name == 'pull_request' &&
37+
github.event.pull_request.head.repo.full_name == github.repository
38+
runs-on: github-ubuntu-24.04-x86_64-2
39+
timeout-minutes: 10
40+
environment: automations
41+
permissions:
42+
contents: read
43+
id-token: write
44+
concurrency:
45+
group: pull-request-report-${{ github.event.pull_request.number }}-${{ inputs.report }}
46+
cancel-in-progress: false
47+
queue: max
48+
steps:
49+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
50+
with:
51+
repository: ${{ job.workflow_repository }}
52+
ref: ${{ job.workflow_sha }}
53+
sparse-checkout: scripts
54+
persist-credentials: false
55+
- uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
56+
with:
57+
# renovate: datasource=github-release-attachments depName=astral-sh/uv
58+
version: "0.13.4"
59+
checksum: "2b428396f12572d4429cf210ca234dd599a33b3af0958a4d5ed569d63e3f344f"
60+
enable-cache: false
61+
- name: Read the stored comment ID
62+
uses: astral-sh/github-actions/key-value-store/get@9ece8e1afa7e9485a0bc35c40e34e1fa495ae454
63+
with:
64+
service-url: ${{ secrets.KV_API_URL }}
65+
scope: pull-request
66+
key: report-comment-${{ inputs.report }}
67+
path: ${{ runner.temp }}/report-comment-id-${{ github.run_id }}-${{ github.run_attempt }}
68+
- name: Get a report publishing token
69+
id: token
70+
uses: open-security-tools/ost-simple-sts@9e012247e07c39080fb6a832dbfbcfeacebc19c4
71+
with:
72+
exchange-url: ${{ secrets.STS_API_URL }}/exchange
73+
audience: ${{ secrets.STS_API_URL }}
74+
repository: astral-sh/ruff
75+
permissions: |
76+
actions: read
77+
pull_requests: write
78+
- name: Publish the report
79+
id: publish
80+
env:
81+
GH_TOKEN: ${{ steps.token.outputs.token }}
82+
RUN_ID: ${{ github.run_id }}
83+
RUN_ATTEMPT: ${{ github.run_attempt }}
84+
WORKFLOW_REF: ${{ github.workflow_ref }}
85+
REPORT: ${{ inputs.report }}
86+
REPORT_ARTIFACT: ${{ inputs.artifact }}
87+
REPORT_FILENAME: ${{ inputs.filename }}
88+
REPORT_TITLE: ${{ inputs.title }}
89+
FULL_REPORT_ARTIFACT: ${{ inputs.full-report-artifact }}
90+
PULL_REQUEST: ${{ github.event.pull_request.number }}
91+
COMMENT_ID_FILE: ${{ runner.temp }}/report-comment-id-${{ github.run_id }}-${{ github.run_attempt }}
92+
run: >-
93+
uv run --script scripts/publish_pr_report.py
94+
--run-id "$RUN_ID" --run-attempt "$RUN_ATTEMPT"
95+
--workflow-ref "$WORKFLOW_REF"
96+
--report "$REPORT" --pull-request "$PULL_REQUEST"
97+
--artifact "$REPORT_ARTIFACT" --filename "$REPORT_FILENAME"
98+
--title "$REPORT_TITLE" --full-report-artifact "$FULL_REPORT_ARTIFACT"
99+
--comment-id-file "$COMMENT_ID_FILE"
100+
- name: Store the comment ID
101+
if: steps.publish.outputs.comment-id != ''
102+
uses: astral-sh/github-actions/key-value-store/put@9ece8e1afa7e9485a0bc35c40e34e1fa495ae454
103+
with:
104+
service-url: ${{ secrets.KV_API_URL }}
105+
scope: pull-request
106+
key: report-comment-${{ inputs.report }}
107+
value: ${{ steps.publish.outputs.comment-id }}

0 commit comments

Comments
 (0)