Skip to content

Commit 020c051

Browse files
fix: keep oasdiff.* lookup as back-compat fallback after .oasdiff.*
The previous commit dropped the legacy oasdiff.{yaml,...} cwd lookup entirely. That's a real backward-compatibility break: the lookup has been live for a long time, and we don't know how many CLI users have oasdiff.yaml committed to their working directories. Silently breaking those users for the sake of strict convention isn't worth it when the fix costs nothing. Lookup order now (in cwd, first hit wins): 1. .oasdiff.{json,yaml,yml,toml,hcl} — preferred (dotfile convention) 2. oasdiff.{json,yaml,yml,toml,hcl} — legacy fallback, no warning, no plan to remove Existing oasdiff.* users don't have to do anything; .oasdiff.* is recommended for new setups. Tests: TestViper_DefaultLookup_LegacyOasdiffYamlIsIgnored renamed and inverted to TestViper_DefaultLookup_LegacyOasdiffYamlStillWorks. New TestViper_DefaultLookup_DotPreferredOverLegacy asserts the precedence order when both files coexist. CONFIG-FILES.md documents both filenames and the precedence.
1 parent 6acb70a commit 020c051

3 files changed

Lines changed: 45 additions & 18 deletions

File tree

docs/CONFIG-FILES.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,12 @@ This is useful for complex configurations or repeated usage patterns.
44

55
## Default lookup
66

7-
By default, `oasdiff` looks for `.oasdiff.{json,yaml,yml,toml,hcl}` in the directory where the command is run.
7+
By default, `oasdiff` looks for a config file in the directory where the command is run, in this order:
8+
9+
1. `.oasdiff.{json,yaml,yml,toml,hcl}` — preferred (dotfile convention)
10+
2. `oasdiff.{json,yaml,yml,toml,hcl}` — legacy fallback, kept for back-compat with existing setups
11+
12+
`.oasdiff.*` is recommended for new setups. Existing `oasdiff.*` users don't need to migrate — both filenames continue to work.
813

914
For example, see [.oasdiff.yaml](../examples/.oasdiff.yaml).
1015

internal/viper.go

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,9 @@ func RunViper(cmd *cobra.Command, v IViper) *ReturnError {
4848
//
4949
// 1. --config <path> flag (when set, the file MUST exist; missing or malformed file is an error)
5050
// 2. OASDIFF_CONFIG environment variable (same semantics)
51-
// 3. Default cwd lookup for .oasdiff.{json,yaml,yml,toml,hcl} (silent when missing)
51+
// 3. Default cwd lookup, in order:
52+
// a. .oasdiff.{json,yaml,yml,toml,hcl} (preferred — dotfile convention)
53+
// b. oasdiff.{json,yaml,yml,toml,hcl} (legacy — kept for back-compat, still works without warning)
5254
//
5355
// Returns nil when no config is found via the default lookup; only the two
5456
// explicit-override paths surface "file not found" as an error.
@@ -61,18 +63,24 @@ func readConfFile(cmd *cobra.Command, v IViper) error {
6163
return nil
6264
}
6365

64-
// Default lookup: .oasdiff.{json,yaml,yml,toml,hcl} in cwd.
65-
v.SetConfigName(".oasdiff")
66-
v.AddConfigPath(".")
66+
// Default lookup: try .oasdiff.* first (preferred), then oasdiff.*
67+
// (legacy back-compat) — cwd-scoped, all viper-supported extensions.
68+
for _, name := range []string{".oasdiff", "oasdiff"} {
69+
v.SetConfigName(name)
70+
v.AddConfigPath(".")
6771

68-
if err := v.ReadInConfig(); err != nil {
69-
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
70-
// Config file not found; ignore error
71-
} else {
72-
return fmt.Errorf("read error: %s", err)
72+
err := v.ReadInConfig()
73+
if err == nil {
74+
return nil
75+
}
76+
if _, notFound := err.(viper.ConfigFileNotFoundError); notFound {
77+
continue // try the next candidate
7378
}
79+
// File found but malformed — surface the error.
80+
return fmt.Errorf("read error: %s", err)
7481
}
7582

83+
// No config file found in cwd; not an error.
7684
return nil
7785
}
7886

internal/viper_test.go

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -205,18 +205,32 @@ func TestViper_DefaultLookup_DotOasdiffYaml(t *testing.T) {
205205
"failed to load config file: invalid lang \"invalid\", allowed values: en, ru, pt-br, es")
206206
}
207207

208-
// TestViper_DefaultLookup_LegacyOasdiffYamlIsIgnored: a legacy
209-
// oasdiff.yaml (no leading dot) at repo root is no longer recognized
210-
// by the default lookup. The CLI should silently skip it.
211-
func TestViper_DefaultLookup_LegacyOasdiffYamlIsIgnored(t *testing.T) {
208+
// TestViper_DefaultLookup_LegacyOasdiffYamlStillWorks: the legacy
209+
// oasdiff.{yaml,...} filename remains supported as a back-compat
210+
// fallback for CLI users who had it set up before the .oasdiff.* move.
211+
// .oasdiff.* is preferred, but oasdiff.* keeps working when no dotfile
212+
// is present.
213+
func TestViper_DefaultLookup_LegacyOasdiffYamlStillWorks(t *testing.T) {
212214
chdirIsolated(t)
213-
// Legacy filename — would have been picked up before the .oasdiff.*
214-
// move. Now it should be ignored entirely.
215215
writeFile(t, "oasdiff.yaml", "lang: invalid\n")
216216

217217
cmd := cobra.Command{}
218-
// No error: validate() never sees the bad value because the file
219-
// wasn't loaded.
218+
require.EqualError(t,
219+
internal.RunViper(&cmd, viper.New()),
220+
"failed to load config file: invalid lang \"invalid\", allowed values: en, ru, pt-br, es")
221+
}
222+
223+
// TestViper_DefaultLookup_DotPreferredOverLegacy: when both .oasdiff.yaml
224+
// and oasdiff.yaml exist in cwd, the dotfile wins. Proves the lookup
225+
// order — preferred first, legacy as fallback only.
226+
func TestViper_DefaultLookup_DotPreferredOverLegacy(t *testing.T) {
227+
chdirIsolated(t)
228+
// Dotfile is clean; legacy is not. If the legacy file were loaded,
229+
// validate() would error.
230+
writeFile(t, ".oasdiff.yaml", "lang: en\n")
231+
writeFile(t, "oasdiff.yaml", "lang: invalid\n")
232+
233+
cmd := cobra.Command{}
220234
require.Nil(t, internal.RunViper(&cmd, viper.New()))
221235
}
222236

0 commit comments

Comments
 (0)