mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-04-14 10:07:39 +08:00
Bump every GitHub Action in the repository to its latest major version, addressing the upcoming Node.js 20 deprecation. Several of the old versions (checkout v4, cache v4, setup-node v4, labeler v5) use the Node 20 runtime which GitHub is deprecating. The new versions use Node 22. - actions/checkout v4/v5 to v6 - actions/upload-artifact v4 to v7 - actions/download-artifact v4 to v8 - actions/cache, cache/restore, cache/save v4 to v5 - actions/setup-node v4 to v6 - actions/setup-python v5 to v6 - actions/github-script v7/v8 to v9 - actions/labeler v5 to v6 - peter-evans/find-comment v3 to v4 - dorny/paths-filter v3 to v4 - codecov/codecov-action v4 to v6 - docker/setup-buildx-action v3 to v4 - docker/build-push-action v6 to v7 - tj-actions/changed-files v46 to v47 Signed-off-by: Ramon Roche <mrpollo@gmail.com>
178 lines
8.0 KiB
YAML
178 lines
8.0 KiB
YAML
name: PR Review Poster
|
|
|
|
# Generic PR review-comment poster. Sibling of "PR Comment Poster": that
|
|
# workflow posts sticky issue-style comments, this one posts line-anchored
|
|
# review comments on the "Files changed" tab. Any analysis workflow that
|
|
# wants to flag specific lines can produce a `pr-review` artifact and this
|
|
# workflow will dismiss any stale matching review and post a fresh one.
|
|
# Designed so analysis jobs running on untrusted fork PRs can still get
|
|
# their inline annotations posted back to the PR.
|
|
#
|
|
# ==============================================================================
|
|
# SECURITY INVARIANTS
|
|
# ==============================================================================
|
|
# This workflow runs on `workflow_run` which means it runs in the BASE REPO
|
|
# context with a WRITE token, even when the triggering PR comes from a fork.
|
|
# That is the entire reason it exists, and also the reason it is a loaded
|
|
# footgun. Anyone modifying this file MUST preserve the following invariants:
|
|
#
|
|
# 1. NEVER check out PR code. No `actions/checkout` with a ref. No git clone
|
|
# of a fork branch. No execution of scripts from the downloaded artifact.
|
|
# The ONLY things read from the artifact are `manifest.json` and
|
|
# `comments.json`, and both are treated as opaque data (JSON parsed by
|
|
# the poster script and the comment fields posted via the GitHub API).
|
|
#
|
|
# 2. `pr_number` is validated to be a positive integer before use.
|
|
# `marker` is validated to be printable ASCII only before use.
|
|
# `commit_sha` is validated to be 40 lowercase hex characters.
|
|
# `event` is validated against an allowlist of `COMMENT` and
|
|
# `REQUEST_CHANGES`. `APPROVE` is intentionally forbidden so a bot
|
|
# cannot approve a pull request. Validation happens inside
|
|
# Tools/ci/pr-review-poster.py which is checked out from the base
|
|
# branch, not from the artifact.
|
|
#
|
|
# 3. Comment bodies and the optional summary are passed to the GitHub API
|
|
# as JSON fields, never interpolated into a shell command string.
|
|
#
|
|
# 4. This workflow file lives on the default branch. `workflow_run` only
|
|
# loads workflow files from the default branch, so a fork cannot modify
|
|
# THIS file as part of a PR. The fork CAN cause this workflow to fire
|
|
# by triggering a producer workflow that uploads a `pr-review`
|
|
# artifact. That is intended.
|
|
#
|
|
# 5. The artifact-name filter (`pr-review`) is the only gate on which
|
|
# workflow runs get processed. Any workflow in this repo that uploads
|
|
# an artifact named `pr-review` is trusted to have written the
|
|
# manifest and comments itself, NOT copied fork-controlled content
|
|
# into them. Producer workflows are responsible for that.
|
|
#
|
|
# 6. `actions/checkout@v6` below uses NO ref (so it pulls the base branch,
|
|
# the default-branch commit this workflow file was loaded from) AND
|
|
# uses sparse-checkout to materialize ONLY
|
|
# Tools/ci/pr-review-poster.py and its stdlib-only helper module
|
|
# Tools/ci/_github_helpers.py. The rest of the repo never touches the
|
|
# workspace. This is safe: the only files the job executes are
|
|
# base-repo Python scripts that were reviewed through normal code
|
|
# review, never anything from the PR.
|
|
#
|
|
# 7. Stale-review dismissal is restricted to reviews whose AUTHOR is
|
|
# `github-actions[bot]` AND whose body contains the producer's
|
|
# marker. A fork PR cannot impersonate the bot login, and cannot
|
|
# inject the marker into a human reviewer's body without API
|
|
# access. Both filters together prevent the poster from ever
|
|
# dismissing a human review.
|
|
#
|
|
# ==============================================================================
|
|
# ARTIFACT CONTRACT
|
|
# ==============================================================================
|
|
# Producers upload an artifact named exactly `pr-review` containing:
|
|
#
|
|
# manifest.json:
|
|
# {
|
|
# "pr_number": 12345, // required, int > 0
|
|
# "marker": "<!-- pr-review-poster:clang-tidy -->", // required, printable ASCII
|
|
# "event": "REQUEST_CHANGES", // required, "COMMENT" | "REQUEST_CHANGES"
|
|
# "commit_sha": "0123456789abcdef0123456789abcdef01234567", // required, 40 hex chars
|
|
# "summary": "Optional review summary text" // optional
|
|
# }
|
|
#
|
|
# comments.json: JSON array of line-anchored review comment objects:
|
|
# [
|
|
# {"path": "src/foo.cpp", "line": 42, "side": "RIGHT", "body": "..."},
|
|
# {"path": "src/bar.hpp", "start_line": 10, "line": 15,
|
|
# "side": "RIGHT", "start_side": "RIGHT", "body": "..."}
|
|
# ]
|
|
#
|
|
# The `marker` string is used to find an existing matching review to
|
|
# dismiss before posting a new one. It MUST be unique per producer (e.g.
|
|
# include the producer name).
|
|
#
|
|
# Producers MUST write `pr_number` and `commit_sha` from their own
|
|
# workflow context (`github.event.pull_request.number` and
|
|
# `github.event.pull_request.head.sha`) and MUST NOT read either from any
|
|
# fork-controlled source.
|
|
|
|
on:
|
|
workflow_run:
|
|
# Producers that may upload a `pr-review` artifact. When a new
|
|
# producer is wired up, add its workflow name here. Runs of workflows
|
|
# not in this list will never trigger the poster. Every run of a
|
|
# listed workflow will trigger the poster, which will no-op if no
|
|
# `pr-review` artifact exists.
|
|
workflows:
|
|
- "Static Analysis"
|
|
types:
|
|
- completed
|
|
|
|
permissions:
|
|
pull-requests: write
|
|
actions: read
|
|
contents: read
|
|
|
|
jobs:
|
|
post:
|
|
name: Post PR Review
|
|
runs-on: ubuntu-latest
|
|
# Only run for pull_request producer runs. Push-to-main and other
|
|
# non-PR triggers have no review to post, so gating at the job level
|
|
# surfaces those as a clean "Skipped" in the UI instead of a
|
|
# silent no-op buried inside the script.
|
|
if: >-
|
|
github.event.workflow_run.conclusion != 'cancelled'
|
|
&& github.event.workflow_run.event == 'pull_request'
|
|
steps:
|
|
# Checkout runs first so the poster scripts are available AND so
|
|
# that actions/checkout@v6's default clean step does not delete the
|
|
# artifact zip that the next step writes into the workspace.
|
|
# Sparse-checkout restricts the materialized tree to just the
|
|
# poster script and its stdlib helper module.
|
|
- name: Checkout poster script only
|
|
uses: actions/checkout@v6
|
|
with:
|
|
sparse-checkout: |
|
|
Tools/ci/pr-review-poster.py
|
|
Tools/ci/_github_helpers.py
|
|
sparse-checkout-cone-mode: false
|
|
|
|
- name: Download pr-review artifact
|
|
id: download
|
|
uses: actions/github-script@v9
|
|
with:
|
|
script: |
|
|
const artifacts = await github.rest.actions.listWorkflowRunArtifacts({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
run_id: context.payload.workflow_run.id,
|
|
});
|
|
const match = artifacts.data.artifacts.find(a => a.name === 'pr-review');
|
|
if (!match) {
|
|
core.info('No pr-review artifact on this run; nothing to post.');
|
|
core.setOutput('found', 'false');
|
|
return;
|
|
}
|
|
const download = await github.rest.actions.downloadArtifact({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
artifact_id: match.id,
|
|
archive_format: 'zip',
|
|
});
|
|
const fs = require('fs');
|
|
fs.writeFileSync('pr-review.zip', Buffer.from(download.data));
|
|
core.setOutput('found', 'true');
|
|
|
|
- name: Unpack artifact
|
|
if: steps.download.outputs.found == 'true'
|
|
run: |
|
|
mkdir -p pr-review
|
|
unzip -q pr-review.zip -d pr-review
|
|
|
|
- name: Validate artifact
|
|
if: steps.download.outputs.found == 'true'
|
|
run: python3 Tools/ci/pr-review-poster.py validate pr-review
|
|
|
|
- name: Post PR review
|
|
if: steps.download.outputs.found == 'true'
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: python3 Tools/ci/pr-review-poster.py post pr-review
|