◐ Off-By-One · answer catalog

go-cli-cwd-relative-default-path

2 answer(s)godockergodocker

go-cli-cwd-relative-default-path

📦 Source in repository (JSON)

Answer 1

The bug: helix-estimate's default --pricing/--known-friends values were CWD-relative (pkg/estimate/testdata/*.yaml joined against the current working directory). Invoked from outside the checkout root, those paths don't exist → CONFIG_ERROR.

The fix, in ~/helix/pkg/estimate/estimate.go: testdataPath() anchors to the repo root by (1) walking up from CWD to the first go.mod, (2) falling back to the runtime.Caller source location when CWD is outside the repo, (3) returning "" otherwise so the caller emits the normal CONFIG_ERROR. It never returns a relative path — only an absolute path to an existing file under a discovered repo root, or "".

// testdataPath resolves an absolute path to rel under the repo root.
// 1) go.mod walk-up from CWD; 2) runtime.Caller source fallback;
// 3) else "" so the caller emits CONFIG_ERROR. Never a broken relative path.
func testdataPath(rel string) string {
    root := repoRoot()
    if root == "" {
        return ""
    }
    p := filepath.Join(root, rel)
    fi, err := os.Stat(p)
    if err != nil || fi.IsDir() {
        return ""
    }
    return p
}

func repoRoot() string {
    if cwd, err := os.Getwd(); err == nil {
        if root := findRepoRootFromDir(cwd); root != "" {
            return root
        }
    }
    return findRepoRootFromSource()
}

// findRepoRootFromDir walks up from dir to the first directory with go.mod.
func findRepoRootFromDir(dir string) string {
    d := dir
    if !filepath.IsAbs(d) {
        abs, err := filepath.Abs(d)
        if err != nil {
            return ""
        }
        d = abs
    }
    d = filepath.Clean(d)
    for {
        if _, err := os.Stat(filepath.Join(d, "go.mod")); err == nil {
            return d
        }
        parent := filepath.Dir(d)
        if parent == d {
            return ""
        }
        d = parent
    }
}

// findRepoRootFromSource locates the repo root from the compiled-in source
// location of this file, independent of the process working directory.
func findRepoRootFromSource() string {
    for i := 0; i < 8; i++ { // frame 0 is estimate.go; loop guards against inlining
        _, file, _, ok := runtime.Caller(i)
        if !ok {
            break
        }
        if root := findRepoRootFromDir(filepath.Dir(file)); root != "" {
            return root
        }
    }
    return ""
}

LoadConfig/resolvePath then feed empty flag values through testdataPath; a "" result becomes a ConfigError whose message contains CONFIG_ERROR, so the CLI reports it identically to before:

func resolvePath(explicit, rel string) string {
    if explicit != "" {
        abs, err := filepath.Abs(explicit)
        if err != nil {
            return ""
        }
        return abs
    }
    return testdataPath(rel)
}

Layout: helix/go.mod, helix/pkg/estimate/{estimate.go, estimate_test.go, testdata/{pricing,known-friends}.yaml}, helix/cmd/helix-estimate/main.go (stdlib-only, zero external deps — hermetic).

Evidence & signatures

All tests in `helix/pkg/estimate/estimate_test.go` pass (`go test`, `go test -race`, `go vet`, `gofmt` all clean):

```
--- PASS: TestDefaultPathResolvesFromNonRepoCWD      (t.Chdir(t.TempDir()): CWD outside repo still resolves via runtime.Caller)
--- PASS: TestLoadConfigDefaultsFromNonRepoCWD       (full public API from non-repo CWD; previously CONFIG_ERROR)
--- PASS: TestFindRepoRootFromDirWalksUpToGoMod      (hermetic fake repo: at root / 1 level / deep)
--- PASS: TestFindRepoRootFromDirRelativeInput       (relative input absolutized)
--- PASS: TestFindRepoRootFromDirNoGoModReturnsEmpty (no go.mod anywhere -> "")
--- PASS: TestFindRepoRootFromDirNearestGoModWins    (nested modules: nearest wins)
--- PASS: TestTestdataPathFakeRepoPresentFile        (hermetic: fake root + testdata -> absolute path)
--- PASS: TestTestdataPathFakeRepoMissingFileReturnsEmpty (root found but file missing -> "" -> CONFIG_ERROR)
--- PASS: TestTestdataPathNeverReturnsRelativePath   (invariant: every result is "" or absolute)
--- PASS: TestResolvePathExplicitWinsOverDefault
--- PASS: TestResolvePathEmptyUsesDefault
--- PASS: TestLoadConfigExplicitMissingYieldsConfigError
ok  	helix/pkg/estimate	(also under -race)
```

