Skip to content

ci: main cannot enforce required status checks while owned by a user account #192

Description

@TMHSDigital

Goal

Block a red PR from being merged into main.

The ruleset now on main does not do that. main-integrity (ruleset 23797003, no bypass actors) enforces only:

  • deletion
  • non_fast_forward
  • required_linear_history

Force-push to main is now refused (verified, GH013: ... - Cannot force-push to this branch). But required status checks are not enforced, and a pull request is not required. A PR whose smoke jobs are red can still be merged, and anything holding a repo-scoped token can still fast-forward main directly. Merge-on-green remains convention, not enforcement.

Why required status checks cannot be added today

Required status checks block direct pushes to the branch for any actor without a bypass, not just PR merges. release.yml pushes the version-bump commit to main as github-actions[bot] via secrets.GITHUB_TOKEN. Adding the rule therefore breaks the release.

On a user-owned repository there is no valid bypass actor for GitHub Actions. Attempting to add one is rejected at ruleset creation:

POST /repos/TMHSDigital/Blender-Developer-Tools/rulesets
{"actor_id": 15368, "actor_type": "Integration", "bypass_mode": "always"}

422 Validation Failed
"Actor GitHub Actions integration must be part of the ruleset source or owner organization"

Probe results

Measured on a throwaway branch (protection-probe), with a workflow pushing as github-actions[bot] using GITHUB_TOKEN. Branch and probe rulesets have been torn down.

Configuration Owner direct push github-actions[bot] push
Ruleset: PR + required checks, no bypass REFUSED GH013 REFUSED GH013
Ruleset: PR + required checks, bypass RepositoryRole:Write ALLOWED (Bypassed rule violations) REFUSED GH013
Ruleset: required checks only (no PR rule), no bypass — REFUSED GH013
Classic protection, enforce_admins: false, restrictions: null allowed (admin) REFUSED GH006

Classic-protection probe, verbatim:

remote: error: GH006: Protected branch update failed for refs/heads/protection-probe.
remote:
remote: - Changes must be made through a pull request.
remote:
remote: - Required status check "Validate content counts" is expected.
 ! [remote rejected] HEAD -> protection-probe (protected branch hook declined)

Role-based bypass is backwards for this repo: RepositoryRole:Write covers the owner (admin inherits write) and never covers the bot.

Why an owner PAT is not a fix

Routing the bump push through an owner PAT only works if the owner can bypass — i.e. enforce_admins: false on classic protection, or a role bypass on a ruleset. Either one also permits admin merges of red PRs. This repo's agent sessions merge as the owner, so that is precisely the hole the protection exists to close. A PAT converts the problem into a bypass the day-to-day merge path already uses.

Two paths

No recommendation; both are structural.

1. Transfer the repository to a GitHub organization.
In an org, Integration: github-actions is a legal bypass actor. Required status checks and a PR requirement can then coexist with release.yml untouched: the bot bypasses the rules for its bump push while human merges stay gated. Cost: the repository changes owner.

2. Restructure release.yml so it never pushes to main.
Derive VERSION from the git tag and generate changelog content at build time rather than committing it. With no push to main, no bypass actor is needed and full protection applies to every actor including the owner.

Dependency to resolve first: scripts/site/build_site.py:188 reads the committed CHANGELOG.md (changelog_path = repo_root / "CHANGELOG.md"). Path 2 requires that source to move to generated-at-build-time content, or the landing page loses its changelog section. release-doc-sync@v1 also rewrites CLAUDE.md's **Version:** line and ROADMAP.md's **Current:** line in-tree, and .cursor-plugin/plugin.json carries a committed version field validated by CI — all four are commit-to-main couplings that path 2 has to unwind.

Until one of those lands

Merge-on-green is convention, not enforcement. main is protected against history rewrites and branch deletion only.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    cigithub_actionsPull requests that update GitHub Actions code

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions