eas-cli 16.1.0 → 16.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +117 -81
- package/build/build/utils/url.d.ts +1 -0
- package/build/build/utils/url.js +5 -1
- package/build/commandUtils/EasCommand.js +6 -1
- package/build/commandUtils/builds.d.ts +1 -0
- package/build/commandUtils/builds.js +3 -0
- package/build/commandUtils/context/ServerSideEnvironmentVariablesContextField.d.ts +1 -2
- package/build/commands/deploy/index.js +20 -2
- package/build/commands/fingerprint/compare.d.ts +3 -0
- package/build/commands/fingerprint/compare.js +50 -13
- package/build/commands/fingerprint/generate.d.ts +5 -2
- package/build/commands/fingerprint/generate.js +44 -7
- package/build/commands/update/delete.js +13 -6
- package/build/commands/update/index.d.ts +1 -0
- package/build/commands/update/index.js +90 -59
- package/build/graphql/generated.d.ts +60 -5
- package/build/graphql/queries/BackgroundJobReceiptQuery.d.ts +5 -0
- package/build/graphql/queries/BackgroundJobReceiptQuery.js +27 -0
- package/build/graphql/types/BackgroundJobReceipt.d.ts +1 -0
- package/build/graphql/types/BackgroundJobReceipt.js +20 -0
- package/build/project/publish.d.ts +17 -1
- package/build/project/publish.js +22 -1
- package/build/utils/pollForBackgroundJobReceiptAsync.d.ts +29 -0
- package/build/utils/pollForBackgroundJobReceiptAsync.js +92 -0
- package/oclif.manifest.json +34 -5
- package/package.json +3 -2
|
@@ -5,6 +5,7 @@ const eas_build_job_1 = require("@expo/eas-build-job");
|
|
|
5
5
|
const core_1 = require("@oclif/core");
|
|
6
6
|
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
7
7
|
const nullthrows_1 = tslib_1.__importDefault(require("nullthrows"));
|
|
8
|
+
const api_1 = require("../../api");
|
|
8
9
|
const queries_1 = require("../../branch/queries");
|
|
9
10
|
const graphql_1 = require("../../build/graphql");
|
|
10
11
|
const repository_1 = require("../../build/utils/repository");
|
|
@@ -15,6 +16,7 @@ const pagination_1 = require("../../commandUtils/pagination");
|
|
|
15
16
|
const fetch_1 = tslib_1.__importDefault(require("../../fetch"));
|
|
16
17
|
const generated_1 = require("../../graphql/generated");
|
|
17
18
|
const PublishMutation_1 = require("../../graphql/mutations/PublishMutation");
|
|
19
|
+
const AppQuery_1 = require("../../graphql/queries/AppQuery");
|
|
18
20
|
const log_1 = tslib_1.__importStar(require("../../log"));
|
|
19
21
|
const ora_1 = require("../../ora");
|
|
20
22
|
const platform_1 = require("../../platform");
|
|
@@ -374,74 +376,103 @@ class UpdatePublish extends EasCommand_1.default {
|
|
|
374
376
|
}
|
|
375
377
|
if (jsonFlag) {
|
|
376
378
|
(0, json_1.printJsonOnlyOutput)((0, utils_1.getUpdateJsonInfosForUpdates)(newUpdates));
|
|
379
|
+
return;
|
|
377
380
|
}
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
381
|
+
if (new Set(newUpdates.map(update => update.group)).size > 1) {
|
|
382
|
+
log_1.default.addNewLineIfNone();
|
|
383
|
+
log_1.default.log('👉 Since multiple runtime versions are defined, multiple update groups have been published.');
|
|
384
|
+
}
|
|
385
|
+
log_1.default.addNewLineIfNone();
|
|
386
|
+
const runtimeToCompatibleBuilds = await Promise.all(runtimeToPlatformsAndFingerprintInfoAndFingerprintSourceMapping.map(obj => (0, publish_1.findCompatibleBuildsAsync)(graphqlClient, projectId, obj)));
|
|
387
|
+
for (const runtime of (0, uniqBy_1.default)(runtimeToPlatformsAndFingerprintInfoMapping, version => version.runtimeVersion)) {
|
|
388
|
+
const newUpdatesForRuntimeVersion = newUpdates.filter(update => update.runtimeVersion === runtime.runtimeVersion);
|
|
389
|
+
if (newUpdatesForRuntimeVersion.length === 0) {
|
|
390
|
+
throw new Error(`Publish response is missing updates with runtime ${runtime.runtimeVersion}.`);
|
|
382
391
|
}
|
|
392
|
+
const platforms = newUpdatesForRuntimeVersion.map(update => update.platform);
|
|
393
|
+
const newAndroidUpdate = newUpdatesForRuntimeVersion.find(update => update.platform === 'android');
|
|
394
|
+
const newIosUpdate = newUpdatesForRuntimeVersion.find(update => update.platform === 'ios');
|
|
395
|
+
const updateGroupId = newUpdatesForRuntimeVersion[0].group;
|
|
396
|
+
const projectName = exp.slug;
|
|
397
|
+
const accountName = (await (0, projectUtils_1.getOwnerAccountForProjectIdAsync)(graphqlClient, projectId)).name;
|
|
398
|
+
const updateGroupUrl = (0, url_1.getUpdateGroupUrl)(accountName, projectName, updateGroupId);
|
|
399
|
+
const updateGroupLink = (0, log_1.link)(updateGroupUrl, { dim: false });
|
|
400
|
+
log_1.default.log((0, formatFields_1.default)([
|
|
401
|
+
{ label: 'Branch', value: branchName },
|
|
402
|
+
{ label: 'Runtime version', value: runtime.runtimeVersion },
|
|
403
|
+
{ label: 'Platform', value: platforms.join(', ') },
|
|
404
|
+
{ label: 'Update group ID', value: updateGroupId },
|
|
405
|
+
...(newAndroidUpdate ? [{ label: 'Android update ID', value: newAndroidUpdate.id }] : []),
|
|
406
|
+
...(newIosUpdate ? [{ label: 'iOS update ID', value: newIosUpdate.id }] : []),
|
|
407
|
+
...(newAndroidUpdate?.rolloutControlUpdate
|
|
408
|
+
? [
|
|
409
|
+
{
|
|
410
|
+
label: 'Android Rollout',
|
|
411
|
+
value: `${newAndroidUpdate.rolloutPercentage}% (Base update ID: ${newAndroidUpdate.rolloutControlUpdate.id})`,
|
|
412
|
+
},
|
|
413
|
+
]
|
|
414
|
+
: []),
|
|
415
|
+
...(newIosUpdate?.rolloutControlUpdate
|
|
416
|
+
? [
|
|
417
|
+
{
|
|
418
|
+
label: 'iOS Rollout',
|
|
419
|
+
value: `${newIosUpdate.rolloutPercentage}% (Base update ID: ${newIosUpdate.rolloutControlUpdate.id})`,
|
|
420
|
+
},
|
|
421
|
+
]
|
|
422
|
+
: []),
|
|
423
|
+
{ label: 'Message', value: updateMessage ?? '' },
|
|
424
|
+
...(gitCommitHash
|
|
425
|
+
? [
|
|
426
|
+
{
|
|
427
|
+
label: 'Commit',
|
|
428
|
+
value: `${gitCommitHash}${isGitWorkingTreeDirty ? '*' : ''}`,
|
|
429
|
+
},
|
|
430
|
+
]
|
|
431
|
+
: []),
|
|
432
|
+
{ label: 'EAS Dashboard', value: updateGroupLink },
|
|
433
|
+
]));
|
|
383
434
|
log_1.default.addNewLineIfNone();
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
const
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
{ label: 'Update group ID', value: updateGroupId },
|
|
402
|
-
...(newAndroidUpdate
|
|
403
|
-
? [{ label: 'Android update ID', value: newAndroidUpdate.id }]
|
|
404
|
-
: []),
|
|
405
|
-
...(newIosUpdate ? [{ label: 'iOS update ID', value: newIosUpdate.id }] : []),
|
|
406
|
-
...(newAndroidUpdate?.rolloutControlUpdate
|
|
407
|
-
? [
|
|
408
|
-
{
|
|
409
|
-
label: 'Android Rollout',
|
|
410
|
-
value: `${newAndroidUpdate.rolloutPercentage}% (Base update ID: ${newAndroidUpdate.rolloutControlUpdate.id})`,
|
|
411
|
-
},
|
|
412
|
-
]
|
|
413
|
-
: []),
|
|
414
|
-
...(newIosUpdate?.rolloutControlUpdate
|
|
415
|
-
? [
|
|
416
|
-
{
|
|
417
|
-
label: 'iOS Rollout',
|
|
418
|
-
value: `${newIosUpdate.rolloutPercentage}% (Base update ID: ${newIosUpdate.rolloutControlUpdate.id})`,
|
|
419
|
-
},
|
|
420
|
-
]
|
|
421
|
-
: []),
|
|
422
|
-
{ label: 'Message', value: updateMessage ?? '' },
|
|
423
|
-
...(gitCommitHash
|
|
424
|
-
? [
|
|
435
|
+
if ((0, publish_1.isUploadedAssetCountAboveWarningThreshold)(uploadedAssetCount, assetLimitPerUpdateGroup)) {
|
|
436
|
+
log_1.default.warn(`This update group contains ${uploadedAssetCount} assets and is nearing the server cap of ${assetLimitPerUpdateGroup}.\n` +
|
|
437
|
+
`${(0, log_1.learnMore)('https://docs.expo.dev/eas-update/optimize-assets/', {
|
|
438
|
+
learnMoreMessage: 'Consider optimizing your usage of assets',
|
|
439
|
+
dim: false,
|
|
440
|
+
})}.`);
|
|
441
|
+
log_1.default.addNewLineIfNone();
|
|
442
|
+
}
|
|
443
|
+
const fingerprintsWithoutCompatibleBuilds = runtimeToCompatibleBuilds.find(({ runtimeVersion }) => runtimeVersion === runtime.runtimeVersion)?.fingerprintInfoGroupWithCompatibleBuilds;
|
|
444
|
+
if (fingerprintsWithoutCompatibleBuilds) {
|
|
445
|
+
const missingBuilds = Object.entries(fingerprintsWithoutCompatibleBuilds).filter(([_platform, fingerprintInfo]) => !fingerprintInfo.build);
|
|
446
|
+
if (missingBuilds.length > 0) {
|
|
447
|
+
const project = await AppQuery_1.AppQuery.byIdAsync(graphqlClient, projectId);
|
|
448
|
+
log_1.default.warn('No compatible builds found for the following fingerprints:');
|
|
449
|
+
for (const [platform, fingerprintInfo] of missingBuilds) {
|
|
450
|
+
const fingerprintUrl = new URL(`/accounts/${project.ownerAccount.name}/projects/${project.slug}/fingerprints/${fingerprintInfo.fingerprintHash}`, (0, api_1.getExpoWebsiteBaseUrl)());
|
|
451
|
+
log_1.default.warn((0, formatFields_1.default)([
|
|
425
452
|
{
|
|
426
|
-
label:
|
|
427
|
-
value:
|
|
453
|
+
label: `${this.prettyPlatform(platform)} fingerprint`,
|
|
454
|
+
value: fingerprintInfo.fingerprintHash,
|
|
428
455
|
},
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
log_1.default.warn(`This update group contains ${uploadedAssetCount} assets and is nearing the server cap of ${assetLimitPerUpdateGroup}.\n` +
|
|
436
|
-
`${(0, log_1.learnMore)('https://docs.expo.dev/eas-update/optimize-assets/', {
|
|
437
|
-
learnMoreMessage: 'Consider optimizing your usage of assets',
|
|
438
|
-
dim: false,
|
|
439
|
-
})}.`);
|
|
440
|
-
log_1.default.addNewLineIfNone();
|
|
456
|
+
{ label: 'URL', value: fingerprintUrl.toString() },
|
|
457
|
+
], {
|
|
458
|
+
labelFormat: label => ` ${chalk_1.default.dim(label)}:`,
|
|
459
|
+
}));
|
|
460
|
+
log_1.default.addNewLineIfNone();
|
|
461
|
+
}
|
|
441
462
|
}
|
|
442
463
|
}
|
|
443
464
|
}
|
|
444
465
|
}
|
|
466
|
+
prettyPlatform(updatePlatform) {
|
|
467
|
+
switch (updatePlatform) {
|
|
468
|
+
case 'android':
|
|
469
|
+
return 'Android';
|
|
470
|
+
case 'ios':
|
|
471
|
+
return 'iOS';
|
|
472
|
+
default:
|
|
473
|
+
return updatePlatform;
|
|
474
|
+
}
|
|
475
|
+
}
|
|
445
476
|
sanitizeFlags(flags) {
|
|
446
477
|
const nonInteractive = flags['non-interactive'] ?? false;
|
|
447
478
|
const { auto, branch: branchName, channel: channelName, message: updateMessage } = flags;
|
|
@@ -167,6 +167,7 @@ export type Account = {
|
|
|
167
167
|
googleServiceAccountKeys: Array<GoogleServiceAccountKey>;
|
|
168
168
|
/** Android credentials for account */
|
|
169
169
|
googleServiceAccountKeysPaginated: AccountGoogleServiceAccountKeysConnection;
|
|
170
|
+
hasBuilds: Scalars['Boolean']['output'];
|
|
170
171
|
id: Scalars['ID']['output'];
|
|
171
172
|
isCurrent: Scalars['Boolean']['output'];
|
|
172
173
|
isDisabled: Scalars['Boolean']['output'];
|
|
@@ -2709,6 +2710,7 @@ export declare enum BuildPriority {
|
|
|
2709
2710
|
export type BuildPublicData = {
|
|
2710
2711
|
__typename?: 'BuildPublicData';
|
|
2711
2712
|
artifacts: PublicArtifacts;
|
|
2713
|
+
buildMode?: Maybe<BuildMode>;
|
|
2712
2714
|
distribution?: Maybe<DistributionType>;
|
|
2713
2715
|
id: Scalars['ID']['output'];
|
|
2714
2716
|
isForIosSimulator: Scalars['Boolean']['output'];
|
|
@@ -4373,6 +4375,7 @@ export type IosSubmissionConfigInput = {
|
|
|
4373
4375
|
ascApiKey?: InputMaybe<AscApiKeyInput>;
|
|
4374
4376
|
ascApiKeyId?: InputMaybe<Scalars['String']['input']>;
|
|
4375
4377
|
ascAppIdentifier: Scalars['String']['input'];
|
|
4378
|
+
groups?: InputMaybe<Array<Scalars['String']['input']>>;
|
|
4376
4379
|
isVerboseFastlaneEnabled?: InputMaybe<Scalars['Boolean']['input']>;
|
|
4377
4380
|
};
|
|
4378
4381
|
/** Represents a Turtle Job Run */
|
|
@@ -6061,6 +6064,8 @@ export type UpdateMutation = {
|
|
|
6061
6064
|
__typename?: 'UpdateMutation';
|
|
6062
6065
|
/** Delete an EAS update group */
|
|
6063
6066
|
deleteUpdateGroup: DeleteUpdateGroupResult;
|
|
6067
|
+
/** Delete an EAS update group in the background */
|
|
6068
|
+
scheduleUpdateGroupDeletion: BackgroundJobReceipt;
|
|
6064
6069
|
/** Set code signing info for an update */
|
|
6065
6070
|
setCodeSigningInfo: Update;
|
|
6066
6071
|
/** Set rollout percentage for an update */
|
|
@@ -6069,6 +6074,9 @@ export type UpdateMutation = {
|
|
|
6069
6074
|
export type UpdateMutationDeleteUpdateGroupArgs = {
|
|
6070
6075
|
group: Scalars['ID']['input'];
|
|
6071
6076
|
};
|
|
6077
|
+
export type UpdateMutationScheduleUpdateGroupDeletionArgs = {
|
|
6078
|
+
group: Scalars['ID']['input'];
|
|
6079
|
+
};
|
|
6072
6080
|
export type UpdateMutationSetCodeSigningInfoArgs = {
|
|
6073
6081
|
codeSigningInfo: CodeSigningInfoInput;
|
|
6074
6082
|
updateId: Scalars['ID']['input'];
|
|
@@ -7571,16 +7579,26 @@ export type AppInfoQuery = {
|
|
|
7571
7579
|
};
|
|
7572
7580
|
};
|
|
7573
7581
|
};
|
|
7574
|
-
export type
|
|
7582
|
+
export type ScheduleUpdateGroupDeletionMutationVariables = Exact<{
|
|
7575
7583
|
group: Scalars['ID']['input'];
|
|
7576
7584
|
}>;
|
|
7577
|
-
export type
|
|
7585
|
+
export type ScheduleUpdateGroupDeletionMutation = {
|
|
7578
7586
|
__typename?: 'RootMutation';
|
|
7579
7587
|
update: {
|
|
7580
7588
|
__typename?: 'UpdateMutation';
|
|
7581
|
-
|
|
7582
|
-
__typename?: '
|
|
7583
|
-
|
|
7589
|
+
scheduleUpdateGroupDeletion: {
|
|
7590
|
+
__typename?: 'BackgroundJobReceipt';
|
|
7591
|
+
id: string;
|
|
7592
|
+
state: BackgroundJobState;
|
|
7593
|
+
tries: number;
|
|
7594
|
+
willRetry: boolean;
|
|
7595
|
+
resultId?: string | null;
|
|
7596
|
+
resultType: BackgroundJobResultType;
|
|
7597
|
+
resultData?: any | null;
|
|
7598
|
+
errorCode?: string | null;
|
|
7599
|
+
errorMessage?: string | null;
|
|
7600
|
+
createdAt: any;
|
|
7601
|
+
updatedAt: any;
|
|
7584
7602
|
};
|
|
7585
7603
|
};
|
|
7586
7604
|
};
|
|
@@ -12331,6 +12349,29 @@ export type LatestAppVersionQuery = {
|
|
|
12331
12349
|
};
|
|
12332
12350
|
};
|
|
12333
12351
|
};
|
|
12352
|
+
export type BackgroundJobReceiptByIdQueryVariables = Exact<{
|
|
12353
|
+
id: Scalars['ID']['input'];
|
|
12354
|
+
}>;
|
|
12355
|
+
export type BackgroundJobReceiptByIdQuery = {
|
|
12356
|
+
__typename?: 'RootQuery';
|
|
12357
|
+
backgroundJobReceipt: {
|
|
12358
|
+
__typename?: 'BackgroundJobReceiptQuery';
|
|
12359
|
+
byId: {
|
|
12360
|
+
__typename?: 'BackgroundJobReceipt';
|
|
12361
|
+
id: string;
|
|
12362
|
+
state: BackgroundJobState;
|
|
12363
|
+
tries: number;
|
|
12364
|
+
willRetry: boolean;
|
|
12365
|
+
resultId?: string | null;
|
|
12366
|
+
resultType: BackgroundJobResultType;
|
|
12367
|
+
resultData?: any | null;
|
|
12368
|
+
errorCode?: string | null;
|
|
12369
|
+
errorMessage?: string | null;
|
|
12370
|
+
createdAt: any;
|
|
12371
|
+
updatedAt: any;
|
|
12372
|
+
};
|
|
12373
|
+
};
|
|
12374
|
+
};
|
|
12334
12375
|
export type ViewBranchQueryVariables = Exact<{
|
|
12335
12376
|
appId: Scalars['String']['input'];
|
|
12336
12377
|
name: Scalars['String']['input'];
|
|
@@ -14175,6 +14216,20 @@ export type AppFragment = {
|
|
|
14175
14216
|
};
|
|
14176
14217
|
} | null;
|
|
14177
14218
|
};
|
|
14219
|
+
export type BackgroundJobReceiptDataFragment = {
|
|
14220
|
+
__typename?: 'BackgroundJobReceipt';
|
|
14221
|
+
id: string;
|
|
14222
|
+
state: BackgroundJobState;
|
|
14223
|
+
tries: number;
|
|
14224
|
+
willRetry: boolean;
|
|
14225
|
+
resultId?: string | null;
|
|
14226
|
+
resultType: BackgroundJobResultType;
|
|
14227
|
+
resultData?: any | null;
|
|
14228
|
+
errorCode?: string | null;
|
|
14229
|
+
errorMessage?: string | null;
|
|
14230
|
+
createdAt: any;
|
|
14231
|
+
updatedAt: any;
|
|
14232
|
+
};
|
|
14178
14233
|
export type BuildFragment = {
|
|
14179
14234
|
__typename?: 'Build';
|
|
14180
14235
|
id: string;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
|
|
2
|
+
import { BackgroundJobReceiptByIdQuery } from '../generated';
|
|
3
|
+
export declare const BackgroundJobReceiptQuery: {
|
|
4
|
+
byIdAsync(graphqlClient: ExpoGraphqlClient, backgroundJobReceiptId: string): Promise<BackgroundJobReceiptByIdQuery['backgroundJobReceipt']['byId'] | null>;
|
|
5
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BackgroundJobReceiptQuery = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const graphql_tag_1 = tslib_1.__importDefault(require("graphql-tag"));
|
|
6
|
+
const client_1 = require("../client");
|
|
7
|
+
const BackgroundJobReceipt_1 = require("../types/BackgroundJobReceipt");
|
|
8
|
+
exports.BackgroundJobReceiptQuery = {
|
|
9
|
+
async byIdAsync(graphqlClient, backgroundJobReceiptId) {
|
|
10
|
+
const data = await (0, client_1.withErrorHandlingAsync)(graphqlClient
|
|
11
|
+
.query((0, graphql_tag_1.default) `
|
|
12
|
+
query BackgroundJobReceiptById($id: ID!) {
|
|
13
|
+
backgroundJobReceipt {
|
|
14
|
+
byId(id: $id) {
|
|
15
|
+
id
|
|
16
|
+
...BackgroundJobReceiptData
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
${BackgroundJobReceipt_1.BackgroundJobReceiptNode}
|
|
21
|
+
`, { id: backgroundJobReceiptId }, {
|
|
22
|
+
additionalTypenames: ['BackgroundJobReceipt'],
|
|
23
|
+
})
|
|
24
|
+
.toPromise());
|
|
25
|
+
return data.backgroundJobReceipt.byId ?? null;
|
|
26
|
+
},
|
|
27
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const BackgroundJobReceiptNode: import("graphql").DocumentNode;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BackgroundJobReceiptNode = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const graphql_tag_1 = tslib_1.__importDefault(require("graphql-tag"));
|
|
6
|
+
exports.BackgroundJobReceiptNode = (0, graphql_tag_1.default) `
|
|
7
|
+
fragment BackgroundJobReceiptData on BackgroundJobReceipt {
|
|
8
|
+
id
|
|
9
|
+
state
|
|
10
|
+
tries
|
|
11
|
+
willRetry
|
|
12
|
+
resultId
|
|
13
|
+
resultType
|
|
14
|
+
resultData
|
|
15
|
+
errorCode
|
|
16
|
+
errorMessage
|
|
17
|
+
createdAt
|
|
18
|
+
updatedAt
|
|
19
|
+
}
|
|
20
|
+
`;
|
|
@@ -4,7 +4,7 @@ import { Env, FingerprintSource, Platform, Workflow } from '@expo/eas-build-job'
|
|
|
4
4
|
import Joi from 'joi';
|
|
5
5
|
import { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient';
|
|
6
6
|
import { PaginatedQueryOptions } from '../commandUtils/pagination';
|
|
7
|
-
import { AppPlatform, PartialManifestAsset, UpdateRolloutInfoGroup } from '../graphql/generated';
|
|
7
|
+
import { AppPlatform, BuildFragment, PartialManifestAsset, UpdateRolloutInfoGroup } from '../graphql/generated';
|
|
8
8
|
import { RequestedPlatform } from '../platform';
|
|
9
9
|
import { UpdateJsonInfo } from '../update/utils';
|
|
10
10
|
import { Client } from '../vcs/vcs';
|
|
@@ -188,6 +188,22 @@ export declare function maybeCalculateFingerprintForRuntimeVersionInfoObjectsWit
|
|
|
188
188
|
expoUpdatesRuntimeFingerprintSource: FingerprintSource | null;
|
|
189
189
|
fingerprintInfoGroup: FingerprintInfoGroup;
|
|
190
190
|
})[]>;
|
|
191
|
+
export declare function findCompatibleBuildsAsync(graphqlClient: ExpoGraphqlClient, appId: string, runtimeToPlatformsAndFingerprintInfoMapping: {
|
|
192
|
+
runtimeVersion: string;
|
|
193
|
+
platforms: UpdatePublishPlatform[];
|
|
194
|
+
fingerprintInfoGroup: FingerprintInfoGroup;
|
|
195
|
+
}): Promise<{
|
|
196
|
+
runtimeVersion: string;
|
|
197
|
+
platforms: UpdatePublishPlatform[];
|
|
198
|
+
fingerprintInfoGroupWithCompatibleBuilds: {
|
|
199
|
+
android?: (FingerprintInfo & {
|
|
200
|
+
build?: BuildFragment;
|
|
201
|
+
}) | undefined;
|
|
202
|
+
ios?: (FingerprintInfo & {
|
|
203
|
+
build?: BuildFragment;
|
|
204
|
+
}) | undefined;
|
|
205
|
+
};
|
|
206
|
+
}>;
|
|
191
207
|
export declare const platformDisplayNames: Record<UpdatePublishPlatform, string>;
|
|
192
208
|
export declare const updatePublishPlatformToAppPlatform: Record<UpdatePublishPlatform, AppPlatform>;
|
|
193
209
|
export declare function getRuntimeToUpdateRolloutInfoGroupMappingAsync(graphqlClient: ExpoGraphqlClient, { appId, branchName, rolloutPercentage, runtimeToPlatformsAndFingerprintInfoMapping, }: {
|
package/build/project/publish.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getRuntimeToUpdateRolloutInfoGroupMappingAsync = exports.updatePublishPlatformToAppPlatform = exports.platformDisplayNames = exports.maybeCalculateFingerprintForRuntimeVersionInfoObjectsWithoutExpoUpdatesAsync = exports.getRuntimeToPlatformsAndFingerprintInfoMappingFromRuntimeVersionInfoObjects = exports.getRuntimeVersionInfoObjectsAsync = exports.defaultPublishPlatforms = exports.getUpdateMessageForCommandAsync = exports.getBranchNameForCommandAsync = exports.isUploadedAssetCountAboveWarningThreshold = exports.uploadAssetsAsync = exports.filterOutAssetsThatAlreadyExistAsync = exports.collectAssetsAsync = exports.getOriginalPathFromAssetMap = exports.getAssetHashFromPath = exports.loadAssetMapAsync = exports.filterCollectedAssetsByRequestedPlatforms = exports.generateEasMetadataAsync = exports.loadMetadata = exports.resolveInputDirectoryAsync = exports.buildBundlesAsync = exports.buildUnsortedUpdateInfoGroupAsync = exports.convertAssetToUpdateInfoGroupFormatAsync = exports.getStorageKeyForAssetAsync = exports.getStorageKey = exports.getBase64URLEncoding = exports.guessContentTypeFromExtension = exports.MetadataJoi = void 0;
|
|
3
|
+
exports.getRuntimeToUpdateRolloutInfoGroupMappingAsync = exports.updatePublishPlatformToAppPlatform = exports.platformDisplayNames = exports.findCompatibleBuildsAsync = exports.maybeCalculateFingerprintForRuntimeVersionInfoObjectsWithoutExpoUpdatesAsync = exports.getRuntimeToPlatformsAndFingerprintInfoMappingFromRuntimeVersionInfoObjects = exports.getRuntimeVersionInfoObjectsAsync = exports.defaultPublishPlatforms = exports.getUpdateMessageForCommandAsync = exports.getBranchNameForCommandAsync = exports.isUploadedAssetCountAboveWarningThreshold = exports.uploadAssetsAsync = exports.filterOutAssetsThatAlreadyExistAsync = exports.collectAssetsAsync = exports.getOriginalPathFromAssetMap = exports.getAssetHashFromPath = exports.loadAssetMapAsync = exports.filterCollectedAssetsByRequestedPlatforms = exports.generateEasMetadataAsync = exports.loadMetadata = exports.resolveInputDirectoryAsync = exports.buildBundlesAsync = exports.buildUnsortedUpdateInfoGroupAsync = exports.convertAssetToUpdateInfoGroupFormatAsync = exports.getStorageKeyForAssetAsync = exports.getStorageKey = exports.getBase64URLEncoding = exports.guessContentTypeFromExtension = exports.MetadataJoi = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const config_plugins_1 = require("@expo/config-plugins");
|
|
6
6
|
const eas_build_job_1 = require("@expo/eas-build-job");
|
|
@@ -19,6 +19,7 @@ const projectUtils_1 = require("./projectUtils");
|
|
|
19
19
|
const resolveRuntimeVersionAsync_1 = require("./resolveRuntimeVersionAsync");
|
|
20
20
|
const queries_1 = require("../branch/queries");
|
|
21
21
|
const utils_1 = require("../branch/utils");
|
|
22
|
+
const builds_1 = require("../commandUtils/builds");
|
|
22
23
|
const cli_1 = require("../fingerprint/cli");
|
|
23
24
|
const generated_1 = require("../graphql/generated");
|
|
24
25
|
const PublishMutation_1 = require("../graphql/mutations/PublishMutation");
|
|
@@ -601,6 +602,26 @@ async function maybeCalculateFingerprintForRuntimeVersionInfoObjectsWithoutExpoU
|
|
|
601
602
|
return [...runtimesWithComputedFingerprint, ...runtimesWithPreviouslyComputedFingerprints];
|
|
602
603
|
}
|
|
603
604
|
exports.maybeCalculateFingerprintForRuntimeVersionInfoObjectsWithoutExpoUpdatesAsync = maybeCalculateFingerprintForRuntimeVersionInfoObjectsWithoutExpoUpdatesAsync;
|
|
605
|
+
async function findCompatibleBuildsAsync(graphqlClient, appId, runtimeToPlatformsAndFingerprintInfoMapping) {
|
|
606
|
+
const { fingerprintInfoGroup } = runtimeToPlatformsAndFingerprintInfoMapping;
|
|
607
|
+
const entriesPromises = Object.entries(fingerprintInfoGroup).map(async ([platform, fingerprintInfo]) => {
|
|
608
|
+
const build = (await (0, builds_1.fetchBuildsAsync)({
|
|
609
|
+
graphqlClient,
|
|
610
|
+
projectId: appId,
|
|
611
|
+
filters: {
|
|
612
|
+
fingerprintHash: fingerprintInfo.fingerprintHash,
|
|
613
|
+
},
|
|
614
|
+
}))[0];
|
|
615
|
+
return [platform, { ...fingerprintInfo, build }];
|
|
616
|
+
});
|
|
617
|
+
const entries = await Promise.all(entriesPromises);
|
|
618
|
+
const fingerprintInfoGroupWithCompatibleBuilds = Object.fromEntries(entries);
|
|
619
|
+
return {
|
|
620
|
+
...runtimeToPlatformsAndFingerprintInfoMapping,
|
|
621
|
+
fingerprintInfoGroupWithCompatibleBuilds,
|
|
622
|
+
};
|
|
623
|
+
}
|
|
624
|
+
exports.findCompatibleBuildsAsync = findCompatibleBuildsAsync;
|
|
604
625
|
exports.platformDisplayNames = {
|
|
605
626
|
android: 'Android',
|
|
606
627
|
ios: 'iOS',
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { CombinedError } from '@urql/core';
|
|
2
|
+
import { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient';
|
|
3
|
+
import { BackgroundJobReceiptDataFragment } from '../graphql/generated';
|
|
4
|
+
export declare enum BackgroundJobReceiptPollErrorType {
|
|
5
|
+
NULL_RECEIPT = 0,
|
|
6
|
+
JOB_FAILED_NO_WILL_RETRY = 1,
|
|
7
|
+
TIMEOUT = 2
|
|
8
|
+
}
|
|
9
|
+
export type BackgroundJobReceiptPollErrorData = {
|
|
10
|
+
errorType: BackgroundJobReceiptPollErrorType.NULL_RECEIPT;
|
|
11
|
+
} | {
|
|
12
|
+
errorType: BackgroundJobReceiptPollErrorType.JOB_FAILED_NO_WILL_RETRY;
|
|
13
|
+
receiptErrorMessage: string | undefined | null;
|
|
14
|
+
} | {
|
|
15
|
+
errorType: BackgroundJobReceiptPollErrorType.TIMEOUT;
|
|
16
|
+
};
|
|
17
|
+
export declare class BackgroundJobReceiptPollError extends Error {
|
|
18
|
+
readonly errorData: BackgroundJobReceiptPollErrorData;
|
|
19
|
+
constructor(errorData: BackgroundJobReceiptPollErrorData);
|
|
20
|
+
static createErrorMessage(errorData: BackgroundJobReceiptPollErrorData): string;
|
|
21
|
+
}
|
|
22
|
+
export type BackgroundJobPollErrorCondition = (error: CombinedError) => {
|
|
23
|
+
errorIndicatesSuccess: boolean;
|
|
24
|
+
};
|
|
25
|
+
export declare function pollForBackgroundJobReceiptAsync(graphqlClient: ExpoGraphqlClient, backgroundJobReceipt: BackgroundJobReceiptDataFragment): Promise<BackgroundJobReceiptDataFragment>;
|
|
26
|
+
export declare function pollForBackgroundJobReceiptAsync(graphqlClient: ExpoGraphqlClient, backgroundJobReceipt: BackgroundJobReceiptDataFragment, options?: {
|
|
27
|
+
onBackgroundJobReceiptPollError?: BackgroundJobPollErrorCondition;
|
|
28
|
+
pollInterval?: number;
|
|
29
|
+
}): Promise<BackgroundJobReceiptDataFragment | null>;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.pollForBackgroundJobReceiptAsync = exports.BackgroundJobReceiptPollError = exports.BackgroundJobReceiptPollErrorType = void 0;
|
|
4
|
+
const core_1 = require("@urql/core");
|
|
5
|
+
const set_interval_async_1 = require("set-interval-async");
|
|
6
|
+
const generated_1 = require("../graphql/generated");
|
|
7
|
+
const BackgroundJobReceiptQuery_1 = require("../graphql/queries/BackgroundJobReceiptQuery");
|
|
8
|
+
var BackgroundJobReceiptPollErrorType;
|
|
9
|
+
(function (BackgroundJobReceiptPollErrorType) {
|
|
10
|
+
BackgroundJobReceiptPollErrorType[BackgroundJobReceiptPollErrorType["NULL_RECEIPT"] = 0] = "NULL_RECEIPT";
|
|
11
|
+
BackgroundJobReceiptPollErrorType[BackgroundJobReceiptPollErrorType["JOB_FAILED_NO_WILL_RETRY"] = 1] = "JOB_FAILED_NO_WILL_RETRY";
|
|
12
|
+
BackgroundJobReceiptPollErrorType[BackgroundJobReceiptPollErrorType["TIMEOUT"] = 2] = "TIMEOUT";
|
|
13
|
+
})(BackgroundJobReceiptPollErrorType || (exports.BackgroundJobReceiptPollErrorType = BackgroundJobReceiptPollErrorType = {}));
|
|
14
|
+
class BackgroundJobReceiptPollError extends Error {
|
|
15
|
+
errorData;
|
|
16
|
+
constructor(errorData) {
|
|
17
|
+
super(BackgroundJobReceiptPollError.createErrorMessage(errorData));
|
|
18
|
+
this.errorData = errorData;
|
|
19
|
+
}
|
|
20
|
+
static createErrorMessage(errorData) {
|
|
21
|
+
switch (errorData.errorType) {
|
|
22
|
+
case BackgroundJobReceiptPollErrorType.NULL_RECEIPT:
|
|
23
|
+
return 'Background job receipt was null.';
|
|
24
|
+
case BackgroundJobReceiptPollErrorType.JOB_FAILED_NO_WILL_RETRY:
|
|
25
|
+
return `Background job failed with error: ${errorData.receiptErrorMessage}`;
|
|
26
|
+
case BackgroundJobReceiptPollErrorType.TIMEOUT:
|
|
27
|
+
return 'Background job timed out.';
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
exports.BackgroundJobReceiptPollError = BackgroundJobReceiptPollError;
|
|
32
|
+
async function fetchBackgroundJobReceiptAsync(graphqlClient, receiptId) {
|
|
33
|
+
try {
|
|
34
|
+
return [await BackgroundJobReceiptQuery_1.BackgroundJobReceiptQuery.byIdAsync(graphqlClient, receiptId), null];
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
if (error instanceof core_1.CombinedError) {
|
|
38
|
+
return [null, error];
|
|
39
|
+
}
|
|
40
|
+
throw error;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
async function pollForBackgroundJobReceiptAsync(graphqlClient, backgroundJobReceipt, options) {
|
|
44
|
+
return await new Promise((resolve, reject) => {
|
|
45
|
+
let numChecks = 0;
|
|
46
|
+
const intervalHandle = (0, set_interval_async_1.setIntervalAsync)(async function pollForDeletionFinishedAsync() {
|
|
47
|
+
function failBackgroundDeletion(error) {
|
|
48
|
+
void (0, set_interval_async_1.clearIntervalAsync)(intervalHandle);
|
|
49
|
+
reject(error);
|
|
50
|
+
}
|
|
51
|
+
const [receipt, error] = await fetchBackgroundJobReceiptAsync(graphqlClient, backgroundJobReceipt.id);
|
|
52
|
+
if (!receipt) {
|
|
53
|
+
if (error instanceof core_1.CombinedError) {
|
|
54
|
+
const errorResult = options?.onBackgroundJobReceiptPollError?.(error);
|
|
55
|
+
if (errorResult?.errorIndicatesSuccess) {
|
|
56
|
+
void (0, set_interval_async_1.clearIntervalAsync)(intervalHandle);
|
|
57
|
+
resolve(null);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
failBackgroundDeletion(new BackgroundJobReceiptPollError({
|
|
62
|
+
errorType: BackgroundJobReceiptPollErrorType.NULL_RECEIPT,
|
|
63
|
+
}));
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
// job failed and will not retry
|
|
67
|
+
if (receipt.state === generated_1.BackgroundJobState.Failure && !receipt.willRetry) {
|
|
68
|
+
failBackgroundDeletion(new BackgroundJobReceiptPollError({
|
|
69
|
+
errorType: BackgroundJobReceiptPollErrorType.JOB_FAILED_NO_WILL_RETRY,
|
|
70
|
+
receiptErrorMessage: receipt.errorMessage,
|
|
71
|
+
}));
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
// all else fails, stop polling after 90 checks. This should only happen if there's an
|
|
75
|
+
// issue with receipts not setting `willRetry` to false when they fail within a reasonable
|
|
76
|
+
// amount of time.
|
|
77
|
+
if (numChecks > 90) {
|
|
78
|
+
failBackgroundDeletion(new BackgroundJobReceiptPollError({
|
|
79
|
+
errorType: BackgroundJobReceiptPollErrorType.TIMEOUT,
|
|
80
|
+
}));
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
if (receipt.state === generated_1.BackgroundJobState.Success) {
|
|
84
|
+
void (0, set_interval_async_1.clearIntervalAsync)(intervalHandle);
|
|
85
|
+
resolve(receipt);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
numChecks++;
|
|
89
|
+
}, options?.pollInterval ?? 1000);
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
exports.pollForBackgroundJobReceiptAsync = pollForBackgroundJobReceiptAsync;
|
package/oclif.manifest.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "16.
|
|
2
|
+
"version": "16.2.0",
|
|
3
3
|
"commands": {
|
|
4
4
|
"analytics": {
|
|
5
5
|
"id": "analytics",
|
|
@@ -2781,6 +2781,7 @@
|
|
|
2781
2781
|
"$ eas fingerprint:compare <FINGERPRINT-HASH> \t # Compare fingerprint against local directory",
|
|
2782
2782
|
"$ eas fingerprint:compare <FINGERPRINT-HASH-1> <FINGERPRINT-HASH-2> \t # Compare provided fingerprints",
|
|
2783
2783
|
"$ eas fingerprint:compare --build-id <BUILD-ID> \t # Compare fingerprint from build against local directory",
|
|
2784
|
+
"$ eas fingerprint:compare --build-id <BUILD-ID> --environment production \t # Compare fingerprint from build against local directory with the \"production\" environment",
|
|
2784
2785
|
"$ eas fingerprint:compare --build-id <BUILD-ID-1> --build-id <BUILD-ID-2>\t # Compare fingerprint from a build against another build",
|
|
2785
2786
|
"$ eas fingerprint:compare --build-id <BUILD-ID> --update-id <UPDATE-ID>\t # Compare fingerprint from build against fingerprint from update",
|
|
2786
2787
|
"$ eas fingerprint:compare <FINGERPRINT-HASH> --update-id <UPDATE-ID> \t # Compare fingerprint from update against provided fingerprint"
|
|
@@ -2810,6 +2811,18 @@
|
|
|
2810
2811
|
"description": "Open the fingerprint comparison in the browser",
|
|
2811
2812
|
"allowNo": false
|
|
2812
2813
|
},
|
|
2814
|
+
"environment": {
|
|
2815
|
+
"name": "environment",
|
|
2816
|
+
"type": "option",
|
|
2817
|
+
"description": "If generating a fingerprint from the local directory, use the specified environment.",
|
|
2818
|
+
"helpValue": "(development|preview|production)",
|
|
2819
|
+
"multiple": false,
|
|
2820
|
+
"options": [
|
|
2821
|
+
"development",
|
|
2822
|
+
"preview",
|
|
2823
|
+
"production"
|
|
2824
|
+
]
|
|
2825
|
+
},
|
|
2813
2826
|
"json": {
|
|
2814
2827
|
"name": "json",
|
|
2815
2828
|
"type": "boolean",
|
|
@@ -2842,7 +2855,8 @@
|
|
|
2842
2855
|
"projectId": {},
|
|
2843
2856
|
"loggedIn": {},
|
|
2844
2857
|
"privateProjectConfig": {},
|
|
2845
|
-
"vcsClient": {}
|
|
2858
|
+
"vcsClient": {},
|
|
2859
|
+
"getServerSideEnvironmentVariablesAsync": {}
|
|
2846
2860
|
}
|
|
2847
2861
|
},
|
|
2848
2862
|
"fingerprint:generate": {
|
|
@@ -2852,11 +2866,11 @@
|
|
|
2852
2866
|
"pluginName": "eas-cli",
|
|
2853
2867
|
"pluginAlias": "eas-cli",
|
|
2854
2868
|
"pluginType": "core",
|
|
2855
|
-
"hidden": true,
|
|
2856
2869
|
"aliases": [],
|
|
2857
2870
|
"examples": [
|
|
2858
2871
|
"$ eas fingerprint:generate \t # Generate fingerprint in interactive mode",
|
|
2859
|
-
"$ eas fingerprint:generate --profile preview \t # Generate a fingerprint using the \"preview\" build profile",
|
|
2872
|
+
"$ eas fingerprint:generate --build-profile preview \t # Generate a fingerprint using the \"preview\" build profile",
|
|
2873
|
+
"$ eas fingerprint:generate --environment preview \t # Generate a fingerprint using the \"preview\" environment",
|
|
2860
2874
|
"$ eas fingerprint:generate --json --non-interactive --platform android \t # Output fingerprint json to stdout"
|
|
2861
2875
|
],
|
|
2862
2876
|
"flags": {
|
|
@@ -2881,6 +2895,19 @@
|
|
|
2881
2895
|
"development",
|
|
2882
2896
|
"preview",
|
|
2883
2897
|
"production"
|
|
2898
|
+
],
|
|
2899
|
+
"exclusive": [
|
|
2900
|
+
"build-profile"
|
|
2901
|
+
]
|
|
2902
|
+
},
|
|
2903
|
+
"build-profile": {
|
|
2904
|
+
"name": "build-profile",
|
|
2905
|
+
"type": "option",
|
|
2906
|
+
"char": "e",
|
|
2907
|
+
"description": "Name of the build profile from eas.json.",
|
|
2908
|
+
"multiple": false,
|
|
2909
|
+
"exclusive": [
|
|
2910
|
+
"environment"
|
|
2884
2911
|
]
|
|
2885
2912
|
},
|
|
2886
2913
|
"json": {
|
|
@@ -2905,7 +2932,9 @@
|
|
|
2905
2932
|
"loggedIn": {},
|
|
2906
2933
|
"privateProjectConfig": {},
|
|
2907
2934
|
"vcsClient": {},
|
|
2908
|
-
"getServerSideEnvironmentVariablesAsync": {}
|
|
2935
|
+
"getServerSideEnvironmentVariablesAsync": {},
|
|
2936
|
+
"getDynamicPublicProjectConfigAsync": {},
|
|
2937
|
+
"getDynamicPrivateProjectConfigAsync": {}
|
|
2909
2938
|
}
|
|
2910
2939
|
},
|
|
2911
2940
|
"metadata:lint": {
|