Skip to content

PoC: Deployment Approvals

Shinya Maeda requested to merge poc-deployment-approval into master

What's changed in this PoC

[NOT FOR MERGE] THIS IS POC/PROTOTYPE

This MR provides a prototype of Deployment Approval feature, that is based on this backend proposal and the UX/UI proposal.

Specifically, this MR introduces the following changes:

  • Add Deployments::Approval active record model (deployment_approvals table). This model represents the approval history of deployments.
  • Add Deployments::ApprovalService as a SSOT facility to approve/reject a deployment and trigger a subsequent process.
  • Add a new status blocked to the deployment model. This represents that the a deployment is waiting for approvals.
  • Add required_approval_count column to protected_environments table, that represents how many approvals are needed to deploy to a protected environment.
  • Add a new failure reason deployment_rejected to pipeline jobs, that represents a deployment job failed by rejection.

Related #344233 (closed) #343864 (closed) #343864 (closed)

How to use this feature

Configure required_approval_count on protected environments

Protect an environment (with 1 additional approval)

curl --header 'Content-Type: application/json' --request POST \
     --data '{"name": "production", "required_approval_count": 1, "deploy_access_levels": [{"access_level": 40}]}' \
     --header "PRIVATE-TOKEN: A3K6cFWthsQrQLaM8Fj1" \
     http://local.gitlab.test:8181/api/v4/projects/219/protected_environments
> {"name":"production","deploy_access_levels":[{"access_level":40,"access_level_description":"Maintainers","user_id":null,"group_id":null}],"required_approval_count":1}

Other utilities:

# Get a single Protected Environment
curl -H 'Private-Token: A3K6cFWthsQrQLaM8Fj1' http://local.gitlab.test:8181/api/v4/projects/219/protected_environments/production
> {"name":"production","deploy_access_levels":[{"access_level":40,"access_level_description":"Maintainers","user_id":null,"group_id":null}],"required_approval_count":0}

# List of Protected Environments 
curl -H 'Private-Token: A3K6cFWthsQrQLaM8Fj1' http://local.gitlab.test:8181/api/v4/projects/219/protected_environments
> [{"name":"production","deploy_access_levels":[{"access_level":40,"access_level_description":"Maintainers","user_id":null,"group_id":null}],"required_approval_count":0}]

# Unprotect an environment
curl -X DELETE -H 'Private-Token: A3K6cFWthsQrQLaM8Fj1' http://local.gitlab.test:8181/api/v4/projects/219/protected_environments/production

Run a pipeline in a project

Here is an example:

deploy:
    script: echo
    environment: production

and confirm that a deployment job is blocked.

2021-11-01_17-43

Approve a deployment to a protected environment

Get the latest deployment and its approval status

curl -H 'Private-Token: A3K6cFWthsQrQLaM8Fj1' "http://local.gitlab.test:8181/api/v4/projects/219/deployments?environment=production&sort=desc" | jq '.[0] | { id: .id, iid: .iid, status: .status, required_approval_count: .required_approval_count, approvals: .approvals }'

{
  "id": 1085,
  "iid": 17,
  "status": "blocked",
  "required_approval_count": 1,
  "approvals": []
}

Approve the deployemnt as a different user

curl -d 'status=approved' -H 'Private-Token: -B_sqZgkw_ptEf_ytyZP' "http://local.gitlab.test:8181/api/v4/projects/219/deployments/1085/approval"

{"user":{"id":1,"name":"Administrator","username":"root","state":"active","avatar_url":"https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon","web_url":"http://local.gitlab.test:8181/root"},"status":"approved"}

2nd time: Get the latest deployment and its approval status

{
  "id": 1085,
  "iid": 17,
  "status": "success",
  "required_approval_count": 0,
  "approvals": [
    {
      "user": {
        "id": 1,
        "name": "Administrator",
        "username": "root",
        "state": "active",
        "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
        "web_url": "http://local.gitlab.test:8181/root"
      },
      "status": "approved"
    }
  ]
}

(Note: A runner is needed to actually run the deployment job and transition the deployment status from blocked to running => success)

Confirm pipeline succeeded

2021-11-01_17-48

Edited by Shinya Maeda

Merge request reports