chore: multi-platform hooks and tests
parent
c1595485e8
commit
0fc027d3a1
|
|
@ -1,6 +1,8 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
. "$(dirname "$0")/_/husky.sh"
|
. "$(dirname "$0")/_/husky.sh"
|
||||||
|
|
||||||
yarn lint-staged --verbose
|
# Check changed files
|
||||||
yarn build
|
yarn lint-staged
|
||||||
git add dist
|
|
||||||
|
# Compile the action
|
||||||
|
yarn build ; git add dist
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,11 @@
|
||||||
"author": "Webber <webber@takken.io>",
|
"author": "Webber <webber@takken.io>",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"prepare": "husky install",
|
||||||
"prebuild": "yarn",
|
"prebuild": "yarn",
|
||||||
"build": "tsc && ncc build lib --source-map --license licenses.txt",
|
"build": "tsc && ncc build lib --source-map --license licenses.txt",
|
||||||
"lint": "prettier --check \"src/**/*.{js,ts}\" && eslint src/**/*.ts",
|
"lint": "prettier --check \"src/**/*.{js,ts}\" && eslint src/**/*.ts",
|
||||||
"format": "prettier --write \"src/**/*.{js,ts}\"",
|
"format": "prettier --write \"src/**/*.{js,ts}\"",
|
||||||
"prepare": "husky install",
|
|
||||||
"cli": "yarn ts-node src/index.ts -m cli",
|
"cli": "yarn ts-node src/index.ts -m cli",
|
||||||
"cli-aws": "cross-env cloudRunnerCluster=aws yarn run test-cli",
|
"cli-aws": "cross-env cloudRunnerCluster=aws yarn run test-cli",
|
||||||
"cli-k8s": "cross-env cloudRunnerCluster=k8s yarn run test-cli",
|
"cli-k8s": "cross-env cloudRunnerCluster=k8s yarn run test-cli",
|
||||||
|
|
@ -66,8 +66,7 @@
|
||||||
"lint-staged": {
|
"lint-staged": {
|
||||||
"*.{js,jsx,ts,tsx}": [
|
"*.{js,jsx,ts,tsx}": [
|
||||||
"prettier --write",
|
"prettier --write",
|
||||||
"eslint",
|
"eslint"
|
||||||
"jest --findRelatedTests --passWithNoTests"
|
|
||||||
],
|
],
|
||||||
"*.{json,md,yaml,yml}": [
|
"*.{json,md,yaml,yml}": [
|
||||||
"prettier --write"
|
"prettier --write"
|
||||||
|
|
|
||||||
|
|
@ -1,57 +1,77 @@
|
||||||
import * as core from '@actions/core';
|
import * as core from '@actions/core';
|
||||||
|
import * as exec from '@actions/exec';
|
||||||
import System from './system';
|
import System from './system';
|
||||||
|
|
||||||
jest.spyOn(core, 'debug').mockImplementation(() => {});
|
jest.spyOn(core, 'debug').mockImplementation(() => {});
|
||||||
const info = jest.spyOn(core, 'info').mockImplementation(() => {});
|
const info = jest.spyOn(core, 'info').mockImplementation(() => {});
|
||||||
jest.spyOn(core, 'warning').mockImplementation(() => {});
|
jest.spyOn(core, 'warning').mockImplementation(() => {});
|
||||||
jest.spyOn(core, 'error').mockImplementation(() => {});
|
jest.spyOn(core, 'error').mockImplementation(() => {});
|
||||||
|
const execSpy = jest.spyOn(exec, 'exec').mockImplementation(async () => 0);
|
||||||
afterEach(() => {
|
|
||||||
jest.clearAllMocks();
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('System', () => {
|
describe('System', () => {
|
||||||
describe('run', () => {
|
describe('run', () => {
|
||||||
it('runs a command successfully', async () => {
|
describe('units', () => {
|
||||||
await expect(System.run('true')).resolves.not.toBeNull();
|
afterEach(() => jest.clearAllMocks());
|
||||||
|
|
||||||
|
it('passes the command to command line', async () => {
|
||||||
|
await expect(System.run('echo test')).resolves.not.toBeNull();
|
||||||
|
await expect(execSpy).toHaveBeenLastCalledWith('echo test', expect.anything(), expect.anything());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws on when error code is not 0', async () => {
|
||||||
|
execSpy.mockImplementationOnce(async () => 1);
|
||||||
|
await expect(System.run('false')).rejects.toThrowError();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws when no command is given', async () => {
|
||||||
|
await expect(System.run('')).rejects.toThrowError();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws when command consists only of spaces', async () => {
|
||||||
|
await expect(System.run(' \t\n')).rejects.toThrowError();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('outputs info', async () => {
|
||||||
|
execSpy.mockImplementationOnce(async (input, _, options) => {
|
||||||
|
options?.listeners?.stdout?.(Buffer.from(input, 'utf8'));
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
await expect(System.run('foo-bar')).resolves.not.toBeNull();
|
||||||
|
expect(info).toHaveBeenCalledTimes(1);
|
||||||
|
expect(info).toHaveBeenLastCalledWith('foo-bar');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('outputs results', async () => {
|
/**
|
||||||
await expect(System.run('echo test')).resolves.toStrictEqual('test\n');
|
* Not all shells (e.g. Powershell, sh) have a reference to `echo` binary (absent or alias).
|
||||||
});
|
* To ensure our integration with '@actions/exec' works as expected we run some specific tests in CI only
|
||||||
|
*/
|
||||||
|
if (process.env.CI) {
|
||||||
|
describe('integration', () => {
|
||||||
|
execSpy.mockRestore();
|
||||||
|
|
||||||
it('throws on when error code is not 0', async () => {
|
it('runs a command successfully', async () => {
|
||||||
await expect(System.run('false')).rejects.toThrowError();
|
await expect(System.run('true')).resolves.not.toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('throws when no arguments are given', async () => {
|
it('outputs results', async () => {
|
||||||
await expect(System.run('')).rejects.toThrowError();
|
await expect(System.run('echo test')).resolves.toStrictEqual('test\n');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('outputs info', async () => {
|
it('throws on when error code is not 0', async () => {
|
||||||
await expect(System.run('echo test')).resolves.not.toBeNull();
|
await expect(System.run('false')).rejects.toThrowError();
|
||||||
expect(info).toHaveBeenLastCalledWith('test\n');
|
});
|
||||||
});
|
|
||||||
|
|
||||||
it('outputs info only once', async () => {
|
it('allows pipes using buffer', async () => {
|
||||||
await expect(System.run('echo 1')).resolves.not.toBeNull();
|
await expect(
|
||||||
expect(info).toHaveBeenCalledTimes(1);
|
System.run('sh', undefined, {
|
||||||
expect(info).toHaveBeenLastCalledWith('1\n');
|
input: Buffer.from('git tag --list --merged HEAD | grep v[0-9]* | wc -l'),
|
||||||
|
// eslint-disable-next-line github/no-then
|
||||||
info.mockClear();
|
}).then((result) => Number(result)),
|
||||||
await expect(System.run('echo 2')).resolves.not.toBeNull();
|
).resolves.not.toBeNaN();
|
||||||
await expect(System.run('echo 3')).resolves.not.toBeNull();
|
});
|
||||||
expect(info).toHaveBeenCalledTimes(2);
|
});
|
||||||
expect(info).toHaveBeenLastCalledWith('3\n');
|
}
|
||||||
});
|
|
||||||
|
|
||||||
it('allows pipes using buffer', async () => {
|
|
||||||
await expect(
|
|
||||||
System.run('sh', undefined, {
|
|
||||||
input: Buffer.from('git tag --list --merged HEAD | grep v[0-9]* | wc -l'),
|
|
||||||
// eslint-disable-next-line github/no-then
|
|
||||||
}).then((result) => Number(result)),
|
|
||||||
).resolves.not.toBeNaN();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,10 @@ class System {
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
if (command.trim() === '') {
|
||||||
|
throw new Error(`Failed to execute empty command`);
|
||||||
|
}
|
||||||
|
|
||||||
const exitCode = await exec(command, arguments_, { silent: true, listeners, ...options });
|
const exitCode = await exec(command, arguments_, { silent: true, listeners, ...options });
|
||||||
showOutput();
|
showOutput();
|
||||||
if (exitCode !== 0) {
|
if (exitCode !== 0) {
|
||||||
|
|
|
||||||
12
yarn.lock
12
yarn.lock
|
|
@ -3941,9 +3941,9 @@ lines-and-columns@^1.1.6:
|
||||||
integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=
|
integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=
|
||||||
|
|
||||||
lint-staged@^12.3.4:
|
lint-staged@^12.3.4:
|
||||||
version "12.3.4"
|
version "12.3.7"
|
||||||
resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-12.3.4.tgz#4b1ff8c394c3e6da436aaec5afd4db18b5dac360"
|
resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-12.3.7.tgz#ad0e2014302f704f9cf2c0ebdb97ac63d0f17be0"
|
||||||
integrity sha512-yv/iK4WwZ7/v0GtVkNb3R82pdL9M+ScpIbJLJNyCXkJ1FGaXvRCOg/SeL59SZtPpqZhE7BD6kPKFLIDUhDx2/w==
|
integrity sha512-/S4D726e2GIsDVWIk1XGvheCaDm1SJRQp8efamZFWJxQMVEbOwSysp7xb49Oo73KYCdy97mIWinhlxcoNqIfIQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
cli-truncate "^3.1.0"
|
cli-truncate "^3.1.0"
|
||||||
colorette "^2.0.16"
|
colorette "^2.0.16"
|
||||||
|
|
@ -3955,6 +3955,7 @@ lint-staged@^12.3.4:
|
||||||
micromatch "^4.0.4"
|
micromatch "^4.0.4"
|
||||||
normalize-path "^3.0.0"
|
normalize-path "^3.0.0"
|
||||||
object-inspect "^1.12.0"
|
object-inspect "^1.12.0"
|
||||||
|
pidtree "^0.5.0"
|
||||||
string-argv "^0.3.1"
|
string-argv "^0.3.1"
|
||||||
supports-color "^9.2.1"
|
supports-color "^9.2.1"
|
||||||
yaml "^1.10.2"
|
yaml "^1.10.2"
|
||||||
|
|
@ -4498,6 +4499,11 @@ picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3:
|
||||||
resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz"
|
resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz"
|
||||||
integrity sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg==
|
integrity sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg==
|
||||||
|
|
||||||
|
pidtree@^0.5.0:
|
||||||
|
version "0.5.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.5.0.tgz#ad5fbc1de78b8a5f99d6fbdd4f6e4eee21d1aca1"
|
||||||
|
integrity sha512-9nxspIM7OpZuhBxPg73Zvyq7j1QMPMPsGKTqRc2XOaFQauDvoNz9fM1Wdkjmeo7l9GXOZiRs97sPkuayl39wjA==
|
||||||
|
|
||||||
pify@^2.0.0:
|
pify@^2.0.0:
|
||||||
version "2.3.0"
|
version "2.3.0"
|
||||||
resolved "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz"
|
resolved "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue