Skip to content

fix(config): resolve relative paths in config files against config dir, not cwd#901

Merged
reuvenharrison merged 1 commit into
mainfrom
fix/config-relative-paths
May 9, 2026
Merged

fix(config): resolve relative paths in config files against config dir, not cwd#901
reuvenharrison merged 1 commit into
mainfrom
fix/config-relative-paths

Conversation

@reuvenharrison
Copy link
Copy Markdown
Collaborator

Closes #900.

Summary

Path-valued config keys (err-ignore, warn-ignore, severity-levels, template) referenced from a config file now resolve relative to the config file's directory, not the process's current working directory. A config file is self-contained: relative paths in it refer to siblings of the config, not arbitrary files at the process's cwd.

Why

Without this fix, the workflow that #899 enables (--config <path> and OASDIFF_CONFIG) silently breaks for path-valued flags as soon as the config file isn't in cwd. The bug as originally reported in #900:

$ oasdiff breaking base.yaml revision.yaml --config examples/.oasdiff.yaml
Error: can't process err ignore file: open ignore-err-example.txt: no such file or directory

The config file referenced ignore-err-example.txt, the file existed at examples/ignore-err-example.txt, but the CLI looked at <cwd>/ignore-err-example.txt. After this fix, the file is found correctly.

What's in the diff

  • internal/viper.go::resolveConfigRelativePaths — new function called from RunViper after bindFlags. For each key in configRelativePathKeys (the four path-valued keys), if the value is non-empty, relative, and not user-set on the CLI, it gets rewritten to filepath.Join(configDir, value).
  • Config struct gains a Template string field so validate()'s UnmarshalExact recognises the key. (Previously absent from the struct, which would have caused a "has invalid keys" error in any test that referenced it.)
  • IViper interface gains ConfigFileUsed, GetString, Set — all already on viper.Viper, so the test mock works unchanged.
  • 6 new tests in internal/viper_test.go covering: relative path resolves against config dir; absolute paths unchanged; CLI flag overrides config and isn't rewritten; all four path keys handled; default cwd lookup unchanged; explicit back-compat for legacy oasdiff.yaml in cwd.
  • docs/CONFIG-FILES.md documents the new resolution semantics.

Backward compatibility

Strict. Existing setups continue to work identically:

Setup Before After Δ
.oasdiff.yaml in cwd, relative path <cwd>/<file> <abs cwd>/<file> Functionally identical
oasdiff.yaml in cwd, relative path (legacy users) <cwd>/<file> <abs cwd>/<file> Functionally identical
Any config file, absolute path inside absolute path absolute path Skipped by rewrite
User passes --err-ignore foo.txt on CLI <cwd>/foo.txt <cwd>/foo.txt Skipped (Changed=true)
--config <subdir>/cfg.yaml, relative path inside broken (cwd-rel, fails) works (config-dir-rel) Bug fix

The only "regression" surface is the theoretical user who relied on --config + cwd-relative-not-config-relative paths. --config is a few hours old (#899 merged today); meaningful adoption hasn't happened.

Test plan

@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented May 8, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 90.67%. Comparing base (3dab475) to head (f9a6d69).

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #901   +/-   ##
=======================================
  Coverage   90.66%   90.67%           
=======================================
  Files         264      264           
  Lines       15845    15859   +14     
=======================================
+ Hits        14366    14380   +14     
  Misses        948      948           
  Partials      531      531           
Flag Coverage Δ
unittests 90.67% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

…r, not cwd

Closes #900.

Path-valued config keys (err-ignore, warn-ignore, severity-levels,
template) referenced from a config file are now resolved relative to
the config file's directory, not the process's current working
directory. Matches the convention established by ESLint, Prettier,
golangci-lint, and similar tools — a config file is self-contained;
relative paths in it refer to siblings of the config, not arbitrary
files at cwd.

Without this fix, --config <subdir>/.oasdiff.yaml silently fails for
any path-valued flag because the CLI looks for those files at cwd
instead of next to the config. Reproduced in #900.

Implementation in internal/viper.go::resolveConfigRelativePaths,
called after CLI flags are bound. Per key, the rewrite is skipped if:
  - The CLI flag was explicitly set by the user (their typed path
    means what they typed, relative to cwd).
  - The value is empty or already absolute.

Skipped overall when no config file was loaded.

Backward compatibility: strict. Existing setups continue to work
identically:
  - Default-cwd-lookup users (.oasdiff.yaml or oasdiff.yaml in cwd):
    configDir == cwd, so relative paths resolve to <abs cwd>/<file>.
    Functionally identical to the previous cwd-relative behaviour.
  - Config-with-absolute-paths users: absolute paths are skipped by
    the rewrite, behaviour unchanged.
  - --config <path> users with relative paths in the config file: this
    case was broken before (the bug from #900) and is now fixed. The
    only "regression" surface is the theoretical user who relied on
    --config + cwd-relative-not-config-relative paths, which is a
    feature that's a few hours old and can't have meaningful adoption.

Tests: 6 new cases in internal/viper_test.go cover relative path
resolution against config dir, absolute paths unchanged, CLI flag
override preserved, all four path keys handled, default lookup in
cwd unchanged, and explicit back-compat for the legacy oasdiff.yaml
filename in cwd. Plus a `template` field added to the Config struct
so validate() recognizes the key.

CONFIG-FILES.md documents the new resolution semantics with the
convention citation.
@reuvenharrison reuvenharrison force-pushed the fix/config-relative-paths branch from 028849f to f9a6d69 Compare May 9, 2026 07:07
@reuvenharrison reuvenharrison merged commit f43b649 into main May 9, 2026
14 checks passed
@reuvenharrison reuvenharrison deleted the fix/config-relative-paths branch May 9, 2026 07:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

config: relative paths in config files should resolve against the config file's directory, not cwd

2 participants