Skip to content

Commit

Permalink
refactor: clean up setup action (#146)
Browse files Browse the repository at this point in the history
* refactor: replace cache with opinionated tool cacher

* refactor: replace install with packager

* refactor: replace various tools with worker

BEARKING CHANGE: Dropping username and password authentication in favor of token authentication only.

* refactor: update setup action with latest refactors

* chore: rebuild project

* chore: remove semver and rebuild project

* refactor: update tests for new components

* chore: fix linting issues and rebuild project
  • Loading branch information
byCedric authored Jan 13, 2022
1 parent 3ae7999 commit 439ff4c
Show file tree
Hide file tree
Showing 19 changed files with 918 additions and 4,677 deletions.
3,946 changes: 372 additions & 3,574 deletions build/setup/index.js

Large diffs are not rendered by default.

38 changes: 0 additions & 38 deletions build/setup/license.txt
Original file line number Diff line number Diff line change
Expand Up @@ -736,25 +736,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.



lru-cache
ISC
The ISC License

Copyright (c) Isaac Z. Schlueter and Contributors

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.


mime-db
MIT

Expand Down Expand Up @@ -1106,22 +1087,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.


yallist
ISC
The ISC License

Copyright (c) Isaac Z. Schlueter and Contributors

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
4 changes: 1 addition & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,14 @@
"@actions/core": "^1.6.0",
"@actions/exec": "^1.1.0",
"@actions/io": "^1.1.1",
"@actions/tool-cache": "^1.7.1",
"semver": "^7.3.5"
"@actions/tool-cache": "^1.7.1"
},
"devDependencies": {
"@semantic-release/changelog": "^6.0.1",
"@semantic-release/git": "^10.0.1",
"@tsconfig/node16": "^1.0.2",
"@types/jest": "^27.4.0",
"@types/node": "^16.11.19",
"@types/semver": "^7.3.9",
"@typescript-eslint/eslint-plugin": "^5.9.1",
"@typescript-eslint/parser": "^5.9.1",
"@vercel/ncc": "^0.33.1",
Expand Down
114 changes: 66 additions & 48 deletions src/actions/setup.ts
Original file line number Diff line number Diff line change
@@ -1,61 +1,79 @@
import { addPath, getBooleanInput, getInput, group, info } from '@actions/core';
import { getBooleanInput, getInput, group, info } from '@actions/core';

import { install } from '../install';
import { resolveVersion } from '../packager';
import * as tools from '../tools';
import { restoreFromCache, saveToCache } from '../cacher';
import { installPackage, resolvePackage } from '../packager';
import { executeAction, expoAuthenticate, findTool, installToolFromPackage, patchWatchers } from '../worker';

// Auto-execute in GitHub actions
tools.performAction(setupAction);

export async function setupAction(): Promise<void> {
const expoVersion = await installCli('expo-cli');
const easVersion = await installCli('eas-cli');

await group('Checking current authenticated account', () =>
tools.maybeAuthenticate({
cli: expoVersion ? 'expo-cli' : easVersion ? 'eas-cli' : undefined,
token: getInput('token') || undefined,
username: getInput('username') || undefined,
password: getInput('password') || undefined,
})
);

if (!getInput('patch-watchers') || getBooleanInput('patch-watchers') !== false) {
await group('Patching system watchers for the `ENOSPC` error', () => tools.maybePatchWatchers());
}
executeAction(setupAction);

export type SetupInput = ReturnType<typeof setupInput>;

export function setupInput() {
return {
easCache: getBooleanInput('eas-cache'),
easVersion: getInput('eas-version'),
expoCache: getBooleanInput('expo-cache'),
expoVersion: getInput('expo-version'),
packager: getInput('packager') || 'yarn',
patchWatchers: !getInput('patch-watchers') || getBooleanInput('patch-watchers'),
token: getInput('token'),
};
}

async function installCli(name: tools.PackageName): Promise<string | void> {
const shortName = tools.getBinaryName(name);
const inputVersion = getInput(`${shortName}-version`);
const packager = getInput('packager') || 'yarn';
export async function setupAction(input: SetupInput = setupInput()): Promise<void> {
if (!input.expoVersion) {
info(`Skipped installing expo-cli: 'expo-version' not provided.`);
} else {
const version = await resolvePackage('expo-cli', input.expoVersion);
const message = input.expoCache
? `Installing expo-cli (${version}) from cache or with ${input.packager}`
: `Installing expo-cli (${version}) with ${input.packager}`;

if (!inputVersion) {
return info(`Skipping installation of ${name}, \`${shortName}-version\` not provided.`);
await group(message, () => installCli('expo-cli', version, input.packager, input.expoCache));
}

const version = await resolveVersion(name, inputVersion);
const cache = getBooleanInput(`${shortName}-cache`);

try {
const path = await group(
cache
? `Installing ${name} (${version}) from cache or with ${packager}`
: `Installing ${name} (${version}) with ${packager}`,
() =>
install({
packager,
version,
cache,
package: name,
cacheKey: getInput(`${shortName}-cache-key`) || undefined,
})
if (!input.easVersion) {
info(`Skipped installing eas-cli: 'eas-version' not provided.`);
} else {
const version = await resolvePackage('eas-cli', input.easVersion);
const message = input.easCache
? `Installing eas-cli (${version}) from cache or with ${input.packager}`
: `Installing eas-cli (${version}) with ${input.packager}`;

await group(message, () => installCli('eas-cli', input.easVersion, input.packager, input.easCache));
}

if (!input.token) {
info(`Skipped authentication: 'token' not provided.`);
} else {
await group('Validating authenticated account', () =>
expoAuthenticate(input.token, input.easVersion ? 'eas' : input.expoVersion ? 'expo' : undefined)
);
}

if (!input.patchWatchers) {
info(`Skipped patching watchers: 'patch-watchers' disabled.`);
} else {
await group(`Patching system watchers for the 'ENOSPC' error`, patchWatchers);
}
}

async function installCli(name: string, version: string, packager: string, cache: boolean = true) {
const cliVersion = await resolvePackage(name, version);
let cliPath = findTool(name, cliVersion) || undefined;

if (!cliPath && cache) {
cliPath = await restoreFromCache(name, cliVersion, packager);
}

if (!cliPath) {
cliPath = await installPackage(name, cliVersion, packager);

addPath(path);
} catch (error) {
tools.handleError(name, error);
if (cache) {
await saveToCache(name, cliVersion, packager);
}
}

return version;
installToolFromPackage(cliPath);
}
94 changes: 0 additions & 94 deletions src/cache.ts

This file was deleted.

61 changes: 61 additions & 0 deletions src/cacher.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { saveCache, restoreCache, ReserveCacheError } from '@actions/cache';
import { warning } from '@actions/core';
import os from 'os';

import { toolPath } from './worker';

/**
* Get the exact cache key for the package.
* We can prefix this when there are breaking changes in this action.
*/
export function cacheKey(name: string, version: string, manager: string): string {
return `${name}-${process.platform}-${os.arch()}-${manager}-${version}`;
}

/**
* Restore a tool from the remote cache.
* This will install the tool back into the local tool cache.
*/
export async function restoreFromCache(name: string, version: string, manager: string) {
const dir = toolPath(name, version)!;
try {
if (await restoreCache([dir], cacheKey(name, version, manager))) {
return dir;
}
} catch (error) {
handleCacheError(error);
}
}

/**
* Save a tool to the remote cache.
* This will fetch the tool from the local tool cache.
*/
export async function saveToCache(name: string, version: string, manager: string) {
try {
await saveCache([toolPath(name, version)], cacheKey(name, version, manager));
} catch (error) {
handleCacheError(error);
}
}

/**
* Try to handle incoming cache errors.
* Because workers can operate in environments without cache configured,
* we need to make sure to only skip the cache instead of fail.
*
* Currently we handle these types of errors:
* - ReserveCacheError
* - "cache service url not found"
*/
export function handleCacheError(error: Error): void {
const isReserveCacheError = error instanceof ReserveCacheError;
const isCacheUnavailable = error.message.toLowerCase().includes('cache service url not found');

if (isReserveCacheError || isCacheUnavailable) {
warning('Skipped remote cache, encountered error:');
warning(error.message);
} else {
throw error;
}
}
Loading

0 comments on commit 439ff4c

Please sign in to comment.