eas-cli 14.7.0 → 15.0.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.
@@ -7,8 +7,7 @@ const local_1 = require("../../build/local");
7
7
  const runBuildAndSubmit_1 = require("../../build/runBuildAndSubmit");
8
8
  const EasCommand_1 = tslib_1.__importDefault(require("../../commandUtils/EasCommand"));
9
9
  const json_1 = require("../../utils/json");
10
- const gitNoCommit_1 = tslib_1.__importDefault(require("../../vcs/clients/gitNoCommit"));
11
- const noVcs_1 = tslib_1.__importDefault(require("../../vcs/clients/noVcs"));
10
+ const git_1 = tslib_1.__importDefault(require("../../vcs/clients/git"));
12
11
  /**
13
12
  * This command will be run on the EAS Build workers, when building
14
13
  * directly from git. This command resolves credentials and other
@@ -52,9 +51,14 @@ class BuildInternal extends EasCommand_1.default {
52
51
  (0, json_1.enableJsonOutput)();
53
52
  const { loggedIn: { actor, graphqlClient }, getDynamicPrivateProjectConfigAsync, projectDir, analytics, vcsClient, } = await this.getContextAsync(BuildInternal, {
54
53
  nonInteractive: true,
55
- vcsClientOverride: process.env.EAS_NO_VCS ? new noVcs_1.default() : new gitNoCommit_1.default(),
56
54
  withServerSideEnvironment: null,
57
55
  });
56
+ if (vcsClient instanceof git_1.default) {
57
+ // `build:internal` is run on EAS workers and the repo may have been changed
58
+ // by pre-install hooks or other scripts. We don't want to require committing changes
59
+ // to continue the build.
60
+ vcsClient.requireCommit = false;
61
+ }
58
62
  await (0, _1.handleDeprecatedEasJsonAsync)(projectDir, flags.nonInteractive);
59
63
  await (0, runBuildAndSubmit_1.runBuildAndSubmitAsync)({
60
64
  graphqlClient,
@@ -2,13 +2,6 @@ import EasCommand from '../../commandUtils/EasCommand';
2
2
  import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
3
3
  import { BuildStatus } from '../../graphql/generated';
4
4
  import { RequestedPlatform } from '../../platform';
5
- export interface FingerprintCompareFlags {
6
- buildId?: string;
7
- hash1?: string;
8
- hash2?: string;
9
- nonInteractive: boolean;
10
- json: boolean;
11
- }
12
5
  export default class FingerprintCompare extends EasCommand {
13
6
  static description: string;
14
7
  static strict: boolean;
@@ -21,7 +14,8 @@ export default class FingerprintCompare extends EasCommand {
21
14
  static flags: {
22
15
  json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
23
16
  'non-interactive': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
24
- 'build-id': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined>;
17
+ 'build-id': import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined>;
18
+ 'update-id': import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined>;
25
19
  };
26
20
  static contextDefinition: {
27
21
  vcsClient: import("../../commandUtils/context/VcsClientContextField").default;
@@ -5,19 +5,24 @@ const tslib_1 = require("tslib");
5
5
  const eas_build_job_1 = require("@expo/eas-build-job");
6
6
  const core_1 = require("@oclif/core");
7
7
  const chalk_1 = tslib_1.__importDefault(require("chalk"));
8
+ const api_1 = require("../../api");
9
+ const queries_1 = require("../../branch/queries");
8
10
  const EasCommand_1 = tslib_1.__importDefault(require("../../commandUtils/EasCommand"));
9
11
  const builds_1 = require("../../commandUtils/builds");
10
12
  const flags_1 = require("../../commandUtils/flags");
11
13
  const generated_1 = require("../../graphql/generated");
12
14
  const FingerprintMutation_1 = require("../../graphql/mutations/FingerprintMutation");
15
+ const AppQuery_1 = require("../../graphql/queries/AppQuery");
13
16
  const BuildQuery_1 = require("../../graphql/queries/BuildQuery");
14
17
  const FingerprintQuery_1 = require("../../graphql/queries/FingerprintQuery");
18
+ const UpdateQuery_1 = require("../../graphql/queries/UpdateQuery");
15
19
  const log_1 = tslib_1.__importDefault(require("../../log"));
16
20
  const ora_1 = require("../../ora");
17
21
  const maybeUploadFingerprintAsync_1 = require("../../project/maybeUploadFingerprintAsync");
18
22
  const projectUtils_1 = require("../../project/projectUtils");
19
23
  const workflow_1 = require("../../project/workflow");
20
24
  const prompts_1 = require("../../prompts");
25
+ const queries_2 = require("../../update/queries");
21
26
  const fingerprintCli_1 = require("../../utils/fingerprintCli");
22
27
  const fingerprintDiff_1 = require("../../utils/fingerprintDiff");
23
28
  const formatFields_1 = tslib_1.__importDefault(require("../../utils/formatFields"));
@@ -25,6 +30,7 @@ const json_1 = require("../../utils/json");
25
30
  var FingerprintOriginType;
26
31
  (function (FingerprintOriginType) {
27
32
  FingerprintOriginType["Build"] = "build";
33
+ FingerprintOriginType["Update"] = "update";
28
34
  FingerprintOriginType["Hash"] = "hash";
29
35
  FingerprintOriginType["Project"] = "project";
30
36
  })(FingerprintOriginType || (FingerprintOriginType = {}));
@@ -33,9 +39,12 @@ class FingerprintCompare extends EasCommand_1.default {
33
39
  static strict = false;
34
40
  static examples = [
35
41
  '$ eas fingerprint:compare \t # Compare fingerprints in interactive mode',
36
- '$ eas fingerprint:compare c71a7d475aa6f75291bc93cd74aef395c3c94eee \t # Compare fingerprint against local directory',
37
- '$ eas fingerprint:compare c71a7d475aa6f75291bc93cd74aef395c3c94eee f0d6a916e73f401d428e6e006e07b12453317ba2 \t # Compare provided fingerprints',
38
- '$ eas fingerprint:compare --build-id 82bc6456-611a-48cb-8db4-5f9eb2ca1003 \t # Compare fingerprint from build against local directory',
42
+ '$ eas fingerprint:compare <FINGERPRINT-HASH> \t # Compare fingerprint against local directory',
43
+ '$ eas fingerprint:compare <FINGERPRINT-HASH-1> <FINGERPRINT-HASH-2> \t # Compare provided fingerprints',
44
+ '$ eas fingerprint:compare --build-id <BUILD-ID> \t # Compare fingerprint from build against local directory',
45
+ '$ eas fingerprint:compare --build-id <BUILD-ID-1> --build-id <BUILD-ID-2>\t # Compare fingerprint from a build against another build',
46
+ '$ eas fingerprint:compare --build-id <BUILD-ID> --update-id <UPDATE-ID>\t # Compare fingerprint from build against fingerprint from update',
47
+ '$ eas fingerprint:compare <FINGERPRINT-HASH> --update-id <UPDATE-ID> \t # Compare fingerprint from update against provided fingerprint',
39
48
  ];
40
49
  static args = [
41
50
  {
@@ -53,6 +62,12 @@ class FingerprintCompare extends EasCommand_1.default {
53
62
  'build-id': core_1.Flags.string({
54
63
  aliases: ['buildId'],
55
64
  description: 'Compare the fingerprint with the build with the specified ID',
65
+ multiple: true,
66
+ }),
67
+ 'update-id': core_1.Flags.string({
68
+ aliases: ['updateId'],
69
+ description: 'Compare the fingerprint with the update with the specified ID',
70
+ multiple: true,
56
71
  }),
57
72
  ...flags_1.EasNonInteractiveAndJsonFlags,
58
73
  };
@@ -65,8 +80,9 @@ class FingerprintCompare extends EasCommand_1.default {
65
80
  async runAsync() {
66
81
  const { args, flags } = await this.parse(FingerprintCompare);
67
82
  const { hash1, hash2 } = args;
68
- const { json, 'non-interactive': nonInteractive, 'build-id': buildId } = flags;
69
- const sanitizedFlagsAndArgs = { json, nonInteractive, buildId, hash1, hash2 };
83
+ const { json, 'non-interactive': nonInteractive, 'build-id': buildIds, 'update-id': updateIds, } = flags;
84
+ const [buildId1, buildId2] = buildIds ?? [];
85
+ const [updateId1, updateId2] = updateIds ?? [];
70
86
  const { projectId, privateProjectConfig: { projectDir }, loggedIn: { graphqlClient }, vcsClient, } = await this.getContextAsync(FingerprintCompare, {
71
87
  nonInteractive,
72
88
  withServerSideEnvironment: null,
@@ -74,16 +90,29 @@ class FingerprintCompare extends EasCommand_1.default {
74
90
  if (json) {
75
91
  (0, json_1.enableJsonOutput)();
76
92
  }
77
- const firstFingerprintInfo = await getFirstFingerprintInfoAsync(graphqlClient, projectId, sanitizedFlagsAndArgs);
93
+ const firstFingerprintInfo = await getFingerprintInfoAsync(graphqlClient, projectDir, projectId, vcsClient, {
94
+ nonInteractive,
95
+ buildId: buildId1,
96
+ updateId: updateId1,
97
+ hash: hash1,
98
+ });
78
99
  const { fingerprint: firstFingerprint, origin: firstFingerprintOrigin } = firstFingerprintInfo;
79
- const secondFingerprintInfo = await getSecondFingerprintInfoAsync(graphqlClient, projectDir, projectId, vcsClient, firstFingerprintInfo, sanitizedFlagsAndArgs);
100
+ const isFirstFingerprintSpecifiedByFlagOrArg = hash1 || buildId1 || updateId1;
101
+ const isSecondFingerprintSpecifiedByFlagOrArg = hash2 || buildId2 || updateId2;
102
+ const secondFingerprintInfo = await getFingerprintInfoAsync(graphqlClient, projectDir, projectId, vcsClient, {
103
+ nonInteractive,
104
+ buildId: buildId2,
105
+ updateId: updateId2,
106
+ hash: hash2,
107
+ useProjectFingerprint: isFirstFingerprintSpecifiedByFlagOrArg && !isSecondFingerprintSpecifiedByFlagOrArg,
108
+ }, firstFingerprintInfo);
80
109
  const { fingerprint: secondFingerprint, origin: secondFingerprintOrigin } = secondFingerprintInfo;
81
110
  if (json) {
82
111
  (0, json_1.printJsonOnlyOutput)({ fingerprint1: firstFingerprint, fingerprint2: secondFingerprint });
83
112
  return;
84
113
  }
85
114
  if (firstFingerprint.hash === secondFingerprint.hash) {
86
- log_1.default.log(`✅ ${capitalizeFirstLetter(prettyPrintFingerprint(firstFingerprint, firstFingerprintOrigin))} matches fingerprint from ${prettyPrintFingerprint(secondFingerprint, secondFingerprintOrigin)}`);
115
+ log_1.default.log(`✅ ${capitalizeFirstLetter(prettyPrintFingerprint(firstFingerprint, firstFingerprintOrigin))} matches ${prettyPrintFingerprint(secondFingerprint, secondFingerprintOrigin)}`);
87
116
  return;
88
117
  }
89
118
  else {
@@ -141,77 +170,95 @@ class FingerprintCompare extends EasCommand_1.default {
141
170
  }
142
171
  }
143
172
  exports.default = FingerprintCompare;
144
- function prettyPrintFingerprint(fingerprint, origin) {
145
- if (origin.type === FingerprintOriginType.Hash) {
146
- return `fingerprint ${fingerprint.hash} from hash`;
173
+ async function getFingerprintInfoAsync(graphqlClient, projectDir, projectId, vcsClient, { buildId, updateId, hash, useProjectFingerprint, nonInteractive, }, firstFingerprintInfo) {
174
+ if (hash) {
175
+ return await getFingerprintInfoFromHashAsync(graphqlClient, projectId, hash);
147
176
  }
148
- return `fingerprint ${fingerprint.hash} from ${origin.type}`;
149
- }
150
- function capitalizeFirstLetter(string) {
151
- return string.charAt(0).toUpperCase() + string.slice(1);
152
- }
153
- async function getFirstFingerprintInfoAsync(graphqlClient, projectId, { buildId: buildIdFromArg, hash1, nonInteractive }) {
154
- if (hash1) {
155
- const fingerprintFragment = await getFingerprintFragmentFromHashAsync(graphqlClient, projectId, hash1);
156
- const fingerprint = await getFingerprintFromFingerprintFragmentAsync(fingerprintFragment);
157
- let platforms;
158
- const fingerprintBuilds = fingerprintFragment.builds?.edges.map(edge => edge.node) ?? [];
159
- const fingerprintUpdates = fingerprintFragment.updates?.edges.map(edge => edge.node) ?? [];
160
- if (fingerprintBuilds.length > 0) {
161
- platforms = [fingerprintBuilds[0].platform];
162
- }
163
- else if (fingerprintUpdates.length > 0) {
164
- platforms = [stringToAppPlatform(fingerprintUpdates[0].platform)];
177
+ else if (updateId) {
178
+ return await getFingerprintInfoFromUpdateGroupIdOrUpdateIdAsync(graphqlClient, projectId, nonInteractive, updateId);
179
+ }
180
+ else if (buildId) {
181
+ return await getFingerprintInfoFromBuildIdAsync(graphqlClient, buildId);
182
+ }
183
+ else if (useProjectFingerprint) {
184
+ if (!firstFingerprintInfo) {
185
+ throw new Error('First fingerprint must be provided in order to compare against the project.');
165
186
  }
166
- return {
167
- fingerprint,
168
- platforms,
169
- origin: {
170
- type: FingerprintOriginType.Hash,
171
- },
172
- };
187
+ return await getFingerprintInfoFromLocalProjectAsync(graphqlClient, projectDir, projectId, vcsClient, firstFingerprintInfo);
173
188
  }
174
- let buildId = buildIdFromArg ?? null;
175
- if (!buildId) {
176
- if (nonInteractive) {
177
- throw new Error('Build ID must be provided in non-interactive mode');
189
+ if (nonInteractive) {
190
+ throw new Error('Insufficent arguments provided for fingerprint comparison in non-interactive mode');
191
+ }
192
+ return await getFingerprintInfoInteractiveAsync(graphqlClient, projectDir, projectId, vcsClient, firstFingerprintInfo);
193
+ }
194
+ async function getFingerprintInfoInteractiveAsync(graphqlClient, projectDir, projectId, vcsClient, firstFingerprintInfo) {
195
+ const prompt = firstFingerprintInfo
196
+ ? 'Select the second fingerprint to compare against'
197
+ : 'Select a reference fingerprint for comparison';
198
+ const originType = await (0, prompts_1.selectAsync)(prompt, [
199
+ ...(firstFingerprintInfo
200
+ ? [{ title: 'Current project fingerprint', value: FingerprintOriginType.Project }]
201
+ : []),
202
+ { title: 'Build fingerprint', value: FingerprintOriginType.Build },
203
+ { title: 'Update fingerprint', value: FingerprintOriginType.Update },
204
+ { title: 'Enter a fingerprint hash manually', value: FingerprintOriginType.Hash },
205
+ ]);
206
+ if (originType === FingerprintOriginType.Project) {
207
+ if (!firstFingerprintInfo) {
208
+ throw new Error('First fingerprint must be provided in order to compare against the project.');
178
209
  }
210
+ return await getFingerprintInfoFromLocalProjectAsync(graphqlClient, projectDir, projectId, vcsClient, firstFingerprintInfo);
211
+ }
212
+ else if (originType === FingerprintOriginType.Build) {
179
213
  const displayName = await (0, projectUtils_1.getDisplayNameForProjectIdAsync)(graphqlClient, projectId);
180
- buildId = await selectBuildToCompareAsync(graphqlClient, projectId, displayName, {
214
+ const buildId = await selectBuildToCompareAsync(graphqlClient, projectId, displayName, {
181
215
  filters: { hasFingerprint: true },
182
216
  });
183
217
  if (!buildId) {
184
218
  throw new Error('Must select build with fingerprint for comparison.');
185
219
  }
220
+ return await getFingerprintInfoFromBuildIdAsync(graphqlClient, buildId);
221
+ }
222
+ else if (originType === FingerprintOriginType.Update) {
223
+ const selectedBranch = await (0, queries_1.selectBranchOnAppAsync)(graphqlClient, {
224
+ projectId,
225
+ promptTitle: 'On which branch would you like search for an update?',
226
+ displayTextForListItem: updateBranch => ({
227
+ title: updateBranch.name,
228
+ }),
229
+ paginatedQueryOptions: {
230
+ json: false,
231
+ nonInteractive: false,
232
+ offset: 0,
233
+ },
234
+ });
235
+ const selectedUpdateGroup = await (0, queries_2.selectUpdateGroupOnBranchAsync)(graphqlClient, {
236
+ projectId,
237
+ branchName: selectedBranch.name,
238
+ paginatedQueryOptions: {
239
+ json: false,
240
+ nonInteractive: false,
241
+ offset: 0,
242
+ },
243
+ });
244
+ const updateGroupId = selectedUpdateGroup[0].group;
245
+ return await getFingerprintInfoFromUpdateGroupIdOrUpdateIdAsync(graphqlClient, projectId, false, updateGroupId);
246
+ }
247
+ else if (originType === FingerprintOriginType.Hash) {
248
+ const { hash } = await (0, prompts_1.promptAsync)({
249
+ type: 'text',
250
+ name: 'hash',
251
+ message: 'Provide the fingerprint hash',
252
+ validate: (value) => !!value.trim(),
253
+ hint: '0000000000000000000000000000000000000000',
254
+ });
255
+ return await getFingerprintInfoFromHashAsync(graphqlClient, projectId, hash);
186
256
  }
187
- log_1.default.log(`Comparing fingerprints of the current project and build ${buildId}…`);
188
- const buildWithFingerprint = await BuildQuery_1.BuildQuery.withFingerprintByIdAsync(graphqlClient, buildId);
189
- if (!buildWithFingerprint.fingerprint) {
190
- throw new Error(`Fingerprint for build ${buildId} was not computed.`);
191
- }
192
- else if (!buildWithFingerprint.fingerprint.debugInfoUrl) {
193
- throw new Error(`Fingerprint source for build ${buildId} was not computed.`);
257
+ else {
258
+ throw new Error(`Unsupported fingerprint origin type: ${originType}`);
194
259
  }
195
- return {
196
- fingerprint: await getFingerprintFromFingerprintFragmentAsync(buildWithFingerprint.fingerprint),
197
- platforms: [buildWithFingerprint.platform],
198
- origin: {
199
- type: FingerprintOriginType.Build,
200
- build: buildWithFingerprint,
201
- },
202
- };
203
260
  }
204
- async function getSecondFingerprintInfoAsync(graphqlClient, projectDir, projectId, vcsClient, firstFingerprintInfo, { hash2 }) {
205
- if (hash2) {
206
- const fingerprintFragment = await getFingerprintFragmentFromHashAsync(graphqlClient, projectId, hash2);
207
- if (!fingerprintFragment) {
208
- throw new Error(`Fingerprint with hash ${hash2} was not uploaded.`);
209
- }
210
- return {
211
- fingerprint: await getFingerprintFromFingerprintFragmentAsync(fingerprintFragment),
212
- origin: { type: FingerprintOriginType.Hash },
213
- };
214
- }
261
+ async function getFingerprintInfoFromLocalProjectAsync(graphqlClient, projectDir, projectId, vcsClient, firstFingerprintInfo) {
215
262
  const firstFingerprintPlatforms = firstFingerprintInfo.platforms;
216
263
  if (!firstFingerprintPlatforms) {
217
264
  throw new Error(`Cannot compare the local directory against the provided fingerprint hash "${firstFingerprintInfo.fingerprint.hash}" because the associated platform could not be determined. Ensure the fingerprint is linked to a build or update to identify the platform.`);
@@ -241,6 +288,96 @@ async function getSecondFingerprintInfoAsync(graphqlClient, projectDir, projectI
241
288
  });
242
289
  return { fingerprint: projectFingerprint, origin: { type: FingerprintOriginType.Project } };
243
290
  }
291
+ async function getFingerprintFromUpdateFragmentAsync(updateWithFingerprint) {
292
+ if (!updateWithFingerprint.fingerprint) {
293
+ throw new Error(`Fingerprint for update ${updateWithFingerprint.id} was not computed.`);
294
+ }
295
+ else if (!updateWithFingerprint.fingerprint.debugInfoUrl) {
296
+ throw new Error(`Fingerprint source for update ${updateWithFingerprint.id} was not computed.`);
297
+ }
298
+ return {
299
+ fingerprint: await getFingerprintFromFingerprintFragmentAsync(updateWithFingerprint.fingerprint),
300
+ platforms: [stringToAppPlatform(updateWithFingerprint.platform)],
301
+ origin: {
302
+ type: FingerprintOriginType.Update,
303
+ update: updateWithFingerprint,
304
+ },
305
+ };
306
+ }
307
+ async function getFingerprintInfoFromHashAsync(graphqlClient, projectId, hash) {
308
+ const fingerprintFragment = await getFingerprintFragmentFromHashAsync(graphqlClient, projectId, hash);
309
+ const fingerprint = await getFingerprintFromFingerprintFragmentAsync(fingerprintFragment);
310
+ let platforms;
311
+ const fingerprintBuilds = fingerprintFragment.builds?.edges.map(edge => edge.node) ?? [];
312
+ const fingerprintUpdates = fingerprintFragment.updates?.edges.map(edge => edge.node) ?? [];
313
+ if (fingerprintBuilds.length > 0) {
314
+ platforms = [fingerprintBuilds[0].platform];
315
+ }
316
+ else if (fingerprintUpdates.length > 0) {
317
+ platforms = [stringToAppPlatform(fingerprintUpdates[0].platform)];
318
+ }
319
+ return {
320
+ fingerprint,
321
+ platforms,
322
+ origin: {
323
+ type: FingerprintOriginType.Hash,
324
+ },
325
+ };
326
+ }
327
+ async function getFingerprintInfoFromUpdateGroupIdOrUpdateIdAsync(graphqlClient, projectId, nonInteractive, updateGroupIdOrUpdateId) {
328
+ // Some people may pass in update group id instead of update id, so add interactive support for that
329
+ try {
330
+ const maybeUpdateGroupId = updateGroupIdOrUpdateId;
331
+ const updateGroup = await UpdateQuery_1.UpdateQuery.viewUpdateGroupAsync(graphqlClient, {
332
+ groupId: maybeUpdateGroupId,
333
+ });
334
+ if (updateGroup.length === 1) {
335
+ const update = updateGroup[0];
336
+ return await getFingerprintFromUpdateFragmentAsync(update);
337
+ }
338
+ if (nonInteractive) {
339
+ const [accountName, project] = await Promise.all([
340
+ (await (0, projectUtils_1.getOwnerAccountForProjectIdAsync)(graphqlClient, projectId)).name,
341
+ AppQuery_1.AppQuery.byIdAsync(graphqlClient, projectId),
342
+ ]);
343
+ const updateUrl = (0, api_1.getExpoWebsiteBaseUrl)() +
344
+ `/accounts/${accountName}/projects/${project.name}/updates/${maybeUpdateGroupId}`;
345
+ throw new Error(`Please pass in your update ID from ${updateUrl} or use interactive mode to select the update ID.`);
346
+ }
347
+ const update = await (0, prompts_1.selectAsync)('Select a platform to compute the fingerprint from', updateGroup.map(update => ({
348
+ title: update.platform,
349
+ value: update,
350
+ })));
351
+ return await getFingerprintFromUpdateFragmentAsync(update);
352
+ }
353
+ catch (error) {
354
+ if (!error?.message.includes('Could not find any updates with group ID')) {
355
+ throw error;
356
+ }
357
+ }
358
+ const updateId = updateGroupIdOrUpdateId;
359
+ const updateWithFingerprint = await UpdateQuery_1.UpdateQuery.viewByUpdateAsync(graphqlClient, {
360
+ updateId,
361
+ });
362
+ return await getFingerprintFromUpdateFragmentAsync(updateWithFingerprint);
363
+ }
364
+ async function getFingerprintInfoFromBuildIdAsync(graphqlClient, buildId) {
365
+ const buildWithFingerprint = await BuildQuery_1.BuildQuery.withFingerprintByIdAsync(graphqlClient, buildId);
366
+ if (!buildWithFingerprint.fingerprint) {
367
+ throw new Error(`Fingerprint for build ${buildId} was not computed.`);
368
+ }
369
+ else if (!buildWithFingerprint.fingerprint.debugInfoUrl) {
370
+ throw new Error(`Fingerprint source for build ${buildId} was not computed.`);
371
+ }
372
+ return {
373
+ fingerprint: await getFingerprintFromFingerprintFragmentAsync(buildWithFingerprint.fingerprint),
374
+ platforms: [buildWithFingerprint.platform],
375
+ origin: {
376
+ type: FingerprintOriginType.Build,
377
+ build: buildWithFingerprint,
378
+ },
379
+ };
380
+ }
244
381
  async function getFingerprintFragmentFromHashAsync(graphqlClient, projectId, hash) {
245
382
  const fingerprint = await FingerprintQuery_1.FingerprintQuery.byHashAsync(graphqlClient, {
246
383
  appId: projectId,
@@ -412,6 +549,21 @@ function printContentsDiff(contents1, contents2) {
412
549
  : stringifiedContents2;
413
550
  (0, fingerprintDiff_1.abridgedDiff)(prettifiedContents1, prettifiedContents2, 0);
414
551
  }
552
+ function prettyPrintFingerprint(fingerprint, origin) {
553
+ if (origin.type === FingerprintOriginType.Project) {
554
+ return `fingerprint ${fingerprint.hash} from local directory`;
555
+ }
556
+ else if (origin.type === FingerprintOriginType.Update) {
557
+ return `fingerprint ${fingerprint.hash} from ${origin.update?.platform ? stringToAppPlatform(origin.update?.platform) : ''} ${origin.type}`;
558
+ }
559
+ else if (origin.type === FingerprintOriginType.Build) {
560
+ return `fingerprint ${fingerprint.hash} from ${origin.build?.platform} ${origin.type}`;
561
+ }
562
+ return `fingerprint ${fingerprint.hash}`;
563
+ }
564
+ function capitalizeFirstLetter(string) {
565
+ return string.charAt(0).toUpperCase() + string.slice(1);
566
+ }
415
567
  function isJSON(str) {
416
568
  try {
417
569
  JSON.parse(str);
@@ -108,7 +108,10 @@ class Onboarding extends EasCommand_1.default {
108
108
  targetProjectDir: initialTargetProjectDirectory,
109
109
  cloneMethod,
110
110
  });
111
- const vcsClient = new git_2.default(finalTargetProjectDirectory);
111
+ const vcsClient = new git_2.default({
112
+ maybeCwdOverride: finalTargetProjectDirectory,
113
+ requireCommit: false,
114
+ });
112
115
  if (!app.githubRepository) {
113
116
  await fs_extra_1.default.remove(path_1.default.join(finalTargetProjectDirectory, '.git'));
114
117
  await (0, runCommand_1.runCommandAsync)({
@@ -13,8 +13,7 @@ const AndroidSubmitCommand_1 = tslib_1.__importDefault(require("../../submit/and
13
13
  const context_1 = require("../../submit/context");
14
14
  const IosSubmitCommand_1 = tslib_1.__importDefault(require("../../submit/ios/IosSubmitCommand"));
15
15
  const json_1 = require("../../utils/json");
16
- const gitNoCommit_1 = tslib_1.__importDefault(require("../../vcs/clients/gitNoCommit"));
17
- const noVcs_1 = tslib_1.__importDefault(require("../../vcs/clients/noVcs"));
16
+ const git_1 = tslib_1.__importDefault(require("../../vcs/clients/git"));
18
17
  /**
19
18
  * This command will be run on the EAS workers.
20
19
  * This command resolves credentials and other
@@ -49,9 +48,14 @@ class SubmitInternal extends EasCommand_1.default {
49
48
  (0, json_1.enableJsonOutput)();
50
49
  const { loggedIn: { actor, graphqlClient }, privateProjectConfig: { exp, projectId, projectDir }, analytics, vcsClient, } = await this.getContextAsync(SubmitInternal, {
51
50
  nonInteractive: true,
52
- vcsClientOverride: process.env.EAS_NO_VCS ? new noVcs_1.default() : new gitNoCommit_1.default(),
53
51
  withServerSideEnvironment: null,
54
52
  });
53
+ if (vcsClient instanceof git_1.default) {
54
+ // `build:internal` is run on EAS workers and the repo may have been changed
55
+ // by pre-install hooks or other scripts. We don't want to require committing changes
56
+ // to continue the build.
57
+ vcsClient.requireCommit = false;
58
+ }
55
59
  const submissionProfile = await eas_json_1.EasJsonUtils.getSubmitProfileAsync(eas_json_1.EasJsonAccessor.fromProjectPath(projectDir), flags.platform, flags.profile);
56
60
  const ctx = await (0, context_1.createSubmissionContextAsync)({
57
61
  platform: flags.platform,
@@ -11705,6 +11705,7 @@ export type UpdatePublishMutation = {
11705
11705
  __typename?: 'Fingerprint';
11706
11706
  id: string;
11707
11707
  hash: string;
11708
+ debugInfoUrl?: string | null;
11708
11709
  source?: {
11709
11710
  __typename?: 'FingerprintSource';
11710
11711
  type: FingerprintSourceType;
@@ -11790,6 +11791,7 @@ export type SetRolloutPercentageMutation = {
11790
11791
  __typename?: 'Fingerprint';
11791
11792
  id: string;
11792
11793
  hash: string;
11794
+ debugInfoUrl?: string | null;
11793
11795
  source?: {
11794
11796
  __typename?: 'FingerprintSource';
11795
11797
  type: FingerprintSourceType;
@@ -12260,6 +12262,7 @@ export type BranchesByAppQuery = {
12260
12262
  __typename?: 'Fingerprint';
12261
12263
  id: string;
12262
12264
  hash: string;
12265
+ debugInfoUrl?: string | null;
12263
12266
  source?: {
12264
12267
  __typename?: 'FingerprintSource';
12265
12268
  type: FingerprintSourceType;
@@ -12373,6 +12376,7 @@ export type ViewBranchesOnUpdateChannelQuery = {
12373
12376
  __typename?: 'Fingerprint';
12374
12377
  id: string;
12375
12378
  hash: string;
12379
+ debugInfoUrl?: string | null;
12376
12380
  source?: {
12377
12381
  __typename?: 'FingerprintSource';
12378
12382
  type: FingerprintSourceType;
@@ -12833,6 +12837,7 @@ export type ViewUpdateChannelOnAppQuery = {
12833
12837
  __typename?: 'Fingerprint';
12834
12838
  id: string;
12835
12839
  hash: string;
12840
+ debugInfoUrl?: string | null;
12836
12841
  source?: {
12837
12842
  __typename?: 'FingerprintSource';
12838
12843
  type: FingerprintSourceType;
@@ -12915,6 +12920,7 @@ export type ViewUpdateChannelsOnAppQuery = {
12915
12920
  __typename?: 'Fingerprint';
12916
12921
  id: string;
12917
12922
  hash: string;
12923
+ debugInfoUrl?: string | null;
12918
12924
  source?: {
12919
12925
  __typename?: 'FingerprintSource';
12920
12926
  type: FingerprintSourceType;
@@ -13434,6 +13440,7 @@ export type ViewUpdatesByGroupQuery = {
13434
13440
  __typename?: 'Fingerprint';
13435
13441
  id: string;
13436
13442
  hash: string;
13443
+ debugInfoUrl?: string | null;
13437
13444
  source?: {
13438
13445
  __typename?: 'FingerprintSource';
13439
13446
  type: FingerprintSourceType;
@@ -13505,6 +13512,7 @@ export type ViewUpdateGroupsOnBranchQuery = {
13505
13512
  __typename?: 'Fingerprint';
13506
13513
  id: string;
13507
13514
  hash: string;
13515
+ debugInfoUrl?: string | null;
13508
13516
  source?: {
13509
13517
  __typename?: 'FingerprintSource';
13510
13518
  type: FingerprintSourceType;
@@ -13575,6 +13583,7 @@ export type ViewUpdateGroupsOnAppQuery = {
13575
13583
  __typename?: 'Fingerprint';
13576
13584
  id: string;
13577
13585
  hash: string;
13586
+ debugInfoUrl?: string | null;
13578
13587
  source?: {
13579
13588
  __typename?: 'FingerprintSource';
13580
13589
  type: FingerprintSourceType;
@@ -13586,6 +13595,69 @@ export type ViewUpdateGroupsOnAppQuery = {
13586
13595
  };
13587
13596
  };
13588
13597
  };
13598
+ export type UpdateByIdQueryVariables = Exact<{
13599
+ updateId: Scalars['ID']['input'];
13600
+ }>;
13601
+ export type UpdateByIdQuery = {
13602
+ __typename?: 'RootQuery';
13603
+ updates: {
13604
+ __typename?: 'UpdateQuery';
13605
+ byId: {
13606
+ __typename?: 'Update';
13607
+ id: string;
13608
+ group: string;
13609
+ message?: string | null;
13610
+ createdAt: any;
13611
+ runtimeVersion: string;
13612
+ platform: string;
13613
+ manifestFragment: string;
13614
+ isRollBackToEmbedded: boolean;
13615
+ manifestPermalink: string;
13616
+ gitCommitHash?: string | null;
13617
+ rolloutPercentage?: number | null;
13618
+ actor?: {
13619
+ __typename: 'Robot';
13620
+ firstName?: string | null;
13621
+ id: string;
13622
+ } | {
13623
+ __typename: 'SSOUser';
13624
+ username: string;
13625
+ id: string;
13626
+ } | {
13627
+ __typename: 'User';
13628
+ username: string;
13629
+ id: string;
13630
+ } | null;
13631
+ branch: {
13632
+ __typename?: 'UpdateBranch';
13633
+ id: string;
13634
+ name: string;
13635
+ };
13636
+ codeSigningInfo?: {
13637
+ __typename?: 'CodeSigningInfo';
13638
+ keyid: string;
13639
+ sig: string;
13640
+ alg: string;
13641
+ } | null;
13642
+ rolloutControlUpdate?: {
13643
+ __typename?: 'Update';
13644
+ id: string;
13645
+ } | null;
13646
+ fingerprint?: {
13647
+ __typename?: 'Fingerprint';
13648
+ id: string;
13649
+ hash: string;
13650
+ debugInfoUrl?: string | null;
13651
+ source?: {
13652
+ __typename?: 'FingerprintSource';
13653
+ type: FingerprintSourceType;
13654
+ bucketKey: string;
13655
+ isDebugFingerprint?: boolean | null;
13656
+ } | null;
13657
+ } | null;
13658
+ };
13659
+ };
13660
+ };
13589
13661
  export type CurrentUserQueryVariables = Exact<{
13590
13662
  [key: string]: never;
13591
13663
  }>;
@@ -14311,6 +14383,7 @@ export type UpdateFragment = {
14311
14383
  __typename?: 'Fingerprint';
14312
14384
  id: string;
14313
14385
  hash: string;
14386
+ debugInfoUrl?: string | null;
14314
14387
  source?: {
14315
14388
  __typename?: 'FingerprintSource';
14316
14389
  type: FingerprintSourceType;
@@ -14368,6 +14441,7 @@ export type UpdateBranchFragment = {
14368
14441
  __typename?: 'Fingerprint';
14369
14442
  id: string;
14370
14443
  hash: string;
14444
+ debugInfoUrl?: string | null;
14371
14445
  source?: {
14372
14446
  __typename?: 'FingerprintSource';
14373
14447
  type: FingerprintSourceType;
@@ -1,7 +1,8 @@
1
1
  import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
2
- import { UpdateFragment, ViewUpdateGroupsOnAppQueryVariables, ViewUpdateGroupsOnBranchQueryVariables, ViewUpdatesByGroupQueryVariables } from '../generated';
2
+ import { UpdateByIdQueryVariables, UpdateFragment, ViewUpdateGroupsOnAppQueryVariables, ViewUpdateGroupsOnBranchQueryVariables, ViewUpdatesByGroupQueryVariables } from '../generated';
3
3
  export declare const UpdateQuery: {
4
4
  viewUpdateGroupAsync(graphqlClient: ExpoGraphqlClient, { groupId }: ViewUpdatesByGroupQueryVariables): Promise<UpdateFragment[]>;
5
5
  viewUpdateGroupsOnBranchAsync(graphqlClient: ExpoGraphqlClient, { limit, offset, appId, branchName, filter }: ViewUpdateGroupsOnBranchQueryVariables): Promise<UpdateFragment[][]>;
6
6
  viewUpdateGroupsOnAppAsync(graphqlClient: ExpoGraphqlClient, { limit, offset, appId, filter }: ViewUpdateGroupsOnAppQueryVariables): Promise<UpdateFragment[][]>;
7
+ viewByUpdateAsync(graphqlClient: ExpoGraphqlClient, { updateId }: UpdateByIdQueryVariables): Promise<UpdateFragment>;
7
8
  };
@@ -96,4 +96,20 @@ exports.UpdateQuery = {
96
96
  }
97
97
  return response.app.byId.updateGroups;
98
98
  },
99
+ async viewByUpdateAsync(graphqlClient, { updateId }) {
100
+ const data = await (0, client_1.withErrorHandlingAsync)(graphqlClient
101
+ .query((0, graphql_tag_1.default) `
102
+ query UpdateByIdQuery($updateId: ID!) {
103
+ updates {
104
+ byId(updateId: $updateId) {
105
+ id
106
+ ...UpdateFragment
107
+ }
108
+ }
109
+ }
110
+ ${(0, graphql_1.print)(Update_1.UpdateFragmentNode)}
111
+ `, { updateId }, { additionalTypenames: ['Update'] })
112
+ .toPromise());
113
+ return data.updates.byId;
114
+ },
99
115
  };