Repository navigation
GitHub Action
The refquiem action installs the tool, resolves the scan range from the triggering event and either posts a request-changes review on the pull request or fails the job on findings. It reports the comments, docs, strings and Markdown that still mention the Rust items, dependencies, features, binaries and examples your history removed.
on: pull_request
permissions:
contents: read
pull-requests: write
jobs:
refquiem:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
# The action and the tool use the same pinned revision.
- name: Install refquiem from the pinned source
run: cargo install refquiem --git https://github.com/LucaCappelletti94/cargo-refquiem.git --rev 5ac009ab93c17d40d3e72d50fa33415f84c1ce7f --locked
- uses: LucaCappelletti94/cargo-refquiem@5ac009ab93c17d40d3e72d50fa33415f84c1ce7f
with:
install: false
pr-number: ${{ github.event.pull_request.number }}With pr-number, the action posts a review with REQUEST_CHANGES instead of failing the job. Each removed name gets one comment on the line of the diff where the pull request deleted it. The comment gives the headline of the removed name, links every remaining mention at the pull request head and embeds the first three as code snippets. In the headline the removed name links to its line at the report's base and the suggested name to its line at the pull request head, wherever the report places them. Every comment ends with a prefilled link to the wrong review form and a sponsor link.
A mention on a line of a file the pull request changes also gets its own comment there. When the report resolves the rewrite, that comment carries the rewritten mention line as a suggestion fence. The fence outgrows the longest backtick run of the line it holds, and several mentions on one line merge into one comment holding every message and the rewritten line of the first mention. Reports covers the replacement field the rewrite comes from.
GitHub attaches a review comment only to a line of the pull request diff. The deleted line comes from the report's declared_at, where the pull request's base declares the name, which is the left side of the diff. When a name has no such line, as when the pull request both added and removed it, or GitHub rejects the comment, its mentions are linked in the review body instead. An unused suppression marker outside the changed files is linked there too.
The review body counts the removed names and their mentions, splits the names into those with a suggested replacement, several possible replacements or none, and ends with the wrong review and sponsor links, the run link and the <!-- refquiem --> marker the action uses to recognize its own reviews. When the review holds a single finding and its comments carry all of it, the body is the marker alone, since the comment already names the place, the replacement and the links. A clean run and every new review dismiss the earlier CHANGES_REQUESTED reviews the marker identifies, whatever token posted them, and close the open threads of every earlier marked review, replied ones included, so only the newest review keeps open threads. A thread resolves when the job's token holds contents: write, which GitHub requires for resolving, and otherwise its comments are hidden as outdated, which pull-requests: write allows. A review GitHub accepted only with every finding in its body closes no thread, since the earlier threads are then the only comments anchored at its findings. A refquiem: allow(Name) marker that suppresses nothing is a finding too, with a comment naming the marker and no suggestion. Find your first stale reference walks the resolution.
Leave out pr-number and the job fails whenever the scan reports a finding, and a scan error fails the job the same way. That suits a push to main, a schedule entry and a workflow_dispatch run.
on:
push:
branches: [main]
schedule:
- cron: "23 4 * * 1"
permissions:
contents: read
jobs:
refquiem:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- name: Install refquiem from the pinned source
run: cargo install refquiem --git https://github.com/LucaCappelletti94/cargo-refquiem.git --rev 5ac009ab93c17d40d3e72d50fa33415f84c1ce7f --locked
- uses: LucaCappelletti94/cargo-refquiem@5ac009ab93c17d40d3e72d50fa33415f84c1ce7f
with:
install: falseThe action resolves the range from the event and deepens the shallow checkout until the two ends share an ancestor, fetching only the history it needs.
| Trigger | Range |
|---|---|
pull_request |
from the merge base of the base branch tip and the pull request head, where the branch forked, to the pull request head, the commit the comments anchor to |
pull_request_target |
refused. The trigger runs with the base repository's credentials, so the job fails before scanning |
push |
from the merge base of before and after, the old tip after a fast-forward and the fork point after a force push, to the new tip. A new branch, or an old tip the remote dropped, starts from the default branch |
merge_group |
from the event's base_sha to its head_sha
|
schedule, workflow_dispatch and the remaining events |
the whole history, or from the since input when given |
The scan covers the base revision and the commits after it, compared against the event's head when it supplies one and the working tree otherwise. When the two ends share no ancestor, the action unshallows the clone and scans the whole history. The since input is ignored on the events that carry their own range. History and cache covers the parsed-file cache under target/refquiem.
| Input | Default | Effect |
|---|---|---|
version |
empty | the refquiem version to install. Empty resolves the newest available |
install |
true |
install refquiem, or false uses the cargo refquiem already on the path |
cwd |
empty | the workspace directory to scan |
package |
empty | scan only the workspace member with this name |
config |
empty | the configuration file, by default .refquiem.toml at the workspace root. See Configuration
|
since |
empty | the revision a manual or scheduled audit starts from. Empty audits the whole history |
pr-number |
empty | post the findings as a review on this pull request instead of failing the job |
dry-run |
false |
render the review into the job summary without posting, in any mode |
annotations |
true |
annotate every finding. Needs no token |
mode |
review |
review posts the findings in one job, prepare writes the report for a later job and post reviews it on the pull request its workflow_run run built |
payload |
empty | the directory prepare writes and post reads, the runner's temp directory when empty |
install: true downloads the prebuilt cargo-refquiem-<target>.tar.gz for the runner, Linux x86_64 and aarch64, macOS x86_64 and aarch64 and Windows x86_64. With version set it reads the v<version> release. Without it the newest release carrying the asset, because the action's own releases carry no binary and GitHub marks the newest one Latest. When no asset is available the step falls back to cargo install refquiem --locked, which needs the crate published on crates.io at the requested version. The examples above set install: false and install the tool from the pinned source instead.
The action exposes one output, review-status, set by its review step.
| Value | Outcome |
|---|---|
posted |
the review and its comments were posted. The earlier change requests were dismissed and their threads closed, unless GitHub accepted the review only with every finding in its body |
dry-run |
the review was rendered into the job summary. Nothing was posted |
prepared |
the report was written to payload for a later post
|
skipped-clean |
no finding. In review and post mode the earlier change requests were dismissed and their threads closed |
skipped-readonly |
the review post came back read-only. The annotations and the job summary carry the findings |
skipped-stale |
post mode found no open pull request at the head the triggering run built, or outside workflow_run the pull request moved on. Nothing was posted |
rejected |
post mode refused the payload because it names a pull request or a head the triggering run did not build, its run did not come from pull_request, or its report failed validation. Nothing was posted or dismissed, and the step exits nonzero |
failed |
the review step could not read the run, the pull request or its files, could not post, read an unexpected review state, or found no prepared payload in post mode. The step exits nonzero |
A gate run that sets neither pr-number nor dry-run skips the review step and leaves the output empty, and a scan error fails the scan step before it runs.
The pull request's code runs in the pull request job, so that job holds a read-only token and only prepares the review. It runs mode: prepare on every pull request and uploads the payload, and a workflow_run job posts it with mode: post. A fork's token is read-only anyway, so this pair is also the only way to review forks. The single-job form above runs the pull request's code with a write token, which this pair avoids.
The posting job holds a write token, so it never checks out or runs the pull request's code. It runs the base repository's workflow and the action at the pinned revision, checks out the default branch without persisting credentials, grants each scope on the job alone and downloads the payload outside the workspace. GitHub's guide on workflow_run explains the risk.
The payload carries the --json report with the pull request number, head commit and version the preparing run recorded, and post treats all of it as data. It reads the triggering run from the API, requires it to come from pull_request, and posts only on an open pull request whose head is the commit, repository and branch that run built. It validates the report and renders the review itself, so no review text comes from the payload. A clean report posts nothing, dismisses the earlier change requests and reports skipped-clean.
name: refquiem
on: pull_request
permissions:
contents: read
pull-requests: read
jobs:
refquiem:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- name: Install refquiem from the pinned source
run: cargo install refquiem --git https://github.com/LucaCappelletti94/cargo-refquiem.git --rev 5ac009ab93c17d40d3e72d50fa33415f84c1ce7f --locked
# The pull request's code runs here, so this job only prepares the review.
- uses: LucaCappelletti94/cargo-refquiem@5ac009ab93c17d40d3e72d50fa33415f84c1ce7f
id: refquiem
with:
install: false
pr-number: ${{ github.event.pull_request.number }}
mode: prepare
payload: refquiem-payload
- if: steps.refquiem.outputs.review-status == 'prepared'
uses: actions/upload-artifact@v4
with:
name: refquiem-payload
path: refquiem-payload
retention-days: 1name: refquiem post
on:
workflow_run:
workflows: [refquiem]
types: [completed]
permissions: {}
jobs:
post:
if: github.event.workflow_run.event == 'pull_request'
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
pull-requests: write
steps:
# The base repository's default branch, so the posting code never comes from the pull request.
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: Download the prepared review
id: download
env:
GH_TOKEN: ${{ github.token }}
RUN_ID: ${{ github.event.workflow_run.id }}
run: |
if gh run download "$RUN_ID" --repo "$GITHUB_REPOSITORY" --name refquiem-payload --dir "$RUNNER_TEMP/refquiem-payload"; then
echo "found=true" >> "$GITHUB_OUTPUT"
else
echo "the run prepared no review"
fi
- if: steps.download.outputs.found == 'true'
uses: LucaCappelletti94/cargo-refquiem@5ac009ab93c17d40d3e72d50fa33415f84c1ce7f
id: refquiem
with:
mode: post
payload: ${{ runner.temp }}/refquiem-payloadThe post job needs no Rust toolchain, because post mode skips the install and scan steps. The Dogfood and Dogfood post workflows run this pair on the repository itself.
annotations: true runs the scan with --github, which writes one workflow annotation per finding, one warning per removed dependency it could not resolve, and a ## refquiem job summary. The annotation level is ::error when the run can fail and ::warning when it cannot, as under a review or a dry run. It needs no token and is the findings display for a fork pull request or a read-only token. annotations: false omits it.
dry-run: true renders every comment the action would post, the deleted-line comments included, and the review body into the job summary, and posts, dismisses and closes nothing. A dry run also renders the comments for mentions in files outside the pull request diff, which a real run links from its deleted-line comments or its review body. The two are independent, so a dry run can carry annotations.