From eebde89a6bb0df6c08e67c8fca7c26cf17193883 Mon Sep 17 00:00:00 2001 From: Will Schurman Date: Tue, 24 Sep 2024 13:05:21 -0700 Subject: [PATCH] [continuous-deploy-fingerprint] Clean up code slightly --- build/continuous-deploy-fingerprint/index.js | 144 +++++++-------- .../actions/preview-comment.test.ts | 12 +- .../__tests__}/actions/preview.test.ts | 6 +- .../__tests__}/actions/setup.test.ts | 18 +- {tests => src/__tests__}/cacher.test.ts | 4 +- {tests => src/__tests__}/comment.test.ts | 6 +- {tests => src/__tests__}/eas.test.ts | 2 +- {tests => src/__tests__}/expo.test.ts | 2 +- .../fingerprint/FingerprintDbManager.test.ts | 2 +- {tests => src/__tests__}/github.test.ts | 2 +- {tests => src/__tests__}/packager.test.ts | 2 +- {tests => src/__tests__}/sqlite.test.ts | 2 +- {tests => src/__tests__}/utils.ts | 0 {tests => src/__tests__}/worker.test.ts | 2 +- src/actions/continuous-deploy-fingerprint.ts | 171 +++++++++--------- tsconfig.json | 5 +- 16 files changed, 174 insertions(+), 206 deletions(-) rename {tests => src/__tests__}/actions/preview-comment.test.ts (95%) rename {tests => src/__tests__}/actions/preview.test.ts (99%) rename {tests => src/__tests__}/actions/setup.test.ts (90%) rename {tests => src/__tests__}/cacher.test.ts (96%) rename {tests => src/__tests__}/comment.test.ts (92%) rename {tests => src/__tests__}/eas.test.ts (95%) rename {tests => src/__tests__}/expo.test.ts (99%) rename {tests => src/__tests__}/fingerprint/FingerprintDbManager.test.ts (98%) rename {tests => src/__tests__}/github.test.ts (97%) rename {tests => src/__tests__}/packager.test.ts (95%) rename {tests => src/__tests__}/sqlite.test.ts (95%) rename {tests => src/__tests__}/utils.ts (100%) rename {tests => src/__tests__}/worker.test.ts (99%) diff --git a/build/continuous-deploy-fingerprint/index.js b/build/continuous-deploy-fingerprint/index.js index f410a2bd..7f76d65a 100644 --- a/build/continuous-deploy-fingerprint/index.js +++ b/build/continuous-deploy-fingerprint/index.js @@ -44537,10 +44537,17 @@ const github_1 = __nccwpck_require__(978); const project_1 = __nccwpck_require__(7191); const worker_1 = __nccwpck_require__(8912); function collectContinuousDeployFingerprintInput() { + function validatePlatformInput(platformInput) { + return ['android', 'ios', 'all'].includes(platformInput); + } + const platformInput = (0, core_1.getInput)('platform'); + if (!validatePlatformInput(platformInput)) { + throw new Error(`Invalid platform: ${platformInput}. Must be one of "all", "ios", "android".`); + } return { profile: (0, core_1.getInput)('profile'), branch: (0, core_1.getInput)('branch'), - platform: (0, core_1.getInput)('platform'), + platform: platformInput, githubToken: (0, core_1.getInput)('github-token'), workingDirectory: (0, core_1.getInput)('working-directory'), }; @@ -44554,89 +44561,24 @@ async function continuousDeployFingerprintAction(input = collectContinuousDeploy if (!projectId) { return (0, core_1.setFailed)(`Missing 'extra.eas.projectId' in app.json or app.config.js.`); } - let platform = 'all'; - switch (input.platform) { - case 'android': - platform = 'android'; - break; - case 'ios': - platform = 'ios'; - break; - } - async function buildAndroidIfNecessaryAsync() { - if (platform === 'ios') { - return null; - } - const androidFingerprintHash = await getFingerprintHashForPlatformAsync({ - cwd: input.workingDirectory, - platform: 'android', - }); - (0, core_1.info)(`Android fingerprint: ${androidFingerprintHash}`); - (0, core_1.info)('Looking for builds with matching runtime version (fingerprint)...'); - const existingAndroidBuildInfo = await getBuildInfoWithFingerprintAsync({ - cwd: input.workingDirectory, - platform: 'android', - profile: input.profile, - fingerprintHash: androidFingerprintHash, - excludeExpiredBuilds: isInPullRequest, - }); - if (existingAndroidBuildInfo) { - (0, core_1.info)(`Existing Android build found with matching fingerprint: ${existingAndroidBuildInfo.id}`); - return { - buildInfo: existingAndroidBuildInfo, - isNew: false, - fingerprintHash: androidFingerprintHash, - }; - } - else { - (0, core_1.info)(`No existing Android build found for fingerprint, starting a new build...`); - return { - buildInfo: await createEASBuildAsync({ - cwd: input.workingDirectory, - platform: 'android', - profile: input.profile, - }), - isNew: true, - fingerprintHash: androidFingerprintHash, - }; - } - } - async function buildIosIfNecessaryAsync() { - if (platform === 'android') { - return null; - } - const iosFingerprintHash = await getFingerprintHashForPlatformAsync({ - cwd: input.workingDirectory, - platform: 'ios', - }); - (0, core_1.info)(`iOS fingerprint: ${iosFingerprintHash}`); - const existingIosBuildInfo = await getBuildInfoWithFingerprintAsync({ - cwd: input.workingDirectory, - platform: 'ios', - profile: input.profile, - fingerprintHash: iosFingerprintHash, - excludeExpiredBuilds: isInPullRequest, - }); - if (existingIosBuildInfo) { - (0, core_1.info)(`Existing iOS build found with matching fingerprint: ${existingIosBuildInfo.id}`); - return { buildInfo: existingIosBuildInfo, isNew: false, fingerprintHash: iosFingerprintHash }; - } - else { - (0, core_1.info)(`No existing iOS build found for fingerprint, starting a new build...`); - return { - buildInfo: await createEASBuildAsync({ - cwd: input.workingDirectory, - platform: 'ios', - profile: input.profile, - }), - isNew: true, - fingerprintHash: iosFingerprintHash, - }; - } - } + const platformsToRun = input.platform === 'all' ? new Set(['ios', 'android']) : new Set([input.platform]); const [androidBuildRunInfo, iosBuildRunInfo] = await Promise.all([ - buildAndroidIfNecessaryAsync(), - buildIosIfNecessaryAsync(), + platformsToRun.has('android') + ? buildForPlatformIfNecessaryAsync({ + platform: 'android', + profile: input.profile, + workingDirectory: input.workingDirectory, + isInPullRequest, + }) + : null, + platformsToRun.has('ios') + ? buildForPlatformIfNecessaryAsync({ + platform: 'ios', + profile: input.profile, + workingDirectory: input.workingDirectory, + isInPullRequest, + }) + : null, ]); (0, core_1.info)(`Publishing EAS Update...`); const updates = await publishEASUpdatesAsync({ @@ -44674,6 +44616,42 @@ async function continuousDeployFingerprintAction(input = collectContinuousDeploy (0, core_1.setOutput)('update-output', updates); } exports.continuousDeployFingerprintAction = continuousDeployFingerprintAction; +async function buildForPlatformIfNecessaryAsync({ platform, workingDirectory, profile, isInPullRequest, }) { + const humanReadablePlatformName = platform === 'ios' ? 'iOS' : 'Android'; + const fingerprintHash = await getFingerprintHashForPlatformAsync({ + cwd: workingDirectory, + platform, + }); + (0, core_1.info)(`${humanReadablePlatformName} fingerprint: ${fingerprintHash}`); + (0, core_1.info)(`Looking for ${humanReadablePlatformName} builds with matching runtime version (fingerprint)...`); + const existingBuildInfo = await getBuildInfoWithFingerprintAsync({ + cwd: workingDirectory, + platform, + profile, + fingerprintHash, + excludeExpiredBuilds: isInPullRequest, + }); + if (existingBuildInfo) { + (0, core_1.info)(`Existing ${humanReadablePlatformName} build found with matching fingerprint: ${existingBuildInfo.id}`); + return { + buildInfo: existingBuildInfo, + isNew: false, + fingerprintHash, + }; + } + else { + (0, core_1.info)(`No existing ${humanReadablePlatformName} build found for fingerprint, starting a new build...`); + return { + buildInfo: await createEASBuildAsync({ + cwd: workingDirectory, + platform, + profile, + }), + isNew: true, + fingerprintHash, + }; + } +} async function getFingerprintHashForPlatformAsync({ cwd, platform, }) { try { const extraArgs = (0, core_1.isDebug)() ? ['--debug'] : []; diff --git a/tests/actions/preview-comment.test.ts b/src/__tests__/actions/preview-comment.test.ts similarity index 95% rename from tests/actions/preview-comment.test.ts rename to src/__tests__/actions/preview-comment.test.ts index 8cd89a63..cdd42fc7 100644 --- a/tests/actions/preview-comment.test.ts +++ b/src/__tests__/actions/preview-comment.test.ts @@ -5,15 +5,15 @@ import { DEFAULT_MESSAGE, commentAction, commentInput, -} from '../../src/actions/preview-comment'; -import * as expo from '../../src/expo'; -import * as github from '../../src/github'; +} from '../../actions/preview-comment'; +import * as expo from '../../expo'; +import * as github from '../../github'; import { mockInput } from '../utils'; jest.mock('@actions/core'); -jest.mock('../../src/expo'); -jest.mock('../../src/github'); -jest.mock('../../src/worker'); +jest.mock('../../expo'); +jest.mock('../../github'); +jest.mock('../../worker'); describe(commentInput, () => { it('returns object with correct defaults', () => { diff --git a/tests/actions/preview.test.ts b/src/__tests__/actions/preview.test.ts similarity index 99% rename from tests/actions/preview.test.ts rename to src/__tests__/actions/preview.test.ts index 4911b9ac..1ba503e2 100644 --- a/tests/actions/preview.test.ts +++ b/src/__tests__/actions/preview.test.ts @@ -1,9 +1,9 @@ import { ExpoConfig } from '@expo/config'; -import { createSummary, getVariables, previewInput } from '../../src/actions/preview'; -import { EasUpdate } from '../../src/eas'; +import { createSummary, getVariables, previewInput } from '../../actions/preview'; +import { EasUpdate } from '../../eas'; -jest.mock('../../src/expo'); +jest.mock('../../expo'); const fakeOptions = { qrTarget: 'dev-client', diff --git a/tests/actions/setup.test.ts b/src/__tests__/actions/setup.test.ts similarity index 90% rename from tests/actions/setup.test.ts rename to src/__tests__/actions/setup.test.ts index 9d7338dc..be0f1ffd 100644 --- a/tests/actions/setup.test.ts +++ b/src/__tests__/actions/setup.test.ts @@ -1,17 +1,17 @@ import * as core from '@actions/core'; -import { setupAction, setupInput } from '../../src/actions/setup'; -import * as cacher from '../../src/cacher'; -import * as expo from '../../src/expo'; -import * as packager from '../../src/packager'; -import * as worker from '../../src/worker'; +import { setupAction, setupInput } from '../../actions/setup'; +import * as cacher from '../../cacher'; +import * as expo from '../../expo'; +import * as packager from '../../packager'; +import * as worker from '../../worker'; import { mockInput } from '../utils'; jest.mock('@actions/core'); -jest.mock('../../src/cacher'); -jest.mock('../../src/expo'); -jest.mock('../../src/packager'); -jest.mock('../../src/worker'); +jest.mock('../../cacher'); +jest.mock('../../expo'); +jest.mock('../../packager'); +jest.mock('../../worker'); describe(setupInput, () => { it('returns object with correct defaults', () => { diff --git a/tests/cacher.test.ts b/src/__tests__/cacher.test.ts similarity index 96% rename from tests/cacher.test.ts rename to src/__tests__/cacher.test.ts index 21386b9d..c4e5412a 100644 --- a/tests/cacher.test.ts +++ b/src/__tests__/cacher.test.ts @@ -2,8 +2,8 @@ import * as cache from '@actions/cache'; import os from 'os'; import { resetEnv, setEnv } from './utils'; -import { cacheKey, restoreFromCache, saveToCache } from '../src/cacher'; -import { toolPath } from '../src/worker'; +import { cacheKey, restoreFromCache, saveToCache } from '../cacher'; +import { toolPath } from '../worker'; jest.mock('@actions/cache'); jest.mock('@actions/core'); diff --git a/tests/comment.test.ts b/src/__tests__/comment.test.ts similarity index 92% rename from tests/comment.test.ts rename to src/__tests__/comment.test.ts index e9168e48..68b40b38 100644 --- a/tests/comment.test.ts +++ b/src/__tests__/comment.test.ts @@ -1,9 +1,9 @@ import { ExpoConfig } from '@expo/config'; -import { getQrTarget, getSchemesInOrderFromConfig } from '../src/comment'; -import { projectAppType } from '../src/expo'; +import { getQrTarget, getSchemesInOrderFromConfig } from '../comment'; +import { projectAppType } from '../expo'; -jest.mock('../src/expo'); +jest.mock('../expo'); const fakeOptions = { workingDirectory: '', diff --git a/tests/eas.test.ts b/src/__tests__/eas.test.ts similarity index 95% rename from tests/eas.test.ts rename to src/__tests__/eas.test.ts index a7053327..1771771c 100644 --- a/tests/eas.test.ts +++ b/src/__tests__/eas.test.ts @@ -1,4 +1,4 @@ -import { getUpdateGroupQr } from '../src/eas'; +import { getUpdateGroupQr } from '../eas'; describe(getUpdateGroupQr, () => { it('returns url for expo-go', () => { diff --git a/tests/expo.test.ts b/src/__tests__/expo.test.ts similarity index 99% rename from tests/expo.test.ts rename to src/__tests__/expo.test.ts index 8e62e3d7..2f6c7c75 100644 --- a/tests/expo.test.ts +++ b/src/__tests__/expo.test.ts @@ -2,7 +2,7 @@ import * as core from '@actions/core'; import * as exec from '@actions/exec'; import * as io from '@actions/io'; -import { authenticate, parseCommand, projectDeepLink, projectLink, projectQR } from '../src/expo'; +import { authenticate, parseCommand, projectDeepLink, projectLink, projectQR } from '../expo'; jest.mock('@actions/core'); jest.mock('@actions/exec'); diff --git a/tests/fingerprint/FingerprintDbManager.test.ts b/src/__tests__/fingerprint/FingerprintDbManager.test.ts similarity index 98% rename from tests/fingerprint/FingerprintDbManager.test.ts rename to src/__tests__/fingerprint/FingerprintDbManager.test.ts index 5ff5ac64..70e36e2a 100644 --- a/tests/fingerprint/FingerprintDbManager.test.ts +++ b/src/__tests__/fingerprint/FingerprintDbManager.test.ts @@ -1,6 +1,6 @@ import type { FingerprintSource } from '@expo/fingerprint'; -import { FingerprintDbManager } from '../../src/fingerprint/FingerprintDbManager'; +import { FingerprintDbManager } from '../../fingerprint/FingerprintDbManager'; describe(FingerprintDbManager, () => { let fingerprintDbManager: FingerprintDbManager; diff --git a/tests/github.test.ts b/src/__tests__/github.test.ts similarity index 97% rename from tests/github.test.ts rename to src/__tests__/github.test.ts index 1a5eec68..373ec77f 100644 --- a/tests/github.test.ts +++ b/src/__tests__/github.test.ts @@ -1,7 +1,7 @@ import * as github from '@actions/github'; import { resetEnv, setEnv } from './utils'; -import { githubApi, pullContext } from '../src/github'; +import { githubApi, pullContext } from '../github'; jest.mock('@actions/github'); diff --git a/tests/packager.test.ts b/src/__tests__/packager.test.ts similarity index 95% rename from tests/packager.test.ts rename to src/__tests__/packager.test.ts index dbac5494..d642f528 100644 --- a/tests/packager.test.ts +++ b/src/__tests__/packager.test.ts @@ -1,4 +1,4 @@ -import { resolvePackage } from '../src/packager'; +import { resolvePackage } from '../packager'; describe(resolvePackage, () => { it('resolves expo-cli@^2.0.0 to 2.21.2', async () => { diff --git a/tests/sqlite.test.ts b/src/__tests__/sqlite.test.ts similarity index 95% rename from tests/sqlite.test.ts rename to src/__tests__/sqlite.test.ts index 8aa956d7..c20f8844 100644 --- a/tests/sqlite.test.ts +++ b/src/__tests__/sqlite.test.ts @@ -1,4 +1,4 @@ -import { Database, openDatabaseAsync } from '../src/sqlite'; +import { Database, openDatabaseAsync } from '../sqlite'; describe(openDatabaseAsync, () => { let db: Database; diff --git a/tests/utils.ts b/src/__tests__/utils.ts similarity index 100% rename from tests/utils.ts rename to src/__tests__/utils.ts diff --git a/tests/worker.test.ts b/src/__tests__/worker.test.ts similarity index 99% rename from tests/worker.test.ts rename to src/__tests__/worker.test.ts index f066f079..1f7681ea 100644 --- a/tests/worker.test.ts +++ b/src/__tests__/worker.test.ts @@ -10,7 +10,7 @@ import { patchWatchers, tempPath, toolPath, -} from '../src/worker'; +} from '../worker'; jest.mock('@actions/core'); jest.mock('@actions/exec'); diff --git a/src/actions/continuous-deploy-fingerprint.ts b/src/actions/continuous-deploy-fingerprint.ts index c9d468be..9c8e3cc1 100644 --- a/src/actions/continuous-deploy-fingerprint.ts +++ b/src/actions/continuous-deploy-fingerprint.ts @@ -14,10 +14,19 @@ type BuildRunInfo = { buildInfo: BuildInfo; isNew: boolean; fingerprintHash: str type PlatformArg = 'android' | 'ios' | 'all'; export function collectContinuousDeployFingerprintInput() { + function validatePlatformInput(platformInput: string): platformInput is PlatformArg { + return ['android', 'ios', 'all'].includes(platformInput); + } + + const platformInput = getInput('platform'); + if (!validatePlatformInput(platformInput)) { + throw new Error(`Invalid platform: ${platformInput}. Must be one of "all", "ios", "android".`); + } + return { profile: getInput('profile'), branch: getInput('branch'), - platform: getInput('platform'), + platform: platformInput, githubToken: getInput('github-token'), workingDirectory: getInput('working-directory'), }; @@ -36,99 +45,25 @@ export async function continuousDeployFingerprintAction( return setFailed(`Missing 'extra.eas.projectId' in app.json or app.config.js.`); } - let platform: PlatformArg = 'all'; - switch (input.platform) { - case 'android': - platform = 'android'; - break; - case 'ios': - platform = 'ios'; - break; - } - - async function buildAndroidIfNecessaryAsync(): Promise { - if (platform === 'ios') { - return null; - } - - const androidFingerprintHash = await getFingerprintHashForPlatformAsync({ - cwd: input.workingDirectory, - platform: 'android', - }); - - info(`Android fingerprint: ${androidFingerprintHash}`); - - info('Looking for builds with matching runtime version (fingerprint)...'); - - const existingAndroidBuildInfo = await getBuildInfoWithFingerprintAsync({ - cwd: input.workingDirectory, - platform: 'android', - profile: input.profile, - fingerprintHash: androidFingerprintHash, - excludeExpiredBuilds: isInPullRequest, - }); - if (existingAndroidBuildInfo) { - info( - `Existing Android build found with matching fingerprint: ${existingAndroidBuildInfo.id}` - ); - return { - buildInfo: existingAndroidBuildInfo, - isNew: false, - fingerprintHash: androidFingerprintHash, - }; - } else { - info(`No existing Android build found for fingerprint, starting a new build...`); - return { - buildInfo: await createEASBuildAsync({ - cwd: input.workingDirectory, + const platformsToRun: Set = + input.platform === 'all' ? new Set(['ios', 'android']) : new Set([input.platform]); + const [androidBuildRunInfo, iosBuildRunInfo] = await Promise.all([ + platformsToRun.has('android') + ? buildForPlatformIfNecessaryAsync({ platform: 'android', profile: input.profile, - }), - isNew: true, - fingerprintHash: androidFingerprintHash, - }; - } - } - - async function buildIosIfNecessaryAsync(): Promise { - if (platform === 'android') { - return null; - } - - const iosFingerprintHash = await getFingerprintHashForPlatformAsync({ - cwd: input.workingDirectory, - platform: 'ios', - }); - - info(`iOS fingerprint: ${iosFingerprintHash}`); - - const existingIosBuildInfo = await getBuildInfoWithFingerprintAsync({ - cwd: input.workingDirectory, - platform: 'ios', - profile: input.profile, - fingerprintHash: iosFingerprintHash, - excludeExpiredBuilds: isInPullRequest, - }); - if (existingIosBuildInfo) { - info(`Existing iOS build found with matching fingerprint: ${existingIosBuildInfo.id}`); - return { buildInfo: existingIosBuildInfo, isNew: false, fingerprintHash: iosFingerprintHash }; - } else { - info(`No existing iOS build found for fingerprint, starting a new build...`); - return { - buildInfo: await createEASBuildAsync({ - cwd: input.workingDirectory, + workingDirectory: input.workingDirectory, + isInPullRequest, + }) + : null, + platformsToRun.has('ios') + ? buildForPlatformIfNecessaryAsync({ platform: 'ios', profile: input.profile, - }), - isNew: true, - fingerprintHash: iosFingerprintHash, - }; - } - } - - const [androidBuildRunInfo, iosBuildRunInfo] = await Promise.all([ - buildAndroidIfNecessaryAsync(), - buildIosIfNecessaryAsync(), + workingDirectory: input.workingDirectory, + isInPullRequest, + }) + : null, ]); info(`Publishing EAS Update...`); @@ -171,6 +106,62 @@ export async function continuousDeployFingerprintAction( setOutput('update-output', updates); } +async function buildForPlatformIfNecessaryAsync({ + platform, + workingDirectory, + profile, + isInPullRequest, +}: { + platform: 'ios' | 'android'; + profile: string; + workingDirectory: string; + isInPullRequest: boolean; +}): Promise { + const humanReadablePlatformName = platform === 'ios' ? 'iOS' : 'Android'; + + const fingerprintHash = await getFingerprintHashForPlatformAsync({ + cwd: workingDirectory, + platform, + }); + + info(`${humanReadablePlatformName} fingerprint: ${fingerprintHash}`); + + info( + `Looking for ${humanReadablePlatformName} builds with matching runtime version (fingerprint)...` + ); + + const existingBuildInfo = await getBuildInfoWithFingerprintAsync({ + cwd: workingDirectory, + platform, + profile, + fingerprintHash, + excludeExpiredBuilds: isInPullRequest, + }); + if (existingBuildInfo) { + info( + `Existing ${humanReadablePlatformName} build found with matching fingerprint: ${existingBuildInfo.id}` + ); + return { + buildInfo: existingBuildInfo, + isNew: false, + fingerprintHash, + }; + } else { + info( + `No existing ${humanReadablePlatformName} build found for fingerprint, starting a new build...` + ); + return { + buildInfo: await createEASBuildAsync({ + cwd: workingDirectory, + platform, + profile, + }), + isNew: true, + fingerprintHash, + }; + } +} + async function getFingerprintHashForPlatformAsync({ cwd, platform, diff --git a/tsconfig.json b/tsconfig.json index ba439877..a0e78873 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,8 +1,8 @@ { "extends": "@tsconfig/node20", "compilerOptions": { - "strictNullChecks": true, - "outDir": "./build", + "strict": true, + "noEmit": true, "rootDir": "./src", "module": "CommonJS", "moduleResolution": "node" @@ -10,6 +10,5 @@ "exclude": [ "build", "node_modules", - "tests/**" ] }