Skip to content

Commit

Permalink
Expand Job definition to include Generic.Job too (#371)
Browse files Browse the repository at this point in the history
# Why

I'm thinking we should have `Job = Android.Job | Ios.Job | Generic.Job` so we can use the same `Job` concept in existing functions (some of which will work for generic jobs too) and worker code.

# How

This, however, as one can see, requires a lot of, mostly, typing changes.

# Test Plan

TSC passes. Tests should too.
  • Loading branch information
sjchmiela authored Mar 27, 2024
1 parent 5f40fea commit e15bbd6
Show file tree
Hide file tree
Showing 31 changed files with 191 additions and 112 deletions.
6 changes: 3 additions & 3 deletions packages/build-tools/src/android/expoUpdates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import assert from 'assert';

import fs from 'fs-extra';
import { AndroidConfig, XML } from '@expo/config-plugins';
import { Job } from '@expo/eas-build-job';
import { BuildJob, Job } from '@expo/eas-build-job';

import { BuildContext } from '../context';

Expand Down Expand Up @@ -35,7 +35,7 @@ export async function androidSetRuntimeVersionNativelyAsync(
await AndroidConfig.Manifest.writeAndroidManifestAsync(manifestPath, androidManifest);
}

export async function androidSetChannelNativelyAsync(ctx: BuildContext<Job>): Promise<void> {
export async function androidSetChannelNativelyAsync(ctx: BuildContext<BuildJob>): Promise<void> {
assert(ctx.job.updates?.channel, 'updates.channel must be defined');

const manifestPath = await AndroidConfig.Paths.getAndroidManifestAsync(
Expand Down Expand Up @@ -91,7 +91,7 @@ export async function androidGetNativelyDefinedChannelAsync(
}

export async function androidSetClassicReleaseChannelNativelyAsync(
ctx: BuildContext<Job>
ctx: BuildContext<BuildJob>
): Promise<void> {
const { releaseChannel } = ctx.job;
assert(releaseChannel, 'releaseChannel must be defined');
Expand Down
4 changes: 2 additions & 2 deletions packages/build-tools/src/buildErrors/detectError.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ function resolveError<TError extends Error>(
xcodeBuildLogs?: string
): TError | undefined {
const { job, phase } = errorContext;
const { platform, mode } = job;
const { platform } = job;
const logs = logLines.join('\n');
const handlers = errorHandlers
.filter((handler) => handler.platform === platform || !handler.platform)
Expand All @@ -45,7 +45,7 @@ function resolveError<TError extends Error>(
handler.phase === phase ||
!handler.phase
)
.filter((handler) => handler.mode === mode || !handler.mode);
.filter((handler) => ('mode' in job && handler.mode === job.mode) || !handler.mode);

for (const handler of handlers) {
const regexp =
Expand Down
4 changes: 2 additions & 2 deletions packages/build-tools/src/buildErrors/errors.types.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { BuildMode, BuildPhase, Env, Job, Platform } from '@expo/eas-build-job';

export interface ErrorContext {
export interface ErrorContext<TJob extends Job = Job> {
phase: BuildPhase;
job: Job;
job: TJob;
env: Env;
}

Expand Down
4 changes: 2 additions & 2 deletions packages/build-tools/src/buildErrors/userErrorHandlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ export const userErrorHandlers: ErrorHandler<UserFacingError>[] = [
'EAS_BUILD_HIGHER_MINIMUM_DEPLOYMENT_TARGET_ERROR',
`Some pods require a higher minimum deployment target.
${
job.type === Workflow.MANAGED
'type' in job && job.type === Workflow.MANAGED
? 'You can use the expo-build-properties config plugin (https://docs.expo.dev/versions/latest/sdk/build-properties/) to override the default native build properties and set a different minimum deployment target.'
: 'You need to manually update the minimum deployment target in your project to resolve this issue.'
}
Expand Down Expand Up @@ -229,7 +229,7 @@ You are seeing this error because either:
// /Users/expo/workingdir/build/managed/ios/Pods/Pods.xcodeproj: error: Signing for "EXUpdates-EXUpdates" requires a development team. Select a development team in the Signing & Capabilities editor. (in target 'EXUpdates-EXUpdates' from project 'Pods')
regexp: /error: Signing for "[a-zA-Z-0-9_]+" requires a development team/,
createError: (_, { job }) =>
job.type === Workflow.MANAGED
'type' in job && job.type === Workflow.MANAGED
? new UserFacingError(
'XCODE_RESOURCE_BUNDLE_CODE_SIGNING_ERROR',
`Starting from Xcode 14, resource bundles are signed by default, which requires setting the development team for each resource bundle target.
Expand Down
4 changes: 2 additions & 2 deletions packages/build-tools/src/builders/common.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { BuildPhase, Ios, Job, Platform } from '@expo/eas-build-job';
import { BuildJob, BuildPhase, Ios, Platform } from '@expo/eas-build-job';

import { Artifacts, BuildContext } from '../context';
import { findAndUploadXcodeBuildLogsAsync } from '../ios/xcodeBuildLogs';
import { maybeFindAndUploadBuildArtifacts } from '../utils/artifacts';
import { Hook, runHookIfPresent } from '../utils/hooks';

export async function runBuilderWithHooksAsync<T extends Job>(
export async function runBuilderWithHooksAsync<T extends BuildJob>(
ctx: BuildContext<T>,
builderAsync: (ctx: BuildContext<T>) => Promise<void>
): Promise<Artifacts> {
Expand Down
19 changes: 12 additions & 7 deletions packages/build-tools/src/builders/custom.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import path from 'path';

import { BuildPhase, BuildTrigger, Ios, Job, Platform } from '@expo/eas-build-job';
import { BuildJob, BuildPhase, BuildTrigger, Ios, Job, Platform } from '@expo/eas-build-job';
import { BuildConfigParser, BuildStepGlobalContext, errors } from '@expo/steps';
import nullthrows from 'nullthrows';

Expand All @@ -16,12 +16,17 @@ export async function runCustomBuildAsync<T extends Job>(ctx: BuildContext<T>):
const customBuildCtx = new CustomBuildContext(ctx);
await prepareProjectSourcesAsync(ctx, customBuildCtx.projectSourceDirectory);
if (ctx.job.triggeredBy === BuildTrigger.GIT_BASED_INTEGRATION) {
// We need to setup envs from eas.json
const env = await resolveEnvFromBuildProfileAsync(ctx, {
cwd: customBuildCtx.projectSourceDirectory,
});
ctx.updateEnv(env);
customBuildCtx.updateEnv(ctx.env);
// TODO: Add support for resolving env from job profile.

// If platform is present, the job must be BuildJob
if (ctx.job.platform) {
// We need to setup envs from eas.json
const env = await resolveEnvFromBuildProfileAsync(ctx as BuildContext<BuildJob>, {
cwd: customBuildCtx.projectSourceDirectory,
});
ctx.updateEnv(env);
customBuildCtx.updateEnv(ctx.env);
}
}
const relativeConfigPath = nullthrows(
ctx.job.customBuildConfig?.path,
Expand Down
10 changes: 5 additions & 5 deletions packages/build-tools/src/common/easBuildInternal.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import assert from 'assert';

import { Env, Job, Metadata, sanitizeJob, sanitizeMetadata } from '@expo/eas-build-job';
import { BuildJob, Env, Metadata, sanitizeBuildJob, sanitizeMetadata } from '@expo/eas-build-job';
import { PipeMode, bunyan } from '@expo/logger';
import spawn from '@expo/turtle-spawn';
import Joi from 'joi';
Expand All @@ -18,7 +18,7 @@ const EasBuildInternalResultSchema = Joi.object<{ job: object; metadata: object
metadata: Joi.object().unknown(),
});

export async function runEasBuildInternalAsync<TJob extends Job>({
export async function runEasBuildInternalAsync<TJob extends BuildJob>({
job,
logger,
env,
Expand Down Expand Up @@ -75,7 +75,7 @@ export async function runEasBuildInternalAsync<TJob extends Job>({
});
}

export async function resolveEnvFromBuildProfileAsync<TJob extends Job>(
export async function resolveEnvFromBuildProfileAsync<TJob extends BuildJob>(
ctx: BuildContext<TJob>,
{ cwd }: { cwd: string }
): Promise<Env> {
Expand Down Expand Up @@ -140,7 +140,7 @@ async function resolveEasCommandPrefixAndEnvAsync(): Promise<{
}
}

function validateEasBuildInternalResult<TJob extends Job>({
function validateEasBuildInternalResult<TJob extends BuildJob>({
oldJob,
result,
}: {
Expand All @@ -155,7 +155,7 @@ function validateEasBuildInternalResult<TJob extends Job>({
if (error) {
throw error;
}
const newJob = sanitizeJob(value.job) as TJob;
const newJob = sanitizeBuildJob(value.job) as TJob;
assert(newJob.platform === oldJob.platform, 'eas-cli returned a job for a wrong platform');
const newMetadata = sanitizeMetadata(value.metadata);
return { newJob, newMetadata };
Expand Down
6 changes: 3 additions & 3 deletions packages/build-tools/src/common/prebuild.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Job } from '@expo/eas-build-job';
import { BuildJob } from '@expo/eas-build-job';
import { SpawnOptions } from '@expo/turtle-spawn';
import semver from 'semver';
import { bunyan } from '@expo/logger';
Expand All @@ -13,7 +13,7 @@ export interface PrebuildOptions {
extraEnvs?: Record<string, string>;
}

export async function prebuildAsync<TJob extends Job>(
export async function prebuildAsync<TJob extends BuildJob>(
ctx: BuildContext<TJob>,
{ logger, workingDir, options }: { logger: bunyan; workingDir: string; options?: PrebuildOptions }
): Promise<void> {
Expand Down Expand Up @@ -44,7 +44,7 @@ export async function prebuildAsync<TJob extends Job>(
await installDependenciesSpawnPromise;
}

function getPrebuildCommandArgs<TJob extends Job>(ctx: BuildContext<TJob>): string[] {
function getPrebuildCommandArgs<TJob extends BuildJob>(ctx: BuildContext<TJob>): string[] {
let prebuildCommand =
ctx.job.experimental?.prebuildCommand ??
`prebuild --non-interactive --no-install --platform ${ctx.job.platform}`;
Expand Down
4 changes: 2 additions & 2 deletions packages/build-tools/src/common/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import path from 'path';

import spawn, { SpawnPromise, SpawnResult } from '@expo/turtle-spawn';
import fs from 'fs-extra';
import { BuildPhase, Ios, Job, Platform } from '@expo/eas-build-job';
import { BuildJob, BuildPhase, Ios, Job, Platform } from '@expo/eas-build-job';
import { BuildTrigger } from '@expo/eas-build-job/dist/common';
import nullthrows from 'nullthrows';
import { ExpoConfig } from '@expo/config';
Expand All @@ -27,7 +27,7 @@ const INSTALL_DEPENDENCIES_KILL_TIMEOUT_MS = 30 * 60 * 1000;
class DoctorTimeoutError extends Error {}
class InstallDependenciesTimeoutError extends Error {}

export async function setupAsync<TJob extends Job>(ctx: BuildContext<TJob>): Promise<void> {
export async function setupAsync<TJob extends BuildJob>(ctx: BuildContext<TJob>): Promise<void> {
await ctx.runBuildPhase(BuildPhase.PREPARE_PROJECT, async () => {
await prepareProjectSourcesAsync(ctx);
await setUpNpmrcAsync(ctx, ctx.logger);
Expand Down
5 changes: 5 additions & 0 deletions packages/build-tools/src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,11 @@ export class BuildContext<TJob extends Job> {
}

public getReactNativeProjectDirectory(baseDirectory = this.buildDirectory): string {
if (!this.job.platform) {
// Generic jobs start from base directory.
return baseDirectory;
}

return path.join(baseDirectory, this.job.projectRootDirectory ?? '.');
}

Expand Down
26 changes: 22 additions & 4 deletions packages/build-tools/src/customBuildContext.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import assert from 'assert';
import path from 'path';

import {
BuildJob,
BuildPhase,
BuildStaticContext,
BuildTrigger,
Expand All @@ -23,7 +25,7 @@ export interface BuilderRuntimeApi {
uploadArtifact: (spec: { artifact: ArtifactToUpload; logger: bunyan }) => Promise<void>;
}

export class CustomBuildContext implements ExternalBuildContextProvider {
export class CustomBuildContext<TJob extends Job = Job> implements ExternalBuildContextProvider {
/*
* Directory that contains project sources before eas/checkout.
*/
Expand All @@ -46,12 +48,12 @@ export class CustomBuildContext implements ExternalBuildContextProvider {

public readonly logger: bunyan;
public readonly runtimeApi: BuilderRuntimeApi;
public job: Job;
public job: TJob;
public metadata?: Metadata;

private _env: Env;

constructor(buildCtx: BuildContext<Job>) {
constructor(buildCtx: BuildContext<TJob>) {
this._env = buildCtx.env;
this.job = buildCtx.job;
this.metadata = buildCtx.metadata;
Expand All @@ -66,7 +68,23 @@ export class CustomBuildContext implements ExternalBuildContextProvider {
};
}

public hasBuildJob(): this is BuildContext<BuildJob> {
return Boolean(this.job.platform);
}

public get runtimePlatform(): BuildRuntimePlatform {
// Generic jobs are not per-platform.
if (!this.job.platform) {
assert(
process.platform === 'linux' || process.platform === 'darwin',
`Invalid platform, expected linux or darwin, got: ${process.platform}`
);
return {
linux: BuildRuntimePlatform.LINUX,
darwin: BuildRuntimePlatform.DARWIN,
}[process.platform];
}

return platformToBuildRuntimePlatform[this.job.platform];
}

Expand All @@ -86,7 +104,7 @@ export class CustomBuildContext implements ExternalBuildContextProvider {
this._env = env;
}

public updateJobInformation(job: Job, metadata: Metadata): void {
public updateJobInformation(job: TJob, metadata: Metadata): void {
if (this.job.triggeredBy !== BuildTrigger.GIT_BASED_INTEGRATION) {
throw new Error(
'Updating job information is only allowed when build was triggered by a git-based integration.'
Expand Down
6 changes: 3 additions & 3 deletions packages/build-tools/src/ios/expoUpdates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import assert from 'assert';
import { IOSConfig } from '@expo/config-plugins';
import fs from 'fs-extra';
import plist from '@expo/plist';
import { Job } from '@expo/eas-build-job';
import { BuildJob, Job } from '@expo/eas-build-job';

import { BuildContext } from '../context';

Expand Down Expand Up @@ -31,7 +31,7 @@ export async function iosSetRuntimeVersionNativelyAsync(
await fs.writeFile(expoPlistPath, updatedExpoPlistContents);
}

export async function iosSetChannelNativelyAsync(ctx: BuildContext<Job>): Promise<void> {
export async function iosSetChannelNativelyAsync(ctx: BuildContext<BuildJob>): Promise<void> {
assert(ctx.job.updates?.channel, 'updates.channel must be defined');

const expoPlistPath = IOSConfig.Paths.getExpoPlistPath(ctx.getReactNativeProjectDirectory());
Expand Down Expand Up @@ -78,7 +78,7 @@ export async function iosGetNativelyDefinedChannelAsync(
}

export async function iosSetClassicReleaseChannelNativelyAsync(
ctx: BuildContext<Job>
ctx: BuildContext<BuildJob>
): Promise<void> {
assert(ctx.job.releaseChannel, 'releaseChannel must be defined');

Expand Down
8 changes: 7 additions & 1 deletion packages/build-tools/src/steps/easFunctionGroups.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,11 @@ import { createEasBuildBuildFunctionGroup } from './functionGroups/build';
import { createEasMaestroTestFunctionGroup } from './functionGroups/maestroTest';

export function getEasFunctionGroups(ctx: CustomBuildContext): BuildFunctionGroup[] {
return [createEasBuildBuildFunctionGroup(ctx), createEasMaestroTestFunctionGroup(ctx)];
const functionGroups = [createEasMaestroTestFunctionGroup(ctx)];

if (ctx.hasBuildJob()) {
functionGroups.push(...[createEasBuildBuildFunctionGroup(ctx)]);
}

return functionGroups;
}
22 changes: 17 additions & 5 deletions packages/build-tools/src/steps/easFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ import { createResolveBuildConfigBuildFunction } from './functions/resolveBuildC
import { calculateEASUpdateRuntimeVersionFunction } from './functions/calculateEASUpdateRuntimeVersion';

export function getEasFunctions(ctx: CustomBuildContext): BuildFunction[] {
return [
const functions = [
createCheckoutBuildFunction(),
createUploadArtifactBuildFunction(ctx),
createSetUpNpmrcBuildFunction(),
createInstallNodeModulesBuildFunction(),
createPrebuildBuildFunction(),
createFindAndUploadBuildArtifactsBuildFunction(ctx),

configureEASUpdateIfInstalledFunction(),
injectAndroidCredentialsFunction(),
configureAndroidVersionFunction(),
Expand All @@ -46,10 +46,22 @@ export function getEasFunctions(ctx: CustomBuildContext): BuildFunction[] {
createStartAndroidEmulatorBuildFunction(),
createStartIosSimulatorBuildFunction(),
createInstallMaestroBuildFunction(),
createGetCredentialsForBuildTriggeredByGithubIntegration(ctx),

createInstallPodsBuildFunction(),
createSendSlackMessageFunction(),
createResolveBuildConfigBuildFunction(ctx),
calculateEASUpdateRuntimeVersionFunction(),

calculateEASUpdateRuntimeVersionFunction(ctx),
];

if (ctx.hasBuildJob()) {
functions.push(
...[
createFindAndUploadBuildArtifactsBuildFunction(ctx),
createResolveBuildConfigBuildFunction(ctx),
createGetCredentialsForBuildTriggeredByGithubIntegration(ctx),
]
);
}

return functions;
}
Loading

0 comments on commit e15bbd6

Please sign in to comment.