Staging auto-syncs. But production needs a human decision. The GitOps way: a Pull Request in the GitOps repo IS the approval. Merging it IS the deployment. This gives you audit trail, review, and one-click rollback (revert the PR).
The Promotion Flow
The PR IS the approval gate. No need for ArgoCD manual sync buttons or GitHub Environment approvals. The code review process you already have becomes your deployment approval process.
🏋️ CI Workflow: Auto-Promote to Staging, PR for Production
Add a promotion job to your CI pipeline (in the app repo):
promote-to-production:
name: 🚀 Create Production PR
needs: [build, update-gitops] # After staging is deployed
runs-on: ubuntu-latest
steps:
- name: Checkout GitOps repo
uses: actions/checkout@v4
with:
repository: ${{ env.GITOPS_REPO }}
token: ${{ secrets.GITOPS_PAT }}
- name: Update production image tag
run: |
cd environments/production
sed -i "s/newTag: .*/newTag: ${{ needs.build.outputs.tag }}/" kustomization.yaml
- name: Create Pull Request
uses: peter-evans/create-pull-request@v5
with:
token: ${{ secrets.GITOPS_PAT }}
commit-message: "promote: ${{ needs.build.outputs.tag }} → production"
title: "🚀 Deploy ${{ needs.build.outputs.tag }} to Production"
body: |
## Production Deployment
**Image:** `${{ needs.build.outputs.tag }}`
**Staging:** verified ✅
**Source commit:** ${{ github.sha }}
---
Merge this PR to deploy to production.
Revert this PR to rollback.
branch: promote/${{ needs.build.outputs.tag }}
labels: deployment, production
What the Reviewer Sees
Production ArgoCD Config (Manual Sync)
# apps/production.yaml — no automated sync!
spec:
syncPolicy:
# No 'automated' key = manual sync only
syncOptions:
- CreateNamespace=true
# But still self-heal (prevent drift)
ArgoCD detects the change when the PR is merged → shows "OutOfSync" → operator clicks Sync (or you enable auto-sync on production if the PR review IS your approval gate).
Architect decision: Two valid approaches for production:
- Manual ArgoCD sync — PR merge + ArgoCD manual sync (double approval)
- Auto-sync on production — PR merge IS the deployment (the review was the gate)
🧠 Recall Check
- In the PR-based promotion flow, what triggers the actual production deployment?
- How do you rollback a production deployment in this model?
- Why is a PR better than a "manual sync" button in ArgoCD?
- What does the staging→production promotion flow look like end-to-end?
Reveal answers
- Merging the PR in the GitOps repo. This updates the production kustomization.yaml with the new image tag. ArgoCD detects the change and syncs.
- Revert the PR. Git creates a revert commit (changes tag back to previous value) → ArgoCD syncs → old image is deployed. Complete audit trail preserved.
- PRs give you: code review (someone looks at what's deploying), discussion threads, audit trail (who approved, when), easy rollback (revert), and integration with branch protection rules.
- Push code → CI builds image → CI commits tag to staging (direct commit) → ArgoCD auto-syncs staging → staging verified → CI creates PR for production → team reviews → PR merged → ArgoCD syncs production.
GitOps promotion complete. You now have a full production-grade GitOps delivery system: CI → staging (auto) → verified → PR → production (reviewed). Next section: hardening everything with security best practices.