Skip to content

Commit fdfeba0

Browse files
PiratesIRCclaude
andcommitted
ci: stop the publish audit failing on pull requests that cannot reach the deny list
The publish audit failed on all five open Dependabot pull requests, and it did so for a reason unrelated to their content. GitHub withholds repository secrets from fork and Dependabot pull requests, so PUBLISH_AUDIT_RULES arrives empty and check_audit_rules.py exits non-zero by design. Measured in the job log: env: PUBLISH_AUDIT_RULES: no publish-audit rules available: PUBLISH_AUDIT_RULES is unset or empty ... ##[error]Process completed with exit code 1. Failing closed is right when the secret ought to be there. On those runs it never can be, so the check reported the absence of a secret every time, forever. A permanently red audit check is worse than no check, because it teaches the maintainer to stop reading a red audit. The audit now skips with a notice, and only when the secret is genuinely empty AND the event is a pull request. The guarantee that matters is unchanged: nothing reaches master unaudited. Merging a pull request produces a push to master, the push trigger always has the secret, and a push that cannot find the deny list still fails hard. A fork's content is not published by opening a pull request, it is published by merging one, and that merge is audited. All five branches of the decision were exercised locally before pushing, under the same shell options a run block uses: secret present + push -> scan runs secret present + pull request -> scan runs secret empty + pull request -> skip with a notice, exit 0 secret empty + push -> exit 1 secret empty + manual dispatch -> exit 1 The decision is a plain if with no pipeline, because `cmd | grep -q` under pipefail reports no match when there is one, and that has silently disabled a security gate in this workspace before. It tests only whether the value is empty and never echoes it, since this repository's Actions logs are public. Also corrected a false statement in the same file's header. It claimed "This repository is PRIVATE today", which stopped being true on 2026-08-25 when the repository went public. That sentence is the reasoning a future reader relies on when judging how much the audit matters. Also raises the pytest-cov floor to 7.1.0, completing the set of Dependabot updates. The other four merged cleanly; that one conflicted because two of the others had already changed the same file. Verified in a throwaway environment that the newest ruff (0.16.6) and pytest (9.1.1) both pass on this code. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017qbBV3zD1wx78Tq68xyZts
1 parent 55e7eaa commit fdfeba0

2 files changed

Lines changed: 49 additions & 8 deletions

File tree

.github/workflows/publish-audit.yml

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,28 @@
1616
# report a clean result it could not compute. A silent pass here would look
1717
# exactly like a genuinely clean tree.
1818
#
19-
# Secrets are not available to a pull request opened from a fork, so that case
20-
# fails rather than passing quietly. This repository has a single maintainer who
21-
# pushes directly, so no real workflow is blocked by it. Revisit if that changes.
19+
# GitHub does not give repository secrets to a pull request opened from a fork,
20+
# nor to one opened by Dependabot, which has its own separate secret store. So
21+
# on those runs the deny list CANNOT be present, and failing there says nothing
22+
# about the code: it reports the absence of a secret, every time, forever.
2223
#
23-
# This repository is PRIVATE today. That is not a reason to skip the scan: a
24-
# repository can be flipped to public in two clicks, a collaborator can be added
25-
# at any time, and the tree is also the source of any release archive. The audit
26-
# is about what the tree WOULD publish, not about who can read it right now.
24+
# That was the behaviour until 2026-09-05 and it was actively harmful. All five
25+
# open Dependabot pull requests carried a red audit check for a reason unrelated
26+
# to their content, which is how a person learns to stop reading a red audit.
27+
# Now such a run SKIPS with a notice instead, and only when the secret is
28+
# genuinely empty AND the event is a pull request.
29+
#
30+
# THE GUARANTEE THAT MATTERS IS UNCHANGED: nothing reaches master unaudited.
31+
# Merging any pull request produces a push to master, and the push trigger below
32+
# always has the secret and still fails hard without it. A fork's content is not
33+
# published by opening a pull request; it is published by merging one, and that
34+
# merge is audited. A push that cannot find the deny list is still an error.
35+
#
36+
# This repository is PUBLIC (since 2026-08-25). It was private when this file
37+
# was written and the comment here still said so, which was wrong for eleven
38+
# days. Being public raises the stakes but does not change the rule: the audit
39+
# is about what the tree WOULD publish, and the tree is also the source of every
40+
# release archive.
2741
#
2842
# The push trigger is load bearing. The maintainer pushes to master directly, so
2943
# a pull-request-only trigger would leave every direct push unaudited. That
@@ -57,8 +71,35 @@ jobs:
5771
with:
5872
python-version: "3.12"
5973

74+
# Deliberately a plain `if`, with no pipeline. `cmd | grep -q PATTERN`
75+
# under `set -o pipefail` reports "no match" when there IS one, because
76+
# grep exits on its first hit and its feeder dies with 141. That has
77+
# already disabled a security gate in this workspace once, and this step
78+
# decides whether a security scan runs at all.
79+
#
80+
# It tests only whether the value is EMPTY. It never echoes it: the deny
81+
# list names the exact strings it exists to keep out, and this
82+
# repository's Actions logs are public.
83+
- name: Decide whether the deny list can be present at all
84+
id: rules
85+
env:
86+
EVENT_NAME: ${{ github.event_name }}
87+
run: |
88+
if [ -n "${PUBLISH_AUDIT_RULES}" ]; then
89+
echo "run_scan=true" >> "$GITHUB_OUTPUT"
90+
echo "The deny list is present. The scan will run."
91+
elif [ "${EVENT_NAME}" = "pull_request" ]; then
92+
echo "run_scan=false" >> "$GITHUB_OUTPUT"
93+
echo "::notice title=Publish audit skipped::No deny list is reachable from this pull request, because GitHub withholds repository secrets from fork and Dependabot pull requests. This says nothing about the changes. The audit runs in full when the change is pushed to master, which is what merging does."
94+
else
95+
echo "No deny list on a ${EVENT_NAME} run. The deny list is the half that catches real leaks in this repository, so an absent one is an error rather than a reason to skip the scan. Set the PUBLISH_AUDIT_RULES repository secret." >&2
96+
exit 1
97+
fi
98+
6099
- name: Check the deny list is present and parses
100+
if: steps.rules.outputs.run_scan == 'true'
61101
run: python .github/scripts/check_audit_rules.py
62102

63103
- name: Scan the tree against the deny list
104+
if: steps.rules.outputs.run_scan == 'true'
64105
run: python .github/scripts/scan_tree.py

requirements-dev.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
pytest>=9.1.1
2-
pytest-cov>=5.0
2+
pytest-cov>=7.1.0
33
ruff>=0.16.5

0 commit comments

Comments
 (0)