Skip to content
Infrastructure

CI policy gates that stop bad deploys

Fail the pipeline on purpose—before production becomes the first reviewer

July 28, 2025
By Manweba

A green build that still ships a public S3 bucket or a missing migration is not CI—it is optimism. Policy gates turn “we usually remember” into “the pipeline refuses.” That is the whole point.

Separate verify from release

Keep a fast verify lane (lint, typecheck, unit tests) and a stricter release lane (integration, policy-as-code, signed images). Mixing them into one sluggish job teaches teams to skip CI when they are late.

Required checks on the default branch should be few and meaningful. Vanity checks that flake teach people to click “bypass.”

GitHub Actions: plan + policy before apply

yaml
Loading code…

Policy that names the failure

Write policies for decisions you have already made: no public object stores, encryption required, forbidden IAM wildcards on production roles. Fail with a message a human can act on—not a raw Rego stack dump.

Deny public S3 in plan JSON

rego
Loading code…

Human gates stay human

Production applies should still require an environment protection rule or an explicit approval. Policy catches known bad patterns; humans catch novel ones. Neither replaces the other.

Log who approved, what digest shipped, and which commit produced it. Audits are cheaper when the pipeline already recorded the story.

Start with three gates

If you have nothing yet: (1) tests must pass, (2) infrastructure plan must pass policy, (3) production deploy needs approval. Expand only when a real incident shows a missing check—not when a blog post lists twenty tools.

Final thoughts

Good CI is a series of deliberate refusals. Make the pipeline the first reviewer for known risks, keep approvals for production judgment, and resist decorating the workflow with checks nobody trusts.

Ready to build something this considered?