Skip to content

feat(rulesets): reverse-engineer org branch protection + add review gate, conventional commits#4

Merged
JacobPEvans-personal merged 1 commit into
mainfrom
feat/reverse-engineer-org-policy
May 31, 2026
Merged

feat(rulesets): reverse-engineer org branch protection + add review gate, conventional commits#4
JacobPEvans-personal merged 1 commit into
mainfrom
feat/reverse-engineer-org-policy

Conversation

@JacobPEvans-personal
Copy link
Copy Markdown
Member

Summary

Codifies the pre-Terraform live state of the org-level rulesets and applies the directives from PR #2 / #3 review feedback. Single PR because the import blocks must land together with the new resources to avoid duplicate ruleset creation on next apply.

What lands

New rulesets:

Resource Behavior
org_branch_protection Non-bypassable quality gate. required_linear_history, required_signatures, branch name pattern, strict Conventional Commits regex, PR thread resolution. No bypass — applies to every actor including OrganizationAdmins.
org_review_gate Separate ruleset for the review gate so the admin bypass doesn't weaken the quality gates above. 1 approving review + CODEOWNER review on PRs. OrganizationAdmin bypass in pull_request mode — any admin merges their own PRs without external review; non-admin actors must obtain it.

Existing ruleset reconciled:

  • markdown_lint updated to match live state for clean import — ref_name = ~ALL (was ~DEFAULT_BRANCH), do_not_enforce_on_create = true. Default enforcement stays evaluate (legacy); live is currently disabled so apply moves it disabled → evaluate. Pass -var markdown_lint_enforcement=active to flip on.

Import blocks:

```hcl
import { to = github_organization_ruleset.org_branch_protection
id = "15555419" } # was "main"
import { to = github_organization_ruleset.markdown_lint
id = "17062292" } # was "Required Workflows - All Branches"
```

Directive answers

Q Answer Implementation
1 1 reviewer unless author == operator OrganizationAdmin bypass on org_review_gate.pull_request (closest GitHub supports — rulesets have no per-author conditional rules)
2 CODEOWNERS only on critical files Deferred to follow-up PR — see "CODEOWNERS deliberately not in this PR" below
3 Conversation resolution required everywhere required_review_thread_resolution = true in both rulesets
4 Signed commits required + flag unverified required_signatures = true in org_branch_protection, no bypass
5 Strict Conventional Commits commit_message_pattern block with regex ^(build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test)(\([a-z0-9\\-]+\))?(!)?: .+\$
6 Linear history always required_linear_history = true in org_branch_protection, no bypass

CODEOWNERS deliberately not in this PR

An earlier commit attempt added .github/CODEOWNERS with an owner login baked in. That violates the no-identities-in-code rule the PR also codifies in AGENTS.md. CODEOWNERS files for every dryvist repo (this one included) land in a follow-up PR via github_repository_file with the owner identity supplied as a Terraform variable — the repo source tree stays identity-free.

Conventions added to AGENTS.md

  • No identities anywhere except providers.tf owner — no usernames, account logins, email addresses, or person-tied identifiers in any source file. CODEOWNERS materialized at apply time from a variable.
  • Cost policy — never apply a policy or enable a feature that costs money unless the PR body declares the cost and the operator approves it. Includes a free / GHAS-gated / metered / subscription matrix as of 2026-05 with sources:
  • Per-PR "Cost impact" checklist for any change touching Actions, GHAS, Codespaces, Copilot, or org/repo settings affecting those

Cost impact

Free. All ruleset rules are native GitHub features at zero cost on any plan. The markdown_lint workflow runs on Actions; public repos are unlimited free, private repos count against the Team-plan free tier (3000 min/month GitHub-hosted; $0.002/min self-hosted on private as of 2026-03-01). No GHAS feature flipped on by this PR.

Apply (requires gh-claude-org-admin)

```bash
gh-claude-org-admin
tofu init -backend-config=...
tofu apply
```

Apply will:

  1. Adopt rulesets 15555419 + 17062292 into Terraform state
  2. Rename them to org-branch-protection / org-markdown-lint
  3. Add commit_message_pattern rule to the imported branch-protection ruleset
  4. Create new org-review-gate ruleset
  5. Move markdown_lint enforcement from disabledevaluate

Test plan

  • `tofu init -backend=false && tofu validate` — green
  • `pre-commit run --all-files` — green
  • Commit GPG-signed
  • All identities purged from source tree (verified via grep)
  • Apply with `gh-claude-org-admin` and confirm imports succeed without resource churn
  • Sacrificial test: push commit with non-Conventional message on a throwaway branch → rejected
  • Sacrificial test: open PR from a bot account → 1 reviewer required
  • Sacrificial test: open PR from operator account → can self-merge after thread resolution

…ate, conventional commits

Codifies the pre-Terraform live state of the org-level rulesets and applies
the directives from #2/#3 review. Single PR because the imports must land
together with the new resources to avoid duplicate ruleset creation on
next apply.

