Repository navigation
Name Each Job That Posts the Required Check Off a Pull Request Run - #3799
Conversation
check_interface skipped the every-event DRIFT for the whole workflow once any job used the pull_request-only name expression. A second job carrying the literal required name, or an expression falling back to it, still posted the required check on a non-PR run. The check now collects every name a job can post off a pull_request run and raises the DRIFT whenever the required name is among them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Read each job's name with its job key, so the finding names the job that can post the required check off a pull_request run. Word it as a run other than pull_request, which also covers a job whose expression falls back to the required name. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add a case with two literal check-name jobs on a workflow a dispatch also triggers, so collapsing the per-job findings to one fails a test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars.
|
|
A recorded local strict-review pass covers head |
There was a problem hiding this comment.
🟡 Changes recommended
A moderate finding in spec/audit.py shows fallback-only job names bypass the per-job classification and omit the offending job key, leaving the new behavior incomplete.
1 open issue
What changed in this PR
This pull request updates the D1.5 workflow interface audit to evaluate each job’s effective name on runs other than pull_request, preventing one correctly gated job from masking another offending job.
Changes:
- Tracks job names alongside their job keys.
- Reports each offending job with a separate drift finding.
- Adds coverage for literal siblings, fallback expressions, and multiple offending jobs.
- Updates the finding wording to describe non-
pull_requestruns.
| File | Summary | Findings |
|---|---|---|
tests/test_audit_helpers.py |
Adds regression coverage for sibling, fallback, duplicate-name, and job-specific finding scenarios. | Nit: Rename the test at line 663 so its name reflects the non-pull_request behavior rather than “every event.” (1 vote) |
spec/audit.py |
Implements per-job required-check name analysis and reporting. | Moderate/P2: Fallback-only names bypass the per-job path, so findings do not identify the offending job. (2 votes) Nit: Remove the standalone comment near line 994 because it adds a comment-gate obligation without documenting non-obvious rationale. (1 vote) |
Review effort: Lite
The per-job finding sat behind the missing-name branch, so a workflow whose only matching job falls back to the required name off a pull_request run got the generic finding and never the one naming the job. Run the per-job check on its own, beside the missing-name one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## develop #3799 +/- ##
===========================================
+ Coverage 82.71% 82.72% +0.01%
===========================================
Files 29 29
Lines 9626 9629 +3
===========================================
+ Hits 7962 7966 +4
+ Misses 1664 1663 -1
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
An expression yielding the required name on both branches posts it on the pull_request run, so where another event triggers the workflow its job's off-PR finding covers it. Skip the missing-name finding there, which claimed the pull_request run never posts the check. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Literal names cannot reach the suppression, since the missing-name branch already requires the required name not be a literal one. Read the expressions' pull_request strings alone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
A recorded local strict-review pass covers head |
Read the suppression from an expression whose two strings are both the required name, as its comment says, and assert that such a job on a dispatch workflow reports its own off-PR finding, not the generic one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add a case where one job names another check on every event beside a job falling back to the required name, so a suppression reading any every-event expression rather than the required name's fails a test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
A recorded local strict-review pass covers head |
|
Answers to the Copilot round on 01118f0. Its FINDINGS WITH NO THREAD block counted (1), and its overview table names two findings that sit on no thread, so each is answered below.
|
…ings With an Acknowledgment Record, and Mark Direct-Push Closures (#3797) Promotes the changes merged into `develop` since promotion #3778 to `main`, the second round of a backlog burndown. - [#3784](#3784) has the write guard read a push option attached to `-o` as that option's value, as git does, rather than as more short flags. It also walks a short-option cluster carrying a digit, such as `-4f`. - [#3796](#3796) fixes five pull-request-gate and release-task defects: - Each aggregator's `name:` gives the ruleset-bound required check name only on a `pull_request` run, so a dispatch run cannot mask it. `spec/audit.py` `check_interface` reads that expression. - The stubs drop the `pull_request` base-branch filter, and "Adopting the Gates" states the task's preconditions. - A re-run release takes the Latest flag only where its version sorts at or above the current Latest release. - The `lint` job runs its Python steps under the first `python-versions` entry. - `dotnet format` and `dotnet test` run per tracked workspace where the root holds no solution or project. - [#3793](#3793) has `pr_review.py merge` read an acknowledgment record, posted with `comment --ack KEY=OUTCOME`, for findings no thread carries and for a verdict naming no counted finding. Every `merge` run ends on one `next=` line the skills follow, and the digest reads the excluded-files refusal as `refusal=EXCLUDED`. - [#3792](#3792) has a direct push to `develop` on an operational-model repository name the issues it fixes in its commit message's on-promotion line. `backlog-burndown` assembles the promotion body from the pull request that merged each commit, falling back to a direct push's own message. Its claim lookup matches only claim comments, and `git-commit-conventions` names the abandon-discard exception. - [#3798](#3798) has `has_prose` read an inline token's text children outside code, so an inline-code span alone no longer counts as prose. It answers this promotion's first review round. - [#3799](#3799) has `check_interface` read each job by its key on a workflow a non-PR event triggers. A job whose off-PR name is the required check gets its own DRIFT. It answers this promotion's first review round. ## Downstream effect From #3796: once this reaches `main`, every downstream `test-pull-request.yml` whose aggregator carries a literal `name:` shows `check_interface` DRIFT. It shows that until its next resync. A resync clears it by replacing the aggregator's `name:` line with the expression. No ruleset changes, since the `context:` a pull request run posts is unchanged. Fixes #3720 Fixes #3334 Fixes #1516 Fixes #3487 Fixes #1485 Fixes #1938 Fixes #3718 Fixes #3724 Fixes #3777 Fixes #3773 Fixes #1276 Fixes #1307 Fixes #3780 🤖 Generated with [Claude Code](https://claude.com/claude-code)

Summary
In
spec/audit.py,check_interfaceskipped the D1.5 every-event finding for the whole workflow once any one job used the pull_request-only name expression. A second job could still post the required check on a non-PR run, and nothing flagged it.The check now reads each job's
name:together with its job key. A job's name off a pull_request run is its literal name, or the||fallback string when the name uses the pull_request-only expression. Some workflows are triggered by events other thanpull_request. In those, every job whose off-PR name equals the required check gets its own DRIFT, and the finding names that job. The other jobs no longer affect it.The existing missing-name DRIFT keeps its develop behaviour. It covers names that are neither a literal nor the pull_request-only expression, and it still flags an expression whose two branches are both the required name on a pull_request-only workflow. It now runs alongside the per-job check rather than ahead of it.
Repro on a constructed stub triggered by
pull_requestandworkflow_dispatch:Check pull request workflow status job. This returned[]before the change. It now returns one DRIFT naming the second job.${{ github.event_name == 'pull_request' && 'Other job' || 'Check pull request workflow status job' }}. This also returned[]before the change. It now returns one DRIFT naming that job.Unchanged: a gated job alone raises no finding. A literal name on a pull_request-only workflow raises no finding either.
Tests
New
INTERFACE_CASESrows intests/test_audit_helpers.py:Two new tests assert which job each finding names, and that the dispatch every-event case reports its per-job finding rather than the generic one. Run against develop's
spec/audit.py, every new row fails except the dispatch every-event row. That row keeps develop's count, so its message test is what pins it. The last row also fails if the suppression stops checking for the required name.spec/audit.py --selftestand the fullOPERATIONS.md"Local Verification" block pass.Closes on promotion: #3334
🤖 Generated with Claude Code