GitLab Manual Approval & Release Workflow Prompt
Design release workflows with manual approval gates — protected environments, deployment freeze, release tagging, change-management integration.
- Target user
- DevOps engineers building governed release workflows
- Difficulty
- Intermediate
- Tools
- Claude, ChatGPT
The prompt
You are a senior DevOps engineer who has built release workflows with manual approvals — protected environments, approver groups, deployment freeze windows, integration with external change-management systems. I will provide: - The release frequency and structure (tag-based, branch-based, scheduled) - The current approval mechanism (`when: manual`, protected envs, external) - Compliance / audit requirements (SOX, ISO27001, internal change management) - The deployment target (prod cluster, multiple regions) Your job: 1. **Decide the approval model**: - **`when: manual`** — anyone with developer+ can click; minimal - **Protected environment + approval rules** — only specific approvers; N approvals required; recorded in deployment history - **External ticket integration** (ServiceNow, Jira) — webhook-based; CI waits for external approval - **Deployment freeze windows** — block all deploys during specific hours/days (project-level setting) 2. **For protected environments**: - Settings → CI/CD → Protected environments → add env - Allowed to deploy: specific users / groups / roles - Approval rules: minimum approvers, allow self-approval (usually disable) - Deployment access (via API) requires permission 3. **For deployment freeze**: - Project → CI/CD → Deploy freezes (cron-style schedule) - During freeze: jobs targeting frozen envs are skipped (with `if: $CI_DEPLOY_FREEZE` rule) - Example: freeze production deploys Fri 17:00 - Mon 09:00 4. **For release tagging**: - Tag-triggered pipelines: `rules: - if: $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/` - Semantic versioning with conventional commits → tagging via release-please, semantic-release - Tag pipelines run in their own context — no MR 5. **For audit trail**: - GitLab records deployment history per environment - Audit events (Premium+) — every change/deploy logged - Webhook to SIEM for security observability 6. **For approval chain (multiple gates)**: - Manual job per gate (e.g., `approve-staging-smoke-test` → `approve-prod-deploy`) - Each gate can have different approvers via protected env - Pipeline pauses at each manual job until approved 7. **For emergency / hotfix path**: - Separate `hotfix` pipeline that skips some approvals - Carefully restricted by branch protection (only specific people can push to `hotfix/*`) - Post-incident review required 8. **For change-management integration**: - CI creates ticket via API; pipeline waits via long-poll or webhook - Or: CI receives webhook from external system that triggers next stage Mark DESTRUCTIVE: bypassing protected environment approval (`force_push` to protected ref), self-approving in approval flows (against policy), deploy freeze override without compensation control. --- Release frequency + structure: [DESCRIBE] Current approval mechanism: [DESCRIBE] Compliance requirements: [DESCRIBE — SOX/ISO/internal] Target: [single env / multi-region / multi-cluster] Goal: [design new workflow / harden existing / debug a stuck approval]
Why this prompt works
Release workflows balance speed with safety. Naive when: manual everywhere creates approval bureaucracy; no approvals creates risk. This prompt walks the patterns and lets you pick per env.
How to use it
- Match approval rigor to env risk — staging may be auto, prod definitely needs approval.
- Use protected envs for production — not just
when: manual. - Set deploy freezes for non-deploy hours.
- Define hotfix paths separately so emergencies don’t bypass everything.
Useful commands
# Protect environment via API
curl --request POST --header "PRIVATE-TOKEN: <t>" --header "Content-Type: application/json" \
--data '{
"name": "production",
"deploy_access_levels": [{"access_level": 40}],
"required_approval_count": 2
}' \
"https://gitlab.example.com/api/v4/projects/<id>/protected_environments"
# Add deploy freeze
curl --request POST --header "PRIVATE-TOKEN: <t>" --header "Content-Type: application/json" \
--data '{
"freeze_start": "0 17 * * 5", # Friday 17:00
"freeze_end": "0 9 * * 1", # Monday 09:00
"cron_timezone": "America/New_York"
}' \
"https://gitlab.example.com/api/v4/projects/<id>/freeze_periods"
# List recent deployments (audit trail)
curl --header "PRIVATE-TOKEN: <t>" \
"https://gitlab.example.com/api/v4/projects/<id>/deployments?environment=production" | jq
Patterns
Multi-gate approval
stages: [build, test, deploy-staging, smoke-test-staging, approve-prod, deploy-prod]
build:
stage: build
script: ./build.sh
test:
stage: test
script: ./test.sh
deploy-staging:
stage: deploy-staging
script: ./deploy.sh staging
environment: { name: staging, deployment_tier: staging }
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
smoke-test-staging:
stage: smoke-test-staging
needs: [deploy-staging]
script: ./smoke-test.sh https://staging.example.com
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
approve-prod:
stage: approve-prod
needs: [smoke-test-staging]
script:
- echo "Approval received from $GITLAB_USER_LOGIN at $(date)"
environment: { name: production-pre-approval, action: prepare }
when: manual
rules:
- if: $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/
allow_failure: false
deploy-prod:
stage: deploy-prod
needs: [approve-prod]
script: ./deploy.sh production
environment: { name: production, deployment_tier: production }
rules:
- if: $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/
Tag-only production releases
deploy-production:
stage: deploy
script: ./deploy.sh
environment: { name: production, deployment_tier: production }
rules:
- if: $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/
when: manual
In Settings → CI/CD → Protected environments → production → require 2 approvals.
Deploy freeze
deploy-prod:
script: ./deploy.sh
environment: { name: production }
rules:
- if: $CI_DEPLOY_FREEZE
when: never
- if: $CI_COMMIT_TAG
when: manual
(GitLab sets $CI_DEPLOY_FREEZE=true during configured freeze windows.)
Hotfix path
deploy-hotfix:
stage: deploy
script: ./deploy.sh production
environment: { name: production, deployment_tier: production }
rules:
- if: $CI_COMMIT_BRANCH =~ /^hotfix\//
when: manual
# Pair with branch protection on hotfix/* to limit who can push
External change management (ServiceNow)
create-snow-ticket:
stage: approve
script:
- |
TICKET_ID=$(curl -u "$SNOW_USER:$SNOW_PASS" \
-X POST -H "Content-Type: application/json" \
-d "{\"short_description\":\"Deploy $CI_PROJECT_NAME $CI_COMMIT_TAG\",\"...}\"}" \
"https://servicenow.example.com/api/now/table/change_request" | jq -r '.result.number')
echo "Created ticket $TICKET_ID"
echo "$TICKET_ID" > snow-ticket.txt
artifacts:
paths: [snow-ticket.txt]
wait-for-approval:
stage: approve
needs: [create-snow-ticket]
script:
- TICKET=$(cat snow-ticket.txt)
- |
while true; do
STATE=$(curl -u "$SNOW_USER:$SNOW_PASS" \
"https://servicenow.example.com/api/now/table/change_request/$TICKET" | jq -r '.result.state')
case "$STATE" in
implement) echo "Approved"; break ;;
rejected) echo "Rejected"; exit 1 ;;
*) sleep 60 ;;
esac
done
timeout: 4h
Common findings this catches
when: manualbut no protected env → anyone with developer can deploy prod.- Self-approval allowed → policy violation; require N > 1 approvers excluding the requester.
- Deploy freeze defined but rule doesn’t reference
$CI_DEPLOY_FREEZE→ freeze ineffective. - No audit on manual approval clicks → who approved? Use protected env which records.
- Tag-based release but
protect: trueon tags missing → anyone can create a tag. - External CM integration polls forever → no timeout; pipeline stalls. Set job timeout.
- Hotfix path skips smoke tests → consider mini-test even on hotfix; tradeoff with speed.
When to escalate
- Compliance audit failing despite controls — review the audit trail; possibly need GitLab Premium audit events.
- Bus-factor problem (only one approver, unavailable) — back-up approvers required.
- External system integration drift — coordinate with system owner; webhook contracts.
Related prompts
-
GitLab Compliance Frameworks & Mandatory Pipeline Prompt
Design GitLab compliance frameworks — enforced pipeline configurations that run alongside project pipelines, audit-ready evidence collection.
-
GitLab CD: Blue/Green, Canary & Rolling Deployment Patterns Prompt
Design GitLab CD pipelines implementing blue/green, canary, and rolling deployment strategies for Kubernetes, VM, and serverless targets.
-
GitLab Environments & Deployments Debug Prompt
Diagnose GitLab environments — stuck deployments, environment scope, `stop_in` cleanup, protected environments, deployment tier confusion.