Decouple pipeline execution from push/merge permissions on protected branches
<!--IssueSummary start--> <details> <summary> Everyone can contribute. [Help move this issue forward](https://handbook.gitlab.com/handbook/marketing/developer-relations/contributor-success/community-contributors-workflows/#contributor-links) while earning points, leveling up and collecting rewards. </summary> - [Close this issue](https://contributors.gitlab.com/manage-issue?action=close&projectId=278964&issueIid=334413) </details> <!--IssueSummary end--> <!--This template is a great use for issues that are feature::additions or technical tasks for larger issues.--> ## Status Update (12th May 2026) Thanks to everyone who has commented, upvoted, and shared use cases on this issue over the years. We hear you, and we want to share where things stand. We've completed the planning and scoping work for this feature: * **Defined the full scope** across three workstreams: the permission layer (protected branch settings), pipeline execution compatibility, and the custom role integration for Ultimate customers * **Identified the key technical constraints** — most importantly, that the entire pipeline execution stack currently assumes `run_pipeline == write to ref`, and that shipping the permission layer alone without fixing this would create silent failures and need to be carefully audited before we roll out this permission We have a clear plan and understand the work involved. We do not yet have a committed timeline for when this will be scheduled for implementation. We recognize this issue has significant customer interest and has been open for a long time. That context is factored into how we're thinking about priority. We'll update this issue when we have a milestone to share. In the meantime, the description has been updated to reflect the current plan in full — including the known constraints and what "done" looks like. If anything there doesn't match your use case or raises questions, please let us know. ## Problem GitLab currently ties the ability to run a pipeline on a protected branch directly to push/merge permissions. This means any user who needs to trigger, retry, or manually run a pipeline on a protected branch must be granted push or merge access — even if they have no legitimate reason to modify code. This creates two problems: 1. **Separation of duties is impossible.** Teams cannot grant pipeline execution rights without also granting code write access, violating least-privilege principles required in enterprise and government environments. 2. **Multi-project pipeline workflows break.** When a pipeline in Project A triggers a downstream pipeline on a protected branch in Project B, the triggering user needs Developer+ access to Project B — even if their only interaction is pulling the pipeline trigger. ## Steps to reproduce 1. Create a project and protect a branch. 2. Attempt to run a pipeline as a user who does not have merge or push permissions to the branch. This feature has 2 must-have parts (Part 1 and Part 2) and an additional additive feature for Ultimate only customers. ## Goals **Part 1 — The Permission Layer - DRI** ~&quot;group::source code&quot; * Add `run_pipeline` as a standalone configurable permission in protected branch settings, decoupled from push/merge. * Available for all Tiers * Maintain backward compatibility — existing behavior (Maintainer-only by default) does not change unless explicitly reconfigured. **Part 2 — Pipeline Execution Compatibility** - DRI ~&quot;group::pipeline execution&quot; * Block runtime variable injection * Audit and fix (or explicitly document) all pipeline job types that currently assume `run_pipeline == write to ref`. * Ensure the execution stack works correctly when the triggering user has run access but not push/merge access. **Both Part 1 and Part 2 are must have for us to recommend customers to use the new `run_pipeline` permission** A related but not required feature request is to make this permission customizable for Ultimate users ### Custom Role Permission (Ultimate Only) DRI: ~&quot;group::authorization&quot; In parallel, expose `run_pipeline` as a customizable permission within the existing custom roles framework, implemented in collaboration with This allows Ultimate admins to create a role such as "Pipeline Operator" with only the `run_pipeline` permission — no read/write access to code, no merge rights — and assign it to users or groups at the project or group level. **Protected branch settings always take precedence over custom role permissions. A custom role never overrides branch protection configuration.** The relationship between the two is additive, not competitive: * The custom role grants a user the _capability_ to run pipelines (i.e., they are eligible). * The protected branch setting grants _access_ to a specific branch (i.e., they are permitted on that branch). * **Both conditions must be satisfied.** A user with the `run_pipeline` custom role who is not listed in the branch's "Allowed to run pipelines" setting cannot run a pipeline on that branch. This directly addresses the enterprise use case where release engineers or contractors need to execute pipelines without any code access. ## Proposal ### Known Constraints > :warning: Input from the Verify engineering team (April 2026) identified several second-order effects of decoupling `run_pipeline` from `write to ref`. These are not blockers, but they are **implementation requirements** that engineering must explicitly design for. The entire pipeline execution stack currently assumes that triggering a pipeline implies write access to the branch. This assumption is embedded in how deployments, artifact uploads, tag creation, and image pushes work. Users with trigger-only access may find that: * **Deployment jobs fail silently** — jobs that push to environments, write tags, or push container images all assume write access to the ref. * **Artifact operations may fail** — artifact uploads are tied to the same access assumption. * **The pipeline runs but downstream steps break** — the failure mode is not a clean error at trigger time, but silent failures mid-pipeline, which is a poor user experience. We will need to test all this scenarios and either fix them or make them known constraint. #### What you can do with this permission 1. Run a pipeline manually 2. Retry a pipeline #### What you cannot do with this permission 1. Set custom variables at pipeline runtime ### Protected Branch Settings UI (All Tiers) Add a new "Allowed to run pipelines" row to the protected branch configuration UI, mirroring the existing "Allowed to merge" and "Allowed to push" rows. **Default value:** Maintainers (preserves today's behavior — no change for existing projects unless reconfigured). **Configurable values:** * No one * Maintainers * Developers + Maintainers * Specific roles, groups, or individual users ### <!--Use this section to explain the feature and how it will work. It can be helpful to add technical details, design proposals, and links to related epics or issues.--> <!--Consider adding related issues and epics to this issue. You can also reference the Feature Proposal Template (https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/issue_templates/Feature%20proposal%20-%20detailed.md) for additional details to consider adding to this issue. Additionally, as a data oriented organization, when your feature exits planning breakdown, consider adding the `What does success look like, and how can we measure that?` section.--> ##
issue