eas-cli 0.53.1 → 0.55.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.
Files changed (66) hide show
  1. package/README.md +78 -42
  2. package/build/build/android/build.js +2 -1
  3. package/build/build/build.d.ts +2 -2
  4. package/build/build/build.js +9 -3
  5. package/build/build/context.d.ts +2 -0
  6. package/build/build/createContext.d.ts +3 -1
  7. package/build/build/createContext.js +2 -1
  8. package/build/build/ios/build.js +2 -1
  9. package/build/build/runBuildAndSubmit.d.ts +2 -0
  10. package/build/build/runBuildAndSubmit.js +19 -4
  11. package/build/build/types.d.ts +4 -0
  12. package/build/build/types.js +6 -1
  13. package/build/build/utils/url.d.ts +1 -0
  14. package/build/build/utils/url.js +5 -1
  15. package/build/commands/build/index.d.ts +2 -1
  16. package/build/commands/build/index.js +9 -54
  17. package/build/commands/config.js +0 -2
  18. package/build/commands/metadata/pull.d.ts +8 -0
  19. package/build/commands/metadata/pull.js +59 -0
  20. package/build/commands/metadata/push.d.ts +8 -0
  21. package/build/commands/metadata/push.js +53 -0
  22. package/build/commands/submit.js +2 -1
  23. package/build/commands/update/index.d.ts +13 -0
  24. package/build/commands/update/index.js +88 -35
  25. package/build/env.d.ts +11 -0
  26. package/build/env.js +12 -0
  27. package/build/graphql/generated.d.ts +39 -12
  28. package/build/graphql/generated.js +9 -1
  29. package/build/graphql/mutations/BuildMutation.d.ts +3 -1
  30. package/build/graphql/mutations/BuildMutation.js +14 -2
  31. package/build/graphql/queries/UpdateQuery.d.ts +4 -1
  32. package/build/graphql/queries/UpdateQuery.js +8 -7
  33. package/build/graphql/queries/WebhookQuery.d.ts +1 -1
  34. package/build/metadata/apple/config/reader.d.ts +2 -1
  35. package/build/metadata/apple/config/reader.js +68 -10
  36. package/build/metadata/apple/config/writer.d.ts +3 -2
  37. package/build/metadata/apple/config/writer.js +64 -12
  38. package/build/metadata/apple/data.d.ts +2 -1
  39. package/build/metadata/apple/tasks/app-info.js +8 -6
  40. package/build/metadata/apple/tasks/app-review-detail.d.ts +14 -0
  41. package/build/metadata/apple/tasks/app-review-detail.js +49 -0
  42. package/build/metadata/apple/tasks/app-version.js +16 -12
  43. package/build/metadata/apple/tasks/index.js +2 -1
  44. package/build/metadata/apple/types.d.ts +9 -11
  45. package/build/metadata/context.js +7 -14
  46. package/build/metadata/download.js +9 -2
  47. package/build/metadata/errors.d.ts +7 -2
  48. package/build/metadata/errors.js +25 -6
  49. package/build/metadata/upload.d.ts +3 -1
  50. package/build/metadata/upload.js +17 -3
  51. package/build/metadata/utils/date.d.ts +1 -1
  52. package/build/project/android/applicationId.js +4 -0
  53. package/build/project/ensureProjectExists.js +4 -1
  54. package/build/project/publish.d.ts +6 -1
  55. package/build/project/publish.js +23 -5
  56. package/build/project/workflow.js +13 -11
  57. package/build/uploads.d.ts +6 -0
  58. package/build/uploads.js +15 -3
  59. package/build/utils/expodash/uniq.d.ts +1 -0
  60. package/build/{metadata/utils/array.js → utils/expodash/uniq.js} +2 -3
  61. package/build/utils/profiles.d.ts +3 -3
  62. package/build/utils/profiles.js +5 -93
  63. package/oclif.manifest.json +1 -1
  64. package/package.json +11 -6
  65. package/schema/metadata-0.json +988 -0
  66. package/build/metadata/utils/array.d.ts +0 -1
@@ -11,3 +11,7 @@ export declare enum BuildDistributionType {
11
11
  INTERNAL = "internal",
12
12
  SIMULATOR = "simulator"
13
13
  }
14
+ export declare enum UserInputResourceClass {
15
+ DEFAULT = "default",
16
+ LARGE = "large"
17
+ }
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.BuildDistributionType = exports.BuildStatus = void 0;
3
+ exports.UserInputResourceClass = exports.BuildDistributionType = exports.BuildStatus = void 0;
4
4
  var BuildStatus;
5
5
  (function (BuildStatus) {
6
6
  BuildStatus["NEW"] = "new";
@@ -16,3 +16,8 @@ var BuildDistributionType;
16
16
  BuildDistributionType["INTERNAL"] = "internal";
17
17
  BuildDistributionType["SIMULATOR"] = "simulator";
18
18
  })(BuildDistributionType = exports.BuildDistributionType || (exports.BuildDistributionType = {}));
19
+ var UserInputResourceClass;
20
+ (function (UserInputResourceClass) {
21
+ UserInputResourceClass["DEFAULT"] = "default";
22
+ UserInputResourceClass["LARGE"] = "large";
23
+ })(UserInputResourceClass = exports.UserInputResourceClass || (exports.UserInputResourceClass = {}));
@@ -3,3 +3,4 @@ export declare function getProjectDashboardUrl(accountName: string, projectName:
3
3
  export declare function getBuildLogsUrl(build: BuildFragment): string;
4
4
  export declare function getArtifactUrl(artifactId: string): string;
5
5
  export declare function getInternalDistributionInstallUrl(build: BuildFragment): string;
6
+ export declare function getUpdateGroupUrl(accountName: string, projectName: string, updateGroupId: string): string;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getInternalDistributionInstallUrl = exports.getArtifactUrl = exports.getBuildLogsUrl = exports.getProjectDashboardUrl = void 0;
3
+ exports.getUpdateGroupUrl = exports.getInternalDistributionInstallUrl = exports.getArtifactUrl = exports.getBuildLogsUrl = exports.getProjectDashboardUrl = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const assert_1 = tslib_1.__importDefault(require("assert"));
6
6
  const api_1 = require("../../api");
@@ -30,3 +30,7 @@ function getInternalDistributionInstallUrl(build) {
30
30
  return build.artifacts.buildUrl;
31
31
  }
32
32
  exports.getInternalDistributionInstallUrl = getInternalDistributionInstallUrl;
33
+ function getUpdateGroupUrl(accountName, projectName, updateGroupId) {
34
+ return new URL(`/accounts/${encodeURIComponent(accountName)}/projects/${encodeURIComponent(projectName)}/updates/${encodeURIComponent(updateGroupId)}`, (0, api_1.getExpoWebsiteBaseUrl)()).toString();
35
+ }
36
+ exports.getUpdateGroupUrl = getUpdateGroupUrl;
@@ -1,3 +1,4 @@
1
+ import { UserInputResourceClass } from '../../build/types';
1
2
  import EasCommand from '../../commandUtils/EasCommand';
2
3
  export default class Build extends EasCommand {
3
4
  static description: string;
@@ -14,8 +15,8 @@ export default class Build extends EasCommand {
14
15
  'clear-cache': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
15
16
  'auto-submit': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
16
17
  'auto-submit-with-profile': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined>;
18
+ 'resource-class': import("@oclif/core/lib/interfaces").OptionFlag<UserInputResourceClass>;
17
19
  };
18
20
  runAsync(): Promise<void>;
19
21
  private sanitizeFlagsAsync;
20
22
  }
21
- export declare function handleDeprecatedEasJsonAsync(projectDir: string, nonInteractive: boolean): Promise<void>;
@@ -1,24 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.handleDeprecatedEasJsonAsync = void 0;
4
3
  const tslib_1 = require("tslib");
5
- const eas_json_1 = require("@expo/eas-json");
6
4
  const core_1 = require("@oclif/core");
7
- const chalk_1 = tslib_1.__importDefault(require("chalk"));
8
- const figures_1 = tslib_1.__importDefault(require("figures"));
9
- const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
10
5
  const path_1 = tslib_1.__importDefault(require("path"));
11
6
  const runBuildAndSubmit_1 = require("../../build/runBuildAndSubmit");
12
- const repository_1 = require("../../build/utils/repository");
7
+ const types_1 = require("../../build/types");
13
8
  const EasCommand_1 = tslib_1.__importDefault(require("../../commandUtils/EasCommand"));
14
- const log_1 = tslib_1.__importStar(require("../../log"));
9
+ const log_1 = tslib_1.__importDefault(require("../../log"));
15
10
  const platform_1 = require("../../platform");
16
11
  const projectUtils_1 = require("../../project/projectUtils");
17
- const prompts_1 = require("../../prompts");
18
- const easCli_1 = require("../../utils/easCli");
19
12
  const json_1 = require("../../utils/json");
20
- const vcs_1 = require("../../vcs");
21
- const git_1 = tslib_1.__importDefault(require("../../vcs/clients/git"));
22
13
  class Build extends EasCommand_1.default {
23
14
  async runAsync() {
24
15
  const { flags: rawFlags } = await this.parse(Build);
@@ -27,11 +18,10 @@ class Build extends EasCommand_1.default {
27
18
  }
28
19
  const flags = await this.sanitizeFlagsAsync(rawFlags);
29
20
  const projectDir = await (0, projectUtils_1.findProjectRootAsync)();
30
- await handleDeprecatedEasJsonAsync(projectDir, flags.nonInteractive);
31
21
  await (0, runBuildAndSubmit_1.runBuildAndSubmitAsync)(projectDir, flags);
32
22
  }
33
23
  async sanitizeFlagsAsync(flags) {
34
- var _a;
24
+ var _a, _b;
35
25
  const nonInteractive = flags['non-interactive'];
36
26
  if (!flags.local && flags.output) {
37
27
  core_1.Errors.error('--output is allowed only for local builds', { exit: 1 });
@@ -84,6 +74,7 @@ class Build extends EasCommand_1.default {
84
74
  json: flags['json'],
85
75
  autoSubmit: flags['auto-submit'] || flags['auto-submit-with-profile'] !== undefined,
86
76
  submitProfile: (_a = flags['auto-submit-with-profile']) !== null && _a !== void 0 ? _a : profile,
77
+ userInputResourceClass: (_b = flags['resource-class']) !== null && _b !== void 0 ? _b : types_1.UserInputResourceClass.DEFAULT,
87
78
  };
88
79
  }
89
80
  }
@@ -140,45 +131,9 @@ Build.flags = {
140
131
  helpValue: 'PROFILE_NAME',
141
132
  exclusive: ['auto-submit'],
142
133
  }),
134
+ 'resource-class': core_1.Flags.enum({
135
+ options: Object.values(types_1.UserInputResourceClass),
136
+ hidden: true,
137
+ description: 'The instance type that will be used to run this build [experimental]',
138
+ }),
143
139
  };