CLI end-to-end (`go build -o /tmp/helix-estimate ./cmd/helix-estimate`):

| Scenario | Result |
|---|---|
| Run from `/tmp` (outside checkout root — the old failure) | `pricing: ~/helix/pkg/estimate/testdata/pricing.yaml (81 bytes)` — exit 0 |
| Run from `helix/pkg/estimate` (deep inside repo) | resolves to same absolute paths — exit 0 |
| `-pricing /tmp/nope.yaml` | `CONFIG_ERROR: cannot read pricing configuration ...` — exit 1 |
| CWD inside a foreign Go module (`/tmp/foreignmod` with own `go.mod`) | `CONFIG_ERROR: pricing configuration could not be located (no default under the repo root ...)` — exit 1 |

Edge cases exercised: non-repo CWD (source-location fallback), hermetic fake-repo walk-up at three depths, nearest-`go.mod`-wins with nested modules, no-`go.mod` → `""`, repo root found but testdata missing → `""` → CONFIG_ERROR, relative inputs, explicit flag wins, and the never-relative-path invariant. The old CWD-relative behavior is confirmed broken by design: `/tmp/pkg/estimate/testdata/` does not exist, which is exactly the failure this fix eliminates.
{"model": "deepseek-v4-flash", "problem_class": "go-cli-cwd-relative-default-path", "result": "passed", "tests": 12}

Answer 2

The bug: helix-estimate's default --pricing/--known-friends values were CWD-relative (pkg/estimate/testdata/*.yaml joined against the current working directory). Invoked from outside the checkout root, those paths don't exist → CONFIG_ERROR.

The fix, in ~/helix/pkg/estimate/estimate.go: testdataPath() anchors to the repo root by (1) walking up from CWD to the first go.mod, (2) falling back to the runtime.Caller source location when CWD is outside the repo, (3) returning "" otherwise so the caller emits the normal CONFIG_ERROR. It never returns a relative path — only an absolute path to an existing file under a discovered repo root, or "".

// testdataPath resolves an absolute path to rel under the repo root.
// 1) go.mod walk-up from CWD; 2) runtime.Caller source fallback;
// 3) else "" so the caller emits CONFIG_ERROR. Never a broken relative path.
func testdataPath(rel string) string {
    root := repoRoot()
    if root == "" {
        return ""
    }
    p := filepath.Join(root, rel)
    fi, err := os.Stat(p)
    if err != nil || fi.IsDir() {
        return ""
    }
    return p
}

func repoRoot() string {
    if cwd, err := os.Getwd(); err == nil {
        if root := findRepoRootFromDir(cwd); root != "" {
            return root
        }
    }
    return findRepoRootFromSource()
}

// findRepoRootFromDir walks up from dir to the first directory with go.mod.
func findRepoRootFromDir(dir string) string {
    d := dir
    if !filepath.IsAbs(d) {
        abs, err := filepath.Abs(d)
        if err != nil {
            return ""
        }
        d = abs
    }
    d = filepath.Clean(d)
    for {
        if _, err := os.Stat(filepath.Join(d, "go.mod")); err == nil {
            return d
        }
        parent := filepath.Dir(d)
        if parent == d {
            return ""
        }
        d = parent
    }
}

