Skip to content

fix(policy): make runner enforcement actually cover the organization - #2

Merged
thedancingdeveloper merged 3 commits into
mainfrom
fix/self-hosted-runner-policy
Aug 3, 2026
Merged

fix(policy): make runner enforcement actually cover the organization#2
thedancingdeveloper merged 3 commits into
mainfrom
fix/self-hosted-runner-policy

Conversation

@thedancingdeveloper

Copy link
Copy Markdown
Contributor

audit.yml was named "Organization workflow policy audit" but checks out only
this repository and runs the checker against .. It therefore audited exactly
one repository — itself. Its own workflows are compliant, so it reported green
every day while NGMS, agent-harness and nntp-client-bench ran CI on
ubuntu-latest. The checker was never wrong; it was never pointed at the org.

Add enforce-runner-policy.yml, designed to be attached to every repository via
an organization ruleset so it runs in each target repository's context. This
needs no cross-repository token, which is why per-repo enforcement is the right
mechanism here — the org has no Actions secrets at all.

It fetches the checker over HTTPS rather than checking this repo out into the
workspace, so the policy repo's own workflows are not conflated with the target
tree.

Rename audit.yml to "Policy repository self-audit" so its scope is not
overstated again, and document both workflows in the README.

Co-Authored-By: Claude Opus 5 (1M context) noreply@anthropic.com

🤖 Generated with Claude Code

thedancingdeveloper and others added 3 commits August 3, 2026 00:41
audit.yml was named "Organization workflow policy audit" but checks out only
this repository and runs the checker against `.`. It therefore audited exactly
one repository — itself. Its own workflows are compliant, so it reported green
every day while NGMS, agent-harness and nntp-client-bench ran CI on
ubuntu-latest. The checker was never wrong; it was never pointed at the org.

Add enforce-runner-policy.yml, designed to be attached to every repository via
an organization ruleset so it runs in each target repository's context. This
needs no cross-repository token, which is why per-repo enforcement is the right
mechanism here — the org has no Actions secrets at all.

It fetches the checker over HTTPS rather than checking this repo out into the
workspace, so the policy repo's own workflows are not conflated with the target
tree.

Rename audit.yml to "Policy repository self-audit" so its scope is not
overstated again, and document both workflows in the README.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The first version of the gate fetched scripts/audit-workflows.sh over HTTPS.
That cannot work: this repository is private, so raw.githubusercontent.com
returns 404 unauthenticated and the target repository's GITHUB_TOKEN has no
read access here either. It failed on its own pull request with curl (22) 404.

Inline the checker into enforce-runner-policy.yml. The ruleset already delivers
that file from this repository, so there is still a single source of truth.
scripts/audit-workflows.sh stays as the local checker for audit.yml; the two
must be kept in sync.

The inlined gate reads no exceptions file because it cannot see one, so it is
strict. Owner-approved exceptions are expressed in the ruleset conditions or
bypass actors, which is a more auditable record than a JSON entry anyway.

Verified locally against a compliant tree (passes, 2 files) and a deliberately
violating tree (rejects ubuntu-latest and dynamic runs-on).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The dynamic-runner rule needs to look for a literal GitHub Actions expression
delimiter. Writing it literally inside the run block meant Actions tried to
evaluate it while parsing the workflow, so the file never became a valid
workflow at all -- the run showed up under its raw filename with no resolvable
name and failed before executing a step.

Assemble the delimiter at runtime instead. Verified the workflow now parses and
that the dynamic-runner rule still fires against a violating tree.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@thedancingdeveloper
thedancingdeveloper merged commit a3ad009 into main Aug 3, 2026
2 checks passed
@thedancingdeveloper
thedancingdeveloper deleted the fix/self-hosted-runner-policy branch August 3, 2026 00:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant