-
Notifications
You must be signed in to change notification settings - Fork 77
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: clean up setup action (#146)
* 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
Showing
19 changed files
with
918 additions
and
4,677 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} |
Oops, something went wrong.