144
- async function handleDeprecatedEasJsonAsync(projectDir, nonInteractive) {
145
- const easJsonPath = eas_json_1.EasJsonReader.formatEasJsonPath(projectDir);
146
- if (!(await fs_extra_1.default.pathExists(easJsonPath))) {
147
- return;
148
- }
149
- const easJsonReader = new eas_json_1.EasJsonReader(projectDir);
150
- const rawEasJson = await easJsonReader.readAsync();
151
- if (rawEasJson === null || rawEasJson === void 0 ? void 0 : rawEasJson.cli) {
152
- return;
153
- }
154
- if (nonInteractive) {
155
- log_1.default.warn(`${figures_1.default.warning} Action required: the default behavior of EAS CLI has changed and your eas.json must be updated to remove ambiguity around which Git integration workflow to use. Refer to ${(0, log_1.link)('https://expo.fyi/eas-vcs-workflow')} for more information.`);
156
- log_1.default.warn('This warning will become an error in an upcoming EAS CLI release. For now, we will proceed with the old default behavior to avoid disruption of your builds.');
157
- (0, vcs_1.setVcsClient)(new git_1.default());
158
- return;
159
- }
160
- log_1.default.log(`${chalk_1.default.bold('eas-cli@>=0.34.0 no longer requires that you commit changes to Git before starting a build.')} ${(0, log_1.learnMore)('https://expo.fyi/eas-vcs-workflow')}`);
161
- log_1.default.log(`If you want to continue using the Git integration, you can opt in with ${chalk_1.default.bold('cli.requireCommit')} in ${chalk_1.default.bold('eas.json')} or with the following prompt.`);
162
- log_1.default.newLine();
163
- const mode = await (0, prompts_1.selectAsync)('Select your preferred Git integration', [
164
- { title: 'Require changes to be committed in Git (old default)', value: 'requireCommit' },
165
- { title: 'Allow builds with dirty Git working tree (new default)', value: 'noCommit' },
166
- ]);
167
- if (mode === 'requireCommit') {
168
- (0, vcs_1.setVcsClient)(new git_1.default());
169
- await (0, repository_1.ensureRepoIsCleanAsync)(nonInteractive);
170
- }
171
- rawEasJson.cli =
172
- mode === 'requireCommit'
173
- ? { version: `>= ${easCli_1.easCliVersion}`, requireCommit: true }
174
- : { version: `>= ${easCli_1.easCliVersion}` };
175
- await fs_extra_1.default.writeJSON(easJsonPath, rawEasJson, { spaces: 2 });
176
- log_1.default.withTick('Updated eas.json');
177
- if (mode === 'requireCommit') {
178
- await (0, vcs_1.getVcsClient)().trackFileAsync(easJsonPath);
179
- await (0, repository_1.reviewAndCommitChangesAsync)('Set cli.requireCommit to true in eas.json', {
180
- nonInteractive,
181
- });
182
- }
183
- }
184
- exports.handleDeprecatedEasJsonAsync = handleDeprecatedEasJsonAsync;
@@ -13,7 +13,6 @@ const platform_1 = require("../platform");
13
13
  const expoConfig_1 = require("../project/expoConfig");
14
14
  const projectUtils_1 = require("../project/projectUtils");
15
15
  const prompts_1 = require("../prompts");
