name: deployment-safety description: "Production deployment rules, rollback-first recovery, dependency batching, CI cost awareness, framework upgrade verification, fallback observability, and GitHub repo settings standardization."
Deployment Safety
Merging to Main
Wrong -- merge Dependabot PR thinking it's cleanup:
gh pr merge 42 --merge # Dependabot targets main = production deploy
Right -- move the update onto the non-production integration path, close the PR, and release normally:
# develop/main topology:
git checkout develop && git cherry-pick <commit>
gh pr close 42 # release via develop -> main
# main-only topology:
git checkout -b chore/dependency-updates main
git cherry-pick <commit>
gh pr close 42 # validate on branch/PR before merging back to main
Dependency Batching
Wrong -- merge N PRs one-by-one (O(n^2) rebase cascade):
gh pr merge 1 && gh pr merge 2 && gh pr merge 3
# 7 PRs x 9 workflows = ~189 wasted CI runs
Right -- batch into a single branch:
# develop/main topology:
git checkout -b chore/dependency-updates develop
# main-only topology:
git checkout -b chore/dependency-updates main
# Apply all updates, run CI once, merge one PR
CI Cost Awareness
Wrong -- push partial work to see if CI passes:
git push # 9 workflows triggered, guess and check
Right -- justify the run before triggering it, then push once:
Before any CI run, deployment, or API call, ask:
1. Is this needed? (Can I achieve this locally?)
2. Is this justified? (Does this advance the task?)
3. Is this verifiable? (Will I know if it succeeded?)
If any answer is "no" -- do not proceed.
pnpm run typecheck 2>&1; pnpm run lint 2>&1; pnpm run test 2>&1
git push # confident it works
Framework Upgrades
Wrong -- merge after CI passes (CI != production):
gh pr merge 99 --squash # CI green, serverless runtime crashes
Right -- verify on preview deployment first:
# Push to non-main branch -> preview URL
# Verify: site loads, API routes respond, health checks pass
# Only then merge to main
Production Incident Recovery
Wrong -- deploy fixes to prod while investigating:
vercel deploy --prod # fails, deploy again, fails again
Right -- roll back first, investigate second:
vercel rollback # Step 1: restore service immediately
# Step 2: investigate on non-production (logs, preview URL)
# Step 3: fix on the integration path, verify on preview,
# then merge to the production branch
Fallback Observability
Wrong -- a fallback path activates silently, hiding a production bug:
function getConfig() {
try {
return loadFromRemote();
} catch {
return DEFAULT_CONFIG; // nobody is ever told this happened
}
}
Right -- log at ERROR level, expose the degraded state in the health endpoint, and wire an alert:
function getConfig() {
try {
return loadFromRemote();
} catch (error) {
logger.error('[CONFIG_FALLBACK] using default config', { error });
metrics.increment('fallback.config_default'); // feeds the alert
return DEFAULT_CONFIG;
}
}
app.get('/health', () => ({
status: usingFallback ? 'degraded' : 'healthy',
}));
A silent fallback is a silent production bug. Treat any degraded-mode branch as a first-class code path -- logging, health-endpoint coverage, and alerting -- not just a catch block that quietly saves the request.
Repo Settings Standardization
Wrong -- bootstrap a repo and leave GitHub defaults in place, letting merge commits, stale branches, and disabled security updates drift in:
gh repo create myorg/new-project --public
# defaults: merge commits + rebase merges allowed, no auto-merge,
# branches linger after merge, Dependabot alerts off
Right -- choose merge settings that match the branch topology. For a long-lived
develop plus main, keep squash for feature PRs and enable merge commits for
release PRs:
gh api -X PATCH repos/{owner}/{repo} \
-f allow_squash_merge=true \
-f allow_merge_commit=true \
-f allow_rebase_merge=false \
-f delete_branch_on_merge=true \
-f allow_auto_merge=true
Feature PRs into develop use squash. Release PRs from develop to main use
a merge commit. Never squash the release PR: squash discards shared ancestry
and makes later releases depend on a manual back-merge. Never pass
--delete-branch for the permanent develop branch.
For a main-only repository, squash can remain the only merge method:
gh api -X PATCH repos/{owner}/{repo} \
-f allow_squash_merge=true \
-f allow_merge_commit=false \
-f allow_rebase_merge=false \
-f delete_branch_on_merge=true \
-f allow_auto_merge=true
Also turn on Dependabot alerts and security update PRs, and restrict the
Production deployment environment to protected branches only. Squash-merged
feature branches still need git branch -D instead of -d during cleanup.
Architecte Docker Compose
DevOps
Concoit des configurations Docker Compose optimisees.
Rapport de Post-Mortem
DevOps
Rédige des rapports post-mortem d'incidents structurés et blameless.
Créateur de Runbooks
DevOps
Crée des runbooks opérationnels clairs pour les procédures DevOps courantes.