New rulesets
------------
- `github_organization_ruleset.org_branch_protection` — non-bypassable
  quality gate on every default branch. Reverse-engineered from the
  pre-Terraform "main" org ruleset (id 15555419) and extended with strict
  Conventional Commits enforcement. Rules:
    - required_linear_history = true
    - required_signatures     = true
    - branch_name_pattern     = starts_with (main|develop|feat|fix|hotfix|release|chore)
    - commit_message_pattern  = regex enforcing Conventional Commits v1.0.0
    - pull_request            = thread resolution required, 0 approvers
                                (the approver requirement lives in
                                org_review_gate with admin bypass)
  No bypass_actors: signed commits, linear history, and Conventional
  Commits apply to every actor including OrganizationAdmins.

- `github_organization_ruleset.org_review_gate` — separate ruleset so the
  admin bypass below doesn't accidentally weaken the quality gates above.
  Rules:
    - pull_request { required_approving_review_count = 1,
                     require_code_owner_review = true,
                     required_review_thread_resolution = true,
                     allowed_merge_methods = [squash, rebase] }
  bypass_actors: OrganizationAdmin (actor_id=1, the API constant) in
  pull_request mode. Any OrganizationAdmin merges their own PRs without
  external review; non-admin actors must obtain the review.

  GitHub rulesets do not support per-author conditional rules. The closest
  approximation — "everyone but an admin needs a reviewer" — is
  implemented via OrganizationAdmin bypass. Granting a new account the
  OrganizationAdmin role extends this bypass to them.

Existing ruleset reconciled
---------------------------
- `github_organization_ruleset.markdown_lint` updated to match live state
  for clean import: ref_name = ~ALL (was ~DEFAULT_BRANCH),
  do_not_enforce_on_create = true. Default enforcement stays "evaluate"
  (legacy default); pass `-var markdown_lint_enforcement=active` to flip
  on. Live is currently "disabled" — apply moves it to "evaluate".

Import blocks
-------------
Declared in rulesets.tf so `tofu apply` adopts pre-Terraform state in the
same run that adds the new resources:

  import { to = github_organization_ruleset.org_branch_protection
           id = "15555419" }
  import { to = github_organization_ruleset.markdown_lint
           id = "17062292" }

org_review_gate is new (no existing live ruleset), so no import needed.

Config — no magic numbers
-------------------------
- config/rulesets-defaults.yml gains a `branch_protection` block with the
  branch name pattern, the Conventional Commits regex, and the allowed
  merge methods. Patterns are tunable here without editing .tf.
- locals.tf decodes the full config file once and exposes per-section
  locals (push_protection_defaults, branch_protection_defaults).

Conventions — identities out of source tree
-------------------------------------------
- AGENTS.md adds a "No identities anywhere except providers.tf owner"
  rule. No usernames, account logins, or person-tied identifiers in .tf
  resource bodies, comments, variable descriptions, config/*.yml, or
  CODEOWNERS-style files committed in this repo. CODEOWNERS for managed
  repos materializes at apply time from a Terraform variable.
- The `.github/CODEOWNERS` file that an earlier commit attempt added is
  intentionally NOT in this PR — it would have hardcoded an owner login.
  CODEOWNERS for this repo and all dryvist repos lands in a follow-up PR
  via `github_repository_file` with the owner identity as a `-var` input.

Conventions — cost policy
-------------------------
- AGENTS.md adds a "Cost policy" section documenting GitHub's pricing
  model and the rule "never apply a policy or enable a feature that
  costs money unless the PR body declares the cost and the operator
  approves it." Includes a matrix of free / GHAS-gated / metered /
  subscription features as of 2026-05, with sources, and a per-PR
  cost-impact checklist for any change that touches Actions, GHAS,
  Codespaces, Copilot, or org/repo settings affecting those.

Variables
---------
- New: org_branch_protection_enforcement (default "active")
- New: org_review_gate_enforcement (default "active")

Apply
-----
Requires the ORG_ADMIN token tier (gh-claude-org-admin). Apply will:
  1. Adopt rulesets 15555419 and 17062292 into Terraform state
  2. Rename the imported rulesets to org-branch-protection /
     org-markdown-lint
  3. Add commit_message_pattern rule to the imported branch-protection
     ruleset
  4. Create new org-review-gate ruleset
  5. Move markdown_lint enforcement from disabled -> evaluate

Cost impact
-----------
Free — all ruleset rules are native GitHub features at zero cost on any
plan. The markdown_lint workflow runs on Actions; public repos are free,
private repos count against the Team-plan free-tier minutes (3000/month
GitHub-hosted, $0.002/min self-hosted as of 2026-03-01). No GHAS feature
flipped on by this PR.

Verification
------------
- tofu init -backend=false and tofu validate -> green
- pre-commit run --all-files -> all hooks pass

Assisted-by: Claude <noreply@anthropic.com>
@JacobPEvans-personal JacobPEvans-personal merged commit 3612969 into main May 31, 2026
3 checks passed
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