First-class concept for Deployment Approval (API Based)
This issue is to define the technical specification of "Deployment Approval" feature and implement the essential functionalities of it. Especially, this issue focuses on the architectural design and backend work, such as database models, internal process flow and API designs, that are scalable and extensible across domains and techstack (i.e. frontend).
Later, we'll improve the usability in the UI/UX issue.
Today, we do NOT have the first-class concept
Deployment Approval is one of the frequently requested features, however, we have never introduced the first class concept until today.
A few years ago, we documented a workaround that combines Manual Job and Protected Environment features (i.e. byproduct). However, this approach has a bunch of issues:
- Multiple approvals can't be supported. When the first approver triggeres a job, the job runs without waiting for further appropvals.
- Inappropriate team members can change the pipeline config
e.g. Basically, Developer role or above has a permission
to change
.gitlab-ci.yml
in a repository, including Manual Job setup. - Backend doesn't preserve any database records nor have class definitions. i.e. The system doesn't recognize the solution as approval feature.
Having said that we need to introduce the first-class concept at first, in order to properly execute the feature vision.
Proposal: The first-class concept
Here is the overview of the feature spec of Deployment Approval:
- Configuration:
- The feature can be configured as a part of Protected Environments feature.
- We already have a feature to specify which user/group/role is allowed to deploy to which environment. The same users have a privilege to approve/reject actions.
- As a new configuration, users can set Required Approval Count in a protected environment entry. The number represents how many approvals are
needed to proceed the deployment. The default/initial value is
0
. - If the required approval count is zero, the deployment job is processed without manual intervention (i.e. no behavioal change by default).
- If the required approval count is set to more than one, a deployment job waits until sufficient approvals are collected from the privileged users.
- The deployment executor (= job triggerer) and the deployment approver can NOT be the same. This is to prevent the deployment executor from accidentally bypassing the approval process.
- One user can give one approval, meaning the number of priviledged users should exceed the required approval count.
- Protected Environments, including Deployment Approval, are activated regardless of Manual Job setup (=
manual
keyword in.gitlab-ci.yml
). - Maintainer role or above has an access to the configuration.
- Control:
- A privileged user can take approve or reject action on a deployment. The system creates database records on any actions for tracking purpose.
- When user approves or rejects:
- If a deployment collects sufficient approvals, the system proceeds the deployment.
- If a deployment collects at least one rejection, the system fails the deployment.
- Else the deployment keeps waiting.
- After a deployment is proceeded or failed, users can't take any further actions. The records will be read-only.
- Developer role or above has a read access to deployment approvals. On top of that, privileged users have read-write access.
The following sections explain the technical spec.
The database model
Configuration table for deployment approvals:
protected_environments (existing)
- project_id integer,
- group_id bigint,
- name character varying NOT NULL,
- required_approvals_count: integer (New. How many approvals are required to proceed the deployment)
Tracking table for deployment approval actions:
deployment_approvals (new table)
- id (PKey, bigint)
- deployment_id (FK, bigint, NOT NULL, Cascading Deletion)
- user_id (FK, bigint, NOT NULL, Cascading Deletion, the person who took the action)
- status (smallint/enum, NOT NULL, one of `approved` or `rejected`)
- created_at/updated_at timestamp with time zone NOT NULL,
And, add a new status blocked
to deployments
table.
Status transition
- The pipeline jobs that are waiting for approvals are converted to
manual
status. - When a pipeline job transitions to
manual
status because of required approvals, the corresponding deployment transitions toblocked
status. - These
manual
jobs are actionable via deployment pages/APIs and are NOT actinoalbe via pipeline jobs pages/APIs. - When sufficient approvals are collected, the pipeline job transitinos to
pending
status. The rests are the same behavior as today. - When a deployment is rejected, the pipeline job transitinos to
failed
status. The rests are the same behavior as today.
Appearance
- The pipeline job page is decorated as an extended status, that it's waiting for deployment approval. See this class for more information.
Interface
We extend the Public v4 API in this iteration to minimize the scope of this issue. The main UX/UI issue is a follow-up.
- We add
required_approvals_count
field in Protect repository environments API - We add Approval API in the Deployment API:
-
PUT /projects/:id/deployments/:deployment_id/approval
(Approve/Reject a deployment)- Parameters:
status
(String)
- Parameters:
-
For more information, please see the PoC
Limitation
- Maximum 5 approvals can be configured per protected environment. i.e.
required_approvals_count
<= 5 - In this iteration, we only support Project-level Protected Environment. For the Group-Level protected environments, see this issue
- In this iteration, the user list of "Allowed to Deploy" is also used as "Allowed to Approve". This could be separated for more practical situation, see this issue for more information.
- The manual jobs in pipeline pages are visible as
manual
jobs. This UI issue will be addressed in this issue
Alpha Version
This issue is still early iteration and we should wait for calling it as GA (Generally Availlable).
We should expliaicly mention in the documentation that this feature is Alpha version that may be changed in the future without notice.
.gitlab-ci.yml
Why we should not define the authorization models in .gitlab-ci.yml
is stored in a project repository, meaning all users with Developer permission
has a right to modify the scripts. This could be a loop hole that project members
accidentally changes the pipeline configuration and bypass the approval rules.
Basically, protected environments require Maintainer role or above to configure the authorization models. In addition, group-level protected environments can make it read-only for project maintainers. Using these features automatically covers the proper permission for the configuration.
TODO
-
Add Models/Tables - !74932 (merged) -
Add/update Service classes - !75710 (merged) -
Extend APIs - !76165 (merged), !76689 (merged) -
Extend Pipeline job page - !76981 (merged) -
Add a new documentation page or section for explaining the feature concept, purpose and example usages. Also, note that this feature is still alpha version that may be changed without notice. - !77719 (merged) -
Address edge case with manual deployments (!75710 (comment 756445822)) - !77892 (merged), !77898 (merged), !78135 (merged)
PoC
You can find a PoC work in Tech Eval Issue.
Further iteration
- Separate Allowlist (user/group/role-base) for Deployment Approval
- Improve Pipeline Job UI for Deployment Approvals
- Support Deployment Approval for Group-Level Protected Environment
- Support approval/rejection commenting. See #342439 (closed)
- Record the approval/rejection events in Audit Events too.
Release notes
We are excited to introduce deployment approval via API. Prior to this feature, teams had the ability to protect an environment from any changes by requiring a manual job to be executed in a pipeline as a workaround. Now, a deployment approval is a first-class concept in our platform. Teams can configure a number of approvers for a specific environment and use a new endpoint via API to execute an approval or rejection of a deployment.