Skip to content

Commit 8ecb391

Browse files
authored
feat: add bun dependency cache support (#42)
## Summary - Add `bun.lockb` and `bun.lock` lock file detection for dependency caching - Add `Bun` variant to `LockFileType` enum and wire it through cache directory resolution - Add `test-cache-bun` CI job to verify bun caching in GitHub Actions VP supports bun as a package manager since v0.1.15 — this aligns the action with that support. Closes #41 ## Test plan - [x] Unit tests pass (`vp run test` — 92 tests) - [x] Lint/format clean (`vp run check:fix`) - [x] Build up to date (`vp run build`) - [x] CI `test-cache-bun` job passes on PR
1 parent e34774b commit 8ecb391

File tree

5 files changed

+134
-1
lines changed

5 files changed

+134
-1
lines changed

.github/workflows/test.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,38 @@ jobs:
151151
echo "Installed version: ${{ steps.setup.outputs.version }}"
152152
echo "Cache hit: ${{ steps.setup.outputs.cache-hit }}"
153153
154+
test-cache-bun:
155+
strategy:
156+
fail-fast: false
157+
matrix:
158+
version: [latest, alpha]
159+
lockfile: [bun.lock, bun.lockb]
160+
runs-on: ubuntu-latest
161+
steps:
162+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
163+
164+
- name: Create test project with ${{ matrix.lockfile }}
165+
run: |
166+
mkdir -p test-project
167+
cd test-project
168+
echo '{"name":"test-project","private":true}' > package.json
169+
touch ${{ matrix.lockfile }}
170+
171+
- name: Setup Vite+ (${{ matrix.version }}) with bun cache (${{ matrix.lockfile }})
172+
uses: ./
173+
id: setup
174+
with:
175+
version: ${{ matrix.version }}
176+
run-install: false
177+
cache: true
178+
cache-dependency-path: test-project/${{ matrix.lockfile }}
179+
180+
- name: Verify installation
181+
run: |
182+
vp --version
183+
echo "Installed version: ${{ steps.setup.outputs.version }}"
184+
echo "Cache hit: ${{ steps.setup.outputs.cache-hit }}"
185+
154186
test-vp-exec:
155187
strategy:
156188
fail-fast: false

dist/index.mjs

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

src/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export enum LockFileType {
3434
Npm = "npm",
3535
Pnpm = "pnpm",
3636
Yarn = "yarn",
37+
Bun = "bun",
3738
}
3839

3940
export interface LockFileInfo {

src/utils.test.ts

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,30 @@ describe("detectLockFile", () => {
8181
});
8282
});
8383

84+
it("should return lock file info for bun.lockb", () => {
85+
vi.mocked(existsSync).mockReturnValue(true);
86+
87+
const result = detectLockFile("bun.lockb");
88+
89+
expect(result).toEqual({
90+
type: LockFileType.Bun,
91+
path: join(mockWorkspace, "bun.lockb"),
92+
filename: "bun.lockb",
93+
});
94+
});
95+
96+
it("should return lock file info for bun.lock", () => {
97+
vi.mocked(existsSync).mockReturnValue(true);
98+
99+
const result = detectLockFile("bun.lock");
100+
101+
expect(result).toEqual({
102+
type: LockFileType.Bun,
103+
path: join(mockWorkspace, "bun.lock"),
104+
filename: "bun.lock",
105+
});
106+
});
107+
84108
it("should return undefined if explicit file does not exist", () => {
85109
vi.mocked(existsSync).mockReturnValue(false);
86110

@@ -176,6 +200,63 @@ describe("detectLockFile", () => {
176200
});
177201
});
178202

