eas-cli 1.1.0 → 2.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 +68 -46
- package/build/analytics/events.d.ts +4 -1
- package/build/analytics/events.js +3 -0
- package/build/build/createContext.js +1 -0
- package/build/build/ios/graphql.js +0 -1
- package/build/commandUtils/EasCommand.d.ts +2 -0
- package/build/commandUtils/EasCommand.js +44 -3
- package/build/commands/build/index.d.ts +2 -1
- package/build/commands/build/index.js +36 -18
- package/build/commands/submit.d.ts +2 -1
- package/build/commands/submit.js +28 -14
- package/build/commands/update/configure.js +54 -1
- package/build/commands/update/index.js +3 -0
- package/build/credentials/android/api/GraphqlClient.js +1 -1
- package/build/credentials/context.d.ts +3 -0
- package/build/credentials/context.js +1 -0
- package/build/credentials/ios/IosCredentialsProvider.d.ts +1 -0
- package/build/credentials/ios/IosCredentialsProvider.js +33 -5
- package/build/credentials/ios/api/GraphqlClient.js +1 -1
- package/build/credentials/ios/appstore/ascApiKey.d.ts +11 -0
- package/build/credentials/ios/appstore/ascApiKey.js +53 -3
- package/build/credentials/ios/appstore/bundleIdCapabilities.js +176 -15
- package/build/credentials/manager/ManageAndroid.js +2 -8
- package/build/credentials/manager/ManageIos.js +2 -4
- package/build/graphql/generated.d.ts +191 -39
- package/build/graphql/generated.js +39 -1
- package/build/{credentials/ios/api/graphql → graphql}/queries/AppQuery.d.ts +1 -1
- package/build/{credentials/ios/api/graphql → graphql}/queries/AppQuery.js +2 -2
- package/build/graphql/queries/EnvironmentSecretsQuery.d.ts +1 -1
- package/build/graphql/queries/EnvironmentSecretsQuery.js +2 -2
- package/build/graphql/queries/StatuspageServiceQuery.d.ts +4 -0
- package/build/graphql/queries/StatuspageServiceQuery.js +28 -0
- package/build/graphql/types/StatuspageService.d.ts +1 -0
- package/build/graphql/types/StatuspageService.js +19 -0
- package/build/project/ensureProjectExists.d.ts +0 -7
- package/build/project/ensureProjectExists.js +4 -14
- package/build/project/projectUtils.d.ts +0 -1
- package/build/project/projectUtils.js +9 -29
- package/build/submit/android/AndroidSubmitter.js +1 -1
- package/build/submit/submit.js +2 -2
- package/build/submit/utils/errors.js +2 -0
- package/build/utils/statuspageService.d.ts +2 -0
- package/build/utils/statuspageService.js +41 -0
- package/build/vcs/local.d.ts +1 -0
- package/build/vcs/local.js +11 -2
- package/oclif.manifest.json +1 -1
- package/package.json +4 -4
- package/build/graphql/queries/ProjectQuery.d.ts +0 -6
- package/build/graphql/queries/ProjectQuery.js +0 -24
|
@@ -14,5 +14,6 @@ export default class Submit extends EasCommand {
|
|
|
14
14
|
'non-interactive': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
15
15
|
};
|
|
16
16
|
runAsync(): Promise<void>;
|
|
17
|
-
private
|
|
17
|
+
private sanitizeFlags;
|
|
18
|
+
private ensurePlatformSelectedAsync;
|
|
18
19
|
}
|
package/build/commands/submit.js
CHANGED
|
@@ -5,6 +5,7 @@ const eas_json_1 = require("@expo/eas-json");
|
|
|
5
5
|
const core_1 = require("@oclif/core");
|
|
6
6
|
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
7
7
|
const EasCommand_1 = tslib_1.__importDefault(require("../commandUtils/EasCommand"));
|
|
8
|
+
const generated_1 = require("../graphql/generated");
|
|
8
9
|
const AppPlatform_1 = require("../graphql/types/AppPlatform");
|
|
9
10
|
const log_1 = tslib_1.__importDefault(require("../log"));
|
|
10
11
|
const platform_1 = require("../platform");
|
|
@@ -14,19 +15,22 @@ const context_1 = require("../submit/context");
|
|
|
14
15
|
const submit_1 = require("../submit/submit");
|
|
15
16
|
const urls_1 = require("../submit/utils/urls");
|
|
16
17
|
const profiles_1 = require("../utils/profiles");
|
|
18
|
+
const statuspageService_1 = require("../utils/statuspageService");
|
|
17
19
|
class Submit extends EasCommand_1.default {
|
|
18
20
|
async runAsync() {
|
|
19
21
|
const { flags: rawFlags } = await this.parse(Submit);
|
|
20
|
-
const flags =
|
|
22
|
+
const flags = this.sanitizeFlags(rawFlags);
|
|
21
23
|
const projectDir = await (0, projectUtils_1.findProjectRootAsync)();
|
|
22
24
|
const exp = (0, expoConfig_1.getExpoConfig)(projectDir);
|
|
23
25
|
const projectId = await (0, projectUtils_1.getProjectIdAsync)(exp);
|
|
24
|
-
|
|
26
|
+
await (0, statuspageService_1.maybeWarnAboutEasOutagesAsync)([generated_1.StatuspageServiceName.EasSubmit]);
|
|
27
|
+
const flagsWithPlatform = await this.ensurePlatformSelectedAsync(flags);
|
|
28
|
+
const platforms = (0, platform_1.toPlatforms)(flagsWithPlatform.requestedPlatform);
|
|
25
29
|
const submissionProfiles = await (0, profiles_1.getProfilesAsync)({
|
|
26
30
|
type: 'submit',
|
|
27
31
|
easJsonReader: new eas_json_1.EasJsonReader(projectDir),
|
|
28
32
|
platforms,
|
|
29
|
-
profileName:
|
|
33
|
+
profileName: flagsWithPlatform.profile,
|
|
30
34
|
});
|
|
31
35
|
const submissions = [];
|
|
32
36
|
for (const submissionProfile of submissionProfiles) {
|
|
@@ -35,8 +39,8 @@ class Submit extends EasCommand_1.default {
|
|
|
35
39
|
projectDir,
|
|
36
40
|
projectId,
|
|
37
41
|
profile: submissionProfile.profile,
|
|
38
|
-
archiveFlags:
|
|
39
|
-
nonInteractive:
|
|
42
|
+
archiveFlags: flagsWithPlatform.archiveFlags,
|
|
43
|
+
nonInteractive: flagsWithPlatform.nonInteractive,
|
|
40
44
|
});
|
|
41
45
|
if (submissionProfiles.length > 1) {
|
|
42
46
|
log_1.default.newLine();
|
|
@@ -48,24 +52,22 @@ class Submit extends EasCommand_1.default {
|
|
|
48
52
|
}
|
|
49
53
|
log_1.default.newLine();
|
|
50
54
|
(0, urls_1.printSubmissionDetailsUrls)(submissions);
|
|
51
|
-
if (
|
|
55
|
+
if (flagsWithPlatform.wait) {
|
|
52
56
|
const completedSubmissions = await (0, submit_1.waitToCompleteAsync)(submissions, {
|
|
53
|
-
verbose:
|
|
57
|
+
verbose: flagsWithPlatform.verbose,
|
|
54
58
|
});
|
|
55
59
|
(0, submit_1.exitWithNonZeroCodeIfSomeSubmissionsDidntFinish)(completedSubmissions);
|
|
56
60
|
}
|
|
57
61
|
}
|
|
58
|
-
|
|
62
|
+
sanitizeFlags(flags) {
|
|
59
63
|
const { platform, verbose, wait, profile, 'non-interactive': nonInteractive, ...archiveFlags } = flags;
|
|
60
64
|
if (!flags.platform && nonInteractive) {
|
|
61
65
|
core_1.Errors.error('--platform is required when building in non-interactive mode', { exit: 1 });
|
|
62
66
|
}
|
|
63
|
-
const requestedPlatform =
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
}
|
|
67
|
+
const requestedPlatform = flags.platform &&
|
|
68
|
+
Object.values(platform_1.RequestedPlatform).includes(flags.platform.toLowerCase())
|
|
69
|
+
? flags.platform.toLowerCase()
|
|
70
|
+
: undefined;
|
|
69
71
|
return {
|
|
70
72
|
archiveFlags,
|
|
71
73
|
requestedPlatform,
|
|
@@ -75,6 +77,18 @@ class Submit extends EasCommand_1.default {
|
|
|
75
77
|
nonInteractive,
|
|
76
78
|
};
|
|
77
79
|
}
|
|
80
|
+
async ensurePlatformSelectedAsync(flags) {
|
|
81
|
+
const requestedPlatform = await (0, platform_1.selectRequestedPlatformAsync)(flags.requestedPlatform);
|
|
82
|
+
if (requestedPlatform === platform_1.RequestedPlatform.All) {
|
|
83
|
+
if (flags.archiveFlags.id || flags.archiveFlags.path || flags.archiveFlags.url) {
|
|
84
|
+
core_1.Errors.error('--id, --path, and --url params are only supported when performing a single-platform submit', { exit: 1 });
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return {
|
|
88
|
+
...flags,
|
|
89
|
+
requestedPlatform,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
78
92
|
}
|
|
79
93
|
exports.default = Submit;
|
|
80
94
|
Submit.description = 'submit app binary to App Store and/or Play Store';
|
|
@@ -81,6 +81,7 @@ async function configureAppJSONForEASUpdateAsync({ projectDir, exp, platform, wo
|
|
|
81
81
|
const newAndroidRuntimeVersion = (_c = (_b = (_a = exp.android) === null || _a === void 0 ? void 0 : _a.runtimeVersion) !== null && _b !== void 0 ? _b : exp.runtimeVersion) !== null && _c !== void 0 ? _c : androidDefaultRuntimeVersion;
|
|
82
82
|
const newIosRuntimeVersion = (_f = (_e = (_d = exp.ios) === null || _d === void 0 ? void 0 : _d.runtimeVersion) !== null && _e !== void 0 ? _e : exp.runtimeVersion) !== null && _f !== void 0 ? _f : iosDefaultRuntimeVersion;
|
|
83
83
|
let newConfig;
|
|
84
|
+
let newConfigOnlyAddedValues;
|
|
84
85
|
switch (platform) {
|
|
85
86
|
case platform_1.RequestedPlatform.All: {
|
|
86
87
|
if (isRuntimeEqual(newAndroidRuntimeVersion, newIosRuntimeVersion)) {
|
|
@@ -93,6 +94,26 @@ async function configureAppJSONForEASUpdateAsync({ projectDir, exp, platform, wo
|
|
|
93
94
|
ios: { ...exp.ios, runtimeVersion: undefined },
|
|
94
95
|
updates,
|
|
95
96
|
};
|
|
97
|
+
newConfigOnlyAddedValues = {
|
|
98
|
+
runtimeVersion: newAndroidRuntimeVersion,
|
|
99
|
+
...(exp.android && 'runtimeVersion' in exp.android
|
|
100
|
+
? {
|
|
101
|
+
android: {
|
|
102
|
+
runtimeVersion: '<remove this key>',
|
|
103
|
+
},
|
|
104
|
+
}
|
|
105
|
+
: {}),
|
|
106
|
+
...(exp.ios && 'runtimeVersion' in exp.ios
|
|
107
|
+
? {
|
|
108
|
+
ios: {
|
|
109
|
+
runtimeVersion: '<remove this key>',
|
|
110
|
+
},
|
|
111
|
+
}
|
|
112
|
+
: {}),
|
|
113
|
+
updates: {
|
|
114
|
+
url: easUpdateURL,
|
|
115
|
+
},
|
|
116
|
+
};
|
|
96
117
|
}
|
|
97
118
|
else {
|
|
98
119
|
newConfig = {
|
|
@@ -107,6 +128,22 @@ async function configureAppJSONForEASUpdateAsync({ projectDir, exp, platform, wo
|
|
|
107
128
|
},
|
|
108
129
|
updates,
|
|
109
130
|
};
|
|
131
|
+
newConfigOnlyAddedValues = {
|
|
132
|
+
...('runtimeVersion' in exp
|
|
133
|
+
? {
|
|
134
|
+
runtimeVersion: '<remove this key>', // top level runtime is redundant if it is specified in both android and ios
|
|
135
|
+
}
|
|
136
|
+
: {}),
|
|
137
|
+
android: {
|
|
138
|
+
runtimeVersion: newAndroidRuntimeVersion,
|
|
139
|
+
},
|
|
140
|
+
ios: {
|
|
141
|
+
runtimeVersion: newIosRuntimeVersion,
|
|
142
|
+
},
|
|
143
|
+
updates: {
|
|
144
|
+
url: easUpdateURL,
|
|
145
|
+
},
|
|
146
|
+
};
|
|
110
147
|
}
|
|
111
148
|
break;
|
|
112
149
|
}
|
|
@@ -118,6 +155,14 @@ async function configureAppJSONForEASUpdateAsync({ projectDir, exp, platform, wo
|
|
|
118
155
|
},
|
|
119
156
|
updates,
|
|
120
157
|
};
|
|
158
|
+
newConfigOnlyAddedValues = {
|
|
159
|
+
android: {
|
|
160
|
+
runtimeVersion: newAndroidRuntimeVersion,
|
|
161
|
+
},
|
|
162
|
+
updates: {
|
|
163
|
+
url: easUpdateURL,
|
|
164
|
+
},
|
|
165
|
+
};
|
|
121
166
|
break;
|
|
122
167
|
}
|
|
123
168
|
case platform_1.RequestedPlatform.Ios: {
|
|
@@ -128,6 +173,14 @@ async function configureAppJSONForEASUpdateAsync({ projectDir, exp, platform, wo
|
|
|
128
173
|
},
|
|
129
174
|
updates,
|
|
130
175
|
};
|
|
176
|
+
newConfigOnlyAddedValues = {
|
|
177
|
+
ios: {
|
|
178
|
+
runtimeVersion: newIosRuntimeVersion,
|
|
179
|
+
},
|
|
180
|
+
updates: {
|
|
181
|
+
url: easUpdateURL,
|
|
182
|
+
},
|
|
183
|
+
};
|
|
131
184
|
break;
|
|
132
185
|
}
|
|
133
186
|
default: {
|
|
@@ -160,7 +213,7 @@ async function configureAppJSONForEASUpdateAsync({ projectDir, exp, platform, wo
|
|
|
160
213
|
log_1.default.addNewLineIfNone();
|
|
161
214
|
log_1.default.warn(`It looks like you are using a dynamic configuration! ${(0, log_1.learnMore)('https://docs.expo.dev/workflow/configuration/#dynamic-configuration-with-appconfigjs)')}`);
|
|
162
215
|
log_1.default.warn(`In order to finish configuring your project for EAS Update, you are going to need manually add the following to your app.config.js:\n${(0, log_1.learnMore)('https://expo.fyi/eas-update-config.md')}\n`);
|
|
163
|
-
log_1.default.log(chalk_1.default.bold(JSON.stringify(
|
|
216
|
+
log_1.default.log(chalk_1.default.bold(JSON.stringify(newConfigOnlyAddedValues, null, 2)));
|
|
164
217
|
log_1.default.addNewLineIfNone();
|
|
165
218
|
if (workflows['android'] === eas_build_job_1.Workflow.GENERIC || workflows['ios'] === eas_build_job_1.Workflow.GENERIC) {
|
|
166
219
|
log_1.default.warn(`You will also have to manually edit the projects ${chalk_1.default.bold('Expo.plist/AndroidManifest.xml')}. ${(0, log_1.learnMore)('https://expo.fyi/eas-update-config.md#native-configuration')}`);
|
|
@@ -16,6 +16,7 @@ const url_1 = require("../../build/utils/url");
|
|
|
16
16
|
const EasCommand_1 = tslib_1.__importDefault(require("../../commandUtils/EasCommand"));
|
|
17
17
|
const fetch_1 = tslib_1.__importDefault(require("../../fetch"));
|
|
18
18
|
const client_1 = require("../../graphql/client");
|
|
19
|
+
const generated_1 = require("../../graphql/generated");
|
|
19
20
|
const PublishMutation_1 = require("../../graphql/mutations/PublishMutation");
|
|
20
21
|
const BranchQuery_1 = require("../../graphql/queries/BranchQuery");
|
|
21
22
|
const UpdateQuery_1 = require("../../graphql/queries/UpdateQuery");
|
|
@@ -32,6 +33,7 @@ const code_signing_1 = require("../../utils/code-signing");
|
|
|
32
33
|
const uniqBy_1 = tslib_1.__importDefault(require("../../utils/expodash/uniqBy"));
|
|
33
34
|
const formatFields_1 = tslib_1.__importDefault(require("../../utils/formatFields"));
|
|
34
35
|
const json_1 = require("../../utils/json");
|
|
36
|
+
const statuspageService_1 = require("../../utils/statuspageService");
|
|
35
37
|
const vcs_1 = require("../../vcs");
|
|
36
38
|
const create_1 = require("../branch/create");
|
|
37
39
|
const create_2 = require("../channel/create");
|
|
@@ -109,6 +111,7 @@ class UpdatePublish extends EasCommand_1.default {
|
|
|
109
111
|
const expPrivate = (0, expoConfig_1.getExpoConfig)(projectDir, {
|
|
110
112
|
isPublicConfig: false,
|
|
111
113
|
});
|
|
114
|
+
await (0, statuspageService_1.maybeWarnAboutEasOutagesAsync)([generated_1.StatuspageServiceName.EasUpdate]);
|
|
112
115
|
const codeSigningInfo = await (0, code_signing_1.getCodeSigningInfoAsync)(expPrivate, privateKeyPath);
|
|
113
116
|
const hasExpoUpdates = (0, projectUtils_1.isExpoUpdatesInstalledOrAvailable)(projectDir, exp.sdkVersion);
|
|
114
117
|
if (!hasExpoUpdates && nonInteractive) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.formatProjectFullName = exports.getGoogleServiceAccountKeysForAccountAsync = exports.deleteGoogleServiceAccountKeyAsync = exports.createGoogleServiceAccountKeyAsync = exports.deleteFcmAsync = exports.createFcmAsync = exports.deleteKeystoreAsync = exports.createKeystoreAsync = exports.createOrUpdateDefaultIosAppBuildCredentialsAsync = exports.createOrUpdateAndroidAppBuildCredentialsByNameAsync = exports.getAndroidAppBuildCredentialsByNameAsync = exports.getDefaultAndroidAppBuildCredentialsAsync = exports.createAndroidAppBuildCredentialsAsync = exports.updateAndroidAppBuildCredentialsAsync = exports.updateAndroidAppCredentialsAsync = exports.createOrGetExistingAndroidAppCredentialsWithBuildCredentialsAsync = exports.getLegacyAndroidAppBuildCredentialsAsync = exports.getLegacyAndroidAppCredentialsWithCommonFieldsAsync = exports.getAndroidAppBuildCredentialsListAsync = exports.getAndroidAppCredentialsWithCommonFieldsAsync = void 0;
|
|
4
|
-
const AppQuery_1 = require("
|
|
4
|
+
const AppQuery_1 = require("../../../graphql/queries/AppQuery");
|
|
5
5
|
const AndroidAppBuildCredentialsMutation_1 = require("./graphql/mutations/AndroidAppBuildCredentialsMutation");
|
|
6
6
|
const AndroidAppCredentialsMutation_1 = require("./graphql/mutations/AndroidAppCredentialsMutation");
|
|
7
7
|
const AndroidFcmMutation_1 = require("./graphql/mutations/AndroidFcmMutation");
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ExpoConfig } from '@expo/config';
|
|
2
2
|
import { Env } from '@expo/eas-build-job';
|
|
3
|
+
import { EasJson } from '@expo/eas-json';
|
|
3
4
|
import { Actor } from '../user/User';
|
|
4
5
|
import * as AndroidGraphqlClient from './android/api/GraphqlClient';
|
|
5
6
|
import * as IosGraphqlClient from './ios/api/GraphqlClient';
|
|
@@ -12,10 +13,12 @@ export declare class CredentialsContext {
|
|
|
12
13
|
readonly nonInteractive: boolean;
|
|
13
14
|
readonly projectDir: string;
|
|
14
15
|
readonly user: Actor;
|
|
16
|
+
readonly easJsonCliConfig?: EasJson['cli'];
|
|
15
17
|
private shouldAskAuthenticateAppStore;
|
|
16
18
|
private resolvedExp?;
|
|
17
19
|
constructor(options: {
|
|
18
20
|
exp?: ExpoConfig;
|
|
21
|
+
easJsonCliConfig?: EasJson['cli'];
|
|
19
22
|
nonInteractive?: boolean;
|
|
20
23
|
projectDir: string;
|
|
21
24
|
user: Actor;
|
|
@@ -20,6 +20,7 @@ class CredentialsContext {
|
|
|
20
20
|
this.appStore = new AppStoreApi_1.default();
|
|
21
21
|
this.ios = IosGraphqlClient;
|
|
22
22
|
this.shouldAskAuthenticateAppStore = true;
|
|
23
|
+
this.easJsonCliConfig = options.easJsonCliConfig;
|
|
23
24
|
this.projectDir = options.projectDir;
|
|
24
25
|
this.user = options.user;
|
|
25
26
|
this.nonInteractive = (_a = options.nonInteractive) !== null && _a !== void 0 ? _a : false;
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
const tslib_1 = require("tslib");
|
|
4
4
|
const eas_build_job_1 = require("@expo/eas-build-job");
|
|
5
5
|
const eas_json_1 = require("@expo/eas-json");
|
|
6
|
+
const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
|
|
6
7
|
const log_1 = tslib_1.__importDefault(require("../../log"));
|
|
7
8
|
const target_1 = require("../../project/ios/target");
|
|
8
9
|
const prompts_1 = require("../../prompts");
|
|
@@ -12,6 +13,12 @@ const BuildCredentialsUtils_1 = require("./actions/BuildCredentialsUtils");
|
|
|
12
13
|
const SetUpBuildCredentials_1 = require("./actions/SetUpBuildCredentials");
|
|
13
14
|
const SetUpPushKey_1 = require("./actions/SetUpPushKey");
|
|
14
15
|
const provisioningProfile_1 = require("./utils/provisioningProfile");
|
|
16
|
+
var PushNotificationSetupOption;
|
|
17
|
+
(function (PushNotificationSetupOption) {
|
|
18
|
+
PushNotificationSetupOption[PushNotificationSetupOption["YES"] = 0] = "YES";
|
|
19
|
+
PushNotificationSetupOption[PushNotificationSetupOption["NO"] = 1] = "NO";
|
|
20
|
+
PushNotificationSetupOption[PushNotificationSetupOption["NO_DONT_ASK_AGAIN"] = 2] = "NO_DONT_ASK_AGAIN";
|
|
21
|
+
})(PushNotificationSetupOption || (PushNotificationSetupOption = {}));
|
|
15
22
|
class IosCredentialsProvider {
|
|
16
23
|
constructor(ctx, options) {
|
|
17
24
|
this.ctx = ctx;
|
|
@@ -47,6 +54,7 @@ class IosCredentialsProvider {
|
|
|
47
54
|
}).runAsync(this.ctx);
|
|
48
55
|
}
|
|
49
56
|
async getPushKeyAsync(ctx, targets) {
|
|
57
|
+
var _a;
|
|
50
58
|
if (ctx.nonInteractive) {
|
|
51
59
|
return null;
|
|
52
60
|
}
|
|
@@ -63,13 +71,33 @@ class IosCredentialsProvider {
|
|
|
63
71
|
log_1.default.succeed(`Push Notifications setup for ${app.projectName}: ${applicationTarget.bundleIdentifier}`);
|
|
64
72
|
return null;
|
|
65
73
|
}
|
|
66
|
-
|
|
67
|
-
message: `Would you like to set up Push Notifications for your project?`,
|
|
68
|
-
});
|
|
69
|
-
if (!confirmSetup) {
|
|
74
|
+
if (((_a = ctx.easJsonCliConfig) === null || _a === void 0 ? void 0 : _a.promptToConfigurePushNotifications) === false) {
|
|
70
75
|
return null;
|
|
71
76
|
}
|
|
72
|
-
|
|
77
|
+
const setupOption = await (0, prompts_1.selectAsync)(`Would you like to set up Push Notifications for your project?`, [
|
|
78
|
+
{ title: 'Yes', value: PushNotificationSetupOption.YES },
|
|
79
|
+
{ title: 'No', value: PushNotificationSetupOption.NO },
|
|
80
|
+
{
|
|
81
|
+
title: `No, don't ask again (preference will be saved to eas.json)`,
|
|
82
|
+
value: PushNotificationSetupOption.NO_DONT_ASK_AGAIN,
|
|
83
|
+
},
|
|
84
|
+
]);
|
|
85
|
+
if (setupOption === PushNotificationSetupOption.YES) {
|
|
86
|
+
return await setupPushKeyAction.runAsync(ctx);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
if (setupOption === PushNotificationSetupOption.NO_DONT_ASK_AGAIN) {
|
|
90
|
+
await this.disablePushNotificationsSetupInEasJsonAsync(ctx);
|
|
91
|
+
}
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
async disablePushNotificationsSetupInEasJsonAsync(ctx) {
|
|
96
|
+
const easJsonPath = eas_json_1.EasJsonReader.formatEasJsonPath(ctx.projectDir);
|
|
97
|
+
const easJson = await fs_extra_1.default.readJSON(easJsonPath);
|
|
98
|
+
easJson.cli = { ...easJson === null || easJson === void 0 ? void 0 : easJson.cli, promptToConfigurePushNotifications: false };
|
|
99
|
+
await fs_extra_1.default.writeFile(easJsonPath, `${JSON.stringify(easJson, null, 2)}\n`);
|
|
100
|
+
log_1.default.withTick('Updated eas.json');
|
|
73
101
|
}
|
|
74
102
|
assertProvisioningProfileType(provisioningProfile, targetName) {
|
|
75
103
|
const isAdHoc = (0, provisioningProfile_1.isAdHocProfile)(provisioningProfile);
|
|
@@ -5,6 +5,7 @@ const tslib_1 = require("tslib");
|
|
|
5
5
|
const apple_utils_1 = require("@expo/apple-utils");
|
|
6
6
|
const nullthrows_1 = tslib_1.__importDefault(require("nullthrows"));
|
|
7
7
|
const generated_1 = require("../../../graphql/generated");
|
|
8
|
+
const AppQuery_1 = require("../../../graphql/queries/AppQuery");
|
|
8
9
|
const bundleIdentifier_1 = require("../../../project/ios/bundleIdentifier");
|
|
9
10
|
const errors_1 = require("../errors");
|
|
10
11
|
const AppStoreConnectApiKeyMutation_1 = require("./graphql/mutations/AppStoreConnectApiKeyMutation");
|
|
@@ -15,7 +16,6 @@ const ApplePushKeyMutation_1 = require("./graphql/mutations/ApplePushKeyMutation
|
|
|
15
16
|
const AppleTeamMutation_1 = require("./graphql/mutations/AppleTeamMutation");
|
|
16
17
|
const IosAppBuildCredentialsMutation_1 = require("./graphql/mutations/IosAppBuildCredentialsMutation");
|
|
17
18
|
const IosAppCredentialsMutation_1 = require("./graphql/mutations/IosAppCredentialsMutation");
|
|
18
|
-
const AppQuery_1 = require("./graphql/queries/AppQuery");
|
|
19
19
|
const AppStoreConnectApiKeyQuery_1 = require("./graphql/queries/AppStoreConnectApiKeyQuery");
|
|
20
20
|
const AppleAppIdentifierQuery_1 = require("./graphql/queries/AppleAppIdentifierQuery");
|
|
21
21
|
const AppleDeviceQuery_1 = require("./graphql/queries/AppleDeviceQuery");
|
|
@@ -12,6 +12,17 @@ export declare function listAscApiKeysAsync(userAuthCtx: UserAuthCtx): Promise<A
|
|
|
12
12
|
* **Does not support App Store Connect API (CI).**
|
|
13
13
|
*/
|
|
14
14
|
export declare function getAscApiKeyAsync(userAuthCtx: UserAuthCtx, keyId: string): Promise<AscApiKeyInfo | null>;
|
|
15
|
+
/**
|
|
16
|
+
* There is a bug in Apple's infrastructure that does not propagate newly created objects for a
|
|
17
|
+
* while. If the key has not propagated and you try to download it, Apple will error saying that
|
|
18
|
+
* the resource does not exist. We retry with exponential backoff until the key propagates and
|
|
19
|
+
* is available for download.
|
|
20
|
+
* */
|
|
21
|
+
export declare function downloadWithRetryAsync(key: ApiKey, { minTimeout, retries, factor, }?: {
|
|
22
|
+
minTimeout?: number;
|
|
23
|
+
retries?: number;
|
|
24
|
+
factor?: number;
|
|
25
|
+
}): Promise<string | null>;
|
|
15
26
|
/**
|
|
16
27
|
* Create an App Store Connect API Key.
|
|
17
28
|
* **Does not support App Store Connect API (CI).**
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getAscApiKeyInfo = exports.revokeAscApiKeyAsync = exports.createAscApiKeyAsync = exports.getAscApiKeyAsync = exports.listAscApiKeysAsync = void 0;
|
|
3
|
+
exports.getAscApiKeyInfo = exports.revokeAscApiKeyAsync = exports.createAscApiKeyAsync = exports.downloadWithRetryAsync = exports.getAscApiKeyAsync = exports.listAscApiKeysAsync = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const apple_utils_1 = require("@expo/apple-utils");
|
|
6
|
-
const
|
|
6
|
+
const promise_retry_1 = tslib_1.__importDefault(require("promise-retry"));
|
|
7
|
+
const events_1 = require("../../../analytics/events");
|
|
8
|
+
const log_1 = tslib_1.__importStar(require("../../../log"));
|
|
7
9
|
const ora_1 = require("../../../ora");
|
|
8
10
|
const authenticate_1 = require("./authenticate");
|
|
9
11
|
/**
|
|
@@ -49,6 +51,54 @@ async function getAscApiKeyAsync(userAuthCtx, keyId) {
|
|
|
49
51
|
}
|
|
50
52
|
}
|
|
51
53
|
exports.getAscApiKeyAsync = getAscApiKeyAsync;
|
|
54
|
+
/**
|
|
55
|
+
* There is a bug in Apple's infrastructure that does not propagate newly created objects for a
|
|
56
|
+
* while. If the key has not propagated and you try to download it, Apple will error saying that
|
|
57
|
+
* the resource does not exist. We retry with exponential backoff until the key propagates and
|
|
58
|
+
* is available for download.
|
|
59
|
+
* */
|
|
60
|
+
async function downloadWithRetryAsync(key, { minTimeout = 1000, retries = 6, factor = 2, } = {}) {
|
|
61
|
+
const RESOURCE_DOES_NOT_EXIST_MESSAGE = 'The specified resource does not exist - There is no resource of type';
|
|
62
|
+
try {
|
|
63
|
+
const keyP8 = await (0, promise_retry_1.default)(async (retry, number) => {
|
|
64
|
+
try {
|
|
65
|
+
return await key.downloadAsync();
|
|
66
|
+
}
|
|
67
|
+
catch (e) {
|
|
68
|
+
if (e.name === 'UnexpectedAppleResponse' &&
|
|
69
|
+
e.message.includes(RESOURCE_DOES_NOT_EXIST_MESSAGE)) {
|
|
70
|
+
const secondsToRetry = Math.pow(factor, number);
|
|
71
|
+
log_1.default.log(`Received an unexpected response from Apple, retrying in ${secondsToRetry} seconds...`);
|
|
72
|
+
events_1.Analytics.logEvent(events_1.SubmissionEvent.API_KEY_DOWNLOAD_RETRY, {
|
|
73
|
+
errorName: e.name,
|
|
74
|
+
reason: e.message,
|
|
75
|
+
retry: number,
|
|
76
|
+
});
|
|
77
|
+
return retry(e);
|
|
78
|
+
}
|
|
79
|
+
throw e;
|
|
80
|
+
}
|
|
81
|
+
}, {
|
|
82
|
+
retries,
|
|
83
|
+
factor,
|
|
84
|
+
minTimeout,
|
|
85
|
+
});
|
|
86
|
+
events_1.Analytics.logEvent(events_1.SubmissionEvent.API_KEY_DOWNLOAD_SUCCESS, {});
|
|
87
|
+
return keyP8;
|
|
88
|
+
}
|
|
89
|
+
catch (e) {
|
|
90
|
+
if (e.name === 'UnexpectedAppleResponse' &&
|
|
91
|
+
e.message.includes(RESOURCE_DOES_NOT_EXIST_MESSAGE)) {
|
|
92
|
+
log_1.default.warn(`Unable to download Api Key from Apple at this time. Create and upload your key manually by running 'eas credentials' ${(0, log_1.learnMore)('https://expo.fyi/creating-asc-api-key')}`);
|
|
93
|
+
}
|
|
94
|
+
events_1.Analytics.logEvent(events_1.SubmissionEvent.API_KEY_DOWNLOAD_FAIL, {
|
|
95
|
+
errorName: e.name,
|
|
96
|
+
reason: e.message,
|
|
97
|
+
});
|
|
98
|
+
throw e;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
exports.downloadWithRetryAsync = downloadWithRetryAsync;
|
|
52
102
|
/**
|
|
53
103
|
* Create an App Store Connect API Key.
|
|
54
104
|
* **Does not support App Store Connect API (CI).**
|
|
@@ -63,7 +113,7 @@ async function createAscApiKeyAsync(userAuthCtx, { nickname, allAppsVisible, rol
|
|
|
63
113
|
roles: roles !== null && roles !== void 0 ? roles : [apple_utils_1.UserRole.ADMIN],
|
|
64
114
|
keyType: keyType !== null && keyType !== void 0 ? keyType : apple_utils_1.ApiKeyType.PUBLIC_API,
|
|
65
115
|
});
|
|
66
|
-
const keyP8 = await key
|
|
116
|
+
const keyP8 = await downloadWithRetryAsync(key);
|
|
67
117
|
if (!keyP8) {
|
|
68
118
|
const { nickname, roles } = key.attributes;
|
|
69
119
|
const humanReadableKey = `App Store Connect Key '${nickname}' (${key.id}) with roles {${roles.join(',')}}`;
|