16
- const build_1 = require("./build");
17
16
  class Config extends EasCommand_1.default {
18
17
  constructor() {
19
18
  super(...arguments);
@@ -23,7 +22,6 @@ class Config extends EasCommand_1.default {
23
22
  const { flags } = await this.parse(Config);
24
23
  const { platform: maybePlatform, profile: maybeProfile } = flags;
25
24
  const projectDir = await (0, projectUtils_1.findProjectRootAsync)();
26
- await (0, build_1.handleDeprecatedEasJsonAsync)(projectDir, false);
27
25
  const reader = new eas_json_1.EasJsonReader(projectDir);
28
26
  const profileName = maybeProfile !== null && maybeProfile !== void 0 ? maybeProfile : (await (0, prompts_1.selectAsync)('Select build profile', (await reader.getBuildProfileNamesAsync()).map(profileName => ({
29
27
  title: profileName,
@@ -0,0 +1,8 @@
1
+ import EasCommand from '../../commandUtils/EasCommand';
2
+ export default class MetadataPull extends EasCommand {
3
+ static description: string;
4
+ static flags: {
5
+ profile: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined>;
6
+ };
7
+ runAsync(): Promise<void>;
8
+ }
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const config_1 = require("@expo/config");
5
+ const core_1 = require("@oclif/core");
6
+ const chalk_1 = tslib_1.__importDefault(require("chalk"));
7
+ const path_1 = tslib_1.__importDefault(require("path"));
8
+ const configure_1 = require("../../build/configure");
9
+ const EasCommand_1 = tslib_1.__importDefault(require("../../commandUtils/EasCommand"));
10
+ const context_1 = require("../../credentials/context");
11
+ const log_1 = tslib_1.__importStar(require("../../log"));
12
+ const context_2 = require("../../metadata/context");
13
+ const download_1 = require("../../metadata/download");
14
+ const errors_1 = require("../../metadata/errors");
15
+ const projectUtils_1 = require("../../project/projectUtils");
16
+ const actions_1 = require("../../user/actions");
17
+ class MetadataPull extends EasCommand_1.default {
18
+ async runAsync() {
19
+ log_1.default.warn('EAS Metadata is in beta and subject to breaking changes.');
20
+ const { flags } = await this.parse(MetadataPull);
21
+ const projectDir = await (0, projectUtils_1.findProjectRootAsync)();
22
+ const { exp } = (0, config_1.getConfig)(projectDir, { skipSDKVersionRequirement: true });
23
+ await (0, projectUtils_1.getProjectIdAsync)(exp);
24
+ await (0, configure_1.ensureProjectConfiguredAsync)({ projectDir, nonInteractive: false });
25
+ const credentialsCtx = new context_1.CredentialsContext({
26
+ exp,
27
+ projectDir,
28
+ user: await (0, actions_1.ensureLoggedInAsync)(),
29
+ nonInteractive: false,
30
+ });
31
+ const metadataCtx = await (0, context_2.createMetadataContextAsync)({
32
+ credentialsCtx,
33
+ projectDir,
34
+ exp,
35
+ profileName: flags.profile,
36
+ });
37
+ try {
38
+ const filePath = await (0, download_1.downloadMetadataAsync)(metadataCtx);
39
+ const relativePath = path_1.default.relative(process.cwd(), filePath);
40
+ log_1.default.addNewLineIfNone();
41
+ log_1.default.log(`🎉 Your store configuration is ready.
42
+
43
+ - Update the ${chalk_1.default.bold(relativePath)} file to prepare the app information.
44
+ - Run ${chalk_1.default.bold('eas submit')} or manually upload a new app version to the app stores.
45
+ - Once the app is uploaded, run ${chalk_1.default.bold('eas metadata:push')} to sync the store configuration.
46
+ - ${(0, log_1.learnMore)('https://docs.expo.dev/eas-metadata/introduction/')}`);
47
+ }
48
+ catch (error) {
49
+ (0, errors_1.handleMetadataError)(error);
50
+ }
51
+ }
52
+ }
53
+ exports.default = MetadataPull;
54
+ MetadataPull.description = 'generate the local store configuration from the app stores';
55
+ MetadataPull.flags = {
56
+ profile: core_1.Flags.string({
57
+ description: 'Name of the submit profile from eas.json. Defaults to "production" if defined in eas.json.',
58
+ }),
59
+ };
@@ -0,0 +1,8 @@
1
+ import EasCommand from '../../commandUtils/EasCommand';
2
+ export default class MetadataPush extends EasCommand {
3
+ static description: string;
4
+ static flags: {
5
+ profile: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined>;
6
+ };
7
+ runAsync(): Promise<void>;
8
+ }
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const config_1 = require("@expo/config");
5
+ const core_1 = require("@oclif/core");
6
+ const configure_1 = require("../../build/configure");
7
+ const EasCommand_1 = tslib_1.__importDefault(require("../../commandUtils/EasCommand"));
8
+ const context_1 = require("../../credentials/context");
9
+ const log_1 = tslib_1.__importStar(require("../../log"));
10
+ const context_2 = require("../../metadata/context");
11
+ const errors_1 = require("../../metadata/errors");
12
+ const upload_1 = require("../../metadata/upload");
13
+ const projectUtils_1 = require("../../project/projectUtils");
14
+ const actions_1 = require("../../user/actions");
15
+ class MetadataPush extends EasCommand_1.default {
16
+ async runAsync() {
17
+ log_1.default.warn('EAS Metadata is in beta and subject to breaking changes.');
18
+ const { flags } = await this.parse(MetadataPush);
19
+ const projectDir = await (0, projectUtils_1.findProjectRootAsync)();
20
+ const { exp } = (0, config_1.getConfig)(projectDir, { skipSDKVersionRequirement: true });
21
+ await (0, projectUtils_1.getProjectIdAsync)(exp);
22
+ await (0, configure_1.ensureProjectConfiguredAsync)({ projectDir, nonInteractive: false });
23
+ const credentialsCtx = new context_1.CredentialsContext({
24
+ exp,
25
+ projectDir,
26
+ user: await (0, actions_1.ensureLoggedInAsync)(),
27
+ nonInteractive: false,
28
+ });
29
+ const metadataCtx = await (0, context_2.createMetadataContextAsync)({
30
+ credentialsCtx,
31
+ projectDir,
32
+ exp,
33
+ profileName: flags.profile,
34
+ });
35
+ try {
36
+ const { appleLink } = await (0, upload_1.uploadMetadataAsync)(metadataCtx);
37
+ log_1.default.addNewLineIfNone();
38
+ log_1.default.log(`🎉 Store configuration is synced with the app stores.
39
+
40
+ ${(0, log_1.learnMore)(appleLink, { learnMoreMessage: 'See the changes in App Store Connect' })}`);
41
+ }
42
+ catch (error) {
43
+ (0, errors_1.handleMetadataError)(error);
44
+ }
45
+ }
46
+ }
47
+ exports.default = MetadataPush;
48
+ MetadataPush.description = 'sync the local store configuration to the app stores';
49
+ MetadataPush.flags = {
50
+ profile: core_1.Flags.string({
51
+ description: 'Name of the submit profile from eas.json. Defaults to "production" if defined in eas.json.',
52
+ }),
53
+ };
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
+ const eas_json_1 = require("@expo/eas-json");
4
5
  const core_1 = require("@oclif/core");
5
6
  const chalk_1 = tslib_1.__importDefault(require("chalk"));
6
7
  const EasCommand_1 = tslib_1.__importDefault(require("../commandUtils/EasCommand"));
@@ -23,7 +24,7 @@ class Submit extends EasCommand_1.default {
23
24
  const platforms = (0, platform_1.toPlatforms)(flags.requestedPlatform);
24
25
  const submissionProfiles = await (0, profiles_1.getProfilesAsync)({
25
26
  type: 'submit',
26
- projectDir,
27
+ easJsonReader: new eas_json_1.EasJsonReader(projectDir),
27
28
  platforms,
28
29
  profileName: flags.profile,
29
30
  });
@@ -1,6 +1,17 @@
1
1
  import EasCommand from '../../commandUtils/EasCommand';
2
+ import { ViewBranchUpdatesQuery } from '../../graphql/generated';
2
3
  import { PublishPlatform } from '../../project/publish';
3
4
  export declare const defaultPublishPlatforms: PublishPlatform[];
5
+ export declare type PublishPlatformFlag = PublishPlatform | 'all';
6
+ export declare function ensureBranchExistsAsync({ appId, name: branchName, limit, offset, }: {
7
+ appId: string;
8
+ name: string;
9
+ limit?: number;
10
+ offset?: number;
11
+ }): Promise<{
12
+ id: string;
13
+ updates: Exclude<Exclude<ViewBranchUpdatesQuery['app'], null | undefined>['byId']['updateBranchByName'], null | undefined>['updates'];
14
+ }>;
4
15
  export default class UpdatePublish extends EasCommand {
5
16
  static description: string;
6
17
  static flags: {
@@ -18,3 +29,5 @@ export default class UpdatePublish extends EasCommand {
18
29
  };
19
30
  runAsync(): Promise<void>;
20
31
  }
32
+ export declare function getUpdatesToRepublishInteractiveAsync(projectId: string, branchName: string, platformFlag: string, pageSize: number, offset?: number, cumulativeUpdates?: Exclude<Exclude<ViewBranchUpdatesQuery['app'], null | undefined>['byId']['updateBranchByName'], null | undefined>['updates']): Promise<Exclude<Exclude<ViewBranchUpdatesQuery['app'], null | undefined>['byId']['updateBranchByName'], null | undefined>['updates']>;
33
+ export declare const truncatePublishUpdateMessage: (originalMessage: string) => string;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.defaultPublishPlatforms = void 0;
3
+ exports.truncatePublishUpdateMessage = exports.getUpdatesToRepublishInteractiveAsync = exports.ensureBranchExistsAsync = exports.defaultPublishPlatforms = 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");
@@ -11,12 +11,13 @@ const dateformat_1 = tslib_1.__importDefault(require("dateformat"));
11
11
  const graphql_tag_1 = tslib_1.__importDefault(require("graphql-tag"));
12
12
  const nullthrows_1 = tslib_1.__importDefault(require("nullthrows"));
13
13
  const api_1 = require("../../api");
14
+ const url_1 = require("../../build/utils/url");
14
15
  const EasCommand_1 = tslib_1.__importDefault(require("../../commandUtils/EasCommand"));
15
16
  const fetch_1 = tslib_1.__importDefault(require("../../fetch"));
16
17
  const client_1 = require("../../graphql/client");
17
18
  const PublishMutation_1 = require("../../graphql/mutations/PublishMutation");
18
19
  const UpdateQuery_1 = require("../../graphql/queries/UpdateQuery");
19
- const log_1 = tslib_1.__importDefault(require("../../log"));
20
+ const log_1 = tslib_1.__importStar(require("../../log"));
20
21
  const ora_1 = require("../../ora");
21
22
  const expoConfig_1 = require("../../project/expoConfig");
22
23
  const projectUtils_1 = require("../../project/projectUtils");
@@ -24,6 +25,7 @@ const publish_1 = require("../../project/publish");
24
25
  const workflow_1 = require("../../project/workflow");
25
26
  const prompts_1 = require("../../prompts");
26
27
  const utils_1 = require("../../update/utils");
28
+ const actions_1 = require("../../user/actions");
27
29
  const code_signing_1 = require("../../utils/code-signing");
28
30
  const uniqBy_1 = tslib_1.__importDefault(require("../../utils/expodash/uniqBy"));
29
31
  const formatFields_1 = tslib_1.__importDefault(require("../../utils/formatFields"));
@@ -70,10 +72,12 @@ async function ensureChannelExistsAsync({ appId, branchId, channelName, }) {
70
72
  }
71
73
  }
72
74
  }
73
- async function ensureBranchExistsAsync({ appId, name: branchName, }) {
75
+ async function ensureBranchExistsAsync({ appId, name: branchName, limit, offset, }) {
74
76
  const { app } = await UpdateQuery_1.UpdateQuery.viewBranchAsync({
75
77
  appId,
76
78
  name: branchName,
79
+ limit,
80
+ offset,
77
81
  });
78
82
  const updateBranch = app === null || app === void 0 ? void 0 : app.byId.updateBranchByName;
79
83
  if (updateBranch) {
@@ -86,6 +90,7 @@ async function ensureBranchExistsAsync({ appId, name: branchName, }) {
86
90
  await ensureChannelExistsAsync({ appId, branchId: newUpdateBranch.id, channelName: branchName });
87
91
  return { id: newUpdateBranch.id, updates: [] };
88
92
  }
93
+ exports.ensureBranchExistsAsync = ensureBranchExistsAsync;
89
94
  class UpdatePublish extends EasCommand_1.default {
90
95
  async runAsync() {
91
96
  var _a, _b, _c;
@@ -159,12 +164,9 @@ class UpdatePublish extends EasCommand_1.default {
159
164
  }
160
165
  (0, assert_1.default)(branchName, 'Branch name must be specified.');
161
166
  }
162
- const { id: branchId, updates } = await ensureBranchExistsAsync({
163
- appId: projectId,
164
- name: branchName,
165
- });
166
167
  let unsortedUpdateInfoGroups = {};
167
168
  let oldMessage, oldRuntimeVersion;
169
+ let uploadedAssetCount = 0;
168
170
  if (republish) {
169
171
  // If we are republishing, we don't need to worry about building the bundle or uploading the assets.
170
172
  // Instead we get the `updateInfoGroup` from the update we wish to republish.
@@ -180,26 +182,13 @@ class UpdatePublish extends EasCommand_1.default {
180
182
  if (jsonFlag) {
181
183
  throw new Error('You must specify the update group to republish.');
182
184
  }
183
- const updateGroups = (0, uniqBy_1.default)(updates, u => u.group)
184
- .filter(update => {
185
- // Only show groups that have updates on the specified platform(s).
186
- return platformFlag === 'all' || update.platform === platformFlag;
187
- })
188
- .map(update => ({
189
- title: formatUpdateTitle(update),
190
- value: update.group,
191
- }));
192
- if (updateGroups.length === 0) {
193
- throw new Error(`There are no updates on branch "${branchName}" published on the platform(s) ${platformFlag}. Did you mean to publish a new update instead?`);
194
- }
195
- const selectedUpdateGroup = await (0, prompts_1.selectAsync)('which update would you like to republish?', updateGroups);
196
- updatesToRepublish = updates.filter(update => update.group === selectedUpdateGroup);
185
+ updatesToRepublish = await getUpdatesToRepublishInteractiveAsync(projectId, branchName, platformFlag, 50);
197
186
  }
198
187
  const updatesToRepublishFilteredByPlatform = updatesToRepublish.filter(
199
188
  // Only republish to the specified platforms
200
189
  update => platformFlag === 'all' || update.platform === platformFlag);
201
190
  if (updatesToRepublishFilteredByPlatform.length === 0) {
202
- throw new Error(`There are no updates on branch "${branchName}" published on the platform(s) "${platformFlag}" with group ID "${group ? group : updatesToRepublish[0].group}". Did you mean to publish a new update instead?`);
191
+ throw new Error(`There are no updates on branch "${branchName}" published for the platform(s) "${platformFlag}" with group ID "${group ? group : updatesToRepublish[0].group}". Did you mean to publish a new update instead?`);
203
192
  }
204
193
  let publicationPlatformMessage;
205
194
  if (platformFlag === 'all') {
@@ -276,21 +265,31 @@ class UpdatePublish extends EasCommand_1.default {
276
265
  try {
277
266
  const platforms = platformFlag === 'all' ? exports.defaultPublishPlatforms : [platformFlag];
278
267
  const assets = await (0, publish_1.collectAssetsAsync)({ inputDir: inputDir, platforms });
279
- await (0, publish_1.uploadAssetsAsync)(assets);
268
+ const { uniqueUploadedAssetCount } = await (0, publish_1.uploadAssetsAsync)(assets, spinnerText => (assetSpinner.text = `Uploading assets... ${spinnerText}`));
269
+ uploadedAssetCount = uniqueUploadedAssetCount;
280
270
  unsortedUpdateInfoGroups = await (0, publish_1.buildUnsortedUpdateInfoGroupAsync)(assets, exp);
281
- assetSpinner.succeed('Uploaded assets!');
271
+ const uploadAssetSuccessMessage = uploadedAssetCount
272
+ ? `Uploaded ${uploadedAssetCount} ${uploadedAssetCount === 1 ? 'asset' : 'assets'}!`
273
+ : `Uploading assets skipped -- no new assets found!`;
274
+ assetSpinner.succeed(uploadAssetSuccessMessage);
282
275
  }
283
276
  catch (e) {
284
277
  assetSpinner.fail('Failed to upload assets');
285
278
  throw e;
286
279
  }
287
280
  }
281
+ const truncatedMessage = (0, exports.truncatePublishUpdateMessage)(message);
288
282
  const runtimeToPlatformMapping = {};
289
283
  for (const runtime of new Set(Object.values(runtimeVersions))) {
290
284
  runtimeToPlatformMapping[runtime] = Object.entries(runtimeVersions)
291
285
  .filter(pair => pair[1] === runtime)
292
286
  .map(pair => pair[0]);
293
287
  }
288
+ const { id: branchId } = await ensureBranchExistsAsync({
289
+ appId: projectId,
290
+ name: branchName,
291
+ limit: 0,
292
+ });
294
293
  // Sort the updates into different groups based on their platform specific runtime versions
295
294
  const updateGroups = Object.entries(runtimeToPlatformMapping).map(([runtime, platforms]) => {
296
295
  const localUpdateInfoGroup = Object.fromEntries(platforms.map(platform => [
@@ -304,7 +303,7 @@ class UpdatePublish extends EasCommand_1.default {
304
303
  branchId,
305
304
  updateInfoGroup: localUpdateInfoGroup,
306
305
  runtimeVersion: republish ? oldRuntimeVersion : runtime,
307
- message,
306
+ message: truncatedMessage,
308
307
  awaitingCodeSigningInfo: !!codeSigningInfo,
309
308
  };
310
309
  });
@@ -355,19 +354,29 @@ class UpdatePublish extends EasCommand_1.default {
355
354
  }
356
355
  log_1.default.addNewLineIfNone();
357
356
  for (const runtime of new Set(Object.values(runtimeVersions))) {
358
- const platforms = newUpdates
359
- .filter(update => update.runtimeVersion === runtime)
360
- .map(update => update.platform);
361
- const newUpdate = newUpdates.find(update => update.runtimeVersion === runtime);
362
- if (!newUpdate) {
357
+ const newUpdatesForRuntimeVersion = newUpdates.filter(update => update.runtimeVersion === runtime);
358
+ if (!newUpdatesForRuntimeVersion.length) {
363
359
  throw new Error(`Publish response is missing updates with runtime ${runtime}.`);
364
360
  }
361
+ const platforms = newUpdatesForRuntimeVersion.map(update => update.platform);
362
+ const newAndroidUpdate = newUpdatesForRuntimeVersion.find(update => update.platform === 'android');
363
+ const newIosUpdate = newUpdatesForRuntimeVersion.find(update => update.platform === 'ios');
364
+ const updateGroupId = newUpdatesForRuntimeVersion[0].group;
365
+ const projectName = exp.slug;
366
+ const accountName = (0, projectUtils_1.getProjectAccountName)(exp, await (0, actions_1.ensureLoggedInAsync)());
367
+ const updateGroupUrl = (0, url_1.getUpdateGroupUrl)(accountName, projectName, updateGroupId);
368
+ const updateGroupLink = (0, log_1.link)(updateGroupUrl, { dim: false });
365
369
  log_1.default.log((0, formatFields_1.default)([
366
- { label: 'branch', value: branchName },
367
- { label: 'runtime version', value: runtime },
368
- { label: 'platform', value: platforms.join(', ') },
369
- { label: 'update group ID', value: newUpdate.group },
370
- { label: 'message', value: message },
370
+ { label: 'Branch', value: branchName },
371
+ { label: 'Runtime version', value: runtime },
372
+ { label: 'Platform', value: platforms.join(', ') },
373
+ { label: 'Update group ID', value: updateGroupId },
374
+ ...(newAndroidUpdate
375
+ ? [{ label: 'Android update ID', value: newAndroidUpdate.id }]
376
+ : []),
377
+ ...(newIosUpdate ? [{ label: 'iOS update ID', value: newIosUpdate.id }] : []),
378
+ { label: 'Message', value: truncatedMessage },
379
+ { label: 'Website link', value: updateGroupLink },
371
380
  ]));
372
381
  log_1.default.addNewLineIfNone();
373
382
  }
@@ -425,6 +434,42 @@ UpdatePublish.flags = {
425
434
  description: 'Run command in non-interactive mode',
426
435
  }),
427
436
  };
437
+ async function getUpdatesToRepublishInteractiveAsync(projectId, branchName, platformFlag, pageSize, offset = 0, cumulativeUpdates = []) {
438
+ const fetchMoreValue = '_fetchMore';
439
+ const { updates } = await ensureBranchExistsAsync({
440
+ appId: projectId,
441
+ name: branchName,
442
+ limit: pageSize + 1,
443
+ offset,
444
+ });
445
+ cumulativeUpdates = [
446
+ ...cumulativeUpdates,
447
+ // drop that extra item used for pagination from our render logic
448
+ ...updates.slice(0, updates.length - 1),
449
+ ];
450
+ const cumulativeUpdatesForTargetPlatforms = platformFlag === 'all'
451
+ ? cumulativeUpdates
452
+ : cumulativeUpdates.filter(update => {
453
+ // Only show groups that have updates on the specified platform(s).
454
+ return update.platform === platformFlag;
455
+ });
456
+ const updateGroups = (0, uniqBy_1.default)(cumulativeUpdatesForTargetPlatforms, u => u.group).map(update => ({
457
+ title: formatUpdateTitle(update),
458
+ value: update.group,
459
+ }));
460
+ if (!updateGroups.length) {
461
+ throw new Error(`There are no updates on branch "${branchName}" published for the platform(s) ${platformFlag}. Did you mean to publish a new update instead?`);
462
+ }
463
+ if (updates.length > pageSize) {
464
+ updateGroups.push({ title: 'Next page...', value: fetchMoreValue });
465
+ }
466
+ const selectedUpdateGroup = await (0, prompts_1.selectAsync)('Which update would you like to republish?', updateGroups);
467
+ if (selectedUpdateGroup === fetchMoreValue) {
468
+ return await getUpdatesToRepublishInteractiveAsync(projectId, branchName, platformFlag, pageSize, offset + pageSize, cumulativeUpdates);
469
+ }
470
+ return cumulativeUpdates.filter(update => update.group === selectedUpdateGroup);
471
+ }
472
+ exports.getUpdatesToRepublishInteractiveAsync = getUpdatesToRepublishInteractiveAsync;
428
473
  async function getRuntimeVersionObjectAsync(exp, platformFlag, projectDir) {
429
474
  var _a, _b;
430
475
  const platforms = (platformFlag === 'all' ? ['android', 'ios'] : [platformFlag]);
@@ -469,3 +514,11 @@ async function checkEASUpdateURLIsSetAsync(exp) {
469
514
  throw new Error(`The update URL is incorrectly configured for EAS Update. Please set updates.url to ${expectedURL} in your app.json.`);
470
515
  }
471
516
  }
517
+ const truncatePublishUpdateMessage = (originalMessage) => {
518
+ if (originalMessage.length > 1024) {
519
+ log_1.default.warn('Update message exceeds the allowed 1024 character limit. Truncating message...');
520
+ return originalMessage.substring(0, 1021) + '...';
521
+ }
522
+ return originalMessage;
523
+ };
524
+ exports.truncatePublishUpdateMessage = truncatePublishUpdateMessage;
package/build/env.d.ts ADDED
@@ -0,0 +1,11 @@
1
+ declare const _default: {
2
+ /**
3
+ * Dangerous overrides, use only if you know what you are doing
4
+ */
5
+ /**
6
+ * Overrides applicationId from Android project, setting this option will also
7
+ * ignore failures when parsing build.gradle.
8
+ */
9
+ overrideAndroidApplicationId: string | undefined;
10
+ };
11
+ export default _default;
package/build/env.js ADDED
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = {
4
+ /**
5
+ * Dangerous overrides, use only if you know what you are doing
6
+ */
7
+ /**
8
+ * Overrides applicationId from Android project, setting this option will also
9
+ * ignore failures when parsing build.gradle.
10
+ */
11
+ overrideAndroidApplicationId: process.env.EAS_DANGEROUS_OVERRIDE_ANDROID_APPLICATION_ID,
12
+ };