Stage 5 · Platform
GitOps & Progressive Delivery
Promotion Workflows
Promoting image tags through Git pull requests, Kargo-style stages, policy checks, and signed commits.
Promotion Concept
Promotion is the process of moving an artifact through environments — from development to staging to production. In GitOps, promotion means updating the desired state in Git so that the controller deploys the new version to the target environment.
The key principle is that promotion goes through Git. Every environment change is a commit. Every commit is reviewed and approved. This creates an audit trail and prevents unauthorized deployments.
Git-Based Promotion
name: Promote to Production
on:
workflow_dispatch:
inputs:
image_tag:
description: "Image tag to promote"
required: true
environment:
description: "Target environment"
required: true
type: choice
options:
- staging
- production
jobs:
promote:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
token: ${{ secrets.PAT_TOKEN }}
- name: Update image tag
run: |
cd overlays/${{ inputs.environment }}
kustomize edit set image ghcr.io/myorg/myapp:${{ inputs.image_tag }}
- name: Create pull request
uses: peter-evans/create-pull-request@v6
with:
token: ${{ secrets.PAT_TOKEN }}
commit-message: "promote: ${{ inputs.image_tag }} to ${{ inputs.environment }}"
branch: promote/${{ inputs.environment }}/${{ inputs.image_tag }}
title: "Promote ${{ inputs.image_tag }} to ${{ inputs.environment }}"
body: |
Promoting image tag ${{ inputs.image_tag }} to ${{ inputs.environment }}.
## Checklist
- [ ] Staging tests passed
- [ ] Security scans passed
- [ ] Manual verification complete
labels: promotion
reviewers: platform-teamThe workflow creates a pull request to update the image tag in the target environment's kustomization. The PR requires review and approval before merging. Once merged, the GitOps controller detects the change and deploys the new version.
Automated Promotion
name: Auto-Promote
on:
repository_dispatch:
types: [canary-verified]
jobs:
promote:
runs-on: ubuntu-latest
if: ${{ github.event.client_payload.status == 'verified' }}
steps:
- uses: actions/checkout@v4
- name: Update production image
run: |
TAG=${{ github.event.client_payload.image_tag }}
cd overlays/production
kustomize edit set image ghcr.io/myorg/myapp:${{ TAG }}
- name: Commit and push
run: |
git config user.name "promote-bot"
git config user.email "promote-bot@example.com"
git add .
git commit -m "promote: ${{ github.event.client_payload.image_tag }}"
git push
- name: Notify deployment
uses: slackapi/slack-github-action@v1
with:
payload: |
{
"text": "Auto-promoted ${{ github.event.client_payload.image_tag }} to production"
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}The automated promotion triggers on a repository_dispatch event from the canary analysis system. When the canary is verified, the image tag is updated in production and a Slack notification is sent.
Policy Checks
package promotion
default allow = false
# Allow promotion if all conditions are met
allow {
input.image_tag != ""
input.environment == "production"
input.approved_by != ""
security_scan_passed
staging_test_passed
no_critical_vulnerabilities
}
security_scan_passed {
input.security_scan.status == "passed"
input.security_scan.critical == 0
input.security_scan.high == 0
}
staging_test_passed {
input.staging_tests.status == "passed"
input.staging_tests.passed_rate >= 0.99
}
no_critical_vulnerabilities {
input.vulnerability_scan.critical == 0
}
# Deny promotion on weekends
deny[msg] {
input.day_of_week == "Saturday"
msg := "Promotion not allowed on weekends"
}
deny[msg] {
input.day_of_week == "Sunday"
msg := "Promotion not allowed on weekends"
}OPA policies validate that all requirements are met before promotion. The policy checks security scans, test results, vulnerability scans, and deployment windows. The promotion workflow evaluates this policy before proceeding.
Signed Commits
jobs:
promote:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup GPG key
run: |
echo "${{ secrets.GPG_PRIVATE_KEY }}" | gpg --batch --import
git config user.signingkey ${{ secrets.GPG_KEY_ID }}
git config commit.gpgsign true
git config gpg.format openpgp
- name: Create signed commit
run: |
cd overlays/production
kustomize edit set image ghcr.io/myorg/myapp:${{ inputs.image_tag }}
git add .
git commit -S -m "promote: ${{ inputs.image_tag }} to production"
git pushSigned commits provide cryptographic proof that the commit was created by a trusted identity. The GPG key is stored as a secret and used to sign every promotion commit. This prevents unauthorized commits to the GitOps repository.
Multi-Stage Promotion
- Build CI produces the artifact and publishes it to the registry.
- Dev environment auto-deploys on merge to main.
- Staging auto-deploys after dev verification passes.
- Production promotion requires manual approval and staging verification.
- Each promotion is a separate Git commit with audit trail.
Promotion updates the desired state in Git. Deployment is what the GitOps controller does after detecting the Git change. These are separate processes. The promotion is the human decision; the deployment is the automated execution.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.