CI/CD Integration

Human-in-Loop Approvals

Implement approval workflows that pause for human review and resume on manual trigger.

How It Works

  1. 1. Send Notification - Workflow sends Slack notification with review link
  2. 2. Pause - Workflow pauses after the notification step
  3. 3. Review - Human reviews and approves via GitLab/GitHub
  4. 4. Resume - Resume job loads state and continues execution

Approval Step

Use pause: true to stop execution after sending notification:

json
{
  "id": "request_approval",
  "type": "slack.notify",
  "pause": true,
  "config": {
    "webhook_url": "{{env.SLACK_WEBHOOK_URL}}",
    "channel": "#deployments",
    "message": "Review deployment to production. Click the GitLab button to approve.",
    "gitlab_pipeline_url": "{{env.CI_SERVER_URL}}/{{env.CI_PROJECT_ID}}/-/pipelines/{{env.CI_PIPELINE_ID}}",
    "button_text": "Review in GitLab"
  }
}

GitLab CI Configuration

Split into two jobs: initial run and manual resume:

yaml
stages:
  - deploy
  - resume

deploy-with-approval:
  stage: deploy
  script:
    - shiro run -state-store gitlab -fresh
  artifacts:
    when: always
    paths:
      - .shiro/state/

# Manual job to resume workflow
resume-deployment:
  stage: resume
  when: manual
  needs: [deploy-with-approval]
  script:
    - shiro run -state-store gitlab
  artifacts:
    when: always
    paths:
      - .shiro/state/

Complete Example Workflow

json
{
  "name": "approval-workflow",
  "steps": [
    {
      "id": "prepare",
      "type": "shell",
      "config": {
        "command": "echo 'Preparing deployment...'"
      }
    },
    {
      "id": "request_approval",
      "type": "slack.notify",
      "pause": true,
      "config": {
        "webhook_url": "{{env.SLACK_WEBHOOK_URL}}",
        "channel": "#deployments",
        "message": "Ready to deploy {{env.CI_COMMIT_REF_NAME}}. Please review.",
        "gitlab_pipeline_url": "{{env.CI_SERVER_URL}}/{{env.CI_PROJECT_ID}}/-/pipelines/{{env.CI_PIPELINE_ID}}"
      },
      "depends_on": ["prepare"]
    },
    {
      "id": "deploy",
      "type": "shell",
      "config": {
        "command": "kubectl apply -f k8s/production.yaml"
      },
      "depends_on": ["request_approval"]
    },
    {
      "id": "notify_complete",
      "type": "slack.notify",
      "config": {
        "webhook_url": "{{env.SLACK_WEBHOOK_URL}}",
        "message": "Deployment completed!"
      },
      "depends_on": ["deploy"]
    }
  ]
}