refactor(config): canonical schema with `config set` validation
Summary
Closes #8335 (closed).
Replace the YAML lock file and the assorted manual switches with a single declarative KeyDef registry in internal/config/schema.go. The schema is the single source of truth for every configuration concern. As a user-facing consequence, glab config set now rejects keys that aren't registered — so plausible-looking-but-nonexistent keys (such as the oauth_scopes example from #8334 (closed)) can no longer be silently written to the config file.
What the schema drives
A single KeyDef entry per key now feeds:
- the blank-config tree returned by
NewBlankConfig(what gets written on first run); - validation in
glab config set(KnownKeys/IsKnownKey); - per-key default values (
defaultFor, gated byKeyDef.Fallback); - legacy-alias resolution (
ConfigKeyEquivalence); - environment-variable resolution (
EnvKeyEquivalence), with CI-autologin overrides layered on top; - keyring eligibility for sensitive values.
Internal-state keys (oauth2_*, is_oauth2, refresh_token) are explicit KeyDef entries with UserSettable: false. They're still recognized by Get and env-var lookups but excluded from the blank config and from config set.
What was removed
internal/config/config.yaml.lock— the YAML template is replaced by the schema.internal/config/config_stub.goandinternal/config/gen.go— no codegen step; the runtime builds the blank-config tree fromKeySchema.- The
gen-configMakefile target. - The
chmod 600 internal/config/config.yaml.lockworkaround in.gitlab-ci.yml. - The AST-based drift test. The schema-in-Go shape makes the drift problem impossible at the language level: a
cfg.Get("", "new_key")without a matchingKeyDefhas no env-var resolution, no default, and is rejected byconfig set— no parsing needed. - The hand-maintained switches in
config_mapping.go(ConfigKeyEquivalence,EnvKeyEquivalence,defaultFor) and thekeyringEligibleKeysmap inconfig.go— all derived from the schema now. internal/config/Readme.md— non-standard location, no inbound links; replaced byKeyDefdoc comments and a pointer inAGENTS.md.
What was updated alongside
.gitlab/duo/mr-review-instructions.yaml— the "Config and environment" block referenced the lock file andmake gen-config; it now points contributors atKeySchemaininternal/config/schema.go.AGENTS.md— added a one-line pointer tointernal/config/schema.goin the existing "helpers" list under "Working in this codebase".
Adding a new key
Append a KeyDef to KeySchema:
{
Name: "my_new_key",
Scope: ScopeGlobal, // or ScopePerHost
Type: TypeString, // or TypeBool, TypeList
Default: "",
Description: "What this key controls. Becomes the head comment.",
UserSettable: true,
},No code generation, no file-permission dance, no out-of-band drift check.
Test plan
-
make testpasses -
make lintpasses -
glab config set oauth_scopes "openid profile"errors with the new message -
glab config set editor vimstill works - All env-var lookups still resolve (e.g.
GITLAB_TOKEN,CI_JOB_TOKENin CI auto-login mode) -
glabreads defaults forgit_protocol,api_protocol, andglamour_stylewhen the user's config has no entry (the keys withFallback: true) - CI's
check_go_generated_codejob passes (no morechmodstep against the deleted lock file)