eas-cli 2.9.0 → 3.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.
- package/README.md +78 -54
- package/build/commands/build/run.js +2 -2
- package/build/commands/update/index.js +64 -133
- package/build/commands/update/republish.d.ts +36 -0
- package/build/commands/update/republish.js +218 -0
- package/build/graphql/generated.d.ts +63 -0
- package/build/graphql/types/Update.js +6 -0
- package/build/run/android/emulator.js +3 -3
- package/oclif.manifest.json +1 -1
- package/package.json +3 -3
|
@@ -19,7 +19,6 @@ const pagination_1 = require("../../commandUtils/pagination");
|
|
|
19
19
|
const fetch_1 = tslib_1.__importDefault(require("../../fetch"));
|
|
20
20
|
const generated_1 = require("../../graphql/generated");
|
|
21
21
|
const PublishMutation_1 = require("../../graphql/mutations/PublishMutation");
|
|
22
|
-
const UpdateQuery_1 = require("../../graphql/queries/UpdateQuery");
|
|
23
22
|
const log_1 = tslib_1.__importStar(require("../../log"));
|
|
24
23
|
const ora_1 = require("../../ora");
|
|
25
24
|
const platform_1 = require("../../platform");
|
|
@@ -28,7 +27,6 @@ const publish_1 = require("../../project/publish");
|
|
|
28
27
|
const workflow_1 = require("../../project/workflow");
|
|
29
28
|
const prompts_1 = require("../../prompts");
|
|
30
29
|
const configure_1 = require("../../update/configure");
|
|
31
|
-
const queries_3 = require("../../update/queries");
|
|
32
30
|
const utils_2 = require("../../update/utils");
|
|
33
31
|
const code_signing_1 = require("../../utils/code-signing");
|
|
34
32
|
const uniqBy_1 = tslib_1.__importDefault(require("../../utils/expodash/uniqBy"));
|
|
@@ -53,10 +51,10 @@ function getRequestedPlatform(platform) {
|
|
|
53
51
|
}
|
|
54
52
|
class UpdatePublish extends EasCommand_1.default {
|
|
55
53
|
async runAsync() {
|
|
56
|
-
var _b, _c
|
|
54
|
+
var _b, _c;
|
|
57
55
|
const { flags: rawFlags } = await this.parse(UpdatePublish);
|
|
58
56
|
const paginatedQueryOptions = (0, pagination_1.getPaginatedQueryOptions)(rawFlags);
|
|
59
|
-
let { auto: autoFlag, platform: platformFlag, branchName, updateMessage,
|
|
57
|
+
let { auto: autoFlag, platform: platformFlag, branchName, updateMessage, inputDir, skipBundler, privateKeyPath, json: jsonFlag, nonInteractive, } = this.sanitizeFlags(rawFlags);
|
|
60
58
|
const { getDynamicProjectConfigAsync, loggedIn: { graphqlClient }, } = await this.getContextAsync(UpdatePublish, {
|
|
61
59
|
nonInteractive,
|
|
62
60
|
});
|
|
@@ -90,7 +88,7 @@ class UpdatePublish extends EasCommand_1.default {
|
|
|
90
88
|
try {
|
|
91
89
|
const branch = await (0, queries_1.selectBranchOnAppAsync)(graphqlClient, {
|
|
92
90
|
projectId,
|
|
93
|
-
promptTitle: `Which branch would you like to
|
|
91
|
+
promptTitle: `Which branch would you like to publish on?`,
|
|
94
92
|
displayTextForListItem: updateBranch => `${updateBranch.name} ${chalk_1.default.grey(`- current update: ${(0, utils_2.formatUpdateMessage)(updateBranch.updates[0])}`)}`,
|
|
95
93
|
paginatedQueryOptions,
|
|
96
94
|
});
|
|
@@ -109,131 +107,62 @@ class UpdatePublish extends EasCommand_1.default {
|
|
|
109
107
|
(0, assert_1.default)(branchName, 'Branch name must be specified.');
|
|
110
108
|
}
|
|
111
109
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
let uploadedAssetCount = 0;
|
|
115
|
-
let assetLimitPerUpdateGroup = 0;
|
|
116
|
-
if (republish) {
|
|
117
|
-
// If we are republishing, we don't need to worry about building the bundle or uploading the assets.
|
|
118
|
-
// Instead we get the `updateInfoGroup` from the update we wish to republish.
|
|
119
|
-
let updatesToRepublish;
|
|
120
|
-
if (groupId) {
|
|
121
|
-
const updatesByGroup = await UpdateQuery_1.UpdateQuery.viewUpdateGroupAsync(graphqlClient, {
|
|
122
|
-
groupId,
|
|
123
|
-
});
|
|
124
|
-
updatesToRepublish = updatesByGroup;
|
|
125
|
-
}
|
|
126
|
-
else {
|
|
127
|
-
if (nonInteractive) {
|
|
128
|
-
throw new Error('Must supply --group when in non-interactive mode');
|
|
129
|
-
}
|
|
130
|
-
updatesToRepublish = await (0, queries_3.selectUpdateGroupOnBranchAsync)(graphqlClient, {
|
|
131
|
-
projectId,
|
|
132
|
-
branchName,
|
|
133
|
-
paginatedQueryOptions,
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
const updatesToRepublishFilteredByPlatform = updatesToRepublish.filter(
|
|
137
|
-
// Only republish to the specified platforms
|
|
138
|
-
update => platformFlag === 'all' || update.platform === platformFlag);
|
|
139
|
-
if (updatesToRepublishFilteredByPlatform.length === 0) {
|
|
140
|
-
throw new Error(`There are no updates on branch "${branchName}" published for the platform(s) "${platformFlag}" with group ID "${groupId ? groupId : updatesToRepublish[0].group}". Did you mean to publish a new update instead?`);
|
|
141
|
-
}
|
|
142
|
-
let publicationPlatformMessage;
|
|
143
|
-
if (platformFlag === 'all') {
|
|
144
|
-
if (updatesToRepublishFilteredByPlatform.length < exports.defaultPublishPlatforms.length) {
|
|
145
|
-
log_1.default.warn(`You are republishing an update that wasn't published for all platforms.`);
|
|
146
|
-
}
|
|
147
|
-
publicationPlatformMessage = `The republished update will appear on the same platforms it was originally published on: ${updatesToRepublishFilteredByPlatform
|
|
148
|
-
.map(update => update.platform)
|
|
149
|
-
.join(', ')}`;
|
|
150
|
-
}
|
|
151
|
-
else {
|
|
152
|
-
publicationPlatformMessage = `The republished update will appear only on: ${platformFlag}`;
|
|
153
|
-
}
|
|
154
|
-
log_1.default.withTick(publicationPlatformMessage);
|
|
155
|
-
for (const update of updatesToRepublishFilteredByPlatform) {
|
|
156
|
-
const { manifestFragment } = update;
|
|
157
|
-
const platform = update.platform;
|
|
158
|
-
unsortedUpdateInfoGroups[platform] = JSON.parse(manifestFragment);
|
|
159
|
-
}
|
|
160
|
-
realizedPlatforms = updatesToRepublishFilteredByPlatform.map(update => update.platform);
|
|
161
|
-
// These are the same for each member of an update group
|
|
162
|
-
groupId = updatesToRepublishFilteredByPlatform[0].group;
|
|
163
|
-
oldMessage = (_b = updatesToRepublishFilteredByPlatform[0].message) !== null && _b !== void 0 ? _b : '';
|
|
164
|
-
oldRuntimeVersion = updatesToRepublishFilteredByPlatform[0].runtimeVersion;
|
|
165
|
-
if (!updateMessage) {
|
|
166
|
-
if (nonInteractive) {
|
|
167
|
-
throw new Error('Must supply --message when in non-interactive mode');
|
|
168
|
-
}
|
|
169
|
-
const validationMessage = 'publish message may not be empty.';
|
|
170
|
-
if (jsonFlag) {
|
|
171
|
-
throw new Error(validationMessage);
|
|
172
|
-
}
|
|
173
|
-
({ updateMessage } = await (0, prompts_1.promptAsync)({
|
|
174
|
-
type: 'text',
|
|
175
|
-
name: 'updateMessage',
|
|
176
|
-
message: `Provide an update message.`,
|
|
177
|
-
initial: `Republish "${oldMessage}" - group: ${groupId}`,
|
|
178
|
-
validate: (value) => (value ? true : validationMessage),
|
|
179
|
-
}));
|
|
180
|
-
}
|
|
110
|
+
if (!updateMessage && autoFlag) {
|
|
111
|
+
updateMessage = (_b = (await (0, vcs_1.getVcsClient)().getLastCommitMessageAsync())) === null || _b === void 0 ? void 0 : _b.trim();
|
|
181
112
|
}
|
|
182
|
-
|
|
183
|
-
if (
|
|
184
|
-
|
|
185
|
-
}
|
|
186
|
-
if (!updateMessage) {
|
|
187
|
-
if (nonInteractive) {
|
|
188
|
-
throw new Error('Must supply --message or use --auto when in non-interactive mode');
|
|
189
|
-
}
|
|
190
|
-
const validationMessage = 'publish message may not be empty.';
|
|
191
|
-
if (jsonFlag) {
|
|
192
|
-
throw new Error(validationMessage);
|
|
193
|
-
}
|
|
194
|
-
({ updateMessage } = await (0, prompts_1.promptAsync)({
|
|
195
|
-
type: 'text',
|
|
196
|
-
name: 'updateMessage',
|
|
197
|
-
message: `Provide an update message.`,
|
|
198
|
-
initial: (_d = (await (0, vcs_1.getVcsClient)().getLastCommitMessageAsync())) === null || _d === void 0 ? void 0 : _d.trim(),
|
|
199
|
-
validate: (value) => (value ? true : validationMessage),
|
|
200
|
-
}));
|
|
113
|
+
if (!updateMessage) {
|
|
114
|
+
if (nonInteractive) {
|
|
115
|
+
throw new Error('Must supply --message or use --auto when in non-interactive mode');
|
|
201
116
|
}
|
|
202
|
-
|
|
203
|
-
if (
|
|
204
|
-
|
|
205
|
-
try {
|
|
206
|
-
await (0, publish_1.buildBundlesAsync)({ projectDir, inputDir, exp, platformFlag });
|
|
207
|
-
bundleSpinner.succeed('Exported bundle(s)');
|
|
208
|
-
}
|
|
209
|
-
catch (e) {
|
|
210
|
-
bundleSpinner.fail('Export failed');
|
|
211
|
-
throw e;
|
|
212
|
-
}
|
|
117
|
+
const validationMessage = 'publish message may not be empty.';
|
|
118
|
+
if (jsonFlag) {
|
|
119
|
+
throw new Error(validationMessage);
|
|
213
120
|
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
121
|
+
({ updateMessage } = await (0, prompts_1.promptAsync)({
|
|
122
|
+
type: 'text',
|
|
123
|
+
name: 'updateMessage',
|
|
124
|
+
message: `Provide an update message.`,
|
|
125
|
+
initial: (_c = (await (0, vcs_1.getVcsClient)().getLastCommitMessageAsync())) === null || _c === void 0 ? void 0 : _c.trim(),
|
|
126
|
+
validate: (value) => (value ? true : validationMessage),
|
|
127
|
+
}));
|
|
128
|
+
}
|
|
129
|
+
// build bundle and upload assets for a new publish
|
|
130
|
+
if (!skipBundler) {
|
|
131
|
+
const bundleSpinner = (0, ora_1.ora)().start('Exporting...');
|
|
217
132
|
try {
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
realizedPlatforms = Object.keys(assets);
|
|
221
|
-
const uploadResults = await (0, publish_1.uploadAssetsAsync)(graphqlClient, assets, projectId, (totalAssets, missingAssets) => {
|
|
222
|
-
assetSpinner.text = `Uploading (${totalAssets - missingAssets}/${totalAssets})`;
|
|
223
|
-
});
|
|
224
|
-
uploadedAssetCount = uploadResults.uniqueUploadedAssetCount;
|
|
225
|
-
assetLimitPerUpdateGroup = uploadResults.assetLimitPerUpdateGroup;
|
|
226
|
-
unsortedUpdateInfoGroups = await (0, publish_1.buildUnsortedUpdateInfoGroupAsync)(assets, exp);
|
|
227
|
-
const uploadAssetSuccessMessage = uploadedAssetCount
|
|
228
|
-
? `Uploaded ${uploadedAssetCount} ${uploadedAssetCount === 1 ? 'platform' : 'platforms'}`
|
|
229
|
-
: `Uploaded: No changes detected`;
|
|
230
|
-
assetSpinner.succeed(uploadAssetSuccessMessage);
|
|
133
|
+
await (0, publish_1.buildBundlesAsync)({ projectDir, inputDir, exp, platformFlag });
|
|
134
|
+
bundleSpinner.succeed('Exported bundle(s)');
|
|
231
135
|
}
|
|
232
136
|
catch (e) {
|
|
233
|
-
|
|
137
|
+
bundleSpinner.fail('Export failed');
|
|
234
138
|
throw e;
|
|
235
139
|
}
|
|
236
140
|
}
|
|
141
|
+
// After possibly bundling, assert that the input directory can be found.
|
|
142
|
+
const distRoot = await (0, publish_1.resolveInputDirectoryAsync)(inputDir, { skipBundler });
|
|
143
|
+
const assetSpinner = (0, ora_1.ora)().start('Uploading...');
|
|
144
|
+
let unsortedUpdateInfoGroups = {};
|
|
145
|
+
let uploadedAssetCount = 0;
|
|
146
|
+
let assetLimitPerUpdateGroup = 0;
|
|
147
|
+
try {
|
|
148
|
+
const collectedAssets = await (0, publish_1.collectAssetsAsync)(distRoot);
|
|
149
|
+
const assets = (0, publish_1.filterExportedPlatformsByFlag)(collectedAssets, platformFlag);
|
|
150
|
+
realizedPlatforms = Object.keys(assets);
|
|
151
|
+
const uploadResults = await (0, publish_1.uploadAssetsAsync)(graphqlClient, assets, projectId, (totalAssets, missingAssets) => {
|
|
152
|
+
assetSpinner.text = `Uploading (${totalAssets - missingAssets}/${totalAssets})`;
|
|
153
|
+
});
|
|
154
|
+
uploadedAssetCount = uploadResults.uniqueUploadedAssetCount;
|
|
155
|
+
assetLimitPerUpdateGroup = uploadResults.assetLimitPerUpdateGroup;
|
|
156
|
+
unsortedUpdateInfoGroups = await (0, publish_1.buildUnsortedUpdateInfoGroupAsync)(assets, exp);
|
|
157
|
+
const uploadAssetSuccessMessage = uploadedAssetCount
|
|
158
|
+
? `Uploaded ${uploadedAssetCount} ${uploadedAssetCount === 1 ? 'platform' : 'platforms'}`
|
|
159
|
+
: `Uploaded: No changes detected`;
|
|
160
|
+
assetSpinner.succeed(uploadAssetSuccessMessage);
|
|
161
|
+
}
|
|
162
|
+
catch (e) {
|
|
163
|
+
assetSpinner.fail('Failed to upload');
|
|
164
|
+
throw e;
|
|
165
|
+
}
|
|
237
166
|
const truncatedMessage = (0, utils_2.truncateString)(updateMessage, 1024);
|
|
238
167
|
if (truncatedMessage !== updateMessage) {
|
|
239
168
|
log_1.default.warn('Update message exceeds the allowed 1024 character limit. Truncating message...');
|
|
@@ -269,13 +198,10 @@ class UpdatePublish extends EasCommand_1.default {
|
|
|
269
198
|
platform,
|
|
270
199
|
unsortedUpdateInfoGroups[platform],
|
|
271
200
|
]));
|
|
272
|
-
if (republish && !oldRuntimeVersion) {
|
|
273
|
-
throw new Error('Cannot find the runtime version of the update group that is being republished.');
|
|
274
|
-
}
|
|
275
201
|
return {
|
|
276
202
|
branchId,
|
|
277
203
|
updateInfoGroup: localUpdateInfoGroup,
|
|
278
|
-
runtimeVersion
|
|
204
|
+
runtimeVersion,
|
|
279
205
|
message: truncatedMessage,
|
|
280
206
|
gitCommitHash,
|
|
281
207
|
isGitWorkingTreeDirty,
|
|
@@ -380,17 +306,22 @@ class UpdatePublish extends EasCommand_1.default {
|
|
|
380
306
|
if (nonInteractive && !auto && !(branchName && updateMessage)) {
|
|
381
307
|
core_1.Errors.error('--auto or both --branch and --message are required when updating in non-interactive mode', { exit: 1 });
|
|
382
308
|
}
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
309
|
+
if (flags.group || flags.republish) {
|
|
310
|
+
// Pick the first flag set that is defined, in this specific order
|
|
311
|
+
const args = [
|
|
312
|
+
['--group', flags.group],
|
|
313
|
+
['--branch', flags.branch],
|
|
314
|
+
].filter(([_, value]) => value)[0];
|
|
315
|
+
log_1.default.newLine();
|
|
316
|
+
log_1.default.warn('The --group and --republish flags are deprecated, use the republish command instead:');
|
|
317
|
+
log_1.default.warn(` ${chalk_1.default.bold([`eas update:republish`, ...(args !== null && args !== void 0 ? args : [])].join(' '))}`);
|
|
318
|
+
log_1.default.newLine();
|
|
319
|
+
core_1.Errors.error('--group and --republish flags are deprecated', { exit: 1 });
|
|
387
320
|
}
|
|
388
321
|
return {
|
|
389
322
|
auto,
|
|
390
323
|
branchName,
|
|
391
324
|
updateMessage,
|
|
392
|
-
groupId,
|
|
393
|
-
republish,
|
|
394
325
|
inputDir: flags['input-dir'],
|
|
395
326
|
skipBundler: flags['skip-bundler'],
|
|
396
327
|
platform: flags.platform,
|
|
@@ -413,11 +344,11 @@ UpdatePublish.flags = {
|
|
|
413
344
|
required: false,
|
|
414
345
|
}),
|
|
415
346
|
republish: core_1.Flags.boolean({
|
|
416
|
-
description: 'Republish an update group',
|
|
347
|
+
description: 'Republish an update group (deprecated, see republish command)',
|
|
417
348
|
exclusive: ['input-dir', 'skip-bundler'],
|
|
418
349
|
}),
|
|
419
350
|
group: core_1.Flags.string({
|
|
420
|
-
description: 'Update group to republish',
|
|
351
|
+
description: 'Update group to republish (deprecated, see republish command)',
|
|
421
352
|
exclusive: ['input-dir', 'skip-bundler'],
|
|
422
353
|
}),
|
|
423
354
|
'input-dir': core_1.Flags.string({
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Platform } from '@expo/config';
|
|
2
|
+
import EasCommand from '../../commandUtils/EasCommand';
|
|
3
|
+
declare type UpdateRepublishRawFlags = {
|
|
4
|
+
branch?: string;
|
|
5
|
+
group?: string;
|
|
6
|
+
message?: string;
|
|
7
|
+
platform: string;
|
|
8
|
+
'non-interactive': boolean;
|
|
9
|
+
json?: boolean;
|
|
10
|
+
};
|
|
11
|
+
declare type UpdateRepublishFlags = {
|
|
12
|
+
branchName?: string;
|
|
13
|
+
groupId?: string;
|
|
14
|
+
updateMessage?: string;
|
|
15
|
+
platform: Platform[];
|
|
16
|
+
nonInteractive: boolean;
|
|
17
|
+
json: boolean;
|
|
18
|
+
};
|
|
19
|
+
export default class UpdateRepublish extends EasCommand {
|
|
20
|
+
static description: string;
|
|
21
|
+
static flags: {
|
|
22
|
+
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
23
|
+
'non-interactive': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
24
|
+
branch: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined>;
|
|
25
|
+
group: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined>;
|
|
26
|
+
message: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined>;
|
|
27
|
+
platform: import("@oclif/core/lib/interfaces").OptionFlag<string>;
|
|
28
|
+
};
|
|
29
|
+
static contextDefinition: {
|
|
30
|
+
loggedIn: import("../../commandUtils/context/LoggedInContextField").default;
|
|
31
|
+
projectConfig: import("../../commandUtils/context/ProjectConfigContextField").default;
|
|
32
|
+
};
|
|
33
|
+
runAsync(): Promise<void>;
|
|
34
|
+
sanitizeFlags(rawFlags: UpdateRepublishRawFlags): UpdateRepublishFlags;
|
|
35
|
+
}
|
|
36
|
+
export {};
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var _a;
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const core_1 = require("@oclif/core");
|
|
6
|
+
const url_1 = require("../../build/utils/url");
|
|
7
|
+
const EasCommand_1 = tslib_1.__importDefault(require("../../commandUtils/EasCommand"));
|
|
8
|
+
const flags_1 = require("../../commandUtils/flags");
|
|
9
|
+
const pagination_1 = require("../../commandUtils/pagination");
|
|
10
|
+
const PublishMutation_1 = require("../../graphql/mutations/PublishMutation");
|
|
11
|
+
const UpdateQuery_1 = require("../../graphql/queries/UpdateQuery");
|
|
12
|
+
const log_1 = tslib_1.__importStar(require("../../log"));
|
|
13
|
+
const ora_1 = require("../../ora");
|
|
14
|
+
const projectUtils_1 = require("../../project/projectUtils");
|
|
15
|
+
const prompts_1 = require("../../prompts");
|
|
16
|
+
const queries_1 = require("../../update/queries");
|
|
17
|
+
const utils_1 = require("../../update/utils");
|
|
18
|
+
const formatFields_1 = tslib_1.__importDefault(require("../../utils/formatFields"));
|
|
19
|
+
const json_1 = require("../../utils/json");
|
|
20
|
+
const defaultRepublishPlatforms = ['android', 'ios'];
|
|
21
|
+
class UpdateRepublish extends EasCommand_1.default {
|
|
22
|
+
async runAsync() {
|
|
23
|
+
const { flags: rawFlags } = await this.parse(UpdateRepublish);
|
|
24
|
+
const flags = this.sanitizeFlags(rawFlags);
|
|
25
|
+
const { projectConfig: { exp, projectId }, loggedIn: { graphqlClient }, } = await this.getContextAsync(UpdateRepublish, {
|
|
26
|
+
nonInteractive: flags.nonInteractive,
|
|
27
|
+
});
|
|
28
|
+
if (flags.json) {
|
|
29
|
+
(0, json_1.enableJsonOutput)();
|
|
30
|
+
}
|
|
31
|
+
const existingUpdates = await getOrAskUpdatesAsync(graphqlClient, projectId, flags);
|
|
32
|
+
const updatesToPublish = existingUpdates.filter(update => flags.platform.includes(update.platform));
|
|
33
|
+
if (existingUpdates.length === 0) {
|
|
34
|
+
throw new Error(`There are no published updates found`);
|
|
35
|
+
}
|
|
36
|
+
if (updatesToPublish.length === 0) {
|
|
37
|
+
throw new Error(`There are no updates on branch "${existingUpdates[0].branchName}" published for the platform(s) "${rawFlags.platform}" with group ID "${flags.groupId ? flags.groupId : updatesToPublish[0].groupId}". Did you mean to publish a new update instead?`);
|
|
38
|
+
}
|
|
39
|
+
if (rawFlags.platform === 'all') {
|
|
40
|
+
log_1.default.withTick(`The republished update will appear only on: ${rawFlags.platform}`);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
const platformsFromUpdates = updatesToPublish.map(update => update.platform);
|
|
44
|
+
if (platformsFromUpdates.length < defaultRepublishPlatforms.length) {
|
|
45
|
+
log_1.default.warn(`You are republishing an update that wasn't published for all platforms.`);
|
|
46
|
+
}
|
|
47
|
+
log_1.default.withTick(`The republished update will appear on the same platforms it was originally published on: ${platformsFromUpdates.join(', ')}`);
|
|
48
|
+
}
|
|
49
|
+
// This command only republishes a single update group
|
|
50
|
+
// The update group properties are the same for all updates
|
|
51
|
+
const { branchId, branchName, runtimeVersion } = updatesToPublish[0];
|
|
52
|
+
const updateMessage = await getOrAskUpdateMessageAsync(updatesToPublish, flags);
|
|
53
|
+
// If codesigning was created for the original update, we need to add it to the republish
|
|
54
|
+
const shouldRepublishWithCodesigning = updatesToPublish.some(update => update.codeSigningInfo);
|
|
55
|
+
if (shouldRepublishWithCodesigning) {
|
|
56
|
+
log_1.default.withTick(`The republished update will be signed with the same codesigning as the original update.`);
|
|
57
|
+
}
|
|
58
|
+
const publishIndicator = (0, ora_1.ora)('Republishing...').start();
|
|
59
|
+
let updatesRepublished;
|
|
60
|
+
try {
|
|
61
|
+
updatesRepublished = await PublishMutation_1.PublishMutation.publishUpdateGroupAsync(graphqlClient, [
|
|
62
|
+
{
|
|
63
|
+
branchId,
|
|
64
|
+
runtimeVersion,
|
|
65
|
+
message: updateMessage,
|
|
66
|
+
updateInfoGroup: Object.fromEntries(updatesToPublish.map(update => [update.platform, JSON.parse(update.manifestFragment)])),
|
|
67
|
+
gitCommitHash: updatesToPublish[0].gitCommitHash,
|
|
68
|
+
awaitingCodeSigningInfo: shouldRepublishWithCodesigning,
|
|
69
|
+
},
|
|
70
|
+
]);
|
|
71
|
+
if (shouldRepublishWithCodesigning) {
|
|
72
|
+
const codeSigningByPlatform = Object.fromEntries(updatesToPublish.map(update => [update.platform, update.codeSigningInfo]));
|
|
73
|
+
await Promise.all(updatesRepublished.map(async (update) => {
|
|
74
|
+
const codeSigning = codeSigningByPlatform[update.platform];
|
|
75
|
+
if (codeSigning) {
|
|
76
|
+
await PublishMutation_1.PublishMutation.setCodeSigningInfoAsync(graphqlClient, update.id, codeSigning);
|
|
77
|
+
}
|
|
78
|
+
}));
|
|
79
|
+
}
|
|
80
|
+
publishIndicator.succeed('Republished update');
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
publishIndicator.fail('Failed to republish update');
|
|
84
|
+
throw error;
|
|
85
|
+
}
|
|
86
|
+
if (flags.json) {
|
|
87
|
+
return (0, json_1.printJsonOnlyOutput)(updatesRepublished);
|
|
88
|
+
}
|
|
89
|
+
const updatesRepublishedByPlatform = Object.fromEntries(updatesRepublished.map(update => [update.platform, update]));
|
|
90
|
+
const updateGroupUrl = (0, url_1.getUpdateGroupUrl)((await (0, projectUtils_1.getOwnerAccountForProjectIdAsync)(graphqlClient, projectId)).name, exp.slug, updatesRepublished[0].group);
|
|
91
|
+
log_1.default.addNewLineIfNone();
|
|
92
|
+
log_1.default.log((0, formatFields_1.default)([
|
|
93
|
+
{ label: 'Branch', value: branchName },
|
|
94
|
+
{ label: 'Runtime version', value: updatesRepublished[0].runtimeVersion },
|
|
95
|
+
{ label: 'Platform', value: updatesRepublished.map(update => update.platform).join(', ') },
|
|
96
|
+
{ label: 'Update Group ID', value: updatesRepublished[0].id },
|
|
97
|
+
...(updatesRepublishedByPlatform.android
|
|
98
|
+
? [{ label: 'Android update ID', value: updatesRepublishedByPlatform.android.id }]
|
|
99
|
+
: []),
|
|
100
|
+
...(updatesRepublishedByPlatform.ios
|
|
101
|
+
? [{ label: 'iOS update ID', value: updatesRepublishedByPlatform.ios.id }]
|
|
102
|
+
: []),
|
|
103
|
+
{ label: 'Message', value: updateMessage },
|
|
104
|
+
{ label: 'Website link', value: (0, log_1.link)(updateGroupUrl, { dim: false }) },
|
|
105
|
+
]));
|
|
106
|
+
}
|
|
107
|
+
sanitizeFlags(rawFlags) {
|
|
108
|
+
var _b;
|
|
109
|
+
const branchName = rawFlags.branch;
|
|
110
|
+
const groupId = rawFlags.group;
|
|
111
|
+
if (!branchName && !groupId) {
|
|
112
|
+
throw new Error('Either --branch or --group must be specified');
|
|
113
|
+
}
|
|
114
|
+
const platform = rawFlags.platform === 'all' ? defaultRepublishPlatforms : [rawFlags.platform];
|
|
115
|
+
return {
|
|
116
|
+
branchName,
|
|
117
|
+
groupId,
|
|
118
|
+
platform,
|
|
119
|
+
updateMessage: rawFlags.message,
|
|
120
|
+
json: (_b = rawFlags.json) !== null && _b !== void 0 ? _b : false,
|
|
121
|
+
nonInteractive: rawFlags['non-interactive'],
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
exports.default = UpdateRepublish;
|
|
126
|
+
_a = UpdateRepublish;
|
|
127
|
+
UpdateRepublish.description = 'rollback to an existing update';
|
|
128
|
+
UpdateRepublish.flags = {
|
|
129
|
+
branch: core_1.Flags.string({
|
|
130
|
+
description: 'Branch name to select an update to republish from',
|
|
131
|
+
exclusive: ['group'],
|
|
132
|
+
}),
|
|
133
|
+
group: core_1.Flags.string({
|
|
134
|
+
description: 'Update group ID to republish',
|
|
135
|
+
exclusive: ['branch'],
|
|
136
|
+
}),
|
|
137
|
+
message: core_1.Flags.string({
|
|
138
|
+
description: 'Short message describing the republished update',
|
|
139
|
+
required: false,
|
|
140
|
+
}),
|
|
141
|
+
platform: core_1.Flags.enum({
|
|
142
|
+
char: 'p',
|
|
143
|
+
options: [...defaultRepublishPlatforms, 'all'],
|
|
144
|
+
default: 'all',
|
|
145
|
+
required: false,
|
|
146
|
+
}),
|
|
147
|
+
...flags_1.EasNonInteractiveAndJsonFlags,
|
|
148
|
+
};
|
|
149
|
+
UpdateRepublish.contextDefinition = {
|
|
150
|
+
..._a.ContextOptions.ProjectConfig,
|
|
151
|
+
..._a.ContextOptions.LoggedIn,
|
|
152
|
+
};
|
|
153
|
+
/** Retrieve the update group from either the update group id, or select from branch name. */
|
|
154
|
+
async function getOrAskUpdatesAsync(graphqlClient, projectId, flags) {
|
|
155
|
+
if (flags.groupId) {
|
|
156
|
+
const updateGroups = await UpdateQuery_1.UpdateQuery.viewUpdateGroupAsync(graphqlClient, {
|
|
157
|
+
groupId: flags.groupId,
|
|
158
|
+
});
|
|
159
|
+
return updateGroups.map(group => ({
|
|
160
|
+
...group,
|
|
161
|
+
groupId: group.group,
|
|
162
|
+
branchId: group.branch.id,
|
|
163
|
+
branchName: group.branch.name,
|
|
164
|
+
}));
|
|
165
|
+
}
|
|
166
|
+
if (flags.branchName) {
|
|
167
|
+
return await askUpdatesFromBranchNameAsync(graphqlClient, {
|
|
168
|
+
...flags,
|
|
169
|
+
branchName: flags.branchName,
|
|
170
|
+
projectId,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
throw new Error('Must supply --group or --branch');
|
|
174
|
+
}
|
|
175
|
+
/** Ask the user which update needs to be republished by branch name, this requires interactive mode */
|
|
176
|
+
async function askUpdatesFromBranchNameAsync(graphqlClient, { projectId, branchName, json, nonInteractive, }) {
|
|
177
|
+
if (nonInteractive) {
|
|
178
|
+
throw new Error('Must supply --group when in non-interactive mode');
|
|
179
|
+
}
|
|
180
|
+
const updateGroups = await (0, queries_1.selectUpdateGroupOnBranchAsync)(graphqlClient, {
|
|
181
|
+
projectId,
|
|
182
|
+
branchName,
|
|
183
|
+
paginatedQueryOptions: (0, pagination_1.getPaginatedQueryOptions)({ json, 'non-interactive': nonInteractive }),
|
|
184
|
+
});
|
|
185
|
+
return updateGroups.map(group => ({
|
|
186
|
+
...group,
|
|
187
|
+
groupId: group.id,
|
|
188
|
+
branchId: group.branch.id,
|
|
189
|
+
branchName: group.branch.name,
|
|
190
|
+
}));
|
|
191
|
+
}
|
|
192
|
+
/** Get or ask the user for the update (group) message for the republish */
|
|
193
|
+
async function getOrAskUpdateMessageAsync(updates, flags) {
|
|
194
|
+
if (flags.updateMessage) {
|
|
195
|
+
return sanitizeUpdateMessage(flags.updateMessage);
|
|
196
|
+
}
|
|
197
|
+
if (flags.nonInteractive || flags.json) {
|
|
198
|
+
throw new Error('Must supply --message when in non-interactive mode');
|
|
199
|
+
}
|
|
200
|
+
// This command only uses a single update group to republish, meaning these values are always identical
|
|
201
|
+
const oldGroupId = updates[0].groupId;
|
|
202
|
+
const oldUpdateMessage = updates[0].message;
|
|
203
|
+
const { updateMessage } = await (0, prompts_1.promptAsync)({
|
|
204
|
+
type: 'text',
|
|
205
|
+
name: 'updateMessage',
|
|
206
|
+
message: 'Provide an update message.',
|
|
207
|
+
initial: `Republish "${oldUpdateMessage}" - group: ${oldGroupId}`,
|
|
208
|
+
validate: (value) => (value ? true : 'Update message may not be empty.'),
|
|
209
|
+
});
|
|
210
|
+
return sanitizeUpdateMessage(updateMessage);
|
|
211
|
+
}
|
|
212
|
+
function sanitizeUpdateMessage(updateMessage) {
|
|
213
|
+
if (updateMessage !== (0, utils_1.truncateString)(updateMessage, 1024)) {
|
|
214
|
+
log_1.default.warn('Update message exceeds the allowed 1024 character limit, truncated update message.');
|
|
215
|
+
return (0, utils_1.truncateString)(updateMessage, 1024);
|
|
216
|
+
}
|
|
217
|
+
return updateMessage;
|
|
218
|
+
}
|