From 6217a9d8c4ed43da32ba581d4741b992cca189c3 Mon Sep 17 00:00:00 2001 From: Don Denton Date: Wed, 27 Nov 2024 23:32:44 -0500 Subject: [PATCH] feat: add version_file_path option Using the same logic as `actions/setup-node`, we can support `asdf`, `volta` or other version management techniques. --- .github/workflows/test.yaml | 116 ++++++++++++++++++++++++++++++++ README.md | 26 +++++++ action.yml | 3 + dist/index.js | Bin 672112 -> 673150 bytes src/inputs/index.ts | 2 + src/install-pnpm/run.ts | 75 +++++++++++++++++++-- test/.tool-versions | 1 + test/package.engines.json | 1 + test/package.volta-extends.json | 1 + test/package.volta.json | 1 + 10 files changed, 222 insertions(+), 4 deletions(-) create mode 100644 test/.tool-versions create mode 100644 test/package.engines.json create mode 100644 test/package.volta-extends.json create mode 100644 test/package.volta.json diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 40a91d2..a5fee7f 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -35,6 +35,122 @@ jobs: - name: 'Test: install' run: pnpm install + test_version_file_asdf: + name: Test with version file (asdf) + + runs-on: ${{ matrix.os }} + + strategy: + fail-fast: false + matrix: + pnpm: + - 4.11.1 + os: + - ubuntu-latest + - macos-latest + - windows-latest + + steps: + - uses: actions/checkout@v4 + + - name: Run the action + uses: ./ + with: + version_file_path: test/.tool-versions + + - name: 'Test: which' + run: which pnpm; which pnpx + + - name: 'Test: install' + run: pnpm install + + test_version_file_engines: + name: Test with version file (package.json engines) + + runs-on: ${{ matrix.os }} + + strategy: + fail-fast: false + matrix: + pnpm: + - 4.11.1 + os: + - ubuntu-latest + - macos-latest + - windows-latest + + steps: + - uses: actions/checkout@v4 + + - name: Run the action + uses: ./ + with: + version_file_path: test/package.engines.json + + - name: 'Test: which' + run: which pnpm; which pnpx + + - name: 'Test: install' + run: pnpm install + + test_version_file_volta: + name: Test with version file (volta) + + runs-on: ${{ matrix.os }} + + strategy: + fail-fast: false + matrix: + pnpm: + - 4.11.1 + os: + - ubuntu-latest + - macos-latest + - windows-latest + + steps: + - uses: actions/checkout@v4 + + - name: Run the action + uses: ./ + with: + version_file_path: test/package.volta.json + + - name: 'Test: which' + run: which pnpm; which pnpx + + - name: 'Test: install' + run: pnpm install + + test_version_file_volta_extends: + name: Test with version file (volta extends) + + runs-on: ${{ matrix.os }} + + strategy: + fail-fast: false + matrix: + pnpm: + - 4.11.1 + os: + - ubuntu-latest + - macos-latest + - windows-latest + + steps: + - uses: actions/checkout@v4 + + - name: Run the action + uses: ./ + with: + version_file_path: test/package.volta-extends.json + + - name: 'Test: which' + run: which pnpm; which pnpx + + - name: 'Test: install' + run: pnpm install + test_dest: name: Test with dest diff --git a/README.md b/README.md index 6d00309..777fbaa 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,12 @@ Version of pnpm to install. otherwise, this field is **required** It supports npm versioning scheme, it could be an exact version (such as `6.24.1`), or a version range (such as `6`, `6.x.x`, `6.24.x`, `^6.24.1`, `*`, etc.), or `latest`. +### `version_file_path` + +The `version_file_path` input accepts a path to a file containing the version of pnpm to be used. For example `.tool-versions` (if you use `asdf`), or package.json (if you use the engines property or [`volta`](https://volta.sh) instead of corepack). + +The action will search for the version file relative to the repository root. + ### `dest` **Optional** Where to store pnpm files. @@ -83,6 +89,26 @@ jobs: version: 9 ``` +### Install only pnpm with a version file + +This works when you use `volta`, `asdf`, etc. + +```yaml +on: + - push + - pull_request + +jobs: + install: + runs-on: ubuntu-latest + + steps: + - uses: pnpm/action-setup@v4 + with: + version_file_path: ".tool-versions" # with asdf + # version_file_path: "package.json" # with volta +``` + ### Install only pnpm with `packageManager` Omit `version` input to use the version in the [`packageManager` field in the `package.json`](https://nodejs.org/api/corepack.html). diff --git a/action.yml b/action.yml index 831ced0..52f990b 100644 --- a/action.yml +++ b/action.yml @@ -7,6 +7,9 @@ inputs: version: description: Version of pnpm to install required: false + version_file_path: + description: "Path to a version file. Eg: '.tool-versions' for asdf or 'package.json' for volta" + required: false dest: description: Where to store pnpm files required: false diff --git a/dist/index.js b/dist/index.js index d554a1e0ebd37f5821dec4d0662c7598621b0de1..9b84d1fcc8cff824487df92dbdcf2894aeceb573 100644 GIT binary patch delta 12682 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 delta 12017 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 UGa|8dbHV=uQj)c9U8?B+0Zy1dQUCw| diff --git a/src/inputs/index.ts b/src/inputs/index.ts index a9b705a..97b537b 100644 --- a/src/inputs/index.ts +++ b/src/inputs/index.ts @@ -4,6 +4,7 @@ import { RunInstall, parseRunInstall } from './run-install' export interface Inputs { readonly version?: string + readonly versionFilePath?: string readonly dest: string readonly runInstall: RunInstall[] readonly packageJsonFile: string @@ -18,6 +19,7 @@ const parseInputPath = (name: string) => expandTilde(getInput(name, options)) export const getInputs = (): Inputs => ({ version: getInput('version'), + versionFilePath: getInput('version_file_path'), dest: parseInputPath('dest'), runInstall: parseRunInstall('run_install'), packageJsonFile: parseInputPath('package_json_file'), diff --git a/src/install-pnpm/run.ts b/src/install-pnpm/run.ts index e02fb98..d07c900 100644 --- a/src/install-pnpm/run.ts +++ b/src/install-pnpm/run.ts @@ -1,14 +1,14 @@ import { addPath, exportVariable } from '@actions/core' import { spawn } from 'child_process' import { rm, writeFile, mkdir } from 'fs/promises' -import { readFileSync } from 'fs' +import { readFileSync, existsSync } from 'fs' import path from 'path' import { execPath } from 'process' import util from 'util' import { Inputs } from '../inputs' export async function runSelfInstaller(inputs: Inputs): Promise { - const { version, dest, packageJsonFile, standalone } = inputs + const { version, versionFilePath, dest, packageJsonFile, standalone } = inputs // prepare self install await rm(dest, { recursive: true, force: true }) @@ -19,7 +19,7 @@ export async function runSelfInstaller(inputs: Inputs): Promise { await writeFile(pkgJson, JSON.stringify({ private: true })) // prepare target pnpm - const target = await readTarget({ version, packageJsonFile, standalone }) + const target = await readTarget({ version, versionFilePath, packageJsonFile, standalone }) const cp = spawn(execPath, [path.join(__dirname, 'pnpm.cjs'), 'install', target, '--no-lockfile'], { cwd: dest, stdio: ['pipe', 'inherit', 'inherit'], @@ -37,12 +37,71 @@ export async function runSelfInstaller(inputs: Inputs): Promise { return exitCode } +// Nearly identical to the function `actions/setup-node` uses. +// See https://github.com/actions/setup-node/blob/39370e3970a6d050c480ffad4ff0ed4d3fdee5af/src/util.ts#L8 +function getPnpmVersionFromFile(versionFilePath: string) { + if (!existsSync(versionFilePath)) { + throw new Error( + `The specified pnpm version file at: ${versionFilePath} does not exist` + ) + } + + const contents = readFileSync(versionFilePath, 'utf8') + + // Try parsing the file as a `package.json` file. + try { + const manifest = JSON.parse(contents) + + // Presume package.json file. + if (typeof manifest === 'object' && !!manifest) { + // Support Volta. + // See https://docs.volta.sh/guide/understanding#managing-your-project + if (manifest.volta?.pnpm) { + return manifest.volta.pnpm as string + } + + if (manifest.engines?.pnpm) { + return manifest.engines.pnpm as string + } + + // Support Volta workspaces. + // See https://docs.volta.sh/advanced/workspaces + if (manifest.volta?.extends) { + const extendedFilePath = path.resolve( + path.dirname(versionFilePath), + manifest.volta.extends + ) + console.info('Resolving pnpm version from ' + extendedFilePath) + return getPnpmVersionFromFile(extendedFilePath) + } + + // If contents are an object, we parsed JSON + // this can happen if pnpm-version-file is a package.json + // yet contains no volta.pnpm or engines.pnpm + // + // If pnpm-version file is _not_ JSON, control flow + // will not have reached these lines. + // + // And because we've reached here, we know the contents + // *are* JSON, so no further string parsing makes sense. + return + } + } catch { + console.info('pnpm version file is not JSON file') + } + + const found = contents.match(/^(?:pnpm\s+)?v?(?[^\s]+)$/m) + return found?.groups?.version ?? contents.trim() +} + async function readTarget(opts: { readonly version?: string | undefined + readonly versionFilePath?: string | undefined readonly packageJsonFile: string readonly standalone: boolean }) { - const { version, packageJsonFile, standalone } = opts + const { versionFilePath, packageJsonFile, standalone } = opts + let { version } = opts const { GITHUB_WORKSPACE } = process.env let packageManager @@ -56,6 +115,14 @@ async function readTarget(opts: { } } + if (typeof versionFilePath === "string" && typeof version === "string") { + throw new Error("Multiple version determination methods specified: 'version' and 'version_file_path'. Please specify only one.") + } + + if (versionFilePath) { + version = getPnpmVersionFromFile(versionFilePath) + } + if (version) { if ( typeof packageManager === 'string' && diff --git a/test/.tool-versions b/test/.tool-versions new file mode 100644 index 0000000..b5f0550 --- /dev/null +++ b/test/.tool-versions @@ -0,0 +1 @@ +pnpm 4.11.1 \ No newline at end of file diff --git a/test/package.engines.json b/test/package.engines.json new file mode 100644 index 0000000..ae2422c --- /dev/null +++ b/test/package.engines.json @@ -0,0 +1 @@ +{"engines":{"pnpm":"4.11.1"}} \ No newline at end of file diff --git a/test/package.volta-extends.json b/test/package.volta-extends.json new file mode 100644 index 0000000..f6aec47 --- /dev/null +++ b/test/package.volta-extends.json @@ -0,0 +1 @@ +{"volta":{"extends":"./package.volta.json"}} \ No newline at end of file diff --git a/test/package.volta.json b/test/package.volta.json new file mode 100644 index 0000000..4b1551e --- /dev/null +++ b/test/package.volta.json @@ -0,0 +1 @@ +{"volta":{"pnpm":"4.11.1"}} \ No newline at end of file