From 51b68008ee804c8c33605af271c31f9226e6a5b0 Mon Sep 17 00:00:00 2001 From: Joris Wouter Jonkers Date: Thu, 27 Aug 2026 13:13:21 +0200 Subject: [PATCH 1/2] feat(hygiene): schedule the advisory org hygiene sweep from a public runner Actions minutes are billed to the caller, never to the repo holding the reusable workflow. The blocking guard runs in the repo being checked, so each private repo firing it pays for the run -- ~292 minutes a month across fleet-infra and nix-config for a job averaging 6.6 seconds. Standard runners are free in public repositories, and this repo is public. This does not replace repository-hygiene-guard.yml. The guard blocks a merge; this only reports. fleet-infra and nix-config are excluded for now precisely because they still run the blocking guard, so the sweep would otherwise report the same thing twice. Remove a name from that list in the same change that removes its gate. Every 6 hours rather than every 15 minutes: advisory findings gain nothing from a tighter loop, and the sticky PR comment is the real signal. Depends on the sweep added in JorisJonkers-dev/github-workflows#125. Refs #34 Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01AJYmuNrmiYv9wGRABoQYUi --- .github/workflows/org-hygiene-sweep.yml | 49 +++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 .github/workflows/org-hygiene-sweep.yml diff --git a/.github/workflows/org-hygiene-sweep.yml b/.github/workflows/org-hygiene-sweep.yml new file mode 100644 index 0000000..6027073 --- /dev/null +++ b/.github/workflows/org-hygiene-sweep.yml @@ -0,0 +1,49 @@ +# Advisory hygiene sweep over every open pull request in the organization, +# scheduled, from a public repository. +# +# Why here: Actions minutes are billed to the caller, never to the repo +# holding the reusable workflow. The blocking guard runs in the repo being +# checked, so each private repo firing it pays for the run -- ~292 minutes a +# month across fleet-infra and nix-config for a job averaging 6.6 seconds. +# Standard runners are free in public repositories, and this repo is public. +# +# This does NOT replace repository-hygiene-guard.yml. The guard blocks a +# merge; this only reports. Removing a repo's blocking gate is a separate, +# deliberate decision -- see the exclude-repos input below and the tracking +# issue. +name: 'Org Hygiene Sweep' + +'on': + schedule: + # Every 6 hours. Advisory, so there is nothing to gain from reacting + # within minutes; a red sweep and a sticky PR comment are the signal. + - cron: '25 */6 * * *' + workflow_dispatch: + inputs: + comment: + description: 'Post sticky comments on offending pull requests.' + required: false + type: boolean + default: true + +permissions: + contents: 'read' + +concurrency: + group: 'org-hygiene-sweep' + cancel-in-progress: false + +jobs: + sweep: + uses: 'JorisJonkers-dev/github-workflows/.github/workflows/repository-hygiene-sweep.yml@main' + with: + # Repos that still run the blocking guard on every PR. Listing them here + # keeps the sweep from reporting the same thing twice. Remove a name + # from this list in the same change that removes its blocking gate. + exclude-repos: | + fleet-infra + nix-config + comment: "${{ inputs.comment == null && true || inputs.comment }}" + secrets: + HYGIENE_APP_ID: '${{ secrets.RELEASE_APP_ID }}' + HYGIENE_APP_PRIVATE_KEY: '${{ secrets.RELEASE_APP_PRIVATE_KEY }}' From e05dab040d64754b19e3d6360dadc7c62d28f18d Mon Sep 17 00:00:00 2001 From: Joris Wouter Jonkers Date: Thu, 27 Aug 2026 13:15:17 +0200 Subject: [PATCH 2/2] docs(hygiene): correct the claim that the guard blocks merges Repository Hygiene is not a required status check in any repo in this org -- only Pipeline Complete is, and no repo uses classic branch protection. Verified by reading the rulesets directly rather than inferring from the workflow's name. So the guard already only reports, and replacing it with the sweep gives up nothing. The previous comment claimed a blocking gate that does not exist. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01AJYmuNrmiYv9wGRABoQYUi --- .github/workflows/org-hygiene-sweep.yml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/.github/workflows/org-hygiene-sweep.yml b/.github/workflows/org-hygiene-sweep.yml index 6027073..b724d71 100644 --- a/.github/workflows/org-hygiene-sweep.yml +++ b/.github/workflows/org-hygiene-sweep.yml @@ -7,10 +7,11 @@ # month across fleet-infra and nix-config for a job averaging 6.6 seconds. # Standard runners are free in public repositories, and this repo is public. # -# This does NOT replace repository-hygiene-guard.yml. The guard blocks a -# merge; this only reports. Removing a repo's blocking gate is a separate, -# deliberate decision -- see the exclude-repos input below and the tracking -# issue. +# This does NOT replace repository-hygiene-guard.yml, but the difference is +# smaller than it looks: the guard is not a required status check in any repo +# in this org. Only 'Pipeline Complete' is. So the guard already only reports +# -- a hygiene failure has never blocked a merge here. Verified by reading the +# rulesets directly rather than assuming from the workflow's name. name: 'Org Hygiene Sweep' 'on': @@ -37,9 +38,9 @@ jobs: sweep: uses: 'JorisJonkers-dev/github-workflows/.github/workflows/repository-hygiene-sweep.yml@main' with: - # Repos that still run the blocking guard on every PR. Listing them here - # keeps the sweep from reporting the same thing twice. Remove a name - # from this list in the same change that removes its blocking gate. + # Repos that still run the per-PR guard. Listing them here keeps the + # sweep from reporting the same thing twice. Remove a name from this + # list in the same change that removes its per-PR workflow. exclude-repos: | fleet-infra nix-config