Skip to content

Commit 20553a7

Browse files
authored
feat: add working-directory input (#21)
Follow #20 I found that the version printed by vite+ is also incorrect. I'm thinking that adding a `working-directory` might be better, which could also simplify the configuration. It looks like the `working-directory` from the GitHub action does not work with `uses`. https://github.com/orgs/community/discussions/25742 Feel free to close this PR if you do not want to introduce another "cwd" input.
1 parent 906b582 commit 20553a7

File tree

13 files changed

+348
-116
lines changed

13 files changed

+348
-116
lines changed

README.md

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,19 @@ steps:
4040
node-version-file: ".node-version"
4141
```
4242
43+
### With Working Directory
44+
45+
```yaml
46+
steps:
47+
- uses: actions/checkout@v6
48+
- uses: voidzero-dev/setup-vp@v1
49+
with:
50+
working-directory: web
51+
node-version-file: ".nvmrc"
52+
cache: true
53+
run-install: true
54+
```
55+
4356
### With Caching and Install
4457
4558
```yaml
@@ -117,16 +130,19 @@ jobs:
117130

118131
## Inputs
119132

120-
| Input | Description | Required | Default |
121-
| ----------------------- | --------------------------------------------------------------------------------------------------------- | -------- | ------------- |
122-
| `version` | Version of Vite+ to install | No | `latest` |
123-
| `node-version` | Node.js version to install via `vp env use` | No | Latest LTS |
124-
| `node-version-file` | Path to file containing Node.js version (`.nvmrc`, `.node-version`, `.tool-versions`, `package.json`) | No | |
125-
| `run-install` | Run `vp install` after setup. Accepts boolean or YAML object with `cwd`/`args` | No | `true` |
126-
| `cache` | Enable caching of project dependencies | No | `false` |
127-
| `cache-dependency-path` | Path to lock file for cache key generation | No | Auto-detected |
128-
| `registry-url` | Optional registry to set up for auth. Sets the registry in `.npmrc` and reads auth from `NODE_AUTH_TOKEN` | No | |
129-
| `scope` | Optional scope for scoped registries. Falls back to repo owner for GitHub Packages | No | |
133+
| Input | Description | Required | Default |
134+
| ----------------------- | ----------------------------------------------------------------------------------------------------------- | -------- | -------------- |
135+
| `version` | Version of Vite+ to install | No | `latest` |
136+
| `node-version` | Node.js version to install via `vp env use` | No | Latest LTS |
137+
| `node-version-file` | Path to file containing Node.js version (`.nvmrc`, `.node-version`, `.tool-versions`, `package.json`) | No | |
138+
| `working-directory` | Project directory used for relative paths, lockfile auto-detection, environment checks, and default install | No | Workspace root |
139+
| `run-install` | Run `vp install` after setup. Accepts boolean or YAML object with `cwd`/`args` | No | `true` |
140+
| `cache` | Enable caching of project dependencies | No | `false` |
141+
| `cache-dependency-path` | Path to lock file for cache key generation | No | Auto-detected |
142+
| `registry-url` | Optional registry to set up for auth. Sets the registry in `.npmrc` and reads auth from `NODE_AUTH_TOKEN` | No | |
143+
| `scope` | Optional scope for scoped registries. Falls back to repo owner for GitHub Packages | No | |
144+
145+
When `working-directory` is set, relative `run-install.cwd`, `node-version-file`, and `cache-dependency-path` values are resolved from that directory.
130146

131147
## Outputs
132148

@@ -149,6 +165,8 @@ When `cache: true` is set, the action additionally caches project dependencies b
149165

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

168+
When `working-directory` is set, lockfile auto-detection runs in that directory.
169+
152170
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.
153171

154172
## Example Workflow

action.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ inputs:
2020
node-version-file:
2121
description: "Path to file containing the Node.js version spec (.nvmrc, .node-version, .tool-versions, package.json). Ignored when node-version is specified."
2222
required: false
23+
working-directory:
24+
description: "Project directory to use for relative paths, lockfile auto-detection, environment checks, and default `vp install` execution."
25+
required: false
2326
cache:
2427
description: "Enable caching of project dependencies"
2528
required: false

dist/index.mjs

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

src/cache-restore.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,27 @@ import { restoreCache as restoreCacheAction } from "@actions/cache";
22
import { hashFiles } from "@actions/glob";
33
import { warning, info, debug, saveState, setOutput } from "@actions/core";
44
import { arch, platform } from "node:os";
5+
import { dirname } from "node:path";
56
import type { Inputs } from "./types.js";
67
import { State, Outputs } from "./types.js";
7-
import { detectLockFile, getCacheDirectories, getCacheDirectoryCwd } from "./utils.js";
8+
import { detectLockFile, getCacheDirectories, getConfiguredProjectDir } from "./utils.js";
89

910
export async function restoreCache(inputs: Inputs): Promise<void> {
11+
const projectDir = getConfiguredProjectDir(inputs);
12+
1013
// Detect lock file
11-
const lockFile = detectLockFile(inputs.cacheDependencyPath);
14+
const lockFile = detectLockFile(inputs.cacheDependencyPath, projectDir);
1215
if (!lockFile) {
1316
const message = inputs.cacheDependencyPath
1417
? `No lock file found for cache-dependency-path: ${inputs.cacheDependencyPath}. Skipping cache restore.`
15-
: "No lock file found in workspace root. Skipping cache restore.";
18+
: `No lock file found in project directory: ${projectDir}. Skipping cache restore.`;
1619
warning(message);
1720
setOutput(Outputs.CacheHit, false);
1821
return;
1922
}
2023

2124
info(`Using lock file: ${lockFile.path}`);
22-
const cacheCwd = getCacheDirectoryCwd(lockFile.path);
25+
const cacheCwd = dirname(lockFile.path);
2326
info(`Resolving dependency cache directory in: ${cacheCwd}`);
2427

2528
// Get cache directories based on lock file type

src/index.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,17 @@ import { State, Outputs } from "./types.js";
99
import type { Inputs } from "./types.js";
1010
import { resolveNodeVersionFile } from "./node-version-file.js";
1111
import { configAuthentication } from "./auth.js";
12+
import { getConfiguredProjectDir } from "./utils.js";
1213

1314
async function runMain(inputs: Inputs): Promise<void> {
1415
// Mark that post action should run
1516
saveState(State.IsPost, "true");
17+
const projectDir = getConfiguredProjectDir(inputs);
1618

1719
// Step 1: Resolve Node.js version (needed for cache key)
1820
let nodeVersion = inputs.nodeVersion;
1921
if (!nodeVersion && inputs.nodeVersionFile) {
20-
nodeVersion = resolveNodeVersionFile(inputs.nodeVersionFile);
22+
nodeVersion = resolveNodeVersionFile(inputs.nodeVersionFile, projectDir);
2123
}
2224

2325
// Step 2: Install Vite+
@@ -45,12 +47,12 @@ async function runMain(inputs: Inputs): Promise<void> {
4547
}
4648

4749
// Print version info at the end
48-
await printViteVersion();
50+
await printViteVersion(projectDir);
4951
}
5052

51-
async function printViteVersion(): Promise<void> {
53+
async function printViteVersion(cwd: string): Promise<void> {
5254
try {
53-
const result = await getExecOutput("vp", ["--version"], { silent: true });
55+
const result = await getExecOutput("vp", ["--version"], { cwd, silent: true });
5456
const versionOutput = result.stdout.trim();
5557
info(versionOutput);
5658

src/inputs.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ describe("getInputs", () => {
2727
version: "latest",
2828
nodeVersion: undefined,
2929
nodeVersionFile: undefined,
30+
workingDirectory: undefined,
3031
runInstall: [],
3132
cache: false,
3233
cacheDependencyPath: undefined,
@@ -128,4 +129,16 @@ describe("getInputs", () => {
128129

129130
expect(inputs.cacheDependencyPath).toBe("custom-lock.yaml");
130131
});
132+
133+
it("should parse working-directory input", () => {
134+
vi.mocked(getInput).mockImplementation((name) => {
135+
if (name === "working-directory") return "web";
136+
return "";
137+
});
138+
vi.mocked(getBooleanInput).mockReturnValue(false);
139+
140+
const inputs = getInputs();
141+
142+
expect(inputs.workingDirectory).toBe("web");
143+
});
131144
});

src/inputs.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export function getInputs(): Inputs {
99
version: getInput("version") || "latest",
1010
nodeVersion: getInput("node-version") || undefined,
1111
nodeVersionFile: getInput("node-version-file") || undefined,
12+
workingDirectory: getInput("working-directory") || undefined,
1213
runInstall: parseRunInstall(getInput("run-install")),
1314
cache: getBooleanInput("cache"),
1415
cacheDependencyPath: getInput("cache-dependency-path") || undefined,

src/node-version-file.test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,14 @@ describe("resolveNodeVersionFile", () => {
3939
expect(readFileSync).toHaveBeenCalledWith("/custom/path/.nvmrc", "utf-8");
4040
});
4141

42+
it("should resolve relative path against an explicit base directory", () => {
43+
vi.mocked(readFileSync).mockReturnValue("20.0.0\n");
44+
45+
resolveNodeVersionFile(".nvmrc", "/workspace/web");
46+
47+
expect(readFileSync).toHaveBeenCalledWith("/workspace/web/.nvmrc", "utf-8");
48+
});
49+
4250
it("should throw if file does not exist", () => {
4351
vi.mocked(readFileSync).mockImplementation(() => {
4452
throw new Error("ENOENT");

src/node-version-file.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
import { info } from "@actions/core";
22
import { readFileSync } from "node:fs";
33
import { basename } from "node:path";
4-
import { resolveWorkspacePath } from "./utils.js";
4+
import { getWorkspaceDir, resolvePath } from "./utils.js";
55

66
/**
77
* Resolve a Node.js version from a version file.
88
*
99
* Supports: .nvmrc, .node-version, .tool-versions, package.json
1010
*/
11-
export function resolveNodeVersionFile(filePath: string): string {
12-
const fullPath = resolveWorkspacePath(filePath);
11+
export function resolveNodeVersionFile(filePath: string, baseDir?: string): string {
12+
const fullPath = resolvePath(filePath, baseDir || getWorkspaceDir());
1313

1414
let content: string;
1515
try {

src/run-install.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
import { startGroup, endGroup, setFailed, info } from "@actions/core";
22
import { exec } from "@actions/exec";
33
import type { Inputs } from "./types.js";
4+
import { getConfiguredProjectDir, getInstallCwd } from "./utils.js";
45

56
export async function runViteInstall(inputs: Inputs): Promise<void> {
7+
const projectDir = getConfiguredProjectDir(inputs);
8+
69
for (const options of inputs.runInstall) {
710
const args = ["install"];
811
if (options.args) {
912
args.push(...options.args);
1013
}
1114

12-
const cwd = options.cwd || process.env.GITHUB_WORKSPACE || process.cwd();
15+
const cwd = getInstallCwd(projectDir, options.cwd);
1316
const cmdStr = `vp ${args.join(" ")}`;
1417

1518
startGroup(`Running ${cmdStr} in ${cwd}...`);

0 commit comments

Comments
 (0)