feat(danger): Block post-deploy migrations on security MRs
What does this MR do and why?
Adds a Danger rule that blocks post-deploy migrations on security merge requests.
Security MRs that add post-deploy migrations create a point of no return in production: once the migration runs, rollback becomes unavailable and the only mitigation is roll-forward (6+ hours, subject to pipeline failures). Historically ~1.3% of security fixes include post-deploy migrations, so blocking them by default is a low-risk, high-value change that guarantees a rollback window during patch releases.
The rule:
- Fails on any security MR touching
db/post_migrate/(including theee/path). - Allows an authorized exception when the
patch-release::pdm-approvedlabel is present and was applied by a member of an authorized group (@gitlab-org/release/managers,@gitlab-org/delivery, or@gitlab-com/gl-security/product-security/psirt-group), verified via the label-events API. - Removes the label via the API and fails the check when it was applied by anyone outside those groups.
- Records every bypass event — approved or rejected — as a permanent MR discussion thread for audit purposes.
This composes with the existing project-level PSIRT approval rule on the security mirror rather than replacing it.
References
- Epic: gitlab-com/gl-infra#1755
- Implementation issue: gitlab-com/gl-infra/delivery#21612 (closed)
- Design discussion + PSIRT/Delivery sign-off (closed): gitlab-com/gl-infra/delivery#22084 (closed)
- 3-type framework informing the escalation path: gitlab-com/gl-infra/delivery#21612 (comment 3340915317)
- Runbook (follow-up): gitlab-com/gl-infra/delivery#21615 (closed)
How to set up and validate locally
The rule was validated end-to-end on a purpose-built test project (anganga/pdm-danger-test!2) since triggering it here requires a real security MR:
- Default block — a security MR adds
db/post_migrate/*with no bypass label → Danger fails, comments the block message + runbook link. - Authorized bypass — the
patch-release::pdm-approvedlabel is applied by a member of an authorized group → Danger warns (does not fail) and posts an approval audit thread. - Unauthorized bypass — the label is applied by anyone else → the label is removed via the API, a rejection audit thread is posted, and the check fails.
All three paths are covered by spec/tooling/danger/post_deployment_migration_spec.rb (runs in CI on this MR).
Risk
Low. The rule only activates on security MRs (helper.security_mr?) that touch db/post_migrate/ — regular MRs and security MRs without post-deploy migrations are unaffected. All API calls (label-events lookup, group-membership check, label removal, audit-thread creation) are wrapped in rescue blocks that degrade gracefully (fail-safe to a warning) rather than crashing the Danger run. No changes to any existing rule.
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist.