GitHub Actions
Add human approval gates to your CI/CD pipelines. Block deployments until someone approves.
Setup
- Go to your repository Settings → Secrets and variables → Actions
- Add
OTTR_API_KEYwith your ottr API key
Deployment Workflow
This workflow creates an approval URL and waits for human approval before deploying:
.github/workflows/deploy.yml
name: Deploy with Approval
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build
run: npm run build
- name: Request Deployment Approval
id: approval
run: |
RESPONSE=$(curl -s -X POST https://api.ottr.run/v1/approvals \
-H "Authorization: Bearer ${{ secrets.OTTR_API_KEY }}" \
-H "Content-Type: application/json" \
-d '{
"key_path": "deploy/${{ github.repository }}/${{ github.run_id }}",
"value": "approved",
"ttl_seconds": 1800,
"info": "Deploy ${{ github.sha }} to production?",
"actions": [
{"key": "approve", "value": "approved", "label": "Deploy", "style": "primary"},
{"key": "reject", "value": "rejected", "label": "Cancel", "style": "danger"}
]
}')
URL=$(echo $RESPONSE | jq -r '.url')
echo "approval_url=$URL" >> $GITHUB_OUTPUT
echo "::notice::Approval required: $URL"
- name: Wait for Approval
run: |
echo "Waiting for approval at: ${{ steps.approval.outputs.approval_url }}"
KEY_PATH="deploy/${{ github.repository }}/${{ github.run_id }}"
while true; do
RESULT=$(curl -s "https://api.ottr.run/v1/key/$KEY_PATH" \
-H "Authorization: Bearer ${{ secrets.OTTR_API_KEY }}")
if [ "$RESULT" = '"approved"' ]; then
echo "Deployment approved!"
exit 0
elif [ "$RESULT" = '"rejected"' ]; then
echo "Deployment rejected"
exit 1
fi
sleep 10
done
timeout-minutes: 30
- name: Deploy
if: success()
run: |
echo "Deploying to production..."
# Your deployment commands hereHow it works
- Workflow runs on push to main
- Build step completes
- ottr creates an approval URL (visible in Actions log)
- Workflow polls for approval (up to 30 min timeout)
- Human clicks link and approves or rejects
- Deployment proceeds or workflow fails
Optional: Slack Notification
Add this step after creating the approval to notify your team in Slack:
slack notification step
- name: Notify Slack
run: |
curl -X POST ${{ secrets.SLACK_WEBHOOK }} \
-H "Content-Type: application/json" \
-d '{
"text": "Deployment approval needed",
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Deployment Approval Required*\nRepository: ${{ github.repository }}\nCommit: ${{ github.sha }}"
}
},
{
"type": "actions",
"elements": [
{
"type": "button",
"text": {"type": "plain_text", "text": "Review & Approve"},
"url": "${{ steps.approval.outputs.approval_url }}"
}
]
}
]
}'Tips
- Use
timeout-minutesto control how long to wait - Include commit SHA in the
infoso reviewers know what they're approving - Use unique
key_pathper run to avoid conflicts - Configure ottr Slack integration for automatic notifications