eas-cli 3.18.2 → 4.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 +76 -65
- package/build/channel/branch-mapping.d.ts +1 -0
- package/build/channel/branch-mapping.js +11 -1
- package/build/channel/print-utils.d.ts +2 -0
- package/build/channel/print-utils.js +39 -0
- package/build/channel/queries.js +3 -3
- package/build/channel/utils.d.ts +0 -11
- package/build/channel/utils.js +1 -93
- package/build/commands/channel/edit.js +6 -1
- package/build/commands/channel/rollout.d.ts +14 -2
- package/build/commands/channel/rollout.js +106 -270
- package/build/commands/update/republish.d.ts +2 -21
- package/build/commands/update/republish.js +15 -6
- package/build/devices/actions/create/action.d.ts +2 -1
- package/build/devices/actions/create/action.js +10 -1
- package/build/devices/actions/create/currentMachineMethod.d.ts +3 -0
- package/build/devices/actions/create/currentMachineMethod.js +100 -0
- package/build/devices/actions/create/developerPortalMethod.js +2 -1
- package/build/devices/actions/create/inputMethod.d.ts +0 -1
- package/build/devices/actions/create/inputMethod.js +6 -64
- package/build/devices/actions/create/utils.d.ts +10 -0
- package/build/devices/actions/create/utils.js +73 -0
- package/build/devices/manager.js +3 -3
- package/build/devices/utils/errors.d.ts +3 -0
- package/build/devices/utils/errors.js +7 -1
- package/build/devices/utils/formatDevice.js +1 -0
- package/build/graphql/generated.d.ts +5 -4
- package/build/graphql/generated.js +1 -0
- package/build/graphql/types/credentials/AppleDevice.js +1 -0
- package/build/rollout/actions/CreateRollout.d.ts +2 -0
- package/build/rollout/actions/CreateRollout.js +79 -5
- package/build/rollout/actions/EditRollout.js +5 -2
- package/build/rollout/actions/EndRollout.d.ts +6 -3
- package/build/rollout/actions/EndRollout.js +22 -21
- package/build/rollout/actions/ManageRollout.d.ts +3 -3
- package/build/rollout/actions/ManageRollout.js +1 -1
- package/build/rollout/actions/NonInteractiveRollout.d.ts +6 -4
- package/build/rollout/actions/NonInteractiveRollout.js +1 -1
- package/build/rollout/actions/RolloutMainMenu.d.ts +4 -4
- package/build/rollout/actions/RolloutMainMenu.js +14 -5
- package/build/rollout/actions/SelectRuntime.d.ts +4 -7
- package/build/rollout/actions/SelectRuntime.js +22 -39
- package/build/rollout/branch-mapping.js +2 -2
- package/build/rollout/utils.d.ts +1 -1
- package/build/rollout/utils.js +5 -5
- package/build/update/republish.d.ts +3 -1
- package/build/update/republish.js +38 -15
- package/build/utils/relay.js +3 -9
- package/oclif.manifest.json +1 -1
- package/package.json +3 -3
- package/build/commands/channel/rollout-preview.d.ts +0 -32
- package/build/commands/channel/rollout-preview.js +0 -109
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.CreateRollout = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
|
+
const config_plugins_1 = require("@expo/config-plugins");
|
|
5
6
|
const assert_1 = tslib_1.__importDefault(require("assert"));
|
|
6
7
|
const SelectBranch_1 = require("../../branch/actions/SelectBranch");
|
|
7
8
|
const branch_mapping_1 = require("../../channel/branch-mapping");
|
|
@@ -12,6 +13,7 @@ const ChannelQuery_1 = require("../../graphql/queries/ChannelQuery");
|
|
|
12
13
|
const UpdateQuery_1 = require("../../graphql/queries/UpdateQuery");
|
|
13
14
|
const log_1 = tslib_1.__importDefault(require("../../log"));
|
|
14
15
|
const prompts_1 = require("../../prompts");
|
|
16
|
+
const filter_1 = require("../../utils/expodash/filter");
|
|
15
17
|
const branch_mapping_2 = require("../branch-mapping");
|
|
16
18
|
const utils_2 = require("../utils");
|
|
17
19
|
const SelectRuntime_1 = require("./SelectRuntime");
|
|
@@ -51,7 +53,7 @@ class CreateRollout {
|
|
|
51
53
|
}
|
|
52
54
|
const runtimeVersion = (_a = this.options.runtimeVersion) !== null && _a !== void 0 ? _a : (await this.selectRuntimeVersionAsync(ctx, branchInfoToRollout, defaultBranchId));
|
|
53
55
|
log_1.default.newLine();
|
|
54
|
-
const promptMessage = `What percent of users should be
|
|
56
|
+
const promptMessage = `What percent of users should be rolled out to branch ${branchInfoToRollout.name}?`;
|
|
55
57
|
const percent = (_b = this.options.percent) !== null && _b !== void 0 ? _b : (await (0, utils_2.promptForRolloutPercentAsync)({ promptMessage }));
|
|
56
58
|
const rolloutBranchMapping = (0, branch_mapping_2.createRolloutBranchMapping)({
|
|
57
59
|
defaultBranchId,
|
|
@@ -125,20 +127,92 @@ class CreateRollout {
|
|
|
125
127
|
channelName: this.channelInfo.name,
|
|
126
128
|
});
|
|
127
129
|
const defaultBranchRtvAgnostic = (0, utils_1.getUpdateBranch)(channelObjectRtvAgnostic, defaultBranchId);
|
|
128
|
-
const
|
|
130
|
+
const selectSharedRuntimeAction = new SelectRuntime_1.SelectRuntime(branchToRollout, {
|
|
129
131
|
anotherBranchToIntersectRuntimesBy: defaultBranchRtvAgnostic,
|
|
130
132
|
});
|
|
131
|
-
|
|
133
|
+
const sharedRuntime = await selectSharedRuntimeAction.runAsync(ctx);
|
|
134
|
+
if (sharedRuntime) {
|
|
135
|
+
return sharedRuntime;
|
|
136
|
+
}
|
|
137
|
+
return await this.selectRuntimeVersionFromAlternativeSourceAsync(ctx, branchToRollout, defaultBranchRtvAgnostic);
|
|
138
|
+
}
|
|
139
|
+
async selectRuntimeVersionFromAlternativeSourceAsync(ctx, branchToRollout, defaultBranch) {
|
|
140
|
+
const { runtimeSource: selectedRuntimeSource } = await (0, prompts_1.promptAsync)({
|
|
141
|
+
type: 'select',
|
|
142
|
+
name: 'runtimeSource',
|
|
143
|
+
message: `What would you like to do?`,
|
|
144
|
+
choices: [
|
|
145
|
+
{
|
|
146
|
+
value: 'DEFAULT_BRANCH_RUNTIME',
|
|
147
|
+
title: `Find a runtime supported on the ${defaultBranch.name} branch`,
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
value: 'ROLLED_OUT_BRANCH_RUNTIME',
|
|
151
|
+
title: `Find a runtime supported on the ${branchToRollout.name} branch`,
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
value: 'PROJECT_RUNTIME',
|
|
155
|
+
title: 'Use the runtime specified in your project config',
|
|
156
|
+
},
|
|
157
|
+
],
|
|
158
|
+
});
|
|
159
|
+
if (selectedRuntimeSource === 'DEFAULT_BRANCH_RUNTIME') {
|
|
160
|
+
const selectDefaultBranchRuntimeAction = new SelectRuntime_1.SelectRuntime(defaultBranch);
|
|
161
|
+
const defaultBranchRuntime = await selectDefaultBranchRuntimeAction.runAsync(ctx);
|
|
162
|
+
if (defaultBranchRuntime) {
|
|
163
|
+
return defaultBranchRuntime;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
else if (selectedRuntimeSource === 'ROLLED_OUT_BRANCH_RUNTIME') {
|
|
167
|
+
const selectBranchToRolloutRuntimeAction = new SelectRuntime_1.SelectRuntime(branchToRollout);
|
|
168
|
+
const branchToRolloutRuntime = await selectBranchToRolloutRuntimeAction.runAsync(ctx);
|
|
169
|
+
if (branchToRolloutRuntime) {
|
|
170
|
+
return branchToRolloutRuntime;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
else if (selectedRuntimeSource === 'PROJECT_RUNTIME') {
|
|
174
|
+
return await this.selectRuntimeVersionFromProjectConfigAsync(ctx);
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
throw new Error(`Unexpected runtime source: ${selectedRuntimeSource}`);
|
|
178
|
+
}
|
|
179
|
+
return await this.selectRuntimeVersionFromAlternativeSourceAsync(ctx, branchToRollout, defaultBranch);
|
|
180
|
+
}
|
|
181
|
+
async selectRuntimeVersionFromProjectConfigAsync(ctx) {
|
|
182
|
+
const platforms = ['ios', 'android'];
|
|
183
|
+
const runtimes = platforms
|
|
184
|
+
.map(platform => config_plugins_1.Updates.getRuntimeVersion(ctx.app.exp, platform))
|
|
185
|
+
.filter(filter_1.truthy);
|
|
186
|
+
const dedupedRuntimes = [...new Set(runtimes)];
|
|
187
|
+
if (dedupedRuntimes.length === 0) {
|
|
188
|
+
throw new Error(`Your project config doesn't specify a runtime. Ensure your project is configured correctly for EAS Update by running \`eas update:configure\``);
|
|
189
|
+
}
|
|
190
|
+
else if (dedupedRuntimes.length === 1) {
|
|
191
|
+
const runtime = dedupedRuntimes[0];
|
|
192
|
+
log_1.default.log(`🔧 Your project config currently supports runtime ${runtime}`);
|
|
193
|
+
return runtime;
|
|
194
|
+
}
|
|
195
|
+
const { runtime: selectedRuntime } = await (0, prompts_1.promptAsync)({
|
|
196
|
+
type: 'select',
|
|
197
|
+
name: 'runtime',
|
|
198
|
+
message: `Select a runtime supported by your project config`,
|
|
199
|
+
choices: runtimes.map((runtime, index) => ({
|
|
200
|
+
title: `${runtime} ${index === 0 ? '[iOS runtime]' : '[Android runtime]'}`,
|
|
201
|
+
value: runtime,
|
|
202
|
+
})),
|
|
203
|
+
});
|
|
204
|
+
return selectedRuntime;
|
|
132
205
|
}
|
|
133
206
|
async selectBranchAsync(ctx, defaultBranchId) {
|
|
134
207
|
const selectBranchAction = new SelectBranch_1.SelectBranch({
|
|
135
|
-
printedType: 'branch to
|
|
208
|
+
printedType: 'branch to roll out',
|
|
136
209
|
// we don't want to show the default branch as an option
|
|
137
210
|
filterPredicate: (branchInfo) => branchInfo.id !== defaultBranchId,
|
|
138
211
|
});
|
|
139
212
|
const branchInfo = await selectBranchAction.runAsync(ctx);
|
|
140
213
|
if (!branchInfo) {
|
|
141
|
-
|
|
214
|
+
// We know the user has at least one branch, since we have `defaultBranchId`
|
|
215
|
+
throw new Error(`You don't have a second branch to roll out. Create it with 'eas branch:create'`);
|
|
142
216
|
}
|
|
143
217
|
return branchInfo;
|
|
144
218
|
}
|
|
@@ -33,12 +33,15 @@ class EditRollout {
|
|
|
33
33
|
const channelObject = await this.getChannelObjectAsync(ctx);
|
|
34
34
|
const rollout = (0, branch_mapping_1.getRollout)(channelObject);
|
|
35
35
|
const { rolledOutBranch, defaultBranch } = rollout;
|
|
36
|
-
const promptMessage = `What percent of users should be
|
|
36
|
+
const promptMessage = `What percent of users should be rolled out to the ${rolledOutBranch.name} branch ?`;
|
|
37
37
|
const percent = (_a = this.options.percent) !== null && _a !== void 0 ? _a : (await (0, utils_1.promptForRolloutPercentAsync)({ promptMessage }));
|
|
38
|
+
if (percent === 0 || percent === 100) {
|
|
39
|
+
log_1.default.warn(`Editing the percent to ${percent} will not end the rollout. You'll need to end the rollout from the main menu.`);
|
|
40
|
+
}
|
|
38
41
|
const oldBranchMapping = (0, branch_mapping_1.getRolloutBranchMapping)(channelObject.branchMapping);
|
|
39
42
|
const newBranchMapping = (0, branch_mapping_1.editRolloutBranchMapping)(oldBranchMapping, percent);
|
|
40
43
|
log_1.default.newLine();
|
|
41
|
-
log_1.default.log(`📝
|
|
44
|
+
log_1.default.log(`📝 ${chalk_1.default.bold(percent)}% of users will be rolled out to the ${chalk_1.default.bold(rolledOutBranch.name)} branch and ${chalk_1.default.bold(100 - percent)}% will remain on the ${chalk_1.default.bold(defaultBranch.name)} branch.`);
|
|
42
45
|
const confirmEdit = await this.confirmEditAsync(ctx);
|
|
43
46
|
if (!confirmEdit) {
|
|
44
47
|
throw new Error('Aborting...');
|
|
@@ -3,9 +3,12 @@ import { UpdateChannelBasicInfoFragment } from '../../graphql/generated';
|
|
|
3
3
|
import { UpdateChannelObject } from '../../graphql/queries/ChannelQuery';
|
|
4
4
|
import { Rollout } from '../branch-mapping';
|
|
5
5
|
export declare enum EndOutcome {
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
REPUBLISH_AND_REVERT = "republish-and-revert",
|
|
7
|
+
REVERT = "revert"
|
|
8
8
|
}
|
|
9
|
+
export type GeneralOptions = {
|
|
10
|
+
privateKeyPath: string | null;
|
|
11
|
+
};
|
|
9
12
|
export type NonInteractiveOptions = {
|
|
10
13
|
outcome: EndOutcome;
|
|
11
14
|
};
|
|
@@ -15,7 +18,7 @@ export type NonInteractiveOptions = {
|
|
|
15
18
|
export declare class EndRollout implements EASUpdateAction<UpdateChannelBasicInfoFragment> {
|
|
16
19
|
private channelInfo;
|
|
17
20
|
private options;
|
|
18
|
-
constructor(channelInfo: UpdateChannelBasicInfoFragment, options
|
|
21
|
+
constructor(channelInfo: UpdateChannelBasicInfoFragment, options: Partial<NonInteractiveOptions> & GeneralOptions);
|
|
19
22
|
runAsync(ctx: EASUpdateContext): Promise<UpdateChannelBasicInfoFragment>;
|
|
20
23
|
getChannelObjectAsync(ctx: EASUpdateContext): Promise<UpdateChannelObject>;
|
|
21
24
|
selectOutcomeAsync(rollout: Rollout): Promise<EndOutcome>;
|
|
@@ -10,13 +10,14 @@ const ChannelQuery_1 = require("../../graphql/queries/ChannelQuery");
|
|
|
10
10
|
const log_1 = tslib_1.__importDefault(require("../../log"));
|
|
11
11
|
const prompts_1 = require("../../prompts");
|
|
12
12
|
const republish_1 = require("../../update/republish");
|
|
13
|
+
const code_signing_1 = require("../../utils/code-signing");
|
|
13
14
|
const formatFields_1 = tslib_1.__importDefault(require("../../utils/formatFields"));
|
|
14
15
|
const branch_mapping_2 = require("../branch-mapping");
|
|
15
16
|
const utils_1 = require("../utils");
|
|
16
17
|
var EndOutcome;
|
|
17
18
|
(function (EndOutcome) {
|
|
18
|
-
EndOutcome["
|
|
19
|
-
EndOutcome["
|
|
19
|
+
EndOutcome["REPUBLISH_AND_REVERT"] = "republish-and-revert";
|
|
20
|
+
EndOutcome["REVERT"] = "revert";
|
|
20
21
|
})(EndOutcome = exports.EndOutcome || (exports.EndOutcome = {}));
|
|
21
22
|
function isNonInteractiveOptions(options) {
|
|
22
23
|
return !!options.outcome;
|
|
@@ -28,7 +29,7 @@ function assertNonInteractiveOptions(options) {
|
|
|
28
29
|
* End an existing rollout for the project.
|
|
29
30
|
*/
|
|
30
31
|
class EndRollout {
|
|
31
|
-
constructor(channelInfo, options
|
|
32
|
+
constructor(channelInfo, options) {
|
|
32
33
|
this.channelInfo = channelInfo;
|
|
33
34
|
this.options = options;
|
|
34
35
|
}
|
|
@@ -44,18 +45,15 @@ class EndRollout {
|
|
|
44
45
|
const rolledOutUpdateGroup = rolledOutBranch.updateGroups[0];
|
|
45
46
|
let outcome;
|
|
46
47
|
if (!rolledOutUpdateGroup) {
|
|
47
|
-
log_1.default.log(`⚠️ There is no
|
|
48
|
-
(0, assert_1.default)(this.options.outcome !== EndOutcome.
|
|
49
|
-
outcome = EndOutcome.
|
|
48
|
+
log_1.default.log(`⚠️ There is no update group being served on the ${rolledOutBranch.name} branch.`);
|
|
49
|
+
(0, assert_1.default)(this.options.outcome !== EndOutcome.REPUBLISH_AND_REVERT, `The only valid outcome for this rollout is to revert users back to the ${rollout.defaultBranch.name} branch. `);
|
|
50
|
+
outcome = EndOutcome.REVERT;
|
|
50
51
|
}
|
|
51
52
|
else {
|
|
52
53
|
outcome = (_a = this.options.outcome) !== null && _a !== void 0 ? _a : (await this.selectOutcomeAsync(rollout));
|
|
53
54
|
}
|
|
54
55
|
const didConfirm = await this.confirmOutcomeAsync(ctx, outcome, rollout);
|
|
55
56
|
if (!didConfirm) {
|
|
56
|
-
if (!rolledOutUpdateGroup) {
|
|
57
|
-
log_1.default.log(`If you wish to stop serving updates to your users, you can edit your rollout to 100% on ${chalk_1.default.bold(rolledOutBranch.name)} instead`);
|
|
58
|
-
}
|
|
59
57
|
throw new Error('Aborting...');
|
|
60
58
|
}
|
|
61
59
|
return await this.performOutcomeAsync(ctx, rollout, outcome);
|
|
@@ -81,34 +79,36 @@ class EndRollout {
|
|
|
81
79
|
const defaultUpdateGroup = defaultBranch.updateGroups[0];
|
|
82
80
|
const outcomes = [
|
|
83
81
|
{
|
|
84
|
-
value: EndOutcome.
|
|
82
|
+
value: EndOutcome.REPUBLISH_AND_REVERT,
|
|
85
83
|
title: (0, utils_1.formatBranchWithUpdateGroup)(rolledOutUpdateGroup, rolledOutBranch, percentRolledOut),
|
|
86
84
|
},
|
|
87
85
|
{
|
|
88
|
-
value: EndOutcome.
|
|
86
|
+
value: EndOutcome.REVERT,
|
|
89
87
|
title: (0, utils_1.formatBranchWithUpdateGroup)(defaultUpdateGroup, defaultBranch, 100 - percentRolledOut),
|
|
90
88
|
},
|
|
91
89
|
];
|
|
92
90
|
const { outcome: selectedOutcome } = await (0, prompts_1.promptAsync)({
|
|
93
91
|
type: 'select',
|
|
94
92
|
name: 'outcome',
|
|
95
|
-
message: `Which
|
|
93
|
+
message: `Which update group would you like to serve?`,
|
|
96
94
|
choices: outcomes,
|
|
97
95
|
});
|
|
98
96
|
log_1.default.newLine();
|
|
99
|
-
if (selectedOutcome === EndOutcome.
|
|
100
|
-
log_1.default.log(
|
|
97
|
+
if (selectedOutcome === EndOutcome.REPUBLISH_AND_REVERT) {
|
|
98
|
+
log_1.default.log(`➡️ 📱 The update group you chose is served by branch ${chalk_1.default.bold(rolledOutBranch.name)}`);
|
|
101
99
|
}
|
|
102
100
|
else {
|
|
103
|
-
log_1.default.log(
|
|
101
|
+
log_1.default.log(`➡️ 📱 The update group you chose is served by branch ${chalk_1.default.bold(defaultBranch.name)}`);
|
|
104
102
|
}
|
|
105
103
|
return selectedOutcome;
|
|
106
104
|
}
|
|
107
105
|
async performOutcomeAsync(ctx, rollout, outcome) {
|
|
106
|
+
var _a;
|
|
108
107
|
const { graphqlClient, app } = ctx;
|
|
109
108
|
const { rolledOutBranch, defaultBranch } = rollout;
|
|
110
109
|
const rolledOutUpdateGroup = rolledOutBranch.updateGroups[0];
|
|
111
|
-
if (outcome === EndOutcome.
|
|
110
|
+
if (outcome === EndOutcome.REPUBLISH_AND_REVERT) {
|
|
111
|
+
const codeSigningInfo = await (0, code_signing_1.getCodeSigningInfoAsync)(ctx.app.exp, (_a = this.options.privateKeyPath) !== null && _a !== void 0 ? _a : undefined);
|
|
112
112
|
const arbitraryUpdate = rolledOutUpdateGroup[0];
|
|
113
113
|
const { message: oldUpdateMessage, group: oldGroupId } = arbitraryUpdate;
|
|
114
114
|
const newUpdateMessage = `Republish "${oldUpdateMessage}" - group: ${oldGroupId}`;
|
|
@@ -121,6 +121,7 @@ class EndRollout {
|
|
|
121
121
|
branchId: update.branch.id,
|
|
122
122
|
branchName: update.branch.name,
|
|
123
123
|
})),
|
|
124
|
+
codeSigningInfo,
|
|
124
125
|
targetBranch: { branchId: defaultBranch.id, branchName: defaultBranch.name },
|
|
125
126
|
updateMessage: newUpdateMessage,
|
|
126
127
|
});
|
|
@@ -131,7 +132,7 @@ class EndRollout {
|
|
|
131
132
|
branchMapping: JSON.stringify(alwaysTrueDefaultBranchMapping),
|
|
132
133
|
});
|
|
133
134
|
log_1.default.addNewLineIfNone();
|
|
134
|
-
log_1.default.log(
|
|
135
|
+
log_1.default.log(`⬅️ Reverted all users back to branch ${chalk_1.default.bold(defaultBranch.name)}`);
|
|
135
136
|
log_1.default.log(`✅ Successfully ended rollout`);
|
|
136
137
|
return newChannelInfo;
|
|
137
138
|
}
|
|
@@ -142,19 +143,19 @@ class EndRollout {
|
|
|
142
143
|
}
|
|
143
144
|
const { rolledOutBranch, defaultBranch } = rollout;
|
|
144
145
|
log_1.default.newLine();
|
|
145
|
-
if (selectedOutcome === EndOutcome.
|
|
146
|
+
if (selectedOutcome === EndOutcome.REPUBLISH_AND_REVERT) {
|
|
146
147
|
log_1.default.log(`Ending the rollout will do the following:`);
|
|
147
148
|
const actions = (0, formatFields_1.default)([
|
|
148
149
|
{
|
|
149
150
|
label: '1.',
|
|
150
|
-
value: `🔁 Republish the
|
|
151
|
+
value: `🔁 Republish the update group from ${chalk_1.default.bold(rolledOutBranch.name)} onto ${chalk_1.default.bold(defaultBranch.name)}`,
|
|
151
152
|
},
|
|
152
|
-
{ label: '2.', value: `⬅️
|
|
153
|
+
{ label: '2.', value: `⬅️ Revert all users back to ${chalk_1.default.bold(defaultBranch.name)}` },
|
|
153
154
|
]);
|
|
154
155
|
log_1.default.log(actions);
|
|
155
156
|
}
|
|
156
157
|
else {
|
|
157
|
-
log_1.default.log(`⬅️ Ending the rollout will
|
|
158
|
+
log_1.default.log(`⬅️ Ending the rollout will revert all users back to ${chalk_1.default.bold(defaultBranch.name)}`);
|
|
158
159
|
}
|
|
159
160
|
return await (0, prompts_1.confirmAsync)({
|
|
160
161
|
message: `Continue?`,
|
|
@@ -2,7 +2,7 @@ import { EASUpdateAction, EASUpdateContext } from '../../eas-update/utils';
|
|
|
2
2
|
import { UpdateChannelBasicInfoFragment } from '../../graphql/generated';
|
|
3
3
|
import { UpdateChannelObject } from '../../graphql/queries/ChannelQuery';
|
|
4
4
|
import { NonInteractiveOptions as EditRolloutNonInteractiveOptions } from './EditRollout';
|
|
5
|
-
import { NonInteractiveOptions as EndRolloutNonInteractiveOptions } from './EndRollout';
|
|
5
|
+
import { GeneralOptions as EndRolloutGeneralOptions, NonInteractiveOptions as EndRolloutNonInteractiveOptions } from './EndRollout';
|
|
6
6
|
export declare enum ManageRolloutActions {
|
|
7
7
|
EDIT = "Edit",
|
|
8
8
|
END = "End",
|
|
@@ -14,10 +14,10 @@ export declare enum ManageRolloutActions {
|
|
|
14
14
|
export declare class ManageRollout implements EASUpdateAction<EASUpdateAction> {
|
|
15
15
|
private channelInfo;
|
|
16
16
|
private options;
|
|
17
|
-
constructor(channelInfo: UpdateChannelBasicInfoFragment, options
|
|
17
|
+
constructor(channelInfo: UpdateChannelBasicInfoFragment, options: {
|
|
18
18
|
callingAction?: EASUpdateAction;
|
|
19
19
|
action?: ManageRolloutActions.EDIT | ManageRolloutActions.END;
|
|
20
|
-
} & Partial<EditRolloutNonInteractiveOptions> & Partial<EndRolloutNonInteractiveOptions>);
|
|
20
|
+
} & Partial<EditRolloutNonInteractiveOptions> & Partial<EndRolloutNonInteractiveOptions> & EndRolloutGeneralOptions);
|
|
21
21
|
runAsync(ctx: EASUpdateContext): Promise<EASUpdateAction>;
|
|
22
22
|
selectActionAsync(): Promise<ManageRolloutActions>;
|
|
23
23
|
getChannelObjectAsync(ctx: EASUpdateContext): Promise<UpdateChannelObject>;
|
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
import { EASUpdateAction, EASUpdateContext } from '../../eas-update/utils';
|
|
2
2
|
import { UpdateChannelBasicInfoFragment } from '../../graphql/generated';
|
|
3
|
+
import { CodeSigningInfo } from '../../utils/code-signing';
|
|
3
4
|
import { NonInteractiveOptions as CreateRolloutNonInteractiveOptions } from './CreateRollout';
|
|
4
5
|
import { NonInteractiveOptions as EditRolloutNonInteractiveOptions } from './EditRollout';
|
|
5
|
-
import { NonInteractiveOptions as EndRolloutNonInteractiveOptions } from './EndRollout';
|
|
6
|
+
import { GeneralOptions as EndRolloutGeneralOptions, NonInteractiveOptions as EndRolloutNonInteractiveOptions } from './EndRollout';
|
|
6
7
|
import { RolloutActions } from './RolloutMainMenu';
|
|
7
8
|
/**
|
|
8
9
|
* Control a rollout in non interactive mode.
|
|
9
10
|
*/
|
|
10
11
|
export declare class NonInteractiveRollout implements EASUpdateAction<void> {
|
|
11
12
|
private options;
|
|
12
|
-
constructor(options
|
|
13
|
+
constructor(options: {
|
|
13
14
|
channelName?: string;
|
|
15
|
+
codeSigningInfo?: CodeSigningInfo;
|
|
14
16
|
action?: RolloutActions;
|
|
15
|
-
} & Partial<EditRolloutNonInteractiveOptions> & Partial<EndRolloutNonInteractiveOptions> & Partial<CreateRolloutNonInteractiveOptions>);
|
|
17
|
+
} & Partial<EditRolloutNonInteractiveOptions> & Partial<EndRolloutNonInteractiveOptions> & EndRolloutGeneralOptions & Partial<CreateRolloutNonInteractiveOptions>);
|
|
16
18
|
runAsync(ctx: EASUpdateContext): Promise<void>;
|
|
17
|
-
runActionAsync(ctx: EASUpdateContext, action: RolloutActions, channelInfo: UpdateChannelBasicInfoFragment, options: Partial<EditRolloutNonInteractiveOptions> & Partial<EndRolloutNonInteractiveOptions> & Partial<CreateRolloutNonInteractiveOptions>): Promise<UpdateChannelBasicInfoFragment>;
|
|
19
|
+
runActionAsync(ctx: EASUpdateContext, action: RolloutActions, channelInfo: UpdateChannelBasicInfoFragment, options: Partial<EditRolloutNonInteractiveOptions> & Partial<EndRolloutNonInteractiveOptions> & EndRolloutGeneralOptions & Partial<CreateRolloutNonInteractiveOptions>): Promise<UpdateChannelBasicInfoFragment>;
|
|
18
20
|
}
|
|
@@ -2,7 +2,7 @@ import { EASUpdateAction, EASUpdateContext } from '../../eas-update/utils';
|
|
|
2
2
|
import { UpdateChannelBasicInfoFragment } from '../../graphql/generated';
|
|
3
3
|
import { NonInteractiveOptions as CreateRolloutNonInteractiveOptions } from './CreateRollout';
|
|
4
4
|
import { NonInteractiveOptions as EditRolloutNonInteractiveOptions } from './EditRollout';
|
|
5
|
-
import { NonInteractiveOptions as EndRolloutNonInteractiveOptions } from './EndRollout';
|
|
5
|
+
import { GeneralOptions as EndRolloutGeneralOptions, NonInteractiveOptions as EndRolloutNonInteractiveOptions } from './EndRollout';
|
|
6
6
|
import { ManageRolloutActions } from './ManageRollout';
|
|
7
7
|
export declare enum MainMenuActions {
|
|
8
8
|
CREATE_NEW = "Create a new rollout",
|
|
@@ -14,14 +14,14 @@ export type RolloutActions = MainMenuActions.CREATE_NEW | ManageRolloutActions.E
|
|
|
14
14
|
*/
|
|
15
15
|
export declare class RolloutMainMenu implements EASUpdateAction<void> {
|
|
16
16
|
private options;
|
|
17
|
-
constructor(options
|
|
17
|
+
constructor(options: {
|
|
18
18
|
channelName?: string;
|
|
19
19
|
action?: RolloutActions;
|
|
20
|
-
} & Partial<EditRolloutNonInteractiveOptions> & Partial<EndRolloutNonInteractiveOptions> & Partial<CreateRolloutNonInteractiveOptions>);
|
|
20
|
+
} & Partial<EditRolloutNonInteractiveOptions> & Partial<EndRolloutNonInteractiveOptions> & EndRolloutGeneralOptions & Partial<CreateRolloutNonInteractiveOptions>);
|
|
21
21
|
runAsync(ctx: EASUpdateContext): Promise<void>;
|
|
22
22
|
runActionAsync(ctx: EASUpdateContext, menuAction: MainMenuActions): Promise<null>;
|
|
23
23
|
selectRolloutAsync(ctx: EASUpdateContext): Promise<UpdateChannelBasicInfoFragment | null>;
|
|
24
|
-
|
|
24
|
+
selectChannelToRolloutAsync(ctx: EASUpdateContext): Promise<UpdateChannelBasicInfoFragment>;
|
|
25
25
|
resolveChannelNameAsync(ctx: EASUpdateContext, channelName: string): Promise<UpdateChannelBasicInfoFragment>;
|
|
26
26
|
toMainMenuAction(action: RolloutActions): MainMenuActions;
|
|
27
27
|
promptMenuActionAsync(): Promise<MainMenuActions>;
|
|
@@ -20,7 +20,7 @@ var MainMenuActions;
|
|
|
20
20
|
* Manage a rollout for the project.
|
|
21
21
|
*/
|
|
22
22
|
class RolloutMainMenu {
|
|
23
|
-
constructor(options
|
|
23
|
+
constructor(options) {
|
|
24
24
|
this.options = options;
|
|
25
25
|
}
|
|
26
26
|
async runAsync(ctx) {
|
|
@@ -38,7 +38,7 @@ class RolloutMainMenu {
|
|
|
38
38
|
case MainMenuActions.CREATE_NEW: {
|
|
39
39
|
const channelInfo = channelName
|
|
40
40
|
? await this.resolveChannelNameAsync(ctx, channelName)
|
|
41
|
-
: await this.
|
|
41
|
+
: await this.selectChannelToRolloutAsync(ctx);
|
|
42
42
|
await new CreateRollout_1.CreateRollout(channelInfo, this.options).runAsync(ctx);
|
|
43
43
|
return null;
|
|
44
44
|
}
|
|
@@ -67,11 +67,20 @@ class RolloutMainMenu {
|
|
|
67
67
|
const channelInfo = await selectRollout.runAsync(ctx);
|
|
68
68
|
return channelInfo;
|
|
69
69
|
}
|
|
70
|
-
async
|
|
71
|
-
|
|
70
|
+
async selectChannelToRolloutAsync(ctx) {
|
|
71
|
+
let hasSomeChannel = false;
|
|
72
|
+
const selectChannelAction = new SelectChannel_1.SelectChannel({
|
|
73
|
+
filterPredicate: (channelInfo) => {
|
|
74
|
+
hasSomeChannel = true;
|
|
75
|
+
return !(0, branch_mapping_1.isRollout)(channelInfo);
|
|
76
|
+
},
|
|
77
|
+
});
|
|
72
78
|
const channelInfo = await selectChannelAction.runAsync(ctx);
|
|
73
79
|
if (!channelInfo) {
|
|
74
|
-
|
|
80
|
+
const error = hasSomeChannel
|
|
81
|
+
? new Error('All your channels are already part of a rollout.')
|
|
82
|
+
: new Error(`You dont have any channels. Create one with \`eas channel:create\``);
|
|
83
|
+
throw error;
|
|
75
84
|
}
|
|
76
85
|
return channelInfo;
|
|
77
86
|
}
|
|
@@ -5,7 +5,7 @@ import { Connection } from '../../utils/relay';
|
|
|
5
5
|
/**
|
|
6
6
|
* Select a runtime from a branch
|
|
7
7
|
*/
|
|
8
|
-
export declare class SelectRuntime implements EASUpdateAction<string> {
|
|
8
|
+
export declare class SelectRuntime implements EASUpdateAction<string | null> {
|
|
9
9
|
private branchInfo;
|
|
10
10
|
private options;
|
|
11
11
|
private printedType;
|
|
@@ -14,23 +14,20 @@ export declare class SelectRuntime implements EASUpdateAction<string> {
|
|
|
14
14
|
});
|
|
15
15
|
warnNoRuntime(): void;
|
|
16
16
|
formatCantFindRuntime(): string;
|
|
17
|
-
runAsync(ctx: EASUpdateContext): Promise<string>;
|
|
17
|
+
runAsync(ctx: EASUpdateContext): Promise<string | null>;
|
|
18
18
|
getNewestRuntimeAsync(graphqlClient: ExpoGraphqlClient, { appId, branchName, anotherBranchIdToIntersectRuntimesBy, }: {
|
|
19
19
|
appId: string;
|
|
20
20
|
branchName: string;
|
|
21
21
|
anotherBranchIdToIntersectRuntimesBy?: string;
|
|
22
|
-
}): Promise<Connection<RuntimeFragment
|
|
22
|
+
}): Promise<Connection<RuntimeFragment>>;
|
|
23
23
|
displayLatestUpdateGroupAsync({ graphqlClient, appId, branchName, runtime, }: {
|
|
24
24
|
graphqlClient: ExpoGraphqlClient;
|
|
25
25
|
appId: string;
|
|
26
26
|
branchName: string;
|
|
27
27
|
runtime: RuntimeFragment;
|
|
28
28
|
}): Promise<string>;
|
|
29
|
-
selectRuntimesAsync(graphqlClient: ExpoGraphqlClient, { appId,
|
|
29
|
+
selectRuntimesAsync(graphqlClient: ExpoGraphqlClient, { appId, batchSize, }: {
|
|
30
30
|
appId: string;
|
|
31
|
-
branchName: string;
|
|
32
|
-
anotherBranchIdToIntersectRuntimesBy?: string;
|
|
33
31
|
batchSize?: number;
|
|
34
32
|
}): Promise<RuntimeFragment | null>;
|
|
35
|
-
promptForRuntimeAsync(): Promise<string>;
|
|
36
33
|
}
|
|
@@ -11,12 +11,6 @@ const log_1 = tslib_1.__importStar(require("../../log"));
|
|
|
11
11
|
const prompts_1 = require("../../prompts");
|
|
12
12
|
const relay_1 = require("../../utils/relay");
|
|
13
13
|
const utils_2 = require("../utils");
|
|
14
|
-
function beginSentence(phrase) {
|
|
15
|
-
if (typeof phrase !== 'string' || phrase.length === 0) {
|
|
16
|
-
return phrase; // Return the input without any modification if it's not a string or empty
|
|
17
|
-
}
|
|
18
|
-
return phrase.charAt(0).toUpperCase() + phrase.slice(1);
|
|
19
|
-
}
|
|
20
14
|
/**
|
|
21
15
|
* Select a runtime from a branch
|
|
22
16
|
*/
|
|
@@ -32,8 +26,7 @@ class SelectRuntime {
|
|
|
32
26
|
if (this.options.anotherBranchToIntersectRuntimesBy) {
|
|
33
27
|
const intersectBranchName = this.options.anotherBranchToIntersectRuntimesBy.name;
|
|
34
28
|
log_1.default.warn(`⚠️ Branches ${this.branchInfo.name} and ${intersectBranchName} dont have any updates with the same runtime.`);
|
|
35
|
-
|
|
36
|
-
log_1.default.warn(`Your updates could be misconfigured. ${(0, log_1.learnMore)('https://expo.fyi/todo')}`);
|
|
29
|
+
log_1.default.warn(`Your updates could be misconfigured. ${(0, log_1.learnMore)('https://expo.fyi/eas-update-rollouts')}`);
|
|
37
30
|
}
|
|
38
31
|
else {
|
|
39
32
|
// no runtime on branch means no updates published on branch
|
|
@@ -41,10 +34,10 @@ class SelectRuntime {
|
|
|
41
34
|
}
|
|
42
35
|
}
|
|
43
36
|
formatCantFindRuntime() {
|
|
44
|
-
return `🕵️ Not finding the update you were looking for? ${(0, log_1.learnMore)('https://expo.fyi/
|
|
37
|
+
return `🕵️ Not finding the update you were looking for? ${(0, log_1.learnMore)('https://expo.fyi/eas-update-rollouts')}`;
|
|
45
38
|
}
|
|
46
39
|
async runAsync(ctx) {
|
|
47
|
-
var _a
|
|
40
|
+
var _a;
|
|
48
41
|
const { nonInteractive, graphqlClient, app } = ctx;
|
|
49
42
|
const { projectId } = app;
|
|
50
43
|
if (nonInteractive) {
|
|
@@ -55,14 +48,14 @@ class SelectRuntime {
|
|
|
55
48
|
branchName: this.branchInfo.name,
|
|
56
49
|
anotherBranchIdToIntersectRuntimesBy: (_a = this.options.anotherBranchToIntersectRuntimesBy) === null || _a === void 0 ? void 0 : _a.id,
|
|
57
50
|
});
|
|
58
|
-
if (
|
|
51
|
+
if (newestRuntimeConnection.edges.length === 0) {
|
|
59
52
|
log_1.default.addNewLineIfNone();
|
|
60
53
|
this.warnNoRuntime();
|
|
61
|
-
return
|
|
54
|
+
return null;
|
|
62
55
|
}
|
|
63
|
-
const
|
|
64
|
-
log_1.default.log(`✅ ${beginSentence(this.printedType)}${
|
|
65
|
-
if (
|
|
56
|
+
const onlyOneRuntime = newestRuntimeConnection.edges.length === 1 && !newestRuntimeConnection.pageInfo.hasNextPage;
|
|
57
|
+
log_1.default.log(`✅ ${beginSentence(this.printedType)}${onlyOneRuntime ? '' : 's'} detected`);
|
|
58
|
+
if (onlyOneRuntime) {
|
|
66
59
|
const runtime = newestRuntimeConnection.edges[0].node;
|
|
67
60
|
const formattedRuntimeWithGroup = await this.displayLatestUpdateGroupAsync({
|
|
68
61
|
graphqlClient,
|
|
@@ -82,14 +75,12 @@ class SelectRuntime {
|
|
|
82
75
|
else {
|
|
83
76
|
log_1.default.newLine();
|
|
84
77
|
log_1.default.warn(this.formatCantFindRuntime());
|
|
85
|
-
return
|
|
78
|
+
return null;
|
|
86
79
|
}
|
|
87
80
|
}
|
|
88
81
|
log_1.default.log(this.formatCantFindRuntime());
|
|
89
82
|
const selectedRuntime = await this.selectRuntimesAsync(graphqlClient, {
|
|
90
83
|
appId: projectId,
|
|
91
|
-
branchName: this.branchInfo.name,
|
|
92
|
-
anotherBranchIdToIntersectRuntimesBy: (_b = this.options.anotherBranchToIntersectRuntimesBy) === null || _b === void 0 ? void 0 : _b.id,
|
|
93
84
|
});
|
|
94
85
|
if (!selectedRuntime) {
|
|
95
86
|
throw new Error(`No ${this.printedType} selected`);
|
|
@@ -97,7 +88,7 @@ class SelectRuntime {
|
|
|
97
88
|
return selectedRuntime.version;
|
|
98
89
|
}
|
|
99
90
|
async getNewestRuntimeAsync(graphqlClient, { appId, branchName, anotherBranchIdToIntersectRuntimesBy, }) {
|
|
100
|
-
|
|
91
|
+
return await RuntimeQuery_1.RuntimeQuery.getRuntimesOnBranchAsync(graphqlClient, {
|
|
101
92
|
appId,
|
|
102
93
|
name: branchName,
|
|
103
94
|
first: 1,
|
|
@@ -105,11 +96,6 @@ class SelectRuntime {
|
|
|
105
96
|
branchId: anotherBranchIdToIntersectRuntimesBy,
|
|
106
97
|
},
|
|
107
98
|
});
|
|
108
|
-
const { edges } = connection;
|
|
109
|
-
if (edges.length === 0) {
|
|
110
|
-
return null;
|
|
111
|
-
}
|
|
112
|
-
return connection;
|
|
113
99
|
}
|
|
114
100
|
async displayLatestUpdateGroupAsync({ graphqlClient, appId, branchName, runtime, }) {
|
|
115
101
|
const updateGroups = await UpdateQuery_1.UpdateQuery.viewUpdateGroupsOnBranchAsync(graphqlClient, {
|
|
@@ -122,19 +108,20 @@ class SelectRuntime {
|
|
|
122
108
|
},
|
|
123
109
|
});
|
|
124
110
|
(0, assert_1.default)(updateGroups.length < 2, `Expected at most one update group. Received: ${JSON.stringify(updateGroups)}`);
|
|
125
|
-
return (0, utils_2.formatRuntimeWithUpdateGroup)(updateGroups[0], runtime);
|
|
111
|
+
return (0, utils_2.formatRuntimeWithUpdateGroup)(updateGroups[0], runtime, branchName);
|
|
126
112
|
}
|
|
127
|
-
async selectRuntimesAsync(graphqlClient, { appId,
|
|
113
|
+
async selectRuntimesAsync(graphqlClient, { appId, batchSize = 5, }) {
|
|
128
114
|
const queryAsync = async (queryParams) => {
|
|
115
|
+
var _a;
|
|
129
116
|
return await RuntimeQuery_1.RuntimeQuery.getRuntimesOnBranchAsync(graphqlClient, {
|
|
130
117
|
appId,
|
|
131
|
-
name:
|
|
118
|
+
name: this.branchInfo.name,
|
|
132
119
|
first: queryParams.first,
|
|
133
120
|
after: queryParams.after,
|
|
134
121
|
last: queryParams.last,
|
|
135
122
|
before: queryParams.before,
|
|
136
123
|
filter: {
|
|
137
|
-
branchId:
|
|
124
|
+
branchId: (_a = this.options.anotherBranchToIntersectRuntimesBy) === null || _a === void 0 ? void 0 : _a.id,
|
|
138
125
|
},
|
|
139
126
|
});
|
|
140
127
|
};
|
|
@@ -142,7 +129,7 @@ class SelectRuntime {
|
|
|
142
129
|
return await this.displayLatestUpdateGroupAsync({
|
|
143
130
|
graphqlClient,
|
|
144
131
|
appId,
|
|
145
|
-
branchName,
|
|
132
|
+
branchName: this.branchInfo.name,
|
|
146
133
|
runtime,
|
|
147
134
|
});
|
|
148
135
|
};
|
|
@@ -153,15 +140,11 @@ class SelectRuntime {
|
|
|
153
140
|
pageSize: batchSize,
|
|
154
141
|
});
|
|
155
142
|
}
|
|
156
|
-
async promptForRuntimeAsync() {
|
|
157
|
-
log_1.default.log(`You can input a runtime manually then publish an update later.`);
|
|
158
|
-
const { runtimeVersion } = await (0, prompts_1.promptAsync)({
|
|
159
|
-
type: 'text',
|
|
160
|
-
name: 'runtimeVersion',
|
|
161
|
-
message: 'Input a runtime version:',
|
|
162
|
-
initial: '1.0.0',
|
|
163
|
-
});
|
|
164
|
-
return runtimeVersion;
|
|
165
|
-
}
|
|
166
143
|
}
|
|
167
144
|
exports.SelectRuntime = SelectRuntime;
|
|
145
|
+
function beginSentence(phrase) {
|
|
146
|
+
if (typeof phrase !== 'string' || phrase.length === 0) {
|
|
147
|
+
return phrase; // Return the input without any modification if it's not a string or empty
|
|
148
|
+
}
|
|
149
|
+
return phrase.charAt(0).toUpperCase() + phrase.slice(1);
|
|
150
|
+
}
|
|
@@ -41,7 +41,7 @@ function getRolloutInfoFromBranchMapping(branchMapping) {
|
|
|
41
41
|
(0, branch_mapping_1.assertNumber)(operand);
|
|
42
42
|
return {
|
|
43
43
|
rolledOutBranchId,
|
|
44
|
-
percentRolledOut: operand * 100,
|
|
44
|
+
percentRolledOut: Math.round(operand * 100),
|
|
45
45
|
runtimeVersion,
|
|
46
46
|
defaultBranchId,
|
|
47
47
|
};
|
|
@@ -53,7 +53,7 @@ function getRolloutInfoFromBranchMapping(branchMapping) {
|
|
|
53
53
|
(0, branch_mapping_1.assertNumber)(operand);
|
|
54
54
|
return {
|
|
55
55
|
rolledOutBranchId,
|
|
56
|
-
percentRolledOut: operand * 100,
|
|
56
|
+
percentRolledOut: Math.round(operand * 100),
|
|
57
57
|
defaultBranchId,
|
|
58
58
|
};
|
|
59
59
|
}
|