GitLab CI

Add human approval steps to your GitLab CI/CD pipelines.

Setup

  1. Go to Settings → CI/CD → Variables
  2. Add OTTR_API_KEY (masked, protected)

Pipeline Configuration

This pipeline builds, requests approval, waits for human action, then deploys:

.gitlab-ci.yml
stages:
  - build
  - approval
  - deploy

variables:
  OTTR_API_URL: "https://api.ottr.run"

build:
  stage: build
  script:
    - npm ci
    - npm run build
  artifacts:
    paths:
      - dist/

request-approval:
  stage: approval
  script:
    - |
      RESPONSE=$(curl -s -X POST "$OTTR_API_URL/v1/approvals" \
        -H "Authorization: Bearer $OTTR_API_KEY" \
        -H "Content-Type: application/json" \
        -d '{
          "key_path": "deploy/'"$CI_PROJECT_PATH"'/'"$CI_PIPELINE_ID"'",
          "value": "approved",
          "ttl_seconds": 1800,
          "info": "Deploy '"$CI_COMMIT_SHORT_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" >> approval.env
      echo "Approval URL: $URL"
  artifacts:
    reports:
      dotenv: approval.env

wait-for-approval:
  stage: approval
  needs: [request-approval]
  script:
    - |
      KEY_PATH="deploy/$CI_PROJECT_PATH/$CI_PIPELINE_ID"
      echo "Waiting for approval..."

      for i in $(seq 1 180); do
        RESULT=$(curl -s "$OTTR_API_URL/v1/key/$KEY_PATH" \
          -H "Authorization: Bearer $OTTR_API_KEY")

        if [ "$RESULT" = '"approved"' ]; then
          echo "Approved!"
          exit 0
        elif [ "$RESULT" = '"rejected"' ]; then
          echo "Rejected"
          exit 1
        fi

        sleep 10
      done

      echo "Timeout waiting for approval"
      exit 1
  timeout: 30 minutes

deploy:
  stage: deploy
  needs: [wait-for-approval]
  script:
    - echo "Deploying to production..."
    # Your deployment commands here
  environment:
    name: production

How it works

  1. build - Compiles your application
  2. request-approval - Creates ottr approval URL, outputs to job log
  3. wait-for-approval - Polls until approved/rejected (30 min timeout)
  4. deploy - Runs only after approval

Why ottr vs GitLab's manual jobs?

  • No GitLab account required for approvers
  • Simple URL - share via Slack, email, SMS
  • Built-in expiry and audit trail
  • Works across GitLab, GitHub, Jenkins, etc.

Tips

  • Use CI_PIPELINE_ID in key_path for unique approvals
  • Adjust the loop count in wait-for-approval to change timeout
  • Configure Slack notifications for automatic alerts