Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add test for caching node's dependencies #1

Open
wants to merge 11 commits into
base: add-caching
Choose a base branch
from
1 change: 1 addition & 0 deletions .github/workflows/build-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ jobs:
- run: npm run build
- run: npm run format-check
- run: npm test
- run: git add .
- name: Verify no unstaged changes
if: runner.os != 'windows'
run: __tests__/verify-no-unstaged-changes.sh
101 changes: 101 additions & 0 deletions .github/workflows/e2e-cache.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
name: e2e-cache

on:
pull_request:
paths-ignore:
- '**.md'
push:
branches:
- main
- releases/*
paths-ignore:
- '**.md'

jobs:
node-npm-depencies-caching:
name: Test npm (Node ${{ matrix.node-version}}, ${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [10, 12, 14]
steps:
- uses: actions/checkout@v2
- name: Clean global cache
run: npm cache clean --force
- name: Setup Node
uses: ./
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Install dependencies
run: npm install
- name: Verify node and npm
run: __tests__/verify-node.sh "${{ matrix.node-version }}"
shell: bash

node-yarn1-depencies-caching:
name: Test yarn 1 (Node ${{ matrix.node-version}}, ${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [10, 12, 14]
steps:
- uses: actions/checkout@v2
- name: Yarn version
run: yarn --version
- name: Generate yarn file
run: yarn install
- name: Remove dependencies
shell: pwsh
run: Remove-Item node_modules -Force -Recurse
- name: Clean global cache
run: yarn cache clean
- name: Setup Node
uses: ./
with:
node-version: ${{ matrix.node-version }}
cache: 'yarn'
- name: Install dependencies
run: yarn install
- name: Verify node and yarn
run: __tests__/verify-node.sh "${{ matrix.node-version }}"
shell: bash

node-yarn2-depencies-caching:
name: Test yarn 2 (Node ${{ matrix.node-version}}, ${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [10, 12, 14]
steps:
- uses: actions/checkout@v2
- name: Update yarn
run: yarn set version berry
- name: Yarn version
run: yarn --version
- name: Generate simple .yarnrc.yml
run: |
echo "nodeLinker: node-modules" >> .yarnrc.yml
- name: Generate yarn file
run: yarn install
- name: Remove dependencies
shell: pwsh
run: Remove-Item node_modules -Force -Recurse
- name: Clean global cache
run: yarn cache clean --all
- name: Setup Node
uses: ./
with:
node-version: ${{ matrix.node-version }}
cache: 'yarn'
- name: Install dependencies
run: yarn install
- name: Verify node and yarn
run: __tests__/verify-node.sh "${{ matrix.node-version }}"
shell: bash
2 changes: 1 addition & 1 deletion .github/workflows/versions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,4 @@ jobs:
architecture: 'x86'
- name: Verify node
run: __tests__/verify-arch.sh "ia32"
shell: bash
shell: bash
168 changes: 168 additions & 0 deletions __tests__/cache-restore.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
import * as core from '@actions/core';
import * as cache from '@actions/cache';
import * as path from 'path';
import * as glob from '@actions/glob';

import * as utils from '../src/cache-utils';
import {restoreCache} from '../src/cache-restore';

describe('cache-restore', () => {
process.env['GITHUB_WORKSPACE'] = path.join(__dirname, 'data');
if (!process.env.RUNNER_OS) {
process.env.RUNNER_OS = 'Linux';
}
const platform = process.env.RUNNER_OS;
const commonPath = '/some/random/path';
const npmCachePath = `${commonPath}/npm`;
const yarn1CachePath = `${commonPath}/yarn1`;
const yarn2CachePath = `${commonPath}/yarn2`;
const yarnFileHash =
'b8a0bae5243251f7c07dd52d1f78ff78281dfefaded700a176261b6b54fa245b';
const npmFileHash =
'abf7c9b306a3149dcfba4673e2362755503bcceaab46f0e4e6fee0ade493e20c';
const cachesObject = {
[npmCachePath]: npmFileHash,
[yarn1CachePath]: yarnFileHash,
[yarn2CachePath]: yarnFileHash
};

function findCacheFolder(command: string) {
switch (command) {
case utils.supportedPackageManagers.npm.getCacheFolderCommand:
return npmCachePath;
case utils.supportedPackageManagers.yarn1.getCacheFolderCommand:
return yarn1CachePath;
case utils.supportedPackageManagers.yarn2.getCacheFolderCommand:
return yarn2CachePath;
default:
return 'packge/not/found';
}
}

let saveStateSpy: jest.SpyInstance;
let infoSpy: jest.SpyInstance;
let debugSpy: jest.SpyInstance;
let setOutputSpy: jest.SpyInstance;
let getCommandOutputSpy: jest.SpyInstance;
let restoreCacheSpy: jest.SpyInstance;
let hashFilesSpy: jest.SpyInstance;

beforeEach(() => {
// core
infoSpy = jest.spyOn(core, 'info');
infoSpy.mockImplementation(() => undefined);

debugSpy = jest.spyOn(core, 'debug');
debugSpy.mockImplementation(() => undefined);

setOutputSpy = jest.spyOn(core, 'setOutput');
setOutputSpy.mockImplementation(() => undefined);

saveStateSpy = jest.spyOn(core, 'saveState');
saveStateSpy.mockImplementation(() => undefined);

// glob
hashFilesSpy = jest.spyOn(glob, 'hashFiles');
hashFilesSpy.mockImplementation((pattern: string) => {
if (pattern.includes('package-lock.json')) {
return npmFileHash;
} else if (pattern.includes('yarn.lock')) {
return yarnFileHash;
} else {
return '';
}
});

// cache
restoreCacheSpy = jest.spyOn(cache, 'restoreCache');
restoreCacheSpy.mockImplementation(
(cachePaths: Array<string>, key: string) => {
if (!cachePaths || cachePaths.length === 0) {
return undefined;
}

const cachPath = cachePaths[0];
const fileHash = cachesObject[cachPath];

if (key.includes(fileHash)) {
return key;
}

return undefined;
}
);

// cache-utils
getCommandOutputSpy = jest.spyOn(utils, 'getCommandOutput');
});

describe('Validate provided package manager', () => {
it.each([['npm7'], ['npm6'], ['yarn1'], ['yarn2'], ['random']])(
'Throw an error because %s is not supported',
async packageManager => {
await expect(restoreCache(packageManager)).rejects.toThrowError(
`Caching for '${packageManager}' is not supported`
);
}
);
});

describe('Restore dependencies', () => {
it.each([
['yarn', '2.1.2', yarnFileHash],
['yarn', '1.2.3', yarnFileHash],
['npm', '', npmFileHash]
])(
'restored dependencies for %s',
async (packageManager, toolVersion, fileHash) => {
getCommandOutputSpy.mockImplementation((command: string) => {
if (command.includes('version')) {
return toolVersion;
} else {
return findCacheFolder(command);
}
});

await restoreCache(packageManager);
expect(hashFilesSpy).toHaveBeenCalled();
expect(infoSpy).toHaveBeenCalledWith(
`Cache restored from key: ${platform}-${packageManager}-${fileHash}`
);
expect(infoSpy).not.toHaveBeenCalledWith(
`${packageManager} cache is not found`
);
}
);
});

describe('Dependencies changed', () => {
it.each([
['yarn', '2.1.2', yarnFileHash],
['yarn', '1.2.3', yarnFileHash],
['npm', '', npmFileHash]
])(
'dependencies are changed %s',
async (packageManager, toolVersion, fileHash) => {
getCommandOutputSpy.mockImplementation((command: string) => {
if (command.includes('version')) {
return toolVersion;
} else {
return findCacheFolder(command);
}
});

restoreCacheSpy.mockImplementationOnce(() => undefined);
await restoreCache(packageManager);
expect(hashFilesSpy).toHaveBeenCalled();
expect(infoSpy).toHaveBeenCalledWith(
`${packageManager} cache is not found`
);
}
);
});

afterEach(() => {
jest.resetAllMocks();
jest.clearAllMocks();
});
});
Loading