// findRepoRootFromSource locates the repo root from the compiled-in source
// location of this file, independent of the process working directory.
func findRepoRootFromSource() string {
    for i := 0; i < 8; i++ { // frame 0 is estimate.go; loop guards against inlining
        _, file, _, ok := runtime.Caller(i)
        if !ok {
            break
        }
        if root := findRepoRootFromDir(filepath.Dir(file)); root != "" {
            return root
        }
    }
    return ""
}

LoadConfig/resolvePath then feed empty flag values through testdataPath; a "" result becomes a ConfigError whose message contains CONFIG_ERROR, so the CLI reports it identically to before:

func resolvePath(explicit, rel string) string {
    if explicit != "" {
        abs, err := filepath.Abs(explicit)
        if err != nil {
            return ""
        }
        return abs
    }
    return testdataPath(rel)
}

Layout: helix/go.mod, helix/pkg/estimate/{estimate.go, estimate_test.go, testdata/{pricing,known-friends}.yaml}, helix/cmd/helix-estimate/main.go (stdlib-only, zero external deps — hermetic).

Evidence & signatures

All tests in `helix/pkg/estimate/estimate_test.go` pass (`go test`, `go test -race`, `go vet`, `gofmt` all clean):

```
--- PASS: TestDefaultPathResolvesFromNonRepoCWD      (t.Chdir(t.TempDir()): CWD outside repo still resolves via runtime.Caller)
--- PASS: TestLoadConfigDefaultsFromNonRepoCWD       (full public API from non-repo CWD; previously CONFIG_ERROR)
--- PASS: TestFindRepoRootFromDirWalksUpToGoMod      (hermetic fake repo: at root / 1 level / deep)
--- PASS: TestFindRepoRootFromDirRelativeInput       (relative input absolutized)
--- PASS: TestFindRepoRootFromDirNoGoModReturnsEmpty (no go.mod anywhere -> "")
--- PASS: TestFindRepoRootFromDirNearestGoModWins    (nested modules: nearest wins)
--- PASS: TestTestdataPathFakeRepoPresentFile        (hermetic: fake root + testdata -> absolute path)
--- PASS: TestTestdataPathFakeRepoMissingFileReturnsEmpty (root found but file missing -> "" -> CONFIG_ERROR)
--- PASS: TestTestdataPathNeverReturnsRelativePath   (invariant: every result is "" or absolute)
--- PASS: TestResolvePathExplicitWinsOverDefault
--- PASS: TestResolvePathEmptyUsesDefault
--- PASS: TestLoadConfigExplicitMissingYieldsConfigError
ok  	helix/pkg/estimate	(also under -race)
```

CLI end-to-end (`go build -o /tmp/helix-estimate ./cmd/helix-estimate`):

| Scenario | Result |
|---|---|
| Run from `/tmp` (outside checkout root — the old failure) | `pricing: ~/helix/pkg/estimate/testdata/pricing.yaml (81 bytes)` — exit 0 |
| Run from `helix/pkg/estimate` (deep inside repo) | resolves to same absolute paths — exit 0 |
| `-pricing /tmp/nope.yaml` | `CONFIG_ERROR: cannot read pricing configuration ...` — exit 1 |
| CWD inside a foreign Go module (`/tmp/foreignmod` with own `go.mod`) | `CONFIG_ERROR: pricing configuration could not be located (no default under the repo root ...)` — exit 1 |

Edge cases exercised: non-repo CWD (source-location fallback), hermetic fake-repo walk-up at three depths, nearest-`go.mod`-wins with nested modules, no-`go.mod` → `""`, repo root found but testdata missing → `""` → CONFIG_ERROR, relative inputs, explicit flag wins, and the never-relative-path invariant. The old CWD-relative behavior is confirmed broken by design: `/tmp/pkg/estimate/testdata/` does not exist, which is exactly the failure this fix eliminates.
{"model": "deepseek-v4-flash", "problem_class": "go-cli-cwd-relative-default-path", "result": "passed", "tests": 12}
Generated from the verified corpus · MIT licensedBack to the catalog