2 Commits

Author SHA1 Message Date
7d95259667 🐛 fix(config): remove racy log.Info in WatchAndApply cancel goroutine
All checks were successful
CI/CD Pipeline / Build Docker Cache (push) Successful in 17s
CI/CD Pipeline / CI Pipeline (push) Successful in 6m20s
CI/CD Pipeline / Trigger Docker Push (push) Has been skipped
The cancel-handler goroutine emitted a "watcher stopped" log AFTER
setting the watcherStopped flag. Because viper's internal watcher
goroutine (started by viper.WatchConfig) has no public Stop and can
outlive the context, this log call would race with subsequent
zerolog.SetGlobalLevel from the next test's LoadConfig → SetupLogging.

Symptom (under go test -race ./pkg/config/...):
  WARNING: DATA RACE
  Write at zerolog.SetGlobalLevel
  Previous read by zerolog.(*Logger).disabled in log.Info(...)

Fix: drop the informational log. The flag is sufficient — the cancel
ack does not need to be observable. Test cleanups (defer cancel())
already serialize via the t.Cleanup teardown order.

Verified: go test -race ./pkg/config/... passes, full BDD suite green.
2026-05-05 09:39:46 +02:00
3d9746ed65 🐛 fix(ci): remove dollar-double-brace expression from comment that still gets interpolated (#47)
All checks were successful
CI/CD Pipeline / Build Docker Cache (push) Successful in 10s
CI/CD Pipeline / CI Pipeline (push) Successful in 3m44s
CI/CD Pipeline / Trigger Docker Push (push) Successful in 5s
Co-authored-by: Gabriel Radureau <arcodange@gmail.com>
Co-committed-by: Gabriel Radureau <arcodange@gmail.com>
2026-05-05 09:34:00 +02:00
2 changed files with 9 additions and 5 deletions

View File

@@ -299,10 +299,11 @@ jobs:
# Check for version bump on main branch # Check for version bump on main branch
if [ "${{ github.ref }}" = "refs/heads/main" ]; then if [ "${{ github.ref }}" = "refs/heads/main" ]; then
echo "🔖 Checking for version bump..." echo "🔖 Checking for version bump..."
# Always read from git log: ${{ github.event.head_commit.message }} expression # Read commit message from git, NOT from the workflow event payload.
# is interpolated literally into the shell script, so any backtick, unbalanced # The event-payload expression is interpolated literally into the
# quote, or special char in a commit body breaks the next line of the script # rendered script (even inside comments — see PR #38 + #46), so any
# (observed on PR #32-#35: 'syntax error: unexpected newline'). git log is safe. # backtick / unbalanced quote / multi-line body breaks bash parsing.
# git log is interpolation-free and safe.
COMMIT_MSG=$(git log -1 --pretty=%B) COMMIT_MSG=$(git log -1 --pretty=%B)
./scripts/ci-version-bump.sh "$COMMIT_MSG" --no-push ./scripts/ci-version-bump.sh "$COMMIT_MSG" --no-push
fi fi

View File

@@ -730,11 +730,14 @@ func (c *Config) WatchAndApply(ctx context.Context) {
// Stop the watcher on context cancel — we set a flag that the // Stop the watcher on context cancel — we set a flag that the
// OnConfigChange handler checks, avoiding the race with viper's // OnConfigChange handler checks, avoiding the race with viper's
// internal state that would occur if we called OnConfigChange again. // internal state that would occur if we called OnConfigChange again.
// We deliberately do NOT log here: viper's internal watcher goroutine
// has no public Stop, so it can outlive ctx, and a zerolog call here
// would race with the next test's LoadConfig → SetupLogging →
// zerolog.SetGlobalLevel under -race (observed 2026-05-05).
go func() { go func() {
<-ctx.Done() <-ctx.Done()
c.reloadMu.Lock() c.reloadMu.Lock()
c.watcherStopped = true c.watcherStopped = true
c.reloadMu.Unlock() c.reloadMu.Unlock()
log.Info().Msg("Config hot-reload watcher stopped")
}() }()
} }