Add CI workflow and main-branch ruleset#5
Merged
Conversation
Sets up everything needed to protect main once the repo flips to public. CI workflow (.github/workflows/ci.yml) runs on every PR: - python (3.9-3.12) — verifies cli.py imports + editable install works on every supported Python version. Catches the 3.9 PEP 604 regression the audit pass fixed and any future drift. - version-sync — verifies pyproject.toml, npm/package.json, and src/rpr/__init__.py agree. - json-lint — validates examples/config.json and npm/package.json. - shellcheck — lints install.sh, scripts/bump.sh, and the new setup-branch-protection.sh. - npm-pack — exercises the npm prepack hook to make sure the package still builds. Branch protection (scripts/setup-branch-protection.sh) is an idempotent script that creates or updates a repository ruleset enforcing: - No deletion or force-push to main - Linear history (squash/rebase merges only) - All changes through pull request, conversations resolved - All eight CI checks must pass before merge - Org admins (dedev-llc maintainers) may bypass in an emergency GitHub gates rulesets behind a paid plan for private repos on the free tier — verified by testing both 'gh api branches/main/protection' and 'gh api rulesets', both 403 with 'Upgrade to GitHub Pro'. So the script can't run today; it's staged for the maintainer to invoke once the repo goes public. CONTRIBUTING.md has the one-line instructions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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 free
to 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.
Sets up everything needed to harden
mainfor the eventual public flip. Two pieces:.github/workflows/ci.yml— runs on every PR tomain. Becomes active immediately on merge.scripts/setup-branch-protection.sh— idempotent script that creates/updates a repository ruleset. Cannot run yet — see "Why not now" below — but the file is staged so it's a one-line invocation the moment you flip the repo to public.What the CI workflow checks (8 jobs)
python (3.9)/(3.10)/(3.11)/(3.12)— runspython src/rpr/cli.py --help, then does an editable install and exercisesimport rpr,rpr --help, andpython -m rpr --help. Specifically catches the PEP 604 regression we fixed in Audit fixes: Python 3.9 compat, version sync, doc cleanup #4 and any future Python-version drift.version-sync— verifiespyproject.toml,npm/package.json, andsrc/rpr/__init__.pyall report the same version. Same logic as the release workflow's preflight check, but runs on PRs so drift is caught before merge instead of at release time.json-lint—json.load()onexamples/config.jsonandnpm/package.json.shellcheck— lintsinstall.sh,scripts/bump.sh, andscripts/setup-branch-protection.sh.npm-pack— runsnpm pack --dry-runfromnpm/, exercising theprepackhook so a brokencopy-python.jsorpackage.jsonis caught before release time.concurrency: ci-${{ github.ref }}cancels in-progress runs when you push new commits to a branch — saves runner minutes.What the ruleset enforces (when applied)
Defined in
scripts/setup-branch-protection.shand applied viagh api -X POST /repos/dedev-llc/rpr/rulesets:mainnon_fast_forward)mainare blockedci.ymlexactly — if you rename a job, update both)OrganizationAdminactor,bypass_mode: always) — escape hatch for emergency hotfixes. Setbypass_mode: pull_requestlater if you want admins to still go through PRs but skip the checks.required_approving_review_count: 0because you're a solo maintainer and can't approve your own PRs. The PR-required-ness is what enforces the workflow; the 0 just lets you self-merge.Why we can't apply the ruleset right now
I tried both legacy branch protection and rulesets via the API:
GitHub gates both systems behind a paid plan (Pro / Team / Enterprise) for private repos. Public repos get them free. Since you've said the repo is going public eventually, the cleanest path is: stage everything now, run the script the moment you flip to public.
Going-public checklist
When you're ready to flip the switch:
The script is idempotent — if a ruleset named
main-protectionalready exists it'll update it in place rather than create a duplicate. So if you later add or remove CI jobs, just update theREQUIRED_CHECKSarray at the top of the script and re-run it.Test plan
bash -n scripts/setup-branch-protection.sh— syntax validchmod +xon the new script committed via git index (mode 100755 confirmed)ci.yml— all 8 jobs present, top-level keys correctCONTEXTS)scripts/setup-branch-protection.shand verify the ruleset shows up at https://github.com/dedev-llc/rpr/rulesThings to know about the protection model
refs/tags/v0.1.x), not branches. Tags aren't covered by branch rulesets, sotag-and-releaseis unaffected.required_approving_review_countis0. The PR requirement is purely about routing changes through CI, not about getting a second human reviewer (which doesn't exist yet).enforce_admins-equivalent: rulesets usebypass_actorsinstead. Currently set to allow any org admin to bypass any rule. If you want stricter enforcement (e.g. force yourself through PRs too), set thebypass_actorsarray to[]in the script and re-run.Notes on the python matrix
CI runs Python 3.9 through 3.12 to match the classifiers in
pyproject.toml. Python 3.13 isn't included because the project doesn't claim to support it yet — if you bump the floor or add 3.13 support, update bothpyproject.tomlclassifiers AND the matrix inci.yml.🤖 Generated with Claude Code