Deployments stuck in unapprovable state if `Prevent outdated deployment jobs` is enabled and unified approval rules are used
Given that this problem will go away with https://docs.gitlab.com/ee/ci/environments/deployment_approvals.html#multiple-approval-rules, we probably won't fix
From the internal investigation.
Users can't approve the deployment and see this screen:
| header |
|---|
![]() |
To reproduce:
- enable deployment approvals feature
- create a few manual deployments(by updating code!)
- deploy the latest deployment
- try to approve/reject old deployment
Workaround
There are 2 workarounds:
- use multiple approval rules instead https://docs.gitlab.com/ee/ci/environments/deployment_approvals.html#multiple-approval-rules (they don't have this bug)
- temporarily disable https://docs.gitlab.com/ee/ci/environments/deployment_safety.html#prevent-outdated-deployment-jobs, reject these old jobs and enable it back
Debugging
DeploymentPolicy.new(user, deployment).debug(:approve_deployment)
- [0] prevent when all?(anonymous, ~public_project) ((@gudekb : Project/38987106))
- [14] prevent when all?(ip_enforcement_prevents_access, ~admin, ~auditor, strict_ip_enforcement)
- [28] prevent when all?(~public_project, ~internal_access, ~project_allowed_for_job_token)
- [267] enable when all?(needs_approval, ~has_approval_rules, can?(:update_deployment))
- [0] enable when all?(needs_approval, has_approval_rules, can?(:read_deployment), approval_rule_for_user)
DeploymentPolicy.new(user, deployment).debug(:update_deployment)
- [0] prevent when archived
- [0] prevent when all?(anonymous, ~public_project)
- [7] prevent when read_only
- [14] prevent when ~can_update_deployment
- [0] prevent when environments_disabled
+ [0] enable when can?(:developer_access)
- [0] prevent when builds_disabled
- [0] prevent when repository_disabled
- [0] prevent when all?(~public_project, ~internal_access, ~project_allowed_for_job_token)
- [0] prevent when all?(ip_enforcement_prevents_access, ~admin, ~auditor, strict_ip_enforcement)
+ [28] prevent when all?(has_deployable, ~can_retry_deployable)
Ci::BuildPolicy.new(user, deployment.deployable).debug(:update_build)
- [0] prevent when archived
- [0] prevent when all?(anonymous, ~public_project)
- [7] prevent when read_only
+ [14] prevent when outdated_deployment
[14] prevent when all?(ip_enforcement_prevents_access, ~admin, ~auditor, strict_ip_enforcement)
[16] enable when reporter_has_access_to_protected_environment
[28] prevent when builds_disabled
[28] prevent when repository_disabled
[28] prevent when all?(~public_project, ~internal_access, ~project_allowed_for_job_token)
[85] prevent when all?(~can?(:jailbreak), any?(archived, protected_ref, protected_environment))
[323] enable when can?(:developer_access)
[337] enable when all?(can?(:public_access), branch_allows_collaboration)
[765] prevent when ~can?(:update_commit_status)
Problem
- Prevent execution of outdated manual deployment... (!97171 - merged) we introduced a mechanism to prevent outdated manual jobs from being run.
- we also made deployment approvals to be dependent on the
update_deploymentpermission
So now when deployment requires approvals, but is outdated it's in this weird state:
- you can't approve or reject it, but it's shown as requesting approvals
Potential solution
- Instead of preventing old manual jobs from running, just cancel them after the newer deployment succeeds.
- Or simply deprecate unified approval rules(we already done this)
Doing the first may still make sense even without context of this bug
