Add governPolicyUpdate GraphQL mutation for the policy store
What does this MR do and why?
Adds a governPolicyUpdate GraphQL mutation so the frontend policy editor can update an existing policy-store policy without going through the REST endpoint. It performs a partial update: only fields supplied by the client change, and omitted fields keep their current values. Experiment and permission gating stay in PolicyStore::UpdateService; the mutation only maps service errors (not_found/forbidden/experiment_not_active → resource-not-available, invalid → payload errors).
Two things reviewers will notice:
- The six optional arguments shared with
governPolicyCreatemove intoMutations::Govern::CommonMutationArguments. This reordersGovernPolicyCreateInputarguments in the introspection artifact — input object fields are unordered in GraphQL, so the create mutation is semantically unchanged. policyIdis a plainInt, not a GlobalID, matching theGovernPolicy.idfield — see the linked decision MR for the rationale and the Int32-widening caveat tracked for experiment graduation.
References
- Closes https://gitlab.com/gitlab-org/gitlab/-/work_items/617786 (confidential issue)
- Approved implementation plan: https://gitlab.com/gitlab-org/gitlab/-/work_items/617786#note_3739611153
- Int-id decision: !250240 (merged)
- Sibling create mutation: !250904 (merged)
Screenshots or screen recordings
No UI changes.
How to set up and validate locally
-
Enable the experiment in a rails console:
Feature.enable(:security_policies_v2) ApplicationSetting.current.update!(policy_store_experiment_enabled: true) -
Create a policy first (as an organization owner) via the
governPolicyCreatemutation or the REST endpoint, and note itsid. -
Run this mutation in GraphiQL (
http://gdk.test:3000/-/graphql-explorer), as an owner of the organization:mutation { governPolicyUpdate(input: { organizationId: "gid://gitlab/Organizations::Organization/1", policyId: 1, name: "Renamed policy", mode: "warn" }) { policy { id name mode description triggerType } errors } } -
Expected:
nameandmodechange;descriptionandtriggerTypekeep their previous values (partial update). A nonexistentpolicyIdreturns a top-level "resource not available" error.
Verification
- Request spec:
ee/spec/requests/api/graphql/mutations/govern/policy_update_spec.rb— 20 examples, 0 failures, 1 pending (pending example is inside the shared granular-token example, same as the create mutation spec). - Unit spec:
ee/spec/graphql/mutations/govern/policy_update_spec.rb— 5 examples, 0 failures. bundle exec rake gitlab:graphql:update_all,gitlab:permissions:validate, andgitlab:permissions:graphql:compile_docsall run clean; artifacts committed.- Adversarial pre-review verdict: pass with findings. All pre-MR findings addressed (full-update spec coverage added, commit restructured so schema artifacts land with the change, changelog omission aligned with the sibling create MR). Remaining low-severity findings deferred as follow-ups: extracting the duplicated error-mapping block into a shared concern, a
MAX_ARRAY_SIZEparity example, and explicit-null/no-op update coverage.
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist.