eas-cli 16.13.4 → 16.14.1
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 +107 -79
- package/build/commands/env/create.d.ts +0 -1
- package/build/commands/env/create.js +1 -28
- package/build/commands/update/delete.js +2 -20
- package/build/commands/update/republish.js +2 -139
- package/build/commands/update/revert-update-rollout.d.ts +24 -0
- package/build/commands/update/revert-update-rollout.js +264 -0
- package/build/commands/update/roll-back-to-embedded.d.ts +0 -2
- package/build/commands/update/roll-back-to-embedded.js +13 -133
- package/build/credentials/ios/actions/AppleTeamUtils.js +1 -1
- package/build/credentials/ios/actions/SetUpTargetBuildCredentialsFromCredentialsJson.js +1 -1
- package/build/credentials/ios/api/GraphqlClient.d.ts +1 -1
- package/build/credentials/ios/api/GraphqlClient.js +14 -8
- package/build/credentials/ios/api/graphql/mutations/AppleTeamMutation.d.ts +3 -5
- package/build/credentials/ios/api/graphql/mutations/AppleTeamMutation.js +22 -6
- package/build/devices/manager.js +2 -15
- package/build/graphql/generated.d.ts +107 -137
- package/build/graphql/generated.js +15 -3
- package/build/graphql/mutations/EnvironmentVariableMutation.d.ts +0 -2
- package/build/graphql/mutations/EnvironmentVariableMutation.js +0 -48
- package/build/graphql/types/Update.js +1 -0
- package/build/project/publish.js +1 -0
- package/build/update/delete.d.ts +5 -0
- package/build/update/delete.js +24 -0
- package/build/update/queries.d.ts +13 -1
- package/build/update/queries.js +62 -1
- package/build/update/republish.d.ts +27 -0
- package/build/update/republish.js +242 -1
- package/build/update/roll-back-to-embedded.d.ts +18 -0
- package/build/update/roll-back-to-embedded.js +119 -0
- package/build/user/fetchUser.js +15 -13
- package/build/utils/statuspageService.js +1 -0
- package/oclif.manifest.json +78 -114
- package/package.json +3 -2
- package/build/commands/env/link.d.ts +0 -23
- package/build/commands/env/link.js +0 -128
- package/build/commands/env/unlink.d.ts +0 -22
- package/build/commands/env/unlink.js +0 -117
package/build/update/queries.js
CHANGED
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.selectUpdateGroupOnBranchAsync = exports.listAndRenderUpdateGroupsOnBranchAsync = exports.listAndRenderUpdateGroupsOnAppAsync = exports.UPDATE_GROUPS_LIMIT = exports.UPDATES_LIMIT = void 0;
|
|
3
|
+
exports.selectRuntimeOnBranchAsync = exports.selectUpdateGroupOnBranchAsync = exports.selectRuntimeAndGetLatestUpdateGroupForEachPublishPlatformOnBranchAsync = exports.listAndRenderUpdateGroupsOnBranchAsync = exports.listAndRenderUpdateGroupsOnAppAsync = exports.RUNTIME_VERSIONS_LIMIT = exports.UPDATE_GROUPS_LIMIT = exports.UPDATES_LIMIT = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const assert_1 = tslib_1.__importDefault(require("assert"));
|
|
6
6
|
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
7
7
|
const utils_1 = require("./utils");
|
|
8
|
+
const generated_1 = require("../graphql/generated");
|
|
9
|
+
const RuntimeQuery_1 = require("../graphql/queries/RuntimeQuery");
|
|
8
10
|
const UpdateQuery_1 = require("../graphql/queries/UpdateQuery");
|
|
9
11
|
const log_1 = tslib_1.__importDefault(require("../log"));
|
|
10
12
|
const formatFields_1 = tslib_1.__importDefault(require("../utils/formatFields"));
|
|
11
13
|
const json_1 = require("../utils/json");
|
|
12
14
|
const queries_1 = require("../utils/queries");
|
|
15
|
+
const relay_1 = require("../utils/relay");
|
|
13
16
|
exports.UPDATES_LIMIT = 50;
|
|
14
17
|
exports.UPDATE_GROUPS_LIMIT = 25;
|
|
18
|
+
exports.RUNTIME_VERSIONS_LIMIT = 25;
|
|
15
19
|
async function listAndRenderUpdateGroupsOnAppAsync(graphqlClient, { projectId, paginatedQueryOptions, }) {
|
|
16
20
|
if (paginatedQueryOptions.nonInteractive) {
|
|
17
21
|
const updateGroups = await queryUpdateGroupsOnAppAsync(graphqlClient, {
|
|
@@ -66,6 +70,41 @@ async function listAndRenderUpdateGroupsOnBranchAsync(graphqlClient, { projectId
|
|
|
66
70
|
}
|
|
67
71
|
}
|
|
68
72
|
exports.listAndRenderUpdateGroupsOnBranchAsync = listAndRenderUpdateGroupsOnBranchAsync;
|
|
73
|
+
async function selectRuntimeAndGetLatestUpdateGroupForEachPublishPlatformOnBranchAsync(graphqlClient, { projectId, branchName, paginatedQueryOptions, }) {
|
|
74
|
+
if (paginatedQueryOptions.nonInteractive) {
|
|
75
|
+
throw new Error('Unable to select an update in non-interactive mode.');
|
|
76
|
+
}
|
|
77
|
+
const runtimeVersion = await selectRuntimeOnBranchAsync(graphqlClient, {
|
|
78
|
+
appId: projectId,
|
|
79
|
+
branchName,
|
|
80
|
+
});
|
|
81
|
+
if (!runtimeVersion) {
|
|
82
|
+
throw new Error('No runtime version selected.');
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
ios: (await queryUpdateGroupsOnBranchAsync(graphqlClient, {
|
|
86
|
+
appId: projectId,
|
|
87
|
+
branchName,
|
|
88
|
+
limit: 1,
|
|
89
|
+
offset: 0,
|
|
90
|
+
filter: {
|
|
91
|
+
runtimeVersions: [runtimeVersion.version],
|
|
92
|
+
platform: generated_1.AppPlatform.Ios,
|
|
93
|
+
},
|
|
94
|
+
}))[0],
|
|
95
|
+
android: (await queryUpdateGroupsOnBranchAsync(graphqlClient, {
|
|
96
|
+
appId: projectId,
|
|
97
|
+
branchName,
|
|
98
|
+
limit: 1,
|
|
99
|
+
offset: 0,
|
|
100
|
+
filter: {
|
|
101
|
+
runtimeVersions: [runtimeVersion.version],
|
|
102
|
+
platform: generated_1.AppPlatform.Android,
|
|
103
|
+
},
|
|
104
|
+
}))[0],
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
exports.selectRuntimeAndGetLatestUpdateGroupForEachPublishPlatformOnBranchAsync = selectRuntimeAndGetLatestUpdateGroupForEachPublishPlatformOnBranchAsync;
|
|
69
108
|
async function selectUpdateGroupOnBranchAsync(graphqlClient, { projectId, branchName, paginatedQueryOptions, }) {
|
|
70
109
|
if (paginatedQueryOptions.nonInteractive) {
|
|
71
110
|
throw new Error('Unable to select an update in non-interactive mode.');
|
|
@@ -140,3 +179,25 @@ function renderUpdateGroupsOnApp({ updateGroups, paginatedQueryOptions: { json }
|
|
|
140
179
|
}))
|
|
141
180
|
.join(`\n\n${chalk_1.default.dim('———')}\n\n`));
|
|
142
181
|
}
|
|
182
|
+
async function selectRuntimeOnBranchAsync(graphqlClient, { appId, branchName, batchSize = 5, }) {
|
|
183
|
+
const queryAsync = async (queryParams) => {
|
|
184
|
+
return await RuntimeQuery_1.RuntimeQuery.getRuntimesOnBranchAsync(graphqlClient, {
|
|
185
|
+
appId,
|
|
186
|
+
name: branchName,
|
|
187
|
+
first: queryParams.first,
|
|
188
|
+
after: queryParams.after,
|
|
189
|
+
last: queryParams.last,
|
|
190
|
+
before: queryParams.before,
|
|
191
|
+
});
|
|
192
|
+
};
|
|
193
|
+
const getTitleAsync = async (runtime) => {
|
|
194
|
+
return runtime.version;
|
|
195
|
+
};
|
|
196
|
+
return await (0, relay_1.selectPaginatedAsync)({
|
|
197
|
+
queryAsync,
|
|
198
|
+
getTitleAsync,
|
|
199
|
+
printedType: 'target runtime',
|
|
200
|
+
pageSize: batchSize,
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
exports.selectRuntimeOnBranchAsync = selectRuntimeOnBranchAsync;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ExpoConfig } from '@expo/config';
|
|
2
2
|
import { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient';
|
|
3
3
|
import { UpdateFragment } from '../graphql/generated';
|
|
4
|
+
import { UpdatePublishPlatform } from '../project/publish';
|
|
4
5
|
import { CodeSigningInfo } from '../utils/code-signing';
|
|
5
6
|
export type UpdateToRepublish = {
|
|
6
7
|
groupId: string;
|
|
@@ -27,3 +28,29 @@ export declare function republishAsync({ graphqlClient, app, updatesToPublish, t
|
|
|
27
28
|
json?: boolean;
|
|
28
29
|
rolloutPercentage?: number;
|
|
29
30
|
}): Promise<void>;
|
|
31
|
+
type GetUpdateOrAskForUpdatesOptions = {
|
|
32
|
+
nonInteractive: boolean;
|
|
33
|
+
json: boolean;
|
|
34
|
+
groupId?: string;
|
|
35
|
+
branchName?: string;
|
|
36
|
+
channelName?: string;
|
|
37
|
+
};
|
|
38
|
+
export declare function getUpdateGroupAsync(graphqlClient: ExpoGraphqlClient, groupId: string): Promise<UpdateToRepublish[]>;
|
|
39
|
+
type AskUpdateGroupForEachPublishPlatformFilteringByRuntimeVersionOptions = {
|
|
40
|
+
nonInteractive: boolean;
|
|
41
|
+
json: boolean;
|
|
42
|
+
branchName?: string;
|
|
43
|
+
channelName?: string;
|
|
44
|
+
};
|
|
45
|
+
export declare function askUpdateGroupForEachPublishPlatformFilteringByRuntimeVersionAsync(graphqlClient: ExpoGraphqlClient, projectId: string, options: AskUpdateGroupForEachPublishPlatformFilteringByRuntimeVersionOptions): Promise<Record<UpdatePublishPlatform, UpdateToRepublish[] | undefined>>;
|
|
46
|
+
export declare function getUpdateGroupOrAskForUpdateGroupAsync(graphqlClient: ExpoGraphqlClient, projectId: string, options: GetUpdateOrAskForUpdatesOptions): Promise<UpdateToRepublish[]>;
|
|
47
|
+
type GetOrAskUpdateMessageOptions = {
|
|
48
|
+
updateMessage?: string;
|
|
49
|
+
nonInteractive: boolean;
|
|
50
|
+
json: boolean;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Get or ask the user for the update (group) message for the republish
|
|
54
|
+
*/
|
|
55
|
+
export declare function getOrAskUpdateMessageAsync(updateGroup: UpdateToRepublish[], options: GetOrAskUpdateMessageOptions): Promise<string>;
|
|
56
|
+
export {};
|
|
@@ -1,16 +1,24 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.republishAsync = void 0;
|
|
3
|
+
exports.getOrAskUpdateMessageAsync = exports.getUpdateGroupOrAskForUpdateGroupAsync = exports.askUpdateGroupForEachPublishPlatformFilteringByRuntimeVersionAsync = exports.getUpdateGroupAsync = exports.republishAsync = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const assert_1 = tslib_1.__importDefault(require("assert"));
|
|
6
6
|
const nullthrows_1 = tslib_1.__importDefault(require("nullthrows"));
|
|
7
|
+
const getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync_1 = require("./getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync");
|
|
8
|
+
const queries_1 = require("./queries");
|
|
9
|
+
const utils_1 = require("./utils");
|
|
10
|
+
const queries_2 = require("../branch/queries");
|
|
7
11
|
const url_1 = require("../build/utils/url");
|
|
12
|
+
const queries_3 = require("../channel/queries");
|
|
13
|
+
const pagination_1 = require("../commandUtils/pagination");
|
|
8
14
|
const fetch_1 = tslib_1.__importDefault(require("../fetch"));
|
|
9
15
|
const PublishMutation_1 = require("../graphql/mutations/PublishMutation");
|
|
16
|
+
const UpdateQuery_1 = require("../graphql/queries/UpdateQuery");
|
|
10
17
|
const log_1 = tslib_1.__importStar(require("../log"));
|
|
11
18
|
const ora_1 = require("../ora");
|
|
12
19
|
const projectUtils_1 = require("../project/projectUtils");
|
|
13
20
|
const publish_1 = require("../project/publish");
|
|
21
|
+
const prompts_1 = require("../prompts");
|
|
14
22
|
const code_signing_1 = require("../utils/code-signing");
|
|
15
23
|
const formatFields_1 = tslib_1.__importDefault(require("../utils/formatFields"));
|
|
16
24
|
const json_1 = require("../utils/json");
|
|
@@ -174,3 +182,236 @@ async function republishAsync({ graphqlClient, app, updatesToPublish, targetBran
|
|
|
174
182
|
]));
|
|
175
183
|
}
|
|
176
184
|
exports.republishAsync = republishAsync;
|
|
185
|
+
async function getUpdateGroupAsync(graphqlClient, groupId) {
|
|
186
|
+
const updateGroup = await UpdateQuery_1.UpdateQuery.viewUpdateGroupAsync(graphqlClient, {
|
|
187
|
+
groupId,
|
|
188
|
+
});
|
|
189
|
+
return updateGroup.map(update => ({
|
|
190
|
+
...update,
|
|
191
|
+
groupId: update.group,
|
|
192
|
+
branchId: update.branch.id,
|
|
193
|
+
branchName: update.branch.name,
|
|
194
|
+
}));
|
|
195
|
+
}
|
|
196
|
+
exports.getUpdateGroupAsync = getUpdateGroupAsync;
|
|
197
|
+
async function askUpdateGroupForEachPublishPlatformFilteringByRuntimeVersionAsync(graphqlClient, projectId, options) {
|
|
198
|
+
if (options.nonInteractive) {
|
|
199
|
+
throw new Error('Must supply --group when in non-interactive mode');
|
|
200
|
+
}
|
|
201
|
+
if (options.branchName) {
|
|
202
|
+
return await askUpdateGroupForEachPublishPlatformFromBranchNameFilteringByRuntimeVersionAsync(graphqlClient, {
|
|
203
|
+
...options,
|
|
204
|
+
branchName: options.branchName,
|
|
205
|
+
projectId,
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
if (options.channelName) {
|
|
209
|
+
return await askUpdateGroupForEachPublishPlatformFromChannelNameFilteringByRuntimeVersionAsync(graphqlClient, {
|
|
210
|
+
...options,
|
|
211
|
+
channelName: options.channelName,
|
|
212
|
+
projectId,
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
const { choice } = await (0, prompts_1.promptAsync)({
|
|
216
|
+
type: 'select',
|
|
217
|
+
message: 'Find update by branch or channel?',
|
|
218
|
+
name: 'choice',
|
|
219
|
+
choices: [
|
|
220
|
+
{ title: 'Branch', value: 'branch' },
|
|
221
|
+
{ title: 'Channel', value: 'channel' },
|
|
222
|
+
],
|
|
223
|
+
});
|
|
224
|
+
if (choice === 'channel') {
|
|
225
|
+
const { name } = await (0, queries_3.selectChannelOnAppAsync)(graphqlClient, {
|
|
226
|
+
projectId,
|
|
227
|
+
selectionPromptTitle: 'Select a channel to view',
|
|
228
|
+
paginatedQueryOptions: {
|
|
229
|
+
json: options.json,
|
|
230
|
+
nonInteractive: options.nonInteractive,
|
|
231
|
+
offset: 0,
|
|
232
|
+
},
|
|
233
|
+
});
|
|
234
|
+
return await askUpdateGroupForEachPublishPlatformFromChannelNameFilteringByRuntimeVersionAsync(graphqlClient, {
|
|
235
|
+
...options,
|
|
236
|
+
channelName: name,
|
|
237
|
+
projectId,
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
else if (choice === 'branch') {
|
|
241
|
+
const { name } = await (0, queries_2.selectBranchOnAppAsync)(graphqlClient, {
|
|
242
|
+
projectId,
|
|
243
|
+
promptTitle: 'Select branch from which to choose update',
|
|
244
|
+
displayTextForListItem: updateBranch => ({
|
|
245
|
+
title: updateBranch.name,
|
|
246
|
+
}),
|
|
247
|
+
// discard limit and offset because this query is not their intended target
|
|
248
|
+
paginatedQueryOptions: {
|
|
249
|
+
json: options.json,
|
|
250
|
+
nonInteractive: options.nonInteractive,
|
|
251
|
+
offset: 0,
|
|
252
|
+
},
|
|
253
|
+
});
|
|
254
|
+
return await askUpdateGroupForEachPublishPlatformFromBranchNameFilteringByRuntimeVersionAsync(graphqlClient, {
|
|
255
|
+
...options,
|
|
256
|
+
branchName: name,
|
|
257
|
+
projectId,
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
else {
|
|
261
|
+
throw new Error('Must choose update via channel or branch');
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
exports.askUpdateGroupForEachPublishPlatformFilteringByRuntimeVersionAsync = askUpdateGroupForEachPublishPlatformFilteringByRuntimeVersionAsync;
|
|
265
|
+
async function getUpdateGroupOrAskForUpdateGroupAsync(graphqlClient, projectId, options) {
|
|
266
|
+
if (options.groupId) {
|
|
267
|
+
return await getUpdateGroupAsync(graphqlClient, options.groupId);
|
|
268
|
+
}
|
|
269
|
+
if (options.nonInteractive) {
|
|
270
|
+
throw new Error('Must supply --group when in non-interactive mode');
|
|
271
|
+
}
|
|
272
|
+
if (options.branchName) {
|
|
273
|
+
return await askUpdatesFromBranchNameAsync(graphqlClient, {
|
|
274
|
+
...options,
|
|
275
|
+
branchName: options.branchName,
|
|
276
|
+
projectId,
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
if (options.channelName) {
|
|
280
|
+
return await askUpdatesFromChannelNameAsync(graphqlClient, {
|
|
281
|
+
...options,
|
|
282
|
+
channelName: options.channelName,
|
|
283
|
+
projectId,
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
const { choice } = await (0, prompts_1.promptAsync)({
|
|
287
|
+
type: 'select',
|
|
288
|
+
message: 'Find update by branch or channel?',
|
|
289
|
+
name: 'choice',
|
|
290
|
+
choices: [
|
|
291
|
+
{ title: 'Branch', value: 'branch' },
|
|
292
|
+
{ title: 'Channel', value: 'channel' },
|
|
293
|
+
],
|
|
294
|
+
});
|
|
295
|
+
if (choice === 'channel') {
|
|
296
|
+
const { name } = await (0, queries_3.selectChannelOnAppAsync)(graphqlClient, {
|
|
297
|
+
projectId,
|
|
298
|
+
selectionPromptTitle: 'Select a channel to view',
|
|
299
|
+
paginatedQueryOptions: {
|
|
300
|
+
json: options.json,
|
|
301
|
+
nonInteractive: options.nonInteractive,
|
|
302
|
+
offset: 0,
|
|
303
|
+
},
|
|
304
|
+
});
|
|
305
|
+
return await askUpdatesFromChannelNameAsync(graphqlClient, {
|
|
306
|
+
...options,
|
|
307
|
+
channelName: name,
|
|
308
|
+
projectId,
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
else if (choice === 'branch') {
|
|
312
|
+
const { name } = await (0, queries_2.selectBranchOnAppAsync)(graphqlClient, {
|
|
313
|
+
projectId,
|
|
314
|
+
promptTitle: 'Select branch from which to choose update',
|
|
315
|
+
displayTextForListItem: updateBranch => ({
|
|
316
|
+
title: updateBranch.name,
|
|
317
|
+
}),
|
|
318
|
+
// discard limit and offset because this query is not their intended target
|
|
319
|
+
paginatedQueryOptions: {
|
|
320
|
+
json: options.json,
|
|
321
|
+
nonInteractive: options.nonInteractive,
|
|
322
|
+
offset: 0,
|
|
323
|
+
},
|
|
324
|
+
});
|
|
325
|
+
return await askUpdatesFromBranchNameAsync(graphqlClient, {
|
|
326
|
+
...options,
|
|
327
|
+
branchName: name,
|
|
328
|
+
projectId,
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
else {
|
|
332
|
+
throw new Error('Must choose update via channel or branch');
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
exports.getUpdateGroupOrAskForUpdateGroupAsync = getUpdateGroupOrAskForUpdateGroupAsync;
|
|
336
|
+
async function askUpdateGroupForEachPublishPlatformFromBranchNameFilteringByRuntimeVersionAsync(graphqlClient, { projectId, branchName, json, nonInteractive, }) {
|
|
337
|
+
const publishPlatformToLatestUpdateGroup = await (0, queries_1.selectRuntimeAndGetLatestUpdateGroupForEachPublishPlatformOnBranchAsync)(graphqlClient, {
|
|
338
|
+
projectId,
|
|
339
|
+
branchName,
|
|
340
|
+
paginatedQueryOptions: (0, pagination_1.getPaginatedQueryOptions)({ json, 'non-interactive': nonInteractive }),
|
|
341
|
+
});
|
|
342
|
+
return {
|
|
343
|
+
ios: publishPlatformToLatestUpdateGroup.ios?.map(update => ({
|
|
344
|
+
...update,
|
|
345
|
+
groupId: update.group,
|
|
346
|
+
branchId: update.branch.id,
|
|
347
|
+
branchName: update.branch.name,
|
|
348
|
+
})),
|
|
349
|
+
android: publishPlatformToLatestUpdateGroup.android?.map(update => ({
|
|
350
|
+
...update,
|
|
351
|
+
groupId: update.group,
|
|
352
|
+
branchId: update.branch.id,
|
|
353
|
+
branchName: update.branch.name,
|
|
354
|
+
})),
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
async function askUpdatesFromBranchNameAsync(graphqlClient, { projectId, branchName, json, nonInteractive, }) {
|
|
358
|
+
const updateGroup = await (0, queries_1.selectUpdateGroupOnBranchAsync)(graphqlClient, {
|
|
359
|
+
projectId,
|
|
360
|
+
branchName,
|
|
361
|
+
paginatedQueryOptions: (0, pagination_1.getPaginatedQueryOptions)({ json, 'non-interactive': nonInteractive }),
|
|
362
|
+
});
|
|
363
|
+
return updateGroup.map(update => ({
|
|
364
|
+
...update,
|
|
365
|
+
groupId: update.group,
|
|
366
|
+
branchId: update.branch.id,
|
|
367
|
+
branchName: update.branch.name,
|
|
368
|
+
}));
|
|
369
|
+
}
|
|
370
|
+
async function askUpdateGroupForEachPublishPlatformFromChannelNameFilteringByRuntimeVersionAsync(graphqlClient, { projectId, channelName, json, nonInteractive, }) {
|
|
371
|
+
const { branchName } = await (0, getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync_1.getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync)(graphqlClient, projectId, channelName);
|
|
372
|
+
return await askUpdateGroupForEachPublishPlatformFromBranchNameFilteringByRuntimeVersionAsync(graphqlClient, {
|
|
373
|
+
projectId,
|
|
374
|
+
branchName,
|
|
375
|
+
json,
|
|
376
|
+
nonInteractive,
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
async function askUpdatesFromChannelNameAsync(graphqlClient, { projectId, channelName, json, nonInteractive, }) {
|
|
380
|
+
const { branchName } = await (0, getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync_1.getBranchFromChannelNameAndCreateAndLinkIfNotExistsAsync)(graphqlClient, projectId, channelName);
|
|
381
|
+
return await askUpdatesFromBranchNameAsync(graphqlClient, {
|
|
382
|
+
projectId,
|
|
383
|
+
branchName,
|
|
384
|
+
json,
|
|
385
|
+
nonInteractive,
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* Get or ask the user for the update (group) message for the republish
|
|
390
|
+
*/
|
|
391
|
+
async function getOrAskUpdateMessageAsync(updateGroup, options) {
|
|
392
|
+
if (options.updateMessage) {
|
|
393
|
+
return sanitizeUpdateMessage(options.updateMessage);
|
|
394
|
+
}
|
|
395
|
+
if (options.nonInteractive || options.json) {
|
|
396
|
+
throw new Error('Must supply --message when in non-interactive mode');
|
|
397
|
+
}
|
|
398
|
+
// This command only uses a single update group to republish, meaning these values are always identical
|
|
399
|
+
const oldGroupId = updateGroup[0].groupId;
|
|
400
|
+
const oldUpdateMessage = updateGroup[0].message;
|
|
401
|
+
const { updateMessage } = await (0, prompts_1.promptAsync)({
|
|
402
|
+
type: 'text',
|
|
403
|
+
name: 'updateMessage',
|
|
404
|
+
message: 'Provide an update message.',
|
|
405
|
+
initial: `Republish "${oldUpdateMessage}" - group: ${oldGroupId}`,
|
|
406
|
+
validate: (value) => (value ? true : 'Update message may not be empty.'),
|
|
407
|
+
});
|
|
408
|
+
return sanitizeUpdateMessage(updateMessage);
|
|
409
|
+
}
|
|
410
|
+
exports.getOrAskUpdateMessageAsync = getOrAskUpdateMessageAsync;
|
|
411
|
+
function sanitizeUpdateMessage(updateMessage) {
|
|
412
|
+
if (updateMessage !== (0, utils_1.truncateString)(updateMessage, 1024)) {
|
|
413
|
+
log_1.default.warn('Update message exceeds the allowed 1024 character limit, truncated update message.');
|
|
414
|
+
return (0, utils_1.truncateString)(updateMessage, 1024);
|
|
415
|
+
}
|
|
416
|
+
return updateMessage;
|
|
417
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ExpoConfig } from '@expo/config';
|
|
2
|
+
import { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient';
|
|
3
|
+
import { UpdatePublishPlatform } from '../project/publish';
|
|
4
|
+
import { CodeSigningInfo } from '../utils/code-signing';
|
|
5
|
+
export declare function publishRollBackToEmbeddedUpdateAsync({ graphqlClient, projectId, exp, updateMessage, branch, codeSigningInfo, platforms, runtimeVersion, json, }: {
|
|
6
|
+
graphqlClient: ExpoGraphqlClient;
|
|
7
|
+
projectId: string;
|
|
8
|
+
exp: ExpoConfig;
|
|
9
|
+
updateMessage: string | undefined;
|
|
10
|
+
branch: {
|
|
11
|
+
name: string;
|
|
12
|
+
id: string;
|
|
13
|
+
};
|
|
14
|
+
codeSigningInfo: CodeSigningInfo | undefined;
|
|
15
|
+
platforms: UpdatePublishPlatform[];
|
|
16
|
+
runtimeVersion: string;
|
|
17
|
+
json: boolean;
|
|
18
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.publishRollBackToEmbeddedUpdateAsync = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const nullthrows_1 = tslib_1.__importDefault(require("nullthrows"));
|
|
6
|
+
const utils_1 = require("./utils");
|
|
7
|
+
const url_1 = require("../build/utils/url");
|
|
8
|
+
const fetch_1 = tslib_1.__importDefault(require("../fetch"));
|
|
9
|
+
const PublishMutation_1 = require("../graphql/mutations/PublishMutation");
|
|
10
|
+
const log_1 = tslib_1.__importStar(require("../log"));
|
|
11
|
+
const ora_1 = require("../ora");
|
|
12
|
+
const projectUtils_1 = require("../project/projectUtils");
|
|
13
|
+
const publish_1 = require("../project/publish");
|
|
14
|
+
const code_signing_1 = require("../utils/code-signing");
|
|
15
|
+
const uniqBy_1 = tslib_1.__importDefault(require("../utils/expodash/uniqBy"));
|
|
16
|
+
const formatFields_1 = tslib_1.__importDefault(require("../utils/formatFields"));
|
|
17
|
+
const json_1 = require("../utils/json");
|
|
18
|
+
async function publishRollBackToEmbeddedUpdateAsync({ graphqlClient, projectId, exp, updateMessage, branch, codeSigningInfo, platforms, runtimeVersion, json, }) {
|
|
19
|
+
const runtimeToPlatformsAndFingerprintInfoMapping = (0, publish_1.getRuntimeToPlatformsAndFingerprintInfoMappingFromRuntimeVersionInfoObjects)(platforms.map(platform => ({
|
|
20
|
+
platform,
|
|
21
|
+
runtimeVersionInfo: {
|
|
22
|
+
runtimeVersion,
|
|
23
|
+
expoUpdatesRuntimeFingerprint: null,
|
|
24
|
+
expoUpdatesRuntimeFingerprintHash: null,
|
|
25
|
+
},
|
|
26
|
+
})));
|
|
27
|
+
let newUpdates;
|
|
28
|
+
const publishSpinner = (0, ora_1.ora)('Publishing...').start();
|
|
29
|
+
try {
|
|
30
|
+
newUpdates = await publishRollbacksAsync({
|
|
31
|
+
graphqlClient,
|
|
32
|
+
updateMessage,
|
|
33
|
+
branchId: branch.id,
|
|
34
|
+
codeSigningInfo,
|
|
35
|
+
runtimeToPlatformsAndFingerprintInfoMapping,
|
|
36
|
+
platforms,
|
|
37
|
+
});
|
|
38
|
+
publishSpinner.succeed('Published!');
|
|
39
|
+
}
|
|
40
|
+
catch (e) {
|
|
41
|
+
publishSpinner.fail('Failed to publish updates');
|
|
42
|
+
throw e;
|
|
43
|
+
}
|
|
44
|
+
if (json) {
|
|
45
|
+
(0, json_1.printJsonOnlyOutput)((0, utils_1.getUpdateJsonInfosForUpdates)(newUpdates));
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
log_1.default.addNewLineIfNone();
|
|
49
|
+
for (const runtime of (0, uniqBy_1.default)(runtimeToPlatformsAndFingerprintInfoMapping, version => version.runtimeVersion)) {
|
|
50
|
+
const newUpdatesForRuntimeVersion = newUpdates.filter(update => update.runtimeVersion === runtime.runtimeVersion);
|
|
51
|
+
if (newUpdatesForRuntimeVersion.length === 0) {
|
|
52
|
+
throw new Error(`Publish response is missing updates with runtime ${runtime.runtimeVersion}.`);
|
|
53
|
+
}
|
|
54
|
+
const platforms = newUpdatesForRuntimeVersion.map(update => update.platform);
|
|
55
|
+
const newAndroidUpdate = newUpdatesForRuntimeVersion.find(update => update.platform === 'android');
|
|
56
|
+
const newIosUpdate = newUpdatesForRuntimeVersion.find(update => update.platform === 'ios');
|
|
57
|
+
const updateGroupId = newUpdatesForRuntimeVersion[0].group;
|
|
58
|
+
const projectName = exp.slug;
|
|
59
|
+
const accountName = (await (0, projectUtils_1.getOwnerAccountForProjectIdAsync)(graphqlClient, projectId)).name;
|
|
60
|
+
const updateGroupUrl = (0, url_1.getUpdateGroupUrl)(accountName, projectName, updateGroupId);
|
|
61
|
+
const updateGroupLink = (0, log_1.link)(updateGroupUrl, { dim: false });
|
|
62
|
+
log_1.default.log((0, formatFields_1.default)([
|
|
63
|
+
{ label: 'Branch', value: branch.name },
|
|
64
|
+
{ label: 'Runtime version', value: runtime.runtimeVersion },
|
|
65
|
+
{ label: 'Platform', value: platforms.join(', ') },
|
|
66
|
+
{ label: 'Update group ID', value: updateGroupId },
|
|
67
|
+
...(newAndroidUpdate ? [{ label: 'Android update ID', value: newAndroidUpdate.id }] : []),
|
|
68
|
+
...(newIosUpdate ? [{ label: 'iOS update ID', value: newIosUpdate.id }] : []),
|
|
69
|
+
{ label: 'Message', value: updateMessage ?? '' },
|
|
70
|
+
{ label: 'EAS Dashboard', value: updateGroupLink },
|
|
71
|
+
]));
|
|
72
|
+
log_1.default.addNewLineIfNone();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
exports.publishRollBackToEmbeddedUpdateAsync = publishRollBackToEmbeddedUpdateAsync;
|
|
77
|
+
async function publishRollbacksAsync({ graphqlClient, updateMessage, branchId, codeSigningInfo, runtimeToPlatformsAndFingerprintInfoMapping, platforms, }) {
|
|
78
|
+
const rollbackInfoGroups = Object.fromEntries(platforms.map(platform => [platform, true]));
|
|
79
|
+
// Sort the updates into different groups based on their platform specific runtime versions
|
|
80
|
+
const updateGroups = runtimeToPlatformsAndFingerprintInfoMapping.map(({ runtimeVersion, platforms }) => {
|
|
81
|
+
const localRollbackInfoGroup = Object.fromEntries(platforms.map(platform => [platform, rollbackInfoGroups[platform]]));
|
|
82
|
+
return {
|
|
83
|
+
branchId,
|
|
84
|
+
rollBackToEmbeddedInfoGroup: localRollbackInfoGroup,
|
|
85
|
+
runtimeVersion,
|
|
86
|
+
message: updateMessage,
|
|
87
|
+
awaitingCodeSigningInfo: !!codeSigningInfo,
|
|
88
|
+
};
|
|
89
|
+
});
|
|
90
|
+
const newUpdates = await PublishMutation_1.PublishMutation.publishUpdateGroupAsync(graphqlClient, updateGroups);
|
|
91
|
+
if (codeSigningInfo) {
|
|
92
|
+
log_1.default.log('🔒 Signing roll back');
|
|
93
|
+
const updatesTemp = [...newUpdates];
|
|
94
|
+
const updateGroupsAndTheirUpdates = updateGroups.map(updateGroup => {
|
|
95
|
+
const newUpdates = updatesTemp.splice(0, Object.keys((0, nullthrows_1.default)(updateGroup.rollBackToEmbeddedInfoGroup)).length);
|
|
96
|
+
return {
|
|
97
|
+
updateGroup,
|
|
98
|
+
newUpdates,
|
|
99
|
+
};
|
|
100
|
+
});
|
|
101
|
+
await Promise.all(updateGroupsAndTheirUpdates.map(async ({ newUpdates }) => {
|
|
102
|
+
await Promise.all(newUpdates.map(async (newUpdate) => {
|
|
103
|
+
const response = await (0, fetch_1.default)(newUpdate.manifestPermalink, {
|
|
104
|
+
method: 'GET',
|
|
105
|
+
headers: { accept: 'multipart/mixed' },
|
|
106
|
+
});
|
|
107
|
+
const directiveBody = (0, nullthrows_1.default)(await (0, code_signing_1.getDirectiveBodyAsync)(response));
|
|
108
|
+
(0, code_signing_1.checkDirectiveBodyAgainstUpdateInfoGroup)(directiveBody);
|
|
109
|
+
const directiveSignature = (0, code_signing_1.signBody)(directiveBody, codeSigningInfo);
|
|
110
|
+
await PublishMutation_1.PublishMutation.setCodeSigningInfoAsync(graphqlClient, newUpdate.id, {
|
|
111
|
+
alg: codeSigningInfo.codeSigningMetadata.alg,
|
|
112
|
+
keyid: codeSigningInfo.codeSigningMetadata.keyid,
|
|
113
|
+
sig: directiveSignature,
|
|
114
|
+
});
|
|
115
|
+
}));
|
|
116
|
+
}));
|
|
117
|
+
}
|
|
118
|
+
return newUpdates;
|
|
119
|
+
}
|
package/build/user/fetchUser.js
CHANGED
|
@@ -4,24 +4,26 @@ exports.fetchUserAsync = void 0;
|
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const graphql_tag_1 = tslib_1.__importDefault(require("graphql-tag"));
|
|
6
6
|
const createGraphqlClient_1 = require("../commandUtils/context/contextUtils/createGraphqlClient");
|
|
7
|
+
const client_1 = require("../graphql/client");
|
|
7
8
|
async function fetchUserAsync({ sessionSecret, }) {
|
|
8
9
|
const graphqlClient = (0, createGraphqlClient_1.createGraphqlClient)({ accessToken: null, sessionSecret });
|
|
9
|
-
const result = await graphqlClient
|
|
10
|
+
const result = await (0, client_1.withErrorHandlingAsync)(graphqlClient
|
|
10
11
|
.query((0, graphql_tag_1.default) `
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
query MeUserActorQuery {
|
|
13
|
+
meUserActor {
|
|
14
|
+
id
|
|
15
|
+
username
|
|
16
|
+
}
|
|
15
17
|
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
.
|
|
21
|
-
|
|
18
|
+
`, {}, { additionalTypenames: ['UserActor'] })
|
|
19
|
+
.toPromise());
|
|
20
|
+
const meUserActor = result.meUserActor;
|
|
21
|
+
if (!meUserActor) {
|
|
22
|
+
throw new Error('Failed to fetch user data after login.');
|
|
23
|
+
}
|
|
22
24
|
return {
|
|
23
|
-
id:
|
|
24
|
-
username:
|
|
25
|
+
id: meUserActor.id,
|
|
26
|
+
username: meUserActor.username,
|
|
25
27
|
};
|
|
26
28
|
}
|
|
27
29
|
exports.fetchUserAsync = fetchUserAsync;
|
|
@@ -19,6 +19,7 @@ const humanReadableServiceName = {
|
|
|
19
19
|
[generated_1.StatuspageServiceName.EasUpdate]: 'EAS Update',
|
|
20
20
|
[generated_1.StatuspageServiceName.GithubApiRequests]: 'GitHub API Requests',
|
|
21
21
|
[generated_1.StatuspageServiceName.GithubWebhooks]: 'Github Webhooks',
|
|
22
|
+
[generated_1.StatuspageServiceName.EasWorkflows]: 'EAS Workflows',
|
|
22
23
|
};
|
|
23
24
|
function warnAboutServiceOutage(service) {
|
|
24
25
|
if (service.status === generated_1.StatuspageServiceStatus.Operational) {
|