Skip to content

feat(tofu): drop gate from required checks (ADR-0001 step 3, closes #35) - #65

Merged
millsmillsymills merged 2 commits into
mainfrom
chore/gate-verified-step-3-drop-gate
Jun 12, 2026
Merged

feat(tofu): drop gate from required checks (ADR-0001 step 3, closes #35)#65
millsmillsymills merged 2 commits into
mainfrom
chore/gate-verified-step-3-drop-gate

Conversation

@millsmillsymills

Copy link
Copy Markdown
Contributor

⚠️ DO NOT MERGE BEFORE 2026-05-22

This PR is held in draft pending the ADR-0001 step 2 observation window (PR #52 merged 2026-05-15; one full week → ≥2026-05-22). When the window closes cleanly, mark this ready and merge.

Summary

Removes `required_check { context = "gate" }` from `github_repository_ruleset.management_repo_checks` in `repos_meta.tf`. `gate-verified` becomes the sole required check sourced from the `tofu` workflow path.

The in-workflow `gate` job stays in `tofu-plan.yml` because `gate-verified` check 1 reads its conclusion via `select(.name == "gate") | .conclusion`. This PR only changes whether `gate` itself is required at the ruleset level.

Why this is safe

`gate-verified` (with the post-#62 two-check shape) subsumes every case the standalone `gate` required check caught:

Bypass attempt `gate` alone `gate-verified` (after step 3)
PR removes `gate` job missing required check → blocked check 1: `select... empty → "missing"` → fail → blocked
PR renames `gate` missing required check → blocked check 1: same outcome → blocked
PR makes `gate` skip/cancel/fail depends on skipped-as-success semantics; `if: always()` closed that locally check 1: `conclusion != "success"` → fail → blocked
PR keeps `gate` but stubs body to `exit 0` bypass (gate posts success) check 2: `tofu-plan.yml` blob differs from main + no `workflow-update` label → fail → blocked
PR keeps `gate` stub + applies `workflow-update` label bypass accepted as documented residual; bounded by maintainer judgment

ADR-0001 Rollout status step 3 line: "Drop is safe because everything `gate` catches on its own (failure or non-skip non-success) is already caught by `gate-verified`'s `conclusion == "success"` assertion." Plus check 2 now covers the stub-with-success residual originally noted there.

What the inline comment now describes

The comment block above the `required_check` list is rewritten to describe gate-verified's two checks + the role of the in-workflow `gate` job (still load-bearing as the source signal). Reads top-to-bottom for a new contributor.

Test plan

Pre-merge

  • Calendar gate: ≥2026-05-22.
  • Step-2 observation window (since 2026-05-15) closed cleanly — no false-positive `gate-verified` failures observed.
  • Rebase onto `main` if any conflicting changes land in between.
  • `tofu fmt` clean, `tofu validate` clean, `tflint` clean.
  • CI `gate` + `gate-verified` both succeed on this PR (gate-verified additive still in force until this merges; both must still pass before then).

Post-merge

  • `tofu-apply` workflow on the merge commit completes successfully.
  • Subsequent normal PRs (e.g., the next docs/feature PR) show `gate` as a check still posting (because the job still runs in tofu-plan.yml) but NOT as a required check; only `gate-verified` blocks merge.
  • No regression observed in nightly `tofu-drift` for one week post-merge.

Adversarial (optional, separate canary)

The acceptance criteria in #35 mentions an adversarial test where a PR renames the `gate` job and gate-verified blocks the merge. Canary #57 already empirically verified the deletion case (`mergeStateStatus: BLOCKED`, both required checks absent). Rename is functionally identical from gate-verified's perspective (`select(.name == "gate") | empty → "missing"`); a fresh rename canary is redundant but can be done if extra confidence is wanted.

Closes #35.

🤖 Generated with Claude Code

DO NOT MERGE BEFORE 2026-05-22. Held draft PR per ADR-0001 *Rollout
status* step 3: drop `gate` from the management-repo
required-status-check set once the one-week observation window for
the additive step 2 (PR #52, merged 2026-05-15) passes cleanly.

`gate-verified` (with the post-#62 two-check shape: gate-conclusion +
workflow-content blob-compare + label exception) subsumes every case
the standalone `gate` required check caught:

- PR removes `gate` job from tofu-plan.yml — gate-verified check 1
  sees no `gate` in jobs list, reports `failure`.
- PR renames the `gate` job — same: no match, `failure`.
- PR makes `gate` skip/cancel/fail — gate-verified check 1's
  `conclusion == "success"` assertion fails.
- PR keeps `gate` but stubs its body to `exit 0` — gate-verified
  check 2 detects the tofu-plan.yml modification; without the
  `workflow-update` label, fails. With the label, intentional
  maintainer exception (residual bounded).

In-workflow `gate` job stays in tofu-plan.yml because gate-verified
check 1 reads its conclusion. Only its required-check status at the
ruleset level changes.

Inline comment block above the `required_check` list rewritten to
describe gate-verified's two-check behavior and the role of the
in-workflow `gate` job post-step-3.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented May 16, 2026

Copy link
Copy Markdown

module.ruleset_tag_protection.github_organization_ruleset.tag_protection: Refreshing state... [id=16260826]
module.org_profile_repo.github_repository.this: Refreshing state... [id=.github]
module.existing["unraid-mcp"].github_repository.this: Refreshing state... [id=unraid-mcp]
module.existing["protonmail-mcp"].github_repository.this: Refreshing state... [id=protonmail-mcp]
module.existing["unifi-mcp"].github_repository.this: Refreshing state... [id=unifi-mcp]
module.ruleset_default_branch.github_organization_ruleset.default_branch: Refreshing state... [id=16259943]
module.existing["shortcut-mcp"].github_repository.this: Refreshing state... [id=shortcut-mcp]
module.org_baseline.github_organization_settings.this: Refreshing state... [id=283017149]
module.existing["gandi-mcp"].github_repository.this: Refreshing state... [id=gandi-mcp]
module.management_repo.github_repository.this: Refreshing state... [id=millsymills-com-org]
module.existing["flipperzero-mcp"].github_repository.this: Refreshing state... [id=flipperzero-mcp]
module.org_profile_repo.github_repository_vulnerability_alerts.this: Refreshing state... [id=1259819149]
module.management_repo.github_repository_vulnerability_alerts.this: Refreshing state... [id=1234310882]
github_repository_environment.tofu_apply: Refreshing state... [id=millsymills-com-org:tofu-apply]
github_repository_environment.tofu_drift: Refreshing state... [id=millsymills-com-org:tofu-drift]
github_repository_environment.tofu_plan: Refreshing state... [id=millsymills-com-org:tofu-plan]
github_repository_ruleset.management_repo_checks: Refreshing state... [id=16278826]
module.existing["gandi-mcp"].github_repository_vulnerability_alerts.this: Refreshing state... [id=1215582042]
module.existing["flipperzero-mcp"].github_repository_vulnerability_alerts.this: Refreshing state... [id=1253783165]
module.existing["unraid-mcp"].github_repository_vulnerability_alerts.this: Refreshing state... [id=1212016738]
module.existing["shortcut-mcp"].github_repository_vulnerability_alerts.this: Refreshing state... [id=1247298585]
module.existing["unifi-mcp"].github_repository_vulnerability_alerts.this: Refreshing state... [id=1212016554]
module.existing["protonmail-mcp"].github_repository_vulnerability_alerts.this: Refreshing state... [id=1221429298]
github_repository_environment_deployment_policy.tofu_drift_main: Refreshing state... [id=millsymills-com-org:tofu-drift:49164603]
github_repository_environment_deployment_policy.tofu_apply_main: Refreshing state... [id=millsymills-com-org:tofu-apply:49164604]

OpenTofu used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
~ update in-place

OpenTofu will perform the following actions:

github_repository_ruleset.management_repo_checks will be updated in-place

~ resource "github_repository_ruleset" "management_repo_checks" {
id = "16278826"
name = "management-repo-checks"
# (6 unchanged attributes hidden)

  ~ rules {
        # (7 unchanged attributes hidden)

      ~ required_status_checks {
            # (2 unchanged attributes hidden)

          - required_check {
              - context        = "gate" -> null
              - integration_id = 0 -> null
            }

            # (5 unchanged blocks hidden)
        }
    }

    # (1 unchanged block hidden)
}

Plan: 0 to add, 1 to change, 0 to destroy.

─────────────────────────────────────────────────────────────────────────────

Note: You didn't use the -out option to save this plan, so OpenTofu can't
guarantee to take exactly these actions if you run "tofu apply" now.

@millsmillsymills

Copy link
Copy Markdown
Contributor Author

Observation-window attribution complete (2026-05-19)

The "Step-2 observation window … closed cleanly" checkbox can be honestly evaluated. Per #66 attribution (now closed):

Net: zero false positives, zero false negatives. ADR-0001 step 2's acceptance criterion is satisfied.

Remaining pre-merge work for this PR: keep observing through 2026-05-22 (calendar gate), rebase if anything lands, then promote out of draft + merge.

@millsmillsymills
millsmillsymills marked this pull request as ready for review June 5, 2026 00:47
@millsmillsymills

Copy link
Copy Markdown
Contributor Author

Review summary (/review-pr + adversarial review)

Verdict: SAFE-TO-MERGE. Preconditions met, both operational blockers cleared.

Security claim — could not be refuted

Dropping gate as a required check loses nothing: every class standalone gate blocked (rename / delete / skip / cancel / fail) flips gate-verified check 1 (conclusion != success), and the stub-with-success case gate never covered is caught by gate-verified check 2 (tofu-plan.yml blob ≠ main + no workflow-update label). No merge path exists that gate blocked and sole-gate-verified admits. The workflow-update-labeled stub residual is unchanged by this PR (pre-existing, documented in ADR-0001).

Preconditions

  • Calendar gate ≥2026-05-22 — today is 2026-06-04. ✓
  • Observation window clean: the 7 gate-verified failures in the window (05-19→06-02) were all event=workflow_run on dependabot tofu-plan runs whose head bumps tofu-plan.yml (check 2 firing correctly), not internal-PR gating false-positives. tofu-apply/tofu-drift carry distinct workflow names so they can't even trigger gate-verified. ✓

Blockers cleared

No code defect. Adversarial review performed by an independent agent (Codex quota was exhausted; ran on Opus instead).

@millsmillsymills
millsmillsymills merged commit e619e9a into main Jun 12, 2026
9 checks passed
@millsmillsymills
millsmillsymills deleted the chore/gate-verified-step-3-drop-gate branch June 12, 2026 02:12
millsmillsymills added a commit that referenced this pull request Aug 21, 2026
ADR-0007 generalized unifi-mcp's six required checks to all six org
repos. Measured per repo instead: only unifi-mcp and unraid-mcp have
that set, gandi-mcp and flipperzero-mcp and shortcut-mcp each have their
own, protonmail-mcp gates on a single `test`, and `.github` has none at
all. Since automerge inherits whatever gate a repo has, the ADR now
carries the real table and names which repos are eligible.

`.github` gets its own consequence: it has no required check and now has
the auto-merge capability, and it holds the preset every other repo
extends.

CLAUDE.md still described `gate` as a required check in four places. PR
#65 dropped it (ADR-0001 step 3, issue #35); the live ruleset requires
gate-verified, zizmor, gitleaks, actionlint, analyze (actions). `gate`
still runs as a job.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

gate-verified step 3: drop gate from management-repo required checks

1 participant