Skip to content

Commit 01c9a6a

Browse files
Copilotphilmillman
andauthored
fix: scan git-root directory before halting lockfile walk in detectWorkspaceInfo (#558)
* Initial plan * fix: scan .git-containing directory before breaking in detectWorkspaceInfo Agent-Logs-Url: https://github.com/dmno-dev/varlock/sessions/7f67de8f-0606-4313-9833-b3a8b00f06ba Co-authored-by: philmillman <3722211+philmillman@users.noreply.github.com> * fix: make .git boundary test resilient to npm_config_user_agent being set in CI Agent-Logs-Url: https://github.com/dmno-dev/varlock/sessions/2526c91a-61c4-4880-916b-1cd300a5c93b Co-authored-by: philmillman <3722211+philmillman@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: philmillman <3722211+philmillman@users.noreply.github.com>
1 parent 6a654ed commit 01c9a6a

3 files changed

Lines changed: 40 additions & 3 deletions

File tree

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"varlock": patch
3+
---
4+
5+
Fix plugin resolution failure in monorepo workspaces where `.git` and the lockfile coexist in the same directory.
6+
7+
`detectWorkspaceInfo()` was checking for a `.git` directory **after** moving to the parent, so in the standard monorepo layout (`monorepo-root/.git` + `monorepo-root/bun.lock`) the root was never scanned and the lockfile was never found. Moving the `.git` boundary check to **before** moving up ensures the git-root directory is always scanned first.

packages/varlock/src/cli/helpers/test/js-package-manager-utils.test.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,4 +121,32 @@ describe('detectWorkspaceInfo', () => {
121121
expect(result?.packageManager.name).toBe('bun');
122122
expect(result?.rootPath).toBe(tempDir);
123123
});
124+
125+
test('finds lockfile when .git and lockfile are in the same directory (standard monorepo layout)', () => {
126+
// Simulates: monorepo-root/.git + monorepo-root/bun.lock, CWD = monorepo-root/packages/my-app
127+
const subDir = path.join(tempDir, 'packages', 'my-app');
128+
fs.mkdirSync(subDir, { recursive: true });
129+
fs.mkdirSync(path.join(tempDir, '.git'), { recursive: true });
130+
fs.writeFileSync(path.join(tempDir, 'bun.lock'), '');
131+
132+
const result = detectWorkspaceInfo({ cwd: subDir });
133+
expect(result?.packageManager.name).toBe('bun');
134+
expect(result?.rootPath).toBe(tempDir);
135+
});
136+
137+
test('stops at .git boundary and does not traverse above it to find lockfiles', () => {
138+
// Structure: grandparent/bun.lock + parent/.git + parent/src/ (CWD)
139+
// The .git boundary should prevent finding bun.lock in grandparent
140+
const grandparentDir = tempDir;
141+
const parentDir = path.join(tempDir, 'parent');
142+
const subDir = path.join(parentDir, 'src');
143+
fs.mkdirSync(subDir, { recursive: true });
144+
fs.mkdirSync(path.join(parentDir, '.git'), { recursive: true });
145+
fs.writeFileSync(path.join(grandparentDir, 'bun.lock'), '');
146+
147+
const result = detectWorkspaceInfo({ cwd: subDir });
148+
// The boundary should prevent finding bun.lock in grandparentDir.
149+
// rootPath should never be grandparentDir regardless of npm_config_user_agent fallback.
150+
expect(result?.rootPath).not.toBe(grandparentDir);
151+
});
124152
});

packages/varlock/src/lib/workspace-utils.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,13 +112,15 @@ export function detectWorkspaceInfo(opts?: {
112112
}
113113
if (multipleLockfilesDetected) break;
114114

115+
// stop at git root as a fallback boundary after scanning the current directory
116+
// NOTE: check before moving to parent so the directory containing .git is always scanned
117+
// (the standard monorepo layout has .git and the lockfile in the same root directory)
118+
if (pathExistsSync(path.join(cwd, '.git'))) break;
119+
115120
// will break when we reach the filesystem root
116121
const parentDir = path.dirname(cwd);
117122
if (parentDir === cwd) break;
118123
cwd = parentDir;
119-
120-
// stop at git root as a fallback boundary when no lockfile has been found yet
121-
if (pathExistsSync(path.join(cwd, '.git'))) break;
122124
} while (cwd);
123125

124126
// if we did not find a lockfile, check env vars for hints (rootPath will be cwd in this case)

0 commit comments

Comments
 (0)