Skip to content

Commit ca28926

Browse files
ostermanclaude
andcommitted
fix(emulator): CI-proof the local-gitops commit identity and kubeconfig retry
Two CI failures on the local-gitops / native-emulator work: - [floci] go e2e: TestLocalGitOpsPushE2E failed with `git commit (exit 128)` — the CI runner has no global git identity, and the deployments repo did not pin one, so the provisioner's commit hit "Please tell me who you are". Pin `commit.author` on the example's deployments repo (the schema documents this as required in CI) and make the E2E run with GIT_CONFIG_GLOBAL/SYSTEM=os.DevNull so it reproduces the no-ambient-identity runner and self-validates the fix. - [Acceptance/windows]: TestManager_Resolve_KubernetesKubeconfigError flaked — with kubeconfigReadyTimeout=0 the harvest retry used `time.Now().After(deadline)` (strict >). On Windows's coarse monotonic clock the first post-attempt read can equal the deadline, so it polled again (an extra List call) and tripped the mock's Times(2). Use reached-or-passed semantics (`!time.Now().Before(deadline)`) so a zero timeout makes exactly one attempt on every platform. Validated on Podman: push E2E passes with no ambient git identity; emulator unit tests (incl. the kubeconfig test) pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 407fee6 commit ca28926

3 files changed

Lines changed: 18 additions & 3 deletions

File tree

examples/local-gitops/atmos.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,13 @@ git:
2121
# demo is self-contained and each fresh `gitserver` lines up with a fresh
2222
# workdir. `atmos teardown` removes it; the .gitignore keeps it out of git.
2323
workdir: .atmos/git/deployments
24+
commit:
25+
# Pin the committer identity so the provisioner's `git commit` works on a CI
26+
# runner with no global git user configured (otherwise: "Please tell me who
27+
# you are", exit 128). Passed as `git -c user.name -c user.email`.
28+
author:
29+
name: Atmos GitOps
30+
email: atmos-gitops@localhost
2431

2532
stacks:
2633
base_path: "stacks"

pkg/emulator/kubeconfig.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,11 @@ func (m *Manager) Kubeconfig(ctx context.Context, stack, name string) ([]byte, e
5050

5151
// Only the readiness race (container up, kubeconfig not yet written) is worth
5252
// polling. A missing container or an unbound port is terminal — fail fast.
53-
if !retryable || time.Now().After(deadline) {
53+
// Use >= (reached-or-passed) rather than strictly-after so a zero timeout makes
54+
// exactly one attempt on every platform: on coarse-granularity clocks (Windows)
55+
// `time.Now()` can still equal the deadline after the first attempt, and a
56+
// strict After() would spuriously poll again.
57+
if !retryable || !time.Now().Before(deadline) {
5458
return nil, lastErr
5559
}
5660
select {

tests/local_gitops_test.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,12 @@ const (
3333
func gitOpsE2EEnv(workdir string) map[string]string {
3434
return map[string]string{
3535
"ATMOS_CLI_CONFIG_PATH": workdir,
36-
// Don't let a developer's global git identity sign or rewrite demo commits.
37-
"GIT_TERMINAL_PROMPT": "0",
36+
"GIT_TERMINAL_PROMPT": "0",
37+
// Reproduce a CI runner: no global/system git identity. The provisioner's
38+
// commit must succeed via the repo's configured commit.author, not an ambient
39+
// developer identity. os.DevNull is cross-platform ("/dev/null" or "NUL").
40+
"GIT_CONFIG_GLOBAL": os.DevNull,
41+
"GIT_CONFIG_SYSTEM": os.DevNull,
3842
}
3943
}
4044

0 commit comments

Comments
 (0)