Skip to content

Commit

Permalink
[eas-cli] compute fingerprint on each build
Browse files Browse the repository at this point in the history
  • Loading branch information
quinlanj committed Oct 30, 2024
1 parent 3e6cf78 commit 4d838b9
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 16 deletions.
55 changes: 50 additions & 5 deletions packages/eas-cli/src/build/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ import { maybeUploadFingerprintAsync } from '../project/maybeUploadFingerprintAs
import { resolveRuntimeVersionAsync } from '../project/resolveRuntimeVersionAsync';
import { uploadFileAtPathToGCSAsync } from '../uploads';
import { formatBytes } from '../utils/files';
import { fingerprintCommandAsync } from '../utils/fingerprintCli';
import { printJsonOnlyOutput } from '../utils/json';
import { createProgressTracker } from '../utils/progress';
import { sleepAsync } from '../utils/promise';
Expand Down Expand Up @@ -174,8 +175,16 @@ export async function prepareBuildRequestForPlatformAsync<
}
assert(projectArchive);

const runtimeMetadata = await createAndMaybeUploadFingerprintAsync(ctx);
const metadata = await collectMetadataAsync(ctx, runtimeMetadata);
let runtimeAndFingerprintMetadata =
await computeAndMaybeUploadFingerprintFromExpoUpdatesAsync(ctx);
if (!runtimeAndFingerprintMetadata?.fingerprint) {
const fingerprint = await computeAndMaybeUploadFingerprintWithoutExpoUpdatesAsync(ctx);
runtimeAndFingerprintMetadata = {
...runtimeAndFingerprintMetadata,
// TODO: generate fingerprint data here
};
}
const metadata = await collectMetadataAsync(ctx, runtimeAndFingerprintMetadata);
const buildParams = resolveBuildParamsInput(ctx, metadata);
const job = await builder.prepareJobAsync(ctx, {
projectArchive,
Expand Down Expand Up @@ -660,11 +669,15 @@ function formatAccountBillingUrl(accountName: string): string {
return new URL(`/accounts/${accountName}/settings/billing`, getExpoWebsiteBaseUrl()).toString();
}

async function createAndMaybeUploadFingerprintAsync<T extends Platform>(
async function computeAndMaybeUploadFingerprintFromExpoUpdatesAsync<T extends Platform>(
ctx: BuildContext<T>
): Promise<{
runtimeVersion?: string;
fingerprintSource?: FingerprintSource;
fingerprint?: {
fingerprintSources: object[];
isDebugFingerprintSource: boolean;
};
}> {
const resolvedRuntimeVersion = await resolveRuntimeVersionAsync({
exp: ctx.exp,
Expand All @@ -689,10 +702,42 @@ async function createAndMaybeUploadFingerprintAsync<T extends Platform>(
};
}

return await maybeUploadFingerprintAsync({
runtimeVersion: resolvedRuntimeVersion.runtimeVersion,
const uploadedFingerprint = await maybeUploadFingerprintAsync({
hash: resolvedRuntimeVersion.runtimeVersion,
fingerprint: resolvedRuntimeVersion.fingerprint,
graphqlClient: ctx.graphqlClient,
localBuildMode: ctx.localBuildOptions.localBuildMode,
});
return {
runtimeVersion: uploadedFingerprint.hash,
fingerprintSource: uploadedFingerprint.fingerprintSource,
fingerprint: resolvedRuntimeVersion.fingerprint,
};
}

async function computeAndMaybeUploadFingerprintWithoutExpoUpdatesAsync<T extends Platform>(
ctx: BuildContext<T>,
{ debug }: { debug?: boolean } = {}
): Promise<{
fingerprintHash?: string;
fingerprintSource?: FingerprintSource;
}> {
const fingerprint = await fingerprintCommandAsync(ctx.projectDir, {
workflow: ctx.workflow,
platform: ctx.platform,
env: ctx.env,
});
const uploadedFingerprint = await maybeUploadFingerprintAsync({
hash: fingerprint.hash,
fingerprint: {
fingerprintSources: fingerprint.sources,
isDebugFingerprintSource: debug ?? false,
},
graphqlClient: ctx.graphqlClient,
localBuildMode: ctx.localBuildOptions.localBuildMode,
});
return {
fingerprintHash: uploadedFingerprint.hash,
fingerprintSource: uploadedFingerprint.fingerprintSource,
};
}
8 changes: 5 additions & 3 deletions packages/eas-cli/src/build/metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ import { easCliVersion } from '../utils/easCli';

export async function collectMetadataAsync<T extends Platform>(
ctx: BuildContext<T>,
runtimeMetadata: {
runtimeAndFingerprintMetadata: {
runtimeVersion?: string | undefined;
fingerprintHash?: string | undefined;
fingerprintSource?: FingerprintSource | undefined;
}
): Promise<Metadata> {
Expand All @@ -30,8 +31,9 @@ export async function collectMetadataAsync<T extends Platform>(
workflow: ctx.workflow,
credentialsSource: ctx.buildProfile.credentialsSource,
sdkVersion: ctx.exp.sdkVersion,
runtimeVersion: runtimeMetadata?.runtimeVersion,
fingerprintSource: runtimeMetadata?.fingerprintSource,
runtimeVersion: runtimeAndFingerprintMetadata?.runtimeVersion,
fingerprintHash: runtimeAndFingerprintMetadata?.fingerprintHash,
fingerprintSource: runtimeAndFingerprintMetadata?.fingerprintSource,
reactNativeVersion: await getReactNativeVersionAsync(ctx.projectDir),
...channelObject,
distribution,
Expand Down
2 changes: 1 addition & 1 deletion packages/eas-cli/src/commands/update/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,7 @@ export default class UpdatePublish extends EasCommand {
fingerprintSource: info.fingerprint
? (
await maybeUploadFingerprintAsync({
runtimeVersion: info.runtimeVersion,
hash: info.runtimeVersion,
fingerprint: info.fingerprint,
graphqlClient,
})
Expand Down
14 changes: 7 additions & 7 deletions packages/eas-cli/src/project/maybeUploadFingerprintAsync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,33 +11,33 @@ import { uploadFileAtPathToGCSAsync } from '../uploads';
import { getTmpDirectory } from '../utils/paths';

export async function maybeUploadFingerprintAsync({
runtimeVersion,
hash,
fingerprint,
graphqlClient,
localBuildMode,
}: {
runtimeVersion: string;
hash: string;
fingerprint: {
fingerprintSources: object[];
isDebugFingerprintSource: boolean;
};
graphqlClient: ExpoGraphqlClient;
localBuildMode?: LocalBuildMode;
}): Promise<{
runtimeVersion: string;
hash: string;
fingerprintSource?: FingerprintSource;
}> {
await fs.mkdirp(getTmpDirectory());
const fingerprintLocation = path.join(getTmpDirectory(), `${uuidv4()}-runtime-fingerprint.json`);

await fs.writeJSON(fingerprintLocation, {
hash: runtimeVersion,
hash,
sources: fingerprint.fingerprintSources,
});

if (localBuildMode === LocalBuildMode.LOCAL_BUILD_PLUGIN) {
return {
runtimeVersion,
hash,
fingerprintSource: {
type: FingerprintSourceType.PATH,
path: fingerprintLocation,
Expand All @@ -62,14 +62,14 @@ export async function maybeUploadFingerprintAsync({

Log.warn(errMessage);
return {
runtimeVersion,
hash,
};
} finally {
await fs.remove(fingerprintLocation);
}

return {
runtimeVersion,
hash,
fingerprintSource: {
type: FingerprintSourceType.GCS,
bucketKey: fingerprintGCSBucketKey,
Expand Down
42 changes: 42 additions & 0 deletions packages/eas-cli/src/utils/fingerprintCli.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { Env, Workflow } from '@expo/eas-build-job';
import spawnAsync from '@expo/spawn-async';

export async function fingerprintCommandAsync(
projectDir: string,
options: {
workflow: Workflow;
platform: string;
debug?: boolean;
env: Env | undefined;
cwd?: string;
}
): Promise<{
hash: string;
sources: object[];
isDebugSource: boolean;
}> {
const args = ['@expo/fingerprint'];
if (options.platform) {
args.push('--platform', options.platform);
}
if (options.workflow === 'managed') {
args.push('--ignorePath', 'android/**/*');
args.push('--ignorePath', 'ios/**/*');
}
if (options.debug) {
args.push('--debug');
}
const fingerprintJsonResult = (
await spawnAsync('npx', [...args, projectDir], {
stdio: 'pipe',
env: { ...process.env, ...options.env },
cwd: options.cwd,
})
).stdout;
const fingerprintResult = JSON.parse(fingerprintJsonResult);
return {
hash: fingerprintResult.hash,
sources: fingerprintResult.fingerprintSources,
isDebugSource: options.debug ?? false,
};
}

0 comments on commit 4d838b9

Please sign in to comment.