Ship branch rulesets as versioned JSON in the re-sync / drift loop - #212
Merged
Conversation
Closes the gap from #211: branch rulesets were live GitHub config applied once at repo creation, so they sat outside the file-based re-sync loop - a corrected template ruleset never propagated to derived repos, and downstream drift was invisible (PlexCleaner's docs said strict=false while live config stayed strict=true on both branches). - Commit the canonical writable subset as .github/rulesets/{develop,main}.json (strict_required_status_checks_policy false on both - the #82 value this exists to keep propagated). They port verbatim: conditions key on refs/heads/{develop,main}, bypass_actors uses global Admin role actor_id 5, the required check binds by name. - README "Rules / Rulesets": repoint the source of truth to the committed files - import from them at setup; the live export becomes the regenerate recipe run when the maintainer changes the template's live rulesets. - AGENTS.md: add the rulesets to the verbatim-carry set and document the live-vs-committed drift check (full-payload PUT to correct) in Staying in Sync. Note that carrying the file only syncs the source of truth; live config changes only on import/PUT. Also folds in pending spell-dictionary / workspace-extension additions and three deferred-item bullets that were already staged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR brings branch rulesets into the repo-based re-sync/drift workflow by committing canonical develop/main ruleset JSON and updating documentation to treat those files as the versioned source of truth, plus minor editor/workspace hygiene updates.
Changes:
- Add committed GitHub ruleset definitions for
developandmainunder.github/rulesets/. - Update
README.mdandAGENTS.mdto import/sync rulesets from committed JSON and document how to detect/correct drift against live GitHub config. - Reformat and extend
ProjectTemplate.code-workspace(spellings + recommended extensions).
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| README.md | Updates ruleset setup docs to import from committed JSON; adds deferred-pattern notes. |
| ProjectTemplate.code-workspace | Normalizes formatting; adds cSpell words and extension recommendations. |
| AGENTS.md | Adds ruleset JSON to verbatim-carry list and documents drift-check procedure. |
| .github/rulesets/main.json | Introduces canonical main branch ruleset JSON (importable subset). |
| .github/rulesets/develop.json | Introduces canonical develop branch ruleset JSON (importable subset). |
Uh oh!
There was an error while loading. Please reload this page.
GitHub returns a ruleset's rules[] (and bypass_actors[]) in arbitrary order, so the plain diff false-positived on a reordered-but-equivalent ruleset (PlexCleaner's develop/main read as DRIFT when only the rule order differed). Sort both arrays before diffing so only real differences surface. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The versioned rulesets are live GitHub config, not a file a derived repo consumes, so copying them into every downstream repo only adds noise and divergence. Drop them from the verbatim-carry set; document that they live only in the template as the source of truth and ride the re-sync loop from the hub - diffing each derived repo's live config against the template's committed JSON and correcting drift via full-payload PUT. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Two of the pre-staged Deferred Patterns are no longer deferred: - "Factor cleanup-artifacts into a reusable workflow" is moot - #214 removes the blanket cleanup job entirely (surgical consume-then-delete instead), so there is nothing left to factor. - "Generalize the input-validation step into a reusable pattern" is realized - #213 codifies the validate-input/state-at-entry pattern in AGENTS.md. Keep the publish-docker-readme "Validate inputs step" downstream-resync entry; that concrete downstream action is still pending. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Reword "never copied into derived repos" (README + AGENTS.md): the JSON is maintained in the template as the source of truth and reconciled against a repo's live config; it is not carried/re-synced as a per-repo copy. Avoids the inaccurate absolute (a template-instantiated repo does receive the files). - Mirror the two new general extensions (actionlint, shellcheck) into both devcontainers and fix the stale `*.code-workspace` reference (the per-language workspaces were consolidated into ProjectTemplate.code-workspace in #210). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
| "customizations": { | ||
| "vscode": { | ||
| // Mirror of `recommendations` in Python.code-workspace. | ||
| // Mirror of `recommendations` in ProjectTemplate.code-workspace. |
| "customizations": { | ||
| "vscode": { | ||
| // Mirror of `recommendations` in DotNet.code-workspace. | ||
| // Mirror of `recommendations` in ProjectTemplate.code-workspace. |
Comment on lines
+285
to
+286
| The branch rulesets ([`.github/rulesets/{develop,main}.json`](./.github/rulesets/)) are deliberately **not** in this carry set: they are live GitHub config, not a file a derived repo consumes, so carrying and re-syncing them downstream only adds noise. They are maintained **in this template** as the source of truth and are reconciled against each repo's *live* config during porting/re-sync - see [Staying in Sync](#staying-in-sync-and-reporting-drift-upstream). | ||
Comment on lines
504
to
+508
| for name in develop main; do | ||
| id=$(gh api repos/ptr727/ProjectTemplate/rulesets --jq ".[] | select(.name==\"$name\") | .id") | ||
| gh api "repos/ptr727/ProjectTemplate/rulesets/$id" \ | ||
| --jq '{name, target, enforcement, bypass_actors, conditions, rules}' > "$name-ruleset.json" | ||
| --jq '{name, target, enforcement, bypass_actors, conditions, rules}' \ | ||
| | jq -S '.' > ".github/rulesets/$name.json" |
This was referenced Jun 26, 2026
ptr727 added a commit
that referenced
this pull request
Jul 4, 2026
Promote the accumulated `develop` work to `main`. Twelve changes since the last promotion: - Add `WORKFLOW.md`: workflow style, architecture, behavioral contract, test methodology (#223) - Use NBGV `IGNORE_GITHUB_REF` instead of the ineffective `GITHUB_REF` override (#222) - Skip validate-release on smoke builds (#220) - Gate asset delete on the release create/refresh condition (#218) - Ship branch rulesets as versioned JSON in the re-sync / drift loop (#212) - Clean up transfer artifacts surgically at consumption, not blanket-delete (#216) - Version each publish leg against its own branch; validate at entry (#215) - Consolidate workspace configurations into a unified ProjectTemplate workspace (#210) - Template convergence barrier: absorb pins, generic release + docker-readme, carry-whole-file (#207) - Key merge-bot concurrency on PR number, not `github.ref` (#206) - Codify orchestrated re-sync personas and full-replacement rule (#205) - Lead action pins; affirm pattern-based artifact handoff (#204) 🤖 Generated with [Claude Code](https://claude.com/claude-code)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Closes#211. Branch rulesets are live GitHub config applied once at repo creation, so they sit outside the file-based re-sync loop (AGENTS.md "Staying in Sync"). Two consequences: a corrected template ruleset never propagates to existing derived repos, and downstream ruleset drift is invisible. This bit
ptr727/PlexCleaner— its synced docs saidstrict=falsewhile its live rulesets stayedstrict=trueon bothdevelopandmain(the exact #82 failure mode), fixed locally only after it broke auto-merge and blocked a promotion.Change
.github/rulesets/develop.jsonand.github/rulesets/main.jsonhold the re-importable writable subset ({name, target, enforcement, bypass_actors, conditions, rules}),strict_required_status_checks_policy: falseon both. They port verbatim with no placeholders —conditionskey onrefs/heads/{develop,main},bypass_actorsuses the global Admin roleactor_id: 5, the required check binds by name.rules[]/bypass_actors[]order so a reordered-but-equivalent ruleset doesn't read as drift.Verification
jq -Sround-trip stable for both files; order-normalized drift diff against the template's own live rulesets reportsdevelop: in sync/main: in sync.Utilitieshas real live drift,homeassistant-purpleairhas no rulesets configured — both surfaced to the maintainer (issues filed), not auto-applied.🤖 Generated with Claude Code