mirror of
https://github.com/actions/setup-node.git
synced 2025-08-14 12:32:14 +00:00
initial commit
This commit is contained in:
parent
4dd8002ba1
commit
fdbef2dddd
2
.github/workflows/basic-validation.yml
vendored
2
.github/workflows/basic-validation.yml
vendored
@ -6,7 +6,7 @@ on:
|
||||
- '**.md'
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- check-686
|
||||
- releases/*
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
|
2
.github/workflows/check-dist.yml
vendored
2
.github/workflows/check-dist.yml
vendored
@ -3,7 +3,7 @@ name: Check dist
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- check-686
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
pull_request:
|
||||
|
2
.github/workflows/codeql-analysis.yml
vendored
2
.github/workflows/codeql-analysis.yml
vendored
@ -2,7 +2,7 @@ name: CodeQL analysis
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
branches: [check-686]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
schedule:
|
||||
|
42
.github/workflows/e2e-cache.yml
vendored
42
.github/workflows/e2e-cache.yml
vendored
@ -6,7 +6,7 @@ on:
|
||||
- '**.md'
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- check-686
|
||||
- releases/*
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
@ -243,3 +243,43 @@ jobs:
|
||||
cache-dependency-path: |
|
||||
sub2/*.lock
|
||||
sub3/*.lock
|
||||
|
||||
test-cache-auto-enabled:
|
||||
name: Test Cache Auto-Enabled
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest, macos-13]
|
||||
node-version: [18, 20, 22]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Change directory to __tests__/data
|
||||
run: cd __tests__/data
|
||||
- name: Setup Node
|
||||
uses: ./
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: Install dependencies
|
||||
run: npm install
|
||||
|
||||
test-cache-explicitly-disabled:
|
||||
name: Test Cache Explicitly Disabled
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest, macos-13]
|
||||
node-version: [18, 20, 22]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Change directory to __tests__/data
|
||||
run: cd __tests__/data
|
||||
- name: Setup Node
|
||||
uses: ./
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: ''
|
||||
- name: Verify node and npm
|
||||
run: __tests__/verify-node.sh "${{ matrix.node-version }}"
|
||||
shell: bash
|
||||
|
2
.github/workflows/licensed.yml
vendored
2
.github/workflows/licensed.yml
vendored
@ -3,7 +3,7 @@ name: Licensed
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- check-686
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
2
.github/workflows/proxy.yml
vendored
2
.github/workflows/proxy.yml
vendored
@ -6,7 +6,7 @@ on:
|
||||
- '**.md'
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- check-686
|
||||
- releases/*
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
|
2
.github/workflows/versions.yml
vendored
2
.github/workflows/versions.yml
vendored
@ -6,7 +6,7 @@ on:
|
||||
- '**.md'
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- check-686
|
||||
- releases/*
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
|
@ -135,7 +135,8 @@ It's **always** recommended to commit the lockfile of your package manager for s
|
||||
|
||||
## Caching global packages data
|
||||
|
||||
The action has a built-in functionality for caching and restoring dependencies. It uses [actions/cache](https://github.com/actions/cache) under the hood for caching global packages data but requires less configuration settings. Supported package managers are `npm`, `yarn`, `pnpm` (v6.10+). The `cache` input is optional, and caching is turned off by default.
|
||||
The action has a built-in functionality for caching and restoring dependencies. It uses [actions/cache](https://github.com/actions/cache) under the hood for caching global packages data but requires less configuration settings. Supported package managers are `npm`, `yarn`, `pnpm` (v6.10+). The `cache` input is optional. If not set, caching is automatically enabled if a supported package manager is detected in your `package.json` (`devEngines.packageManager.name` or `packageManager` field).
|
||||
If set to `''` (empty string), caching is explicitly disabled, even if a package manager is present.
|
||||
|
||||
The action defaults to search for the dependency file (`package-lock.json`, `npm-shrinkwrap.json` or `yarn.lock`) in the repository root, and uses its hash as a part of the cache key. Use `cache-dependency-path` for cases when multiple dependency files are used, or they are located in different subdirectories.
|
||||
|
||||
|
@ -1,4 +1,9 @@
|
||||
{
|
||||
"devEngines": {
|
||||
"packageManager": {
|
||||
"name": "npm"
|
||||
}
|
||||
},
|
||||
"engines": {
|
||||
"node": "^20.0.0"
|
||||
}
|
||||
|
@ -240,6 +240,15 @@ describe('main tests', () => {
|
||||
});
|
||||
|
||||
describe('cache on GHES', () => {
|
||||
beforeEach(() => {
|
||||
// Reset mocks and environment variables before each test
|
||||
jest.resetModules();
|
||||
jest.clearAllMocks();
|
||||
jest.spyOn(core, 'saveState').mockImplementation(() => {});
|
||||
jest.spyOn(core, 'warning').mockImplementation(() => {});
|
||||
delete process.env['GITHUB_SERVER_URL'];
|
||||
});
|
||||
|
||||
it('Should throw an error, because cache is not supported', async () => {
|
||||
inputs['node-version'] = '12';
|
||||
inputs['cache'] = 'npm';
|
||||
@ -253,6 +262,9 @@ describe('main tests', () => {
|
||||
process.env['GITHUB_SERVER_URL'] = 'https://www.test.com';
|
||||
isCacheActionAvailable.mockImplementation(() => false);
|
||||
|
||||
// Mock package.json with no packageManager field
|
||||
jest.spyOn(fs, 'readFileSync').mockReturnValue(JSON.stringify({}));
|
||||
|
||||
await main.run();
|
||||
|
||||
expect(warningSpy).toHaveBeenCalledWith(
|
||||
@ -273,11 +285,107 @@ describe('main tests', () => {
|
||||
process.env['GITHUB_SERVER_URL'] = '';
|
||||
isCacheActionAvailable.mockImplementation(() => false);
|
||||
|
||||
// Mock package.json with no packageManager field
|
||||
jest.spyOn(fs, 'readFileSync').mockReturnValue(JSON.stringify({}));
|
||||
|
||||
await main.run();
|
||||
|
||||
expect(warningSpy).toHaveBeenCalledWith(
|
||||
'The runner was not able to contact the cache service. Caching will be skipped'
|
||||
);
|
||||
});
|
||||
|
||||
it('Should enable caching by default when packageManager field is defined', async () => {
|
||||
inputs['node-version'] = '12';
|
||||
inputs['cache'] = undefined; // User did not specify cache
|
||||
|
||||
inSpy.mockImplementation(name => inputs[name]);
|
||||
const toolPath = path.normalize('/cache/node/18.0.0/x64');
|
||||
findSpy.mockImplementation(() => toolPath);
|
||||
|
||||
process.env['GITHUB_SERVER_URL'] = 'https://www.test.com';
|
||||
isCacheActionAvailable.mockImplementation(() => true);
|
||||
|
||||
// packageManager in package.json
|
||||
(fs.readFileSync as jest.Mock).mockReturnValue(
|
||||
JSON.stringify({
|
||||
packageManager: 'yarn@3.2.0'
|
||||
})
|
||||
);
|
||||
|
||||
await main.run();
|
||||
|
||||
// Should enable caching (saveState called with 'yarn')
|
||||
expect(core.saveState).toHaveBeenCalledWith(expect.anything(), 'yarn');
|
||||
});
|
||||
|
||||
it('Should enable cache if devEngines.packageManager field is present', async () => {
|
||||
inputs['node-version'] = '12';
|
||||
inputs['cache'] = undefined; // Explicitly opt-in via package.json
|
||||
|
||||
inSpy.mockImplementation(name => inputs[name]);
|
||||
findSpy.mockImplementation(() =>
|
||||
path.normalize('/cache/node/12.16.1/x64')
|
||||
);
|
||||
process.env['GITHUB_SERVER_URL'] = 'https://www.test.com';
|
||||
isCacheActionAvailable.mockImplementation(() => true);
|
||||
|
||||
// devEngines.packageManager in package.json
|
||||
(fs.readFileSync as jest.Mock).mockReturnValue(
|
||||
JSON.stringify({
|
||||
devEngines: {
|
||||
packageManager: {name: 'pnpm'}
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
await main.run();
|
||||
|
||||
// Should enable caching (saveState called with 'pnpm')
|
||||
expect(core.saveState).toHaveBeenCalledWith(expect.anything(), 'pnpm');
|
||||
});
|
||||
|
||||
it('Should NOT enable caching when neither cache nor packageManager is set', async () => {
|
||||
inputs['node-version'] = '12';
|
||||
inputs['cache'] = undefined;
|
||||
|
||||
inSpy.mockImplementation(name => inputs[name]);
|
||||
findSpy.mockImplementation(() =>
|
||||
path.normalize('/cache/node/12.16.1/x64')
|
||||
);
|
||||
process.env['GITHUB_SERVER_URL'] = 'https://www.test.com';
|
||||
isCacheActionAvailable.mockImplementation(() => true);
|
||||
|
||||
// package.json with no cache info
|
||||
(fs.readFileSync as jest.Mock).mockReturnValue(JSON.stringify({}));
|
||||
|
||||
await main.run();
|
||||
|
||||
expect(core.saveState).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('Should NOT enable caching when cache is explicitly disabled', async () => {
|
||||
inputs['node-version'] = '12';
|
||||
inputs['cache'] = ''; // Explicitly opt-out
|
||||
|
||||
inSpy.mockImplementation(name => inputs[name]);
|
||||
findSpy.mockImplementation(() =>
|
||||
path.normalize('/cache/node/12.16.1/x64')
|
||||
);
|
||||
process.env['GITHUB_SERVER_URL'] = 'https://www.test.com';
|
||||
isCacheActionAvailable.mockImplementation(() => true);
|
||||
|
||||
// packageManager in package.json
|
||||
(fs.readFileSync as jest.Mock).mockReturnValue(
|
||||
JSON.stringify({
|
||||
packageManager: 'yarn@3.2.0'
|
||||
})
|
||||
);
|
||||
|
||||
await main.run();
|
||||
|
||||
// Should NOT enable caching (saveState not called)
|
||||
expect(core.saveState).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
14452
dist/cache-save/index.js
vendored
14452
dist/cache-save/index.js
vendored
File diff suppressed because one or more lines are too long
21200
dist/setup/index.js
vendored
21200
dist/setup/index.js
vendored
File diff suppressed because one or more lines are too long
27
src/main.ts
27
src/main.ts
@ -1,6 +1,7 @@
|
||||
import * as core from '@actions/core';
|
||||
|
||||
import os from 'os';
|
||||
import fs from 'fs';
|
||||
|
||||
import * as auth from './authutil';
|
||||
import * as path from 'path';
|
||||
@ -63,10 +64,21 @@ export async function run() {
|
||||
auth.configAuthentication(registryUrl, alwaysAuth);
|
||||
}
|
||||
|
||||
if (cache && isCacheFeatureAvailable()) {
|
||||
core.saveState(State.CachePackageManager, cache);
|
||||
const packageManagerFromManifest = getNameFromPackageManagerField();
|
||||
if (
|
||||
cache !== '' &&
|
||||
isCacheFeatureAvailable() &&
|
||||
(cache !== undefined || packageManagerFromManifest)
|
||||
) {
|
||||
const cacheDependencyPath = core.getInput('cache-dependency-path');
|
||||
await restoreCache(cache, cacheDependencyPath);
|
||||
const packageManager =
|
||||
cache !== undefined ? cache : packageManagerFromManifest;
|
||||
if (!packageManager) {
|
||||
// This should NOT happen due to your if, but this satisfies TypeScript.
|
||||
return;
|
||||
}
|
||||
core.saveState(State.CachePackageManager, packageManager);
|
||||
await restoreCache(packageManager, cacheDependencyPath);
|
||||
}
|
||||
|
||||
const matchersPath = path.join(__dirname, '../..', '.github');
|
||||
@ -117,3 +129,12 @@ function resolveVersionInput(): string {
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
export function getNameFromPackageManagerField(): string | undefined {
|
||||
// Check devEngines.packageManager first
|
||||
const packageJson = JSON.parse(fs.readFileSync('package.json', 'utf-8'));
|
||||
return (
|
||||
packageJson.devEngines?.packageManager?.name ||
|
||||
packageJson.packageManager?.replace(/^[^a-zA-Z0-9]+/, '').split('@')[0]
|
||||
);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user