203+
it("should detect bun.lockb", () => {
204+
vi.mocked(readdirSync).mockReturnValue(["bun.lockb"] as unknown as ReturnType<
205+
typeof readdirSync
206+
>);
207+
208+
const result = detectLockFile();
209+
210+
expect(result).toEqual({
211+
type: LockFileType.Bun,
212+
path: join(mockWorkspace, "bun.lockb"),
213+
filename: "bun.lockb",
214+
});
215+
});
216+
217+
it("should detect bun.lock when bun.lockb is absent", () => {
218+
vi.mocked(readdirSync).mockReturnValue(["bun.lock"] as unknown as ReturnType<
219+
typeof readdirSync
220+
>);
221+
222+
const result = detectLockFile();
223+
224+
expect(result).toEqual({
225+
type: LockFileType.Bun,
226+
path: join(mockWorkspace, "bun.lock"),
227+
filename: "bun.lock",
228+
});
229+
});
230+
231+
it("should prioritize bun.lockb over bun.lock", () => {
232+
vi.mocked(readdirSync).mockReturnValue(["bun.lock", "bun.lockb"] as unknown as ReturnType<
233+
typeof readdirSync
234+
>);
235+
236+
const result = detectLockFile();
237+
238+
expect(result).toEqual({
239+
type: LockFileType.Bun,
240+
path: join(mockWorkspace, "bun.lockb"),
241+
filename: "bun.lockb",
242+
});
243+
});
244+
245+
it("should prioritize pnpm-lock.yaml over bun lock files", () => {
246+
vi.mocked(readdirSync).mockReturnValue([
247+
"bun.lockb",
248+
"pnpm-lock.yaml",
249+
] as unknown as ReturnType<typeof readdirSync>);
250+
251+
const result = detectLockFile();
252+
253+
expect(result).toEqual({
254+
type: LockFileType.Pnpm,
255+
path: join(mockWorkspace, "pnpm-lock.yaml"),
256+
filename: "pnpm-lock.yaml",
257+
});
258+
});
259+
179260
it("should return undefined when no lock files found", () => {
180261
vi.mocked(readdirSync).mockReturnValue([
181262
"package.json",
@@ -336,6 +417,19 @@ describe("getCacheDirectories", () => {
336417
}),
337418
);
338419
});
420+
421+
it("should run vp pm cache dir for bun", async () => {
422+
vi.mocked(getExecOutput).mockResolvedValue({
423+
exitCode: 0,
424+
stdout: "/tmp/bun-cache\n",
425+
stderr: "",
426+
});
427+
428+
const cacheCwd = join("/test", "workspace", "web");
429+
const result = await getCacheDirectories(LockFileType.Bun, cacheCwd);
430+
431+
expect(result).toEqual(["/tmp/bun-cache"]);
432+
});
339433
});
340434

341435
describe("getInstallCwd", () => {

src/utils.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ export function getInstallCwd(projectDir: string, cwd?: string): string {
4949
// Lock file patterns in priority order
5050
const LOCK_FILES: Array<{ filename: string; type: LockFileType }> = [
5151
{ filename: "pnpm-lock.yaml", type: LockFileType.Pnpm },
52+
{ filename: "bun.lockb", type: LockFileType.Bun },
53+
{ filename: "bun.lock", type: LockFileType.Bun },
5254
{ filename: "package-lock.json", type: LockFileType.Npm },
5355
{ filename: "npm-shrinkwrap.json", type: LockFileType.Npm },
5456
{ filename: "yarn.lock", type: LockFileType.Yarn },
@@ -108,6 +110,9 @@ function inferLockFileType(fullPath: string, filename: string): LockFileInfo {
108110
if (filename.includes("yarn")) {
109111
return { type: LockFileType.Yarn, path: fullPath, filename };
110112
}
113+
if (filename.startsWith("bun.")) {
114+
return { type: LockFileType.Bun, path: fullPath, filename };
115+
}
111116
// Default to npm
112117
return { type: LockFileType.Npm, path: fullPath, filename };
113118
}
@@ -120,6 +125,7 @@ export async function getCacheDirectories(lockType: LockFileType, cwd: string):
120125
case LockFileType.Npm:
121126
case LockFileType.Pnpm:
122127
case LockFileType.Yarn:
128+
case LockFileType.Bun:
123129
return getViteCacheDir(cwd);
124130
default:
125131
return [];

0 commit comments

Comments
 (0)