|
| 1 | +--- |
| 2 | +weight: 30 |
| 3 | +i18n: |
| 4 | + title: |
| 5 | + en: Manual Approval Gate |
| 6 | + zh: 手动审批关卡 |
| 7 | +title: Manual Approval Gate |
| 8 | +--- |
| 9 | + |
| 10 | +# `Manual Approval Gate` for `Tekton Pipelines` |
| 11 | + |
| 12 | +## Feature Overview |
| 13 | + |
| 14 | +`Manual Approval Gate` lets pipeline authors pause a `PipelineRun` until designated approvers review and approve the operation. Behind the scenes, the Operator-provided controller creates an `ApprovalTask` resource for every approval step, tracks approver responses, and writes the result back to the originating `CustomRun`. |
| 15 | + |
| 16 | +## Use Cases |
| 17 | + |
| 18 | +- Enforcing human checkpoints before deploying to production or performing destructive maintenance. |
| 19 | +- Implementing multi-person approval policies by combining individuals and groups with `numberOfApprovalsRequired`. |
| 20 | +- Auditing who approved or rejected a change by querying `ApprovalTask` status fields or CLI output. |
| 21 | + |
| 22 | +## Prerequisites |
| 23 | + |
| 24 | +- A cluster administrator has deployed `Manual Approval Gate`. If not, refer to the [deployment guide](../../how_to/manual_approval_gate_operator.mdx). |
| 25 | +- You can create or edit `Pipeline`/`PipelineRun` objects in the target namespace. |
| 26 | +- Approvers can patch `approvaltasks.openshift-pipelines.org` resources (typically via `kubectl`) in the target namespace. Platforms such as `Alauda Container Platform` grant this capability by default; only customize RBAC if you have explicitly removed the built-in permissions. |
| 27 | + |
| 28 | +## Steps |
| 29 | + |
| 30 | +### 1. Declare the approval step in a pipeline |
| 31 | + |
| 32 | +```yaml |
| 33 | +apiVersion: tekton.dev/v1 |
| 34 | +kind: Pipeline |
| 35 | +metadata: |
| 36 | + name: deploy-with-approval |
| 37 | +spec: |
| 38 | + tasks: |
| 39 | + - name: build |
| 40 | + taskRef: |
| 41 | + name: build-bundle # Placeholder Task; replace with your build logic |
| 42 | + - name: wait-for-approval |
| 43 | + runAfter: |
| 44 | + - build |
| 45 | + taskRef: |
| 46 | + apiVersion: openshift-pipelines.org/v1alpha1 |
| 47 | + kind: ApprovalTask |
| 48 | + params: |
| 49 | + - name: approvers |
| 50 | + value: |
| 51 | + - alice |
| 52 | + - group:release-managers |
| 53 | + - name: numberOfApprovalsRequired |
| 54 | + value: "1" |
| 55 | + - name: timeout |
| 56 | + value: "24h" |
| 57 | + - name: description |
| 58 | + value: "Approve promotion into production" |
| 59 | + - name: deploy |
| 60 | + runAfter: |
| 61 | + - wait-for-approval |
| 62 | + taskRef: |
| 63 | + name: deploy-prod # Placeholder Task; replace with your deployment logic |
| 64 | +``` |
| 65 | +
|
| 66 | +When the pipeline reaches `wait-for-approval`, `Tekton` emits a `CustomRun`. The approval controller creates an `ApprovalTask` with your parameters and keeps the `PipelineRun` pending until quorum is met or a rejection occurs. |
| 67 | + |
| 68 | +### 2. Monitor approval status |
| 69 | + |
| 70 | +```bash |
| 71 | +$ kubectl get approvaltasks.openshift-pipelines.org |
| 72 | +
|
| 73 | +NAME AGE |
| 74 | +deploy-with-approval-run-wait-for-approval 4m16s |
| 75 | +``` |
| 76 | + |
| 77 | +```bash |
| 78 | +$ kubectl describe approvaltask deploy-with-approval-run-wait-for-approval |
| 79 | +Name: deploy-with-approval-run-wait-for-approval |
| 80 | +Status: |
| 81 | + Approvals Received: 1 |
| 82 | + Approvals Required: 1 |
| 83 | + Approvers: |
| 84 | + alice |
| 85 | + release-managers |
| 86 | + Approvers Response: |
| 87 | + Name: alice |
| 88 | + Response: approved |
| 89 | + Type: User |
| 90 | + Start Time: 2025-11-17T10:37:01Z |
| 91 | + State: approved |
| 92 | +Events: <none> |
| 93 | +``` |
| 94 | + |
| 95 | +Important status fields: |
| 96 | + |
| 97 | +- `status.state`: overall gate state such as `pending`, `approved`, or `rejected`. |
| 98 | +- `status.approvalsRequired` / `status.approvalsReceived`: quorum tracking (the received count appears only after at least one approver responds). |
| 99 | +- `status.approversResponse`: per-user/group outcome plus messages, useful for auditing. |
| 100 | + |
| 101 | +### 3. Approve or reject |
| 102 | + |
| 103 | +```bash |
| 104 | +$ kubectl get approvaltask deploy-with-approval-run-wait-for-approval -o json | jq '.spec.approvers' |
| 105 | +
|
| 106 | +$ kubectl patch approvaltask deploy-with-approval-run-wait-for-approval \ |
| 107 | + --type='json' \ |
| 108 | + --as alice \ |
| 109 | + -p='[ |
| 110 | + {"op":"replace","path":"/spec/approvers/0/input","value":"approve"}, |
| 111 | + {"op":"replace","path":"/spec/approvers/0/message","value":"QA complete"} |
| 112 | + ]' |
| 113 | +
|
| 114 | +$ kubectl patch approvaltask deploy-with-approval-run-wait-for-approval \ |
| 115 | + --type='json' \ |
| 116 | + --as alice \ |
| 117 | + -p='[ |
| 118 | + {"op":"replace","path":"/spec/approvers/0/input","value":"reject"}, |
| 119 | + {"op":"replace","path":"/spec/approvers/0/message","value":"Found regression"} |
| 120 | + ]' |
| 121 | +
|
| 122 | +$ kubectl patch approvaltask deploy-with-approval-run-wait-for-approval \ |
| 123 | + --type='json' \ |
| 124 | + --as bob \ |
| 125 | + --as-group release-managers \ |
| 126 | + -p='[ |
| 127 | + {"op":"replace","path":"/spec/approvers/1/input","value":"approve"}, |
| 128 | + {"op":"replace","path":"/spec/approvers/1/message","value":"Group approval from release-managers"} |
| 129 | + ]' |
| 130 | +``` |
| 131 | + |
| 132 | +The first command helps you determine the array index for your approver entry. The JSON patches then update only the matched entry's `input` and `message`, whether it represents a user (`alice` in the example) or a user impersonating a group (`bob` acting for `release-managers`). The controller sets the corresponding `CustomRun` and `PipelineRun` to `Succeeded` or `Failed` accordingly: approvals accumulate until `numberOfApprovalsRequired` is satisfied, while any rejection immediately fails that section of the pipeline. |
| 133 | + |
| 134 | +> **Tip:** Use `--as <username>` (required) and optionally `--as-group <group>` when you need to approve as a specific identity. The validation webhook allows you to modify only the entry that matches that impersonated user, so you often impersonate a user while also attaching the relevant group. RBAC must grant you impersonation rights. For example, `kubectl patch ... --as release-robot --as-group release-managers` simulates a service account acting for the `release-managers` group. |
| 135 | + |
| 136 | +### 4. Extend `PipelineRun` timeouts for long approvals |
| 137 | + |
| 138 | +If an approval could take hours or days, configure both `PipelineRun.spec.timeouts.pipeline` and `PipelineRun.spec.timeouts.tasks` to exceed the approval window so the run does not terminate before approvers respond. A simple `PipelineRun` to exercise the approval gate looks like the following: |
| 139 | + |
| 140 | +```yaml |
| 141 | +apiVersion: tekton.dev/v1 |
| 142 | +kind: PipelineRun |
| 143 | +metadata: |
| 144 | + name: deploy-with-approval-run |
| 145 | +spec: |
| 146 | + pipelineRef: |
| 147 | + name: deploy-with-approval |
| 148 | + timeouts: |
| 149 | + pipeline: 72h |
| 150 | + tasks: 72h |
| 151 | +``` |
| 152 | + |
| 153 | +Ensure the approval task's `timeout` parameter is shorter than the pipeline timeout. Otherwise, the `PipelineRun` might expire first, leaving the approval unresolved. |
| 154 | + |
| 155 | +## Operation Results |
| 156 | + |
| 157 | +- `kubectl get approvaltasks -o yaml` shows each approval gate with `state` and quorum-related fields (the `approvalsReceived` column appears after someone responds). |
| 158 | +- `PipelineRun` status reflects the approval outcome: when approved, downstream tasks resume; when rejected, the run fails with the reason propagated from the `ApprovalTask`. |
| 159 | +- Dispatch logs or `kubectl get approvaltask -o yaml` output provide the approval history for auditing. |
| 160 | + |
| 161 | +## Troubleshooting |
| 162 | + |
| 163 | +- **Approval task never appears:** Confirm the administrator-installed `ManualApprovalGate` CR is `READY`. Without the controller, `CustomRun` objects remain pending. |
| 164 | +- **Approvers lack permissions:** Grant them `get`, `list`, `update`, and `patch` access to `approvaltasks.openshift-pipelines.org` in the relevant namespace. |
| 165 | +- **Pipeline ended before approval finished:** Set both `PipelineRun.spec.timeouts.pipeline` and `PipelineRun.spec.timeouts.tasks` to cover the expected approval window, and ensure the approval `timeout` is realistic. Otherwise the run may time out even if approvers have not responded. |
| 166 | +- **Stuck in pending even after approvals:** Check `status.approversResponse` for users who changed their vote or rejected. You may need to update the approver list and rerun the pipeline. |
| 167 | + |
| 168 | +## User and group identifiers |
| 169 | + |
| 170 | +`Manual Approval Gate` relies on your platform's identity provider to match approver names. Always use the canonical identifiers exposed by the provider rather than UI display names. For example, on `Alauda Container Platform`: |
| 171 | + |
| 172 | +```bash |
| 173 | +$ kubectl get users.auth.alauda.io |
| 174 | +NAME TYPE USERNAME AGE |
| 175 | +21232f297a57a5a743894a0e4a801fc3 local admin 19d |
| 176 | +``` |
| 177 | + |
| 178 | +Use the `USERNAME` column (such as `admin`) when adding user approvers. |
| 179 | + |
| 180 | +```bash |
| 181 | +$ kubectl get groups.auth.alauda.io |
| 182 | +NAME DISPLAYNAME CONNTYPE CONNID AGE |
| 183 | +g-v9mfs test-group local local 19d |
| 184 | +``` |
| 185 | + |
| 186 | +Use the `NAME` column (such as `g-v9mfs`) when referencing group approvers (for example, `group:g-v9mfs`). Other platforms expose similar resources—consult the identity service documentation for the exact field names. |
| 187 | + |
| 188 | +## Learn More |
| 189 | + |
| 190 | +- [Deploying `Manual Approval Gate` as an administrator](../../how_to/manual_approval_gate_operator.mdx) |
| 191 | +- [Manual Approval Gate upstream repository](https://github.com/openshift-pipelines/manual-approval-gate) |
0 commit comments