docs(plans): plan the charts artifactRegistry appConfig block
Summary
Plans the deployment-config half of the AR-to-GitLab-Rails connection: the
GitLab Helm chart learns a global.appConfig.artifactRegistry block, and
staging GitLab.com sets it.
Adds docs/plans/monolith/2026-08-25-charts-artifact-registry-appconfig.md and
its index row. No spec amendment: the chart delivers values into the
Gitlab.config.artifact_registry stanza monolith/S02 already owns, and changes
no contract that spec states. The keys themselves are planned by
docs/plans/monolith/2026-08-20-s02-service-token-credential.md, merged in
!1827 (merged),
and added by gitlab!252017;
this plan fills them.
Plan shape
Three steps, in three repositories:
gitlab-org/charts/gitlab-- theartifactRegistryappConfig block: thegitlab.ymlrender, the token mount across webservice/sidekiq/toolbox, thecheckConfigguard, chart template specs, and the doc page.gitlab-com/gl-infra/k8s-workloads/gitlab-com-- the gstg ExternalSecret and values block.- This repository --
docs/dev/self-managed-install.mdsection 16, whose "the chart accepts the value and ignores it" stops holding the day Step 1 merges.
Steps 1 and 2 cannot be one MR: the chart change has to merge, ship in a chart release, and be vendored before any values file can name the key.
Three deviations from the precedent
charts/gitlab!5125 (iam_data_access_service) is the model, and the plan
departs from it in three places, each named with its reason:
- The rendered block is gated. The precedent renders its stanza on every
install. The reason for AR is operator legibility, not client behaviour:
""andnilare indistinguishable to the merged client, becauseClient#initializerunsbase_url.presence || Gitlab.config...and then a blank guard, so an empty value never reachesvalidate_base_url!. What a renderedapi_url: ""does buy is a meaningless key in a file operators read and diff, and an unconfigured install that looks configured. - Only keys Rails reads are emitted. No
enabled:ingitlab.yml-- the precedent renders one and Rails ignores it. - The chart mints no token. A chart-generated secret authenticates against
nothing: AR validates against its own
auth.gitlab_api.service_tokenfrom its own Vault path. The secret is operator-supplied.
A fourth decision is not a deviation but an absence in the precedent: api_url
and the token are separable, so the checkConfig requires only apiUrl.
That is what lets an environment set the URL before the token exists.
Two contradictions with cited sources, recorded rather than resolved
- gitlab#619481 says to promote the ExternalSecret to the shared values file
in the gprd follow-up. The precedent it cites tried that in
k8s-workloads/gitlab-com!5589and reverted it, on the risk that a shared definition also syncs againstpre, whose Vault path may not be provisioned. The sources state that conditionally; nobody confirmed the path is absent. Onmastertoday the IAM secret is env-scoped in bothgstg.yaml.gotmplandgprd.yaml.gotmpland absent fromvalues.yaml.gotmpl. - gitlab#606085 is open, and its Scope checklist is Steps 1 and 2 of this
plan. The plan tracks the work under gitlab#619471 and gitlab#619481 instead,
so #606085 needs closing or explicit rescoping -- bookkeeping outside this MR.
Its Risks section also says an unset
api_urlmakes Rails targethttp://localhost:8080; that default applies only underRails.env.development?/test?, so a.compod readsnil.
Merge order
gitlab#617724 (the Rails keys and the header, open as
gitlab!252017)
must land before Step 2 delivers a request; until then a mounted token is an
unread file. It does not gate Step 1. Step 4 adds production behind Step 2's
verification.
AR's guard has two exclusive modes, so an environment configures
auth.gitlab_api.service_token AR-side before Rails mounts the token there.
ops/artifact-registry#356 completed that rollout on 2026-08-21, so the ordering
is already satisfied in every deployed environment and is live only for a new
one. The Vault write still precedes the k8s-workloads merge, because the
ExternalSecret syncs on landing and a missing path is a failing sync rather than
a no-op.
Governing ADRs
- ADR-020 Authentication Flow
governs the credential this chart mounts. Conforms: a static symmetric
per-edge secret, provisioned to the calling service as a deployment credential
and never visible to end users, which is why the chart mints nothing and the
value is operator-supplied. Read against the handbook copy, because
scripts/adr-freshness.shshows the local mirror stale with020_authentication_flow.mdamong the drifted files. - ADR-014 (
docs/adr/014_frontend_to_artifact_registry.md, not drifted) governs the client being configured. Conforms: the credential stays server-side, mounted into webservice, sidekiq and toolbox only. - Neither ADR states chart or deployment mechanics, so nothing here deviates. That is the answer after checking, not a default.
Testing
No code and no tests in this MR; verification is a consistency read. What was checked, and against what:
- Every
charts/gitlabpath, template, helper and count in the precedent table against that project'smasterthrough the API, including the "sixteen files, four new" claim about !5125. - Every
k8s-workloads/gitlab-comclaim againstmaster: the two file paths, the full ExternalSecret shape, the !5589 revert, and the gstg fan-out, which is six environments --gstg,gstg-gitlab-36dv2,gstg-cnyandgstg-us-east1-{b,c,d}.gstg-gitlab-36dv2runs no gitlab release but does sync external secrets under its own Vault auth mount. - Every cited issue's title and state through the API.
- The Rails side against
origin/masterof$GITLAB_MONOLITH_PATHby symbol, and AR's own config againstorigin/mainof this repository. markdownlint-cli2,valeandlycheeclean on both changed files.
Not verifiable from here, and flagged in the plan rather than asserted: Vault
contents on either side, and the config-mgmt policy grant, which is stated
from !5586's description rather than from the MR.
Related to gitlab-org/gitlab#619471 (closed) Related to gitlab-org/gitlab#619481 (closed)