mirror of
https://github.com/pnpm/action-setup.git
synced 2024-12-22 16:02:41 +08:00
feat: add version_file_path option
Using the same logic as `actions/setup-node`, we can support `asdf`, `volta` or other version management techniques.
This commit is contained in:
parent
ac5bf11548
commit
6217a9d8c4
116
.github/workflows/test.yaml
vendored
116
.github/workflows/test.yaml
vendored
|
@ -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
|
||||
|
||||
|
|
26
README.md
26
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).
|
||||
|
|
|
@ -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
|
||||
|
|
BIN
dist/index.js
vendored
BIN
dist/index.js
vendored
Binary file not shown.
|
@ -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'),
|
||||
|
|
|
@ -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<number> {
|
||||
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<number> {
|
|||
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<number> {
|
|||
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?(?<version>[^\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' &&
|
||||
|
|
1
test/.tool-versions
Normal file
1
test/.tool-versions
Normal file
|
@ -0,0 +1 @@
|
|||
pnpm 4.11.1
|
1
test/package.engines.json
Normal file
1
test/package.engines.json
Normal file
|
@ -0,0 +1 @@
|
|||
{"engines":{"pnpm":"4.11.1"}}
|
1
test/package.volta-extends.json
Normal file
1
test/package.volta-extends.json
Normal file
|
@ -0,0 +1 @@
|
|||
{"volta":{"extends":"./package.volta.json"}}
|
1
test/package.volta.json
Normal file
1
test/package.volta.json
Normal file
|
@ -0,0 +1 @@
|
|||
{"volta":{"pnpm":"4.11.1"}}
|
Loading…
Reference in New Issue
Block a user