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:

  1. gitlab-org/charts/gitlab -- the artifactRegistry appConfig block: the gitlab.yml render, the token mount across webservice/sidekiq/toolbox, the checkConfig guard, chart template specs, and the doc page.
  2. gitlab-com/gl-infra/k8s-workloads/gitlab-com -- the gstg ExternalSecret and values block.
  3. This repository -- docs/dev/self-managed-install.md section 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: "" and nil are indistinguishable to the merged client, because Client#initialize runs base_url.presence || Gitlab.config... and then a blank guard, so an empty value never reaches validate_base_url!. What a rendered api_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: in gitlab.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_token from 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!5589 and reverted it, on the risk that a shared definition also syncs against pre, whose Vault path may not be provisioned. The sources state that conditionally; nobody confirmed the path is absent. On master today the IAM secret is env-scoped in both gstg.yaml.gotmpl and gprd.yaml.gotmpl and absent from values.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_url makes Rails target http://localhost:8080; that default applies only under Rails.env.development?/test?, so a .com pod reads nil.

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.sh shows the local mirror stale with 020_authentication_flow.md among 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/gitlab path, template, helper and count in the precedent table against that project's master through the API, including the "sixteen files, four new" claim about !5125.
  • Every k8s-workloads/gitlab-com claim against master: 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-cny and gstg-us-east1-{b,c,d}. gstg-gitlab-36dv2 runs 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/master of $GITLAB_MONOLITH_PATH by symbol, and AR's own config against origin/main of this repository.
  • markdownlint-cli2, vale and lychee clean 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)

Edited by Narendran

Merge request reports

Loading
Loading