diff --git a/packages/worker/src/__unit__/build.test.ts b/packages/worker/src/__unit__/build.test.ts new file mode 100644 index 0000000000..dea4a7e952 --- /dev/null +++ b/packages/worker/src/__unit__/build.test.ts @@ -0,0 +1,75 @@ +import { BuildContext, Builders } from '@expo/build-tools'; +import { Platform } from '@expo/eas-build-job'; + +import { build, warnOnUnknownEnvironment } from '../build'; +import { Analytics } from '../external/analytics'; + +jest.mock('@expo/build-tools', () => { + const actual = jest.requireActual('@expo/build-tools'); + return { + ...actual, + Builders: { + androidBuilder: jest.fn(async () => ({})), + iosBuilder: jest.fn(async () => ({})), + }, + }; +}); +jest.mock('../displayRuntimeInfo', () => ({ displayWorkerRuntimeInfo: jest.fn() })); +jest.mock('../workingdir', () => ({ cleanUpWorkingdir: jest.fn() })); +jest.mock('../external/analytics', () => ({ + ...jest.requireActual('../external/analytics'), + logProjectDependenciesAsync: jest.fn(), +})); + +function createEnvironmentWarningCtx(environment?: string) { + return { + metadata: environment === undefined ? undefined : { environment }, + markBuildPhaseHasWarnings: jest.fn(), + logger: { warn: jest.fn() }, + }; +} + +describe(warnOnUnknownEnvironment.name, () => { + it('warns and marks the phase for an unknown environment', () => { + const ctx = createEnvironmentWarningCtx('staging'); + warnOnUnknownEnvironment(ctx); + expect(ctx.markBuildPhaseHasWarnings).toHaveBeenCalled(); + expect(ctx.logger.warn).toHaveBeenCalledWith( + expect.stringContaining('Unknown environment "staging"') + ); + }); + + it.each(['development', 'preview', 'production'])('does not warn for %s', environment => { + const ctx = createEnvironmentWarningCtx(environment); + warnOnUnknownEnvironment(ctx); + expect(ctx.markBuildPhaseHasWarnings).not.toHaveBeenCalled(); + expect(ctx.logger.warn).not.toHaveBeenCalled(); + }); + + it('does not warn when no environment is set', () => { + const ctx = createEnvironmentWarningCtx(undefined); + warnOnUnknownEnvironment(ctx); + expect(ctx.logger.warn).not.toHaveBeenCalled(); + }); +}); + +describe(build.name, () => { + it('warns during spin-up when the job environment is unknown', async () => { + const warn = jest.fn(); + const markBuildPhaseHasWarnings = jest.fn(); + const ctx = { + metadata: { environment: 'staging' }, + job: { platform: Platform.ANDROID }, + logger: { info: jest.fn(), warn, child: jest.fn() }, + markBuildPhaseHasWarnings, + runBuildPhase: jest.fn(async (_phase, callback) => callback()), + } as unknown as BuildContext; + const analytics = { logEvent: jest.fn(), flushEventsAsync: jest.fn() } as unknown as Analytics; + + await build({ ctx, buildId: 'build-id', analytics }); + + expect(Builders.androidBuilder).toHaveBeenCalled(); + expect(markBuildPhaseHasWarnings).toHaveBeenCalled(); + expect(warn).toHaveBeenCalledWith(expect.stringContaining('Unknown environment "staging"')); + }); +}); diff --git a/packages/worker/src/build.ts b/packages/worker/src/build.ts index e662eaa6ed..e8a805c9a6 100644 --- a/packages/worker/src/build.ts +++ b/packages/worker/src/build.ts @@ -19,6 +19,26 @@ import { Analytics, Event, logProjectDependenciesAsync } from './external/analyt import { prepareRuntimeEnvironment } from './runtimeEnvironment'; import { cleanUpWorkingdir } from './workingdir'; +const KNOWN_BUILD_ENVIRONMENTS = ['development', 'preview', 'production']; + +type EnvironmentWarningContext = { + metadata?: { environment?: string }; + logger: Pick; + markBuildPhaseHasWarnings: () => void; +}; + +export function warnOnUnknownEnvironment(ctx: EnvironmentWarningContext): void { + const environment = ctx.metadata?.environment; + if (environment && !KNOWN_BUILD_ENVIRONMENTS.includes(environment)) { + ctx.markBuildPhaseHasWarnings(); + ctx.logger.warn( + `Unknown environment "${environment}". Expected one of: ${KNOWN_BUILD_ENVIRONMENTS.join( + ', ' + )}. No environment variables were added for it.` + ); + } +} + export async function build({ ctx, buildId, @@ -40,6 +60,7 @@ export async function build({ { job: omit(ctx.job, 'secrets', 'projectArchive') }, 'Builder is ready, starting build' ); + warnOnUnknownEnvironment(ctx); }, { doNotMarkStart: true } );