Skip to content

Commit 3ea717c

Browse files
committed
feat: support installation from custom NPM registry
read and respect registry configuration from .npmrc if it exists
1 parent f2b2b23 commit 3ea717c

File tree

4 files changed

+70
-3
lines changed

4 files changed

+70
-3
lines changed

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ If `run_install` is a YAML string representation of either an object or an array
5252

5353
This is useful when you want to use a incompatible pair of Node.js and pnpm.
5454

55+
## Registry Configuration
56+
57+
The action automatically respects custom registry configuration from `.npmrc` files in your workspace root. If a `.npmrc` file exists and contains a `registry=` line, the action will use that registry URL to install pnpm. Otherwise, the default npm registry will be used.
58+
5559
## Outputs
5660

5761
### `dest`
@@ -83,7 +87,7 @@ jobs:
8387
version: 10
8488
```
8589
86-
### Install only pnpm with `packageManager`
90+
### Install only pnpm with `packageManager`
8791

8892
Omit `version` input to use the version in the [`packageManager` field in the `package.json`](https://nodejs.org/api/corepack.html).
8993

dist/index.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/install-pnpm/run.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ import path from 'path'
66
import { execPath } from 'process'
77
import util from 'util'
88
import { Inputs } from '../inputs'
9+
import { readNpmrcRegistry } from '../utils'
910
import YAML from 'yaml'
1011

1112
export async function runSelfInstaller(inputs: Inputs): Promise<number> {
1213
const { version, dest, packageJsonFile, standalone } = inputs
14+
const { GITHUB_WORKSPACE } = process.env
1315

1416
// prepare self install
1517
await rm(dest, { recursive: true, force: true })
@@ -21,7 +23,18 @@ export async function runSelfInstaller(inputs: Inputs): Promise<number> {
2123

2224
// prepare target pnpm
2325
const target = await readTarget({ version, packageJsonFile, standalone })
24-
const cp = spawn(execPath, [path.join(__dirname, 'pnpm.cjs'), 'install', target, '--no-lockfile'], {
26+
const installArgs = [path.join(__dirname, 'pnpm.cjs'), 'install', target, '--no-lockfile']
27+
28+
if (GITHUB_WORKSPACE) {
29+
const customRegistry = await readNpmrcRegistry(GITHUB_WORKSPACE)
30+
31+
if (customRegistry) {
32+
installArgs.push('--registry', customRegistry)
33+
}
34+
}
35+
36+
// run self-install
37+
const cp = spawn(execPath, installArgs, {
2538
cwd: dest,
2639
stdio: ['pipe', 'inherit', 'inherit'],
2740
})

src/utils/index.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
import { debug, info, warning } from '@actions/core'
2+
import { readFile } from 'fs/promises'
13
import path from 'path'
24
import process from 'process'
5+
import util from 'util'
36
import { Inputs } from '../inputs'
47

58
export const getBinDest = (inputs: Inputs): string => path.join(inputs.dest, 'node_modules', '.bin')
@@ -8,3 +11,50 @@ export const patchPnpmEnv = (inputs: Inputs): NodeJS.ProcessEnv => ({
811
...process.env,
912
PATH: getBinDest(inputs) + path.delimiter + process.env.PATH,
1013
})
14+
15+
/**
16+
* Reads and parses a potential .npmrc file to extract registry configuration
17+
* @param workspaceRoot - The root directory of the workspace
18+
* @returns The registry URL if found, otherwise undefined
19+
*/
20+
export async function readNpmrcRegistry(workspaceRoot: string): Promise<string | undefined> {
21+
try {
22+
const npmrcPath = path.join(workspaceRoot, '.npmrc');
23+
24+
debug(`Attempting to read .npmrc file from: ${npmrcPath}`);
25+
const content = await readFile(npmrcPath, 'utf8');
26+
27+
for (const line of content.split('\n')) {
28+
const trimmedLine = line.trim();
29+
30+
// skip comments and empty lines
31+
if (!trimmedLine || /^[#;]/.test(trimmedLine)) {
32+
continue;
33+
}
34+
35+
const match = trimmedLine.match(/^registry\s*=\s*(.+)$/);
36+
if (match) {
37+
const registry = match[1].trim();
38+
39+
if (!/^https?:\/\//.test(registry)) {
40+
warning(`Invalid registry URL format in .npmrc (must be http/https): ${registry}`);
41+
continue;
42+
}
43+
44+
info(`Using custom registry from .npmrc: ${registry}`);
45+
return registry;
46+
}
47+
}
48+
49+
debug('No valid registry configuration found in .npmrc, using default NPM registry');
50+
} catch (error) {
51+
if (util.types.isNativeError(error) && 'code' in error && error.code === 'ENOENT') {
52+
debug('No .npmrc file found, using default NPM registry');
53+
} else {
54+
const errorMessage = util.types.isNativeError(error) ? error.message : String(error);
55+
warning(`Error reading .npmrc file: ${errorMessage}`);
56+
}
57+
}
58+
59+
return;
60+
}

0 commit comments

Comments
 (0)