Skip to content

Commit 906b582

Browse files
authored
fix: get cache dir for custom path (#20)
Tested in langgenius/dify#33950, it works fine.
1 parent fd19e06 commit 906b582

File tree

5 files changed

+162
-86
lines changed

5 files changed

+162
-86
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,8 @@ When `cache: true` is set, the action additionally caches project dependencies b
149149

150150
The dependency cache key format is: `vite-plus-{OS}-{arch}-{pm}-{lockfile-hash}`
151151

152+
When `cache-dependency-path` points to a lock file in a subdirectory, the action resolves the package-manager cache directory from that lock file's directory.
153+
152154
## Example Workflow
153155

154156
```yaml

dist/index.mjs

Lines changed: 75 additions & 75 deletions
Large diffs are not rendered by default.

src/cache-restore.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,30 @@ import { warning, info, debug, saveState, setOutput } from "@actions/core";
44
import { arch, platform } from "node:os";
55
import type { Inputs } from "./types.js";
66
import { State, Outputs } from "./types.js";
7-
import { detectLockFile, getCacheDirectories } from "./utils.js";
7+
import { detectLockFile, getCacheDirectories, getCacheDirectoryCwd } from "./utils.js";
88

99
export async function restoreCache(inputs: Inputs): Promise<void> {
1010
// Detect lock file
1111
const lockFile = detectLockFile(inputs.cacheDependencyPath);
1212
if (!lockFile) {
13-
warning("No lock file found. Skipping cache restore.");
13+
const message = inputs.cacheDependencyPath
14+
? `No lock file found for cache-dependency-path: ${inputs.cacheDependencyPath}. Skipping cache restore.`
15+
: "No lock file found in workspace root. Skipping cache restore.";
16+
warning(message);
1417
setOutput(Outputs.CacheHit, false);
1518
return;
1619
}
1720

1821
info(`Using lock file: ${lockFile.path}`);
22+
const cacheCwd = getCacheDirectoryCwd(lockFile.path);
23+
info(`Resolving dependency cache directory in: ${cacheCwd}`);
1924

2025
// Get cache directories based on lock file type
21-
const cachePaths = await getCacheDirectories(lockFile.type);
26+
const cachePaths = await getCacheDirectories(lockFile.type, cacheCwd);
2227
if (!cachePaths.length) {
23-
warning("No cache directories found. Skipping cache restore.");
28+
warning(
29+
`No cache directories found for ${lockFile.type} in ${cacheCwd}. Skipping cache restore.`,
30+
);
2431
setOutput(Outputs.CacheHit, false);
2532
return;
2633
}

src/utils.test.ts

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,20 @@
11
import { describe, it, expect, beforeEach, afterEach, vi } from "vite-plus/test";
22
import { existsSync, readdirSync } from "node:fs";
33
import { join } from "node:path";
4-
import { detectLockFile } from "./utils.js";
4+
import { getExecOutput } from "@actions/exec";
5+
import { detectLockFile, getCacheDirectoryCwd, getCacheDirectories } from "./utils.js";
56
import { LockFileType } from "./types.js";
67

8+
vi.mock("@actions/core", () => ({
9+
info: vi.fn(),
10+
warning: vi.fn(),
11+
debug: vi.fn(),
12+
}));
13+
14+
vi.mock("@actions/exec", () => ({
15+
getExecOutput: vi.fn(),
16+
}));
17+
718
// Mock fs module
819
vi.mock("node:fs", async () => {
920
const actual = await vi.importActual<typeof import("node:fs")>("node:fs");
@@ -158,3 +169,50 @@ describe("detectLockFile", () => {
158169
});
159170
});
160171
});
172+
173+
describe("getCacheDirectoryCwd", () => {
174+
const mockWorkspace = "/test/workspace";
175+
176+
beforeEach(() => {
177+
vi.stubEnv("GITHUB_WORKSPACE", mockWorkspace);
178+
});
179+
180+
afterEach(() => {
181+
vi.unstubAllEnvs();
182+
});
183+
184+
it("should resolve cache cwd from relative lock file path", () => {
185+
expect(getCacheDirectoryCwd("web/pnpm-lock.yaml")).toBe("/test/workspace/web");
186+
});
187+
188+
it("should resolve cache cwd from absolute lock file path", () => {
189+
expect(getCacheDirectoryCwd("/custom/path/pnpm-lock.yaml")).toBe("/custom/path");
190+
});
191+
});
192+
193+
describe("getCacheDirectories", () => {
194+
afterEach(() => {
195+
vi.resetAllMocks();
196+
});
197+
198+
it("should run vp pm cache dir in the provided cwd", async () => {
199+
vi.mocked(getExecOutput).mockResolvedValue({
200+
exitCode: 0,
201+
stdout: "/tmp/pnpm-store\n",
202+
stderr: "",
203+
});
204+
205+
const result = await getCacheDirectories(LockFileType.Pnpm, "/test/workspace/web");
206+
207+
expect(result).toEqual(["/tmp/pnpm-store"]);
208+
expect(getExecOutput).toHaveBeenCalledWith(
209+
"vp",
210+
["pm", "cache", "dir"],
211+
expect.objectContaining({
212+
cwd: "/test/workspace/web",
213+
silent: true,
214+
ignoreReturnCode: true,
215+
}),
216+
);
217+
});
218+
});

src/utils.ts

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { info, warning, debug } from "@actions/core";
22
import { getExecOutput } from "@actions/exec";
33
import { existsSync, readdirSync } from "node:fs";
44
import { homedir } from "node:os";
5-
import { isAbsolute, join, basename } from "node:path";
5+
import { isAbsolute, join, basename, dirname } from "node:path";
66
import { LockFileType } from "./types.js";
77
import type { LockFileInfo } from "./types.js";
88

@@ -19,6 +19,10 @@ export function resolveWorkspacePath(filePath: string): string {
1919
return isAbsolute(filePath) ? filePath : join(getWorkspaceDir(), filePath);
2020
}
2121

22+
export function getCacheDirectoryCwd(lockFilePath: string): string {
23+
return dirname(resolveWorkspacePath(lockFilePath));
24+
}
25+
2226
// Lock file patterns in priority order
2327
const LOCK_FILES: Array<{ filename: string; type: LockFileType }> = [
2428
{ filename: "pnpm-lock.yaml", type: LockFileType.Pnpm },
@@ -86,21 +90,26 @@ function inferLockFileType(fullPath: string, filename: string): LockFileInfo {
8690
/**
8791
* Get cache directories based on package manager type
8892
*/
89-
export async function getCacheDirectories(lockType: LockFileType): Promise<string[]> {
93+
export async function getCacheDirectories(lockType: LockFileType, cwd: string): Promise<string[]> {
9094
switch (lockType) {
9195
case LockFileType.Npm:
9296
case LockFileType.Pnpm:
9397
case LockFileType.Yarn:
94-
return getViteCacheDir();
98+
return getViteCacheDir(cwd);
9599
default:
96100
return [];
97101
}
98102
}
99103

100-
async function getCommandOutput(command: string, args: string[]): Promise<string | undefined> {
104+
async function getCommandOutput(
105+
command: string,
106+
args: string[],
107+
options?: { cwd?: string },
108+
): Promise<string | undefined> {
101109
const cmdStr = `${command} ${args.join(" ")}`;
102110
try {
103111
const result = await getExecOutput(command, args, {
112+
cwd: options?.cwd,
104113
silent: true,
105114
ignoreReturnCode: true,
106115
});
@@ -115,7 +124,7 @@ async function getCommandOutput(command: string, args: string[]): Promise<string
115124
}
116125
}
117126

118-
async function getViteCacheDir(): Promise<string[]> {
119-
const cacheDir = await getCommandOutput("vp", ["pm", "cache", "dir"]);
127+
async function getViteCacheDir(cwd: string): Promise<string[]> {
128+
const cacheDir = await getCommandOutput("vp", ["pm", "cache", "dir"], { cwd });
120129
return cacheDir ? [cacheDir] : [];
121130
}

0 commit comments

Comments
 (0)