From fddb3d0946cd29273daafcdf0e85909c9013bf02 Mon Sep 17 00:00:00 2001 From: Kadi Kraman Date: Tue, 25 Jun 2024 11:11:21 +0100 Subject: [PATCH 1/5] Add fingerprint sources to metadata --- packages/eas-build-job/src/metadata.ts | 41 ++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/packages/eas-build-job/src/metadata.ts b/packages/eas-build-job/src/metadata.ts index 32fe6c58..0c99363f 100644 --- a/packages/eas-build-job/src/metadata.ts +++ b/packages/eas-build-job/src/metadata.ts @@ -2,6 +2,17 @@ import Joi from 'joi'; import { Workflow } from './common'; +enum FingerprintSourceType { + 'GCS' = 'GCS', + 'PATH' = 'PATH', + 'URL' = 'URL', +} + +type FingerprintSource = + | { type: FingerprintSourceType.GCS; bucketKey: string } + | { type: FingerprintSourceType.PATH; path: string } + | { type: FingerprintSourceType.URL; url: string }; + export type Metadata = { /** * Tracking context @@ -54,6 +65,11 @@ export type Metadata = { */ runtimeVersion?: string; + /** + * The location of the fingerprint file if one exists + */ + fingerprintSource?: FingerprintSource; + /** * Version of the react-native package used in the project. */ @@ -161,6 +177,30 @@ export type Metadata = { customNodeVersion?: string; }; +export const FingerprintSourceSchema = Joi.object({ + type: Joi.string() + .valid(...Object.values(FingerprintSourceType)) + .required(), +}) + .when(Joi.object({ type: FingerprintSourceType.GCS }).unknown(), { + then: Joi.object({ + type: Joi.string().valid(FingerprintSourceType.GCS).required(), + bucketKey: Joi.string().required(), + }), + }) + .when(Joi.object({ type: FingerprintSourceType.PATH }).unknown(), { + then: Joi.object({ + type: Joi.string().valid(FingerprintSourceType.PATH).required(), + path: Joi.string().required(), + }), + }) + .when(Joi.object({ type: FingerprintSourceType.URL }).unknown(), { + then: Joi.object({ + type: Joi.string().valid(FingerprintSourceType.URL).required(), + url: Joi.string().required(), + }), + }); + export const MetadataSchema = Joi.object({ trackingContext: Joi.object() .pattern(Joi.string(), [Joi.string(), Joi.number(), Joi.boolean()]) @@ -173,6 +213,7 @@ export const MetadataSchema = Joi.object({ credentialsSource: Joi.string().valid('local', 'remote'), sdkVersion: Joi.string(), runtimeVersion: Joi.string(), + fingerprintSource: FingerprintSourceSchema, reactNativeVersion: Joi.string(), channel: Joi.string(), appName: Joi.string(), From 5837b114c081dfd665d1f6de0ec926f5e704339b Mon Sep 17 00:00:00 2001 From: Kadi Kraman Date: Tue, 25 Jun 2024 11:23:29 +0100 Subject: [PATCH 2/5] Add tests for fingerprint sources --- .../src/__tests__/metadata.test.ts | 108 +++++++++++++----- packages/eas-build-job/src/metadata.ts | 2 +- 2 files changed, 81 insertions(+), 29 deletions(-) diff --git a/packages/eas-build-job/src/__tests__/metadata.test.ts b/packages/eas-build-job/src/__tests__/metadata.test.ts index d88968ae..6cf64c5a 100644 --- a/packages/eas-build-job/src/__tests__/metadata.test.ts +++ b/packages/eas-build-job/src/__tests__/metadata.test.ts @@ -1,39 +1,40 @@ -import { MetadataSchema } from '../metadata'; +import { Metadata, MetadataSchema } from '../metadata'; + +const validMetadata: Metadata = { + appName: 'testapp', + appVersion: '1.0.0', + appBuildVersion: '123', + runtimeVersion: '3.2.1', + cliVersion: '1.2.3', + buildProfile: 'release', + credentialsSource: 'remote', + distribution: 'store', + gitCommitHash: '752e99d2b8fde1bf07ebb8af1b4a3c26a6703943', + gitCommitMessage: 'Lorem ipsum', + trackingContext: {}, + workflow: 'generic' as any, + username: 'notdominik', + iosEnterpriseProvisioning: 'adhoc', + message: 'fix foo, bar, and baz', + runFromCI: true, + runWithNoWaitFlag: true, + customWorkflowName: 'blah blah', + developmentClient: true, + requiredPackageManager: 'yarn', + simulator: true, + selectedImage: 'default', + customNodeVersion: '12.0.0', +}; describe('MetadataSchema', () => { test('valid metadata', () => { - const metadata = { - appName: 'testapp', - appVersion: '1.0.0', - appBuildVersion: '123', - runtimeVersion: '3.2.1', - cliVersion: '1.2.3', - buildProfile: 'release', - credentialsSource: 'remote', - distribution: 'store', - gitCommitHash: '752e99d2b8fde1bf07ebb8af1b4a3c26a6703943', - gitCommitMessage: 'Lorem ipsum', - trackingContext: {}, - workflow: 'generic', - username: 'notdominik', - iosEnterpriseProvisioning: 'adhoc', - message: 'fix foo, bar, and baz', - runFromCI: true, - runWithNoWaitFlag: true, - customWorkflowName: 'blah blah', - developmentClient: true, - requiredPackageManager: 'yarn', - simulator: true, - selectedImage: 'default', - customNodeVersion: '12.0.0', - }; - const { value, error } = MetadataSchema.validate(metadata, { + const { value, error } = MetadataSchema.validate(validMetadata, { stripUnknown: true, convert: true, abortEarly: false, }); expect(error).toBeFalsy(); - expect(value).toEqual(metadata); + expect(value).toEqual(validMetadata); }); test('invalid metadata', () => { const metadata = { @@ -69,4 +70,55 @@ describe('MetadataSchema', () => { '"credentialsSource" must be one of [local, remote]. "gitCommitHash" length must be 40 characters long. "gitCommitHash" must only contain hexadecimal characters. "gitCommitMessage" length must be less than or equal to 4096 characters long. "message" length must be less than or equal to 1024 characters long' ); }); + + test('Allows correct fingerprint', () => { + const metadata: Metadata = { + ...validMetadata, + fingerprintSource: { + type: 'GCS' as any, + bucketKey: + 'development/8a9c5554-cfbe-4b4c-814c-c476a1047db9/fd6f8af4-7293-46bd-bec7-3fe639f4fd3e', + }, + }; + const { value, error } = MetadataSchema.validate(metadata, { + stripUnknown: true, + convert: true, + abortEarly: false, + }); + expect(error).toBeFalsy(); + expect(value).toEqual(metadata); + }); + + test('Validates incorrect fingerprint type', () => { + const metadata: Metadata = { + ...validMetadata, + fingerprintSource: { + type: 'BOO' as any, + bucketKey: + 'development/8a9c5554-cfbe-4b4c-814c-c476a1047db9/fd6f8af4-7293-46bd-bec7-3fe639f4fd3e', + }, + }; + const { error } = MetadataSchema.validate(metadata, { + stripUnknown: true, + convert: true, + abortEarly: false, + }); + expect(error?.message).toEqual('"fingerprintSource.type" must be one of [GCS, PATH, URL]'); + }); + + test('Validates incorrect fingerprint key', () => { + const metadata: Metadata = { + ...validMetadata, + fingerprintSource: { + type: 'GCS' as any, + url: 'development/8a9c5554-cfbe-4b4c-814c-c476a1047db9/fd6f8af4-7293-46bd-bec7-3fe639f4fd3e', + }, + }; + const { error } = MetadataSchema.validate(metadata, { + stripUnknown: true, + convert: true, + abortEarly: false, + }); + expect(error?.message).toEqual('"fingerprintSource.bucketKey" is required'); + }); }); diff --git a/packages/eas-build-job/src/metadata.ts b/packages/eas-build-job/src/metadata.ts index 0c99363f..ee4308f1 100644 --- a/packages/eas-build-job/src/metadata.ts +++ b/packages/eas-build-job/src/metadata.ts @@ -8,7 +8,7 @@ enum FingerprintSourceType { 'URL' = 'URL', } -type FingerprintSource = +export type FingerprintSource = | { type: FingerprintSourceType.GCS; bucketKey: string } | { type: FingerprintSourceType.PATH; path: string } | { type: FingerprintSourceType.URL; url: string }; From deefa0a1f161285951dbea9c96fd790c30ce8d1e Mon Sep 17 00:00:00 2001 From: Kadi Kraman Date: Tue, 25 Jun 2024 11:36:28 +0100 Subject: [PATCH 3/5] Export enum --- packages/eas-build-job/src/__tests__/metadata.test.ts | 5 +++-- packages/eas-build-job/src/metadata.ts | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/eas-build-job/src/__tests__/metadata.test.ts b/packages/eas-build-job/src/__tests__/metadata.test.ts index 6cf64c5a..c8ab89c9 100644 --- a/packages/eas-build-job/src/__tests__/metadata.test.ts +++ b/packages/eas-build-job/src/__tests__/metadata.test.ts @@ -1,4 +1,4 @@ -import { Metadata, MetadataSchema } from '../metadata'; +import { FingerprintSourceType, Metadata, MetadataSchema } from '../metadata'; const validMetadata: Metadata = { appName: 'testapp', @@ -110,7 +110,8 @@ describe('MetadataSchema', () => { const metadata: Metadata = { ...validMetadata, fingerprintSource: { - type: 'GCS' as any, + type: FingerprintSourceType.GCS, + // @ts-expect-error TypeScript is too smart. Need to ignore this for the failing test url: 'development/8a9c5554-cfbe-4b4c-814c-c476a1047db9/fd6f8af4-7293-46bd-bec7-3fe639f4fd3e', }, }; diff --git a/packages/eas-build-job/src/metadata.ts b/packages/eas-build-job/src/metadata.ts index ee4308f1..7d89c57d 100644 --- a/packages/eas-build-job/src/metadata.ts +++ b/packages/eas-build-job/src/metadata.ts @@ -2,7 +2,7 @@ import Joi from 'joi'; import { Workflow } from './common'; -enum FingerprintSourceType { +export enum FingerprintSourceType { 'GCS' = 'GCS', 'PATH' = 'PATH', 'URL' = 'URL', From 598b5ab6deb5d4562a10e13dc1e5927a4bbb3165 Mon Sep 17 00:00:00 2001 From: Kadi Kraman Date: Tue, 25 Jun 2024 11:36:53 +0100 Subject: [PATCH 4/5] Imprive url validation --- packages/eas-build-job/src/metadata.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/eas-build-job/src/metadata.ts b/packages/eas-build-job/src/metadata.ts index 7d89c57d..de7cb79e 100644 --- a/packages/eas-build-job/src/metadata.ts +++ b/packages/eas-build-job/src/metadata.ts @@ -197,7 +197,7 @@ export const FingerprintSourceSchema = Joi.object({ .when(Joi.object({ type: FingerprintSourceType.URL }).unknown(), { then: Joi.object({ type: Joi.string().valid(FingerprintSourceType.URL).required(), - url: Joi.string().required(), + url: Joi.string().uri().required(), }), }); From f460743e41e2ae144e8173621aa6bd6931f08575 Mon Sep 17 00:00:00 2001 From: Kadi Kraman Date: Tue, 25 Jun 2024 11:46:38 +0100 Subject: [PATCH 5/5] Export new fingerprint metadata --- packages/eas-build-job/src/index.ts | 2 +- packages/eas-build-job/src/metadata.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/eas-build-job/src/index.ts b/packages/eas-build-job/src/index.ts index edd01fb6..ddbf325a 100644 --- a/packages/eas-build-job/src/index.ts +++ b/packages/eas-build-job/src/index.ts @@ -13,7 +13,7 @@ export { Platform, Cache, } from './common'; -export { Metadata, sanitizeMetadata } from './metadata'; +export { Metadata, sanitizeMetadata, FingerprintSource, FingerprintSourceType } from './metadata'; export * from './job'; export * from './logs'; export * as errors from './errors'; diff --git a/packages/eas-build-job/src/metadata.ts b/packages/eas-build-job/src/metadata.ts index de7cb79e..087bfa09 100644 --- a/packages/eas-build-job/src/metadata.ts +++ b/packages/eas-build-job/src/metadata.ts @@ -177,7 +177,7 @@ export type Metadata = { customNodeVersion?: string; }; -export const FingerprintSourceSchema = Joi.object({ +const FingerprintSourceSchema = Joi.object({ type: Joi.string() .valid(...Object.values(FingerprintSourceType)) .required(),