fix(config): keep glab-managed keys in the global config

What does this MR do and why?

A repository's local config could override keys glab sets for itself, while glab wrote those keys only to the global file. A stale local value then won every read, and every write went somewhere nothing read, so glab duo cli update re-downloaded the same version on every run in that repository.

Scope does not express this. ScopeGlobal means "not per host", and ordinary ScopeGlobal keys such as git_protocol and branch_prefix are meant to be set per repository.

This adds a GlobalOnly attribute to KeyDef and sets it on the ten keys the schema documents as automatically set. Reads skip the local file for those, and config set routes them to the global file. Either change alone breaks the loop; both together also stop new local values being written.

References

Closes #8571 (closed)

Found while reviewing !3981 (merged)

Related: #8568 (closed)

Differences

Before, running the issue's reproduction:

glab config set duo_cli_binary_version 9.5.0      # local
glab config set --global duo_cli_binary_version 9.26.0
glab config get duo_cli_binary_version            # 9.5.0

After: the same sequence returns 9.26.0, and no local file is created at all, because the first set is routed to the global config.

Keys affected, all ten the schema already describes as "(automatically set)": duo_cli_binary_path, duo_cli_binary_version, duo_cli_binary_checksum, duo_cli_last_update_check, the four orbit_cli_* equivalents, last_seen_version and last_whatsnew_version.

Ordinary keys are untouched: a local git_protocol still wins over a global one, and there is a test pinning that.

How to set up and validate locally

End to end, the reproduction from the issue:

go build -o /tmp/glab ./cmd/glab
cd "$(mktemp -d)" && git init -q
export GLAB_CONFIG_DIR="$(mktemp -d)"
/tmp/glab config set duo_cli_binary_version 9.5.0
/tmp/glab config set --global duo_cli_binary_version 9.26.0
/tmp/glab config get duo_cli_binary_version

To see the tests catch each half separately:

  • Change if !IsGlobalOnlyKey(key) in GetWithSource to if true.
    Test_GetWithSource_GlobalOnlyKeySkipsLocalConfig fails with 9.5.0 where
    9.26.0 belongs.
  • Drop || config.IsGlobalOnlyKey(o.key) from writeGlobal in config_set.go.
    TestConfigSet_GlobalOnlyKeyWritesGloballyWithoutTheFlag takes the local path,
    which configStub.Local returns nil for, so the write never reaches the config.
## One decision worth a reviewer's eye

The issue offered two options for `config set` without `--global`: route the
write to the global file, or reject it with an error naming `--global`.

This routes it. These keys are glab's own state rather than something a user
tunes, so the value taking effect is what someone would want, and an error for a
key the user probably did not type deliberately seemed like friction. Happy to
switch it to a rejection if you would rather it be explicit.

MR acceptance checklist

  • Tests added for both halves, each verified to fail without its half of the fix
  • Reproduced end to end against binaries built from this branch and from main
  • Ordinary keys keep local-over-global precedence, with a test
  • The key set is derived from KeySchema at init, aliases included, so it cannot drift
  • Conforms to the code review guidelines

Merge request reports

Loading
Loading