eas-cli 3.12.1 → 3.13.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 +58 -57
- package/build/build/build.js +1 -0
- package/build/build/errors.d.ts +2 -0
- package/build/build/errors.js +4 -1
- package/build/build/ios/version.js +11 -2
- package/build/build/metadata.js +4 -1
- package/build/commands/update/index.d.ts +1 -0
- package/build/commands/update/index.js +7 -2
- package/build/credentials/ios/actions/DeviceUtils.js +1 -0
- package/build/credentials/ios/actions/SetUpAscApiKey.js +3 -3
- package/build/easMultiselect.d.ts +24 -0
- package/build/easMultiselect.js +46 -0
- package/build/graphql/generated.d.ts +11 -0
- package/build/graphql/types/Update.js +1 -1
- package/build/project/ios/target.js +3 -0
- package/build/project/publish.d.ts +2 -1
- package/build/project/publish.js +3 -1
- package/build/prompts.d.ts +2 -1
- package/build/prompts.js +5 -1
- package/build/submit/ios/AscApiKeySource.d.ts +7 -2
- package/build/submit/ios/AscApiKeySource.js +63 -1
- package/build/submit/ios/IosSubmitCommand.d.ts +0 -1
- package/build/submit/ios/IosSubmitCommand.js +4 -49
- package/build/submit/ios/IosSubmitter.d.ts +0 -2
- package/build/submit/ios/IosSubmitter.js +1 -6
- package/build/update/ios/UpdatesModule.js +1 -1
- package/build/update/utils.d.ts +2 -2
- package/build/update/utils.js +4 -2
- package/build/user/User.d.ts +2 -2
- package/build/user/User.js +5 -4
- package/oclif.manifest.json +1 -1
- package/package.json +6 -6
- package/build/credentials/ios/actions/SetUpSubmissionCredentials.d.ts +0 -10
- package/build/credentials/ios/actions/SetUpSubmissionCredentials.js +0 -53
- package/build/submit/ios/CredentialsServiceSource.d.ts +0 -18
- package/build/submit/ios/CredentialsServiceSource.js +0 -62
|
@@ -22,10 +22,10 @@ class SetUpAscApiKey {
|
|
|
22
22
|
this.purpose = purpose;
|
|
23
23
|
this.choices = [
|
|
24
24
|
{
|
|
25
|
-
title: '[Choose an existing
|
|
25
|
+
title: '[Choose an existing key]',
|
|
26
26
|
value: SetupAscApiKeyChoice.USE_EXISTING,
|
|
27
27
|
},
|
|
28
|
-
{ title: '[Add a new
|
|
28
|
+
{ title: '[Add a new key]', value: SetupAscApiKeyChoice.GENERATE },
|
|
29
29
|
];
|
|
30
30
|
}
|
|
31
31
|
async runAsync(ctx) {
|
|
@@ -91,7 +91,7 @@ class SetUpAscApiKey {
|
|
|
91
91
|
const result = await (0, prompts_1.promptAsync)({
|
|
92
92
|
type: 'select',
|
|
93
93
|
name: 'choice',
|
|
94
|
-
message: 'Select
|
|
94
|
+
message: 'Select the App Store Connect Api Key to use for your project:',
|
|
95
95
|
choices,
|
|
96
96
|
});
|
|
97
97
|
choice = result.choice;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Choice, PromptObject } from 'prompts';
|
|
2
|
+
import { MultiselectPrompt } from 'prompts/lib/elements';
|
|
3
|
+
export type Question<T extends string = string> = PromptObject<T> & {
|
|
4
|
+
selectionFormat?: string;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Customized multiselect prompt.
|
|
8
|
+
*
|
|
9
|
+
* Additional parameters:
|
|
10
|
+
*
|
|
11
|
+
* @param selectionFormat
|
|
12
|
+
* String indicating number of selected options. Should contain `<num>` substring.
|
|
13
|
+
*
|
|
14
|
+
* Example:
|
|
15
|
+
* 'Selected <num> devices'
|
|
16
|
+
*
|
|
17
|
+
* Short format is used when more than one option is selected.
|
|
18
|
+
*
|
|
19
|
+
**/
|
|
20
|
+
export default class EasMultiselect extends MultiselectPrompt {
|
|
21
|
+
constructor(opts: Question);
|
|
22
|
+
renderDoneOrInstructions(): string;
|
|
23
|
+
}
|
|
24
|
+
export declare const easMultiselect: (args: Question) => Promise<Choice[]>;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.easMultiselect = void 0;
|
|
4
|
+
const elements_1 = require("prompts/lib/elements");
|
|
5
|
+
const noop = () => { };
|
|
6
|
+
/**
|
|
7
|
+
* Customized multiselect prompt.
|
|
8
|
+
*
|
|
9
|
+
* Additional parameters:
|
|
10
|
+
*
|
|
11
|
+
* @param selectionFormat
|
|
12
|
+
* String indicating number of selected options. Should contain `<num>` substring.
|
|
13
|
+
*
|
|
14
|
+
* Example:
|
|
15
|
+
* 'Selected <num> devices'
|
|
16
|
+
*
|
|
17
|
+
* Short format is used when more than one option is selected.
|
|
18
|
+
*
|
|
19
|
+
**/
|
|
20
|
+
class EasMultiselect extends elements_1.MultiselectPrompt {
|
|
21
|
+
constructor(opts) {
|
|
22
|
+
super(opts);
|
|
23
|
+
this.selectionFormat = opts.selectionFormat;
|
|
24
|
+
}
|
|
25
|
+
renderDoneOrInstructions() {
|
|
26
|
+
if (this.done && this.selectionFormat && this.value) {
|
|
27
|
+
const selectedOptionsCount = this.value.filter(e => e.selected).length;
|
|
28
|
+
if (selectedOptionsCount > 1) {
|
|
29
|
+
return this.selectionFormat.replace('<num>', selectedOptionsCount.toString());
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return super.renderDoneOrInstructions();
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
exports.default = EasMultiselect;
|
|
36
|
+
const easMultiselect = (args) => {
|
|
37
|
+
const toSelected = (items) => items.filter(item => item.selected).map(item => item.value);
|
|
38
|
+
return new Promise((res, rej) => {
|
|
39
|
+
const p = new EasMultiselect(args);
|
|
40
|
+
const onAbort = toSelected || noop;
|
|
41
|
+
const onSubmit = toSelected || noop;
|
|
42
|
+
p.on('submit', x => res(onSubmit(x)));
|
|
43
|
+
p.on('abort', x => rej(onAbort(x)));
|
|
44
|
+
});
|
|
45
|
+
};
|
|
46
|
+
exports.easMultiselect = easMultiselect;
|
|
@@ -4055,6 +4055,7 @@ export type UpdateRollBackToEmbeddedGroup = {
|
|
|
4055
4055
|
export type UpdatesFilter = {
|
|
4056
4056
|
platform?: InputMaybe<AppPlatform>;
|
|
4057
4057
|
runtimeVersions?: InputMaybe<Array<Scalars['String']>>;
|
|
4058
|
+
sdkVersions?: InputMaybe<Array<Scalars['String']>>;
|
|
4058
4059
|
};
|
|
4059
4060
|
export type UploadSession = {
|
|
4060
4061
|
__typename?: 'UploadSession';
|
|
@@ -7862,6 +7863,7 @@ export type UpdatePublishMutation = {
|
|
|
7862
7863
|
id: string;
|
|
7863
7864
|
} | {
|
|
7864
7865
|
__typename: 'SSOUser';
|
|
7866
|
+
username: string;
|
|
7865
7867
|
id: string;
|
|
7866
7868
|
} | {
|
|
7867
7869
|
__typename: 'User';
|
|
@@ -8203,6 +8205,7 @@ export type BranchesByAppQuery = {
|
|
|
8203
8205
|
id: string;
|
|
8204
8206
|
} | {
|
|
8205
8207
|
__typename: 'SSOUser';
|
|
8208
|
+
username: string;
|
|
8206
8209
|
id: string;
|
|
8207
8210
|
} | {
|
|
8208
8211
|
__typename: 'User';
|
|
@@ -8263,6 +8266,7 @@ export type ViewBranchesOnUpdateChannelQuery = {
|
|
|
8263
8266
|
id: string;
|
|
8264
8267
|
} | {
|
|
8265
8268
|
__typename: 'SSOUser';
|
|
8269
|
+
username: string;
|
|
8266
8270
|
id: string;
|
|
8267
8271
|
} | {
|
|
8268
8272
|
__typename: 'User';
|
|
@@ -8597,6 +8601,7 @@ export type ViewUpdateChannelOnAppQuery = {
|
|
|
8597
8601
|
id: string;
|
|
8598
8602
|
} | {
|
|
8599
8603
|
__typename: 'SSOUser';
|
|
8604
|
+
username: string;
|
|
8600
8605
|
id: string;
|
|
8601
8606
|
} | {
|
|
8602
8607
|
__typename: 'User';
|
|
@@ -8659,6 +8664,7 @@ export type ViewUpdateChannelsOnAppQuery = {
|
|
|
8659
8664
|
id: string;
|
|
8660
8665
|
} | {
|
|
8661
8666
|
__typename: 'SSOUser';
|
|
8667
|
+
username: string;
|
|
8662
8668
|
id: string;
|
|
8663
8669
|
} | {
|
|
8664
8670
|
__typename: 'User';
|
|
@@ -8881,6 +8887,7 @@ export type ViewUpdatesByGroupQuery = {
|
|
|
8881
8887
|
id: string;
|
|
8882
8888
|
} | {
|
|
8883
8889
|
__typename: 'SSOUser';
|
|
8890
|
+
username: string;
|
|
8884
8891
|
id: string;
|
|
8885
8892
|
} | {
|
|
8886
8893
|
__typename: 'User';
|
|
@@ -8935,6 +8942,7 @@ export type ViewUpdateGroupsOnBranchQuery = {
|
|
|
8935
8942
|
id: string;
|
|
8936
8943
|
} | {
|
|
8937
8944
|
__typename: 'SSOUser';
|
|
8945
|
+
username: string;
|
|
8938
8946
|
id: string;
|
|
8939
8947
|
} | {
|
|
8940
8948
|
__typename: 'User';
|
|
@@ -8988,6 +8996,7 @@ export type ViewUpdateGroupsOnAppQuery = {
|
|
|
8988
8996
|
id: string;
|
|
8989
8997
|
} | {
|
|
8990
8998
|
__typename: 'SSOUser';
|
|
8999
|
+
username: string;
|
|
8991
9000
|
id: string;
|
|
8992
9001
|
} | {
|
|
8993
9002
|
__typename: 'User';
|
|
@@ -9436,6 +9445,7 @@ export type UpdateFragment = {
|
|
|
9436
9445
|
id: string;
|
|
9437
9446
|
} | {
|
|
9438
9447
|
__typename: 'SSOUser';
|
|
9448
|
+
username: string;
|
|
9439
9449
|
id: string;
|
|
9440
9450
|
} | {
|
|
9441
9451
|
__typename: 'User';
|
|
@@ -9476,6 +9486,7 @@ export type UpdateBranchFragment = {
|
|
|
9476
9486
|
id: string;
|
|
9477
9487
|
} | {
|
|
9478
9488
|
__typename: 'SSOUser';
|
|
9489
|
+
username: string;
|
|
9479
9490
|
id: string;
|
|
9480
9491
|
} | {
|
|
9481
9492
|
__typename: 'User';
|
|
@@ -104,6 +104,9 @@ async function resolveBareProjectDependenciesAsync({ exp, projectDir, buildConfi
|
|
|
104
104
|
const result = [];
|
|
105
105
|
if (target.dependencies && target.dependencies.length > 0) {
|
|
106
106
|
for (const dependency of target.dependencies) {
|
|
107
|
+
if (!dependency.signable) {
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
107
110
|
const dependencyBundleIdentifier = await (0, bundleIdentifier_1.getBundleIdentifierAsync)(projectDir, exp, {
|
|
108
111
|
targetName: dependency.name,
|
|
109
112
|
buildConfiguration,
|
|
@@ -67,11 +67,12 @@ export declare function convertAssetToUpdateInfoGroupFormatAsync(asset: RawAsset
|
|
|
67
67
|
* This will be sorted later based on the platform's runtime versions.
|
|
68
68
|
*/
|
|
69
69
|
export declare function buildUnsortedUpdateInfoGroupAsync(assets: CollectedAssets, exp: ExpoConfig): Promise<UpdateInfoGroup>;
|
|
70
|
-
export declare function buildBundlesAsync({ projectDir, inputDir, exp, platformFlag, }: {
|
|
70
|
+
export declare function buildBundlesAsync({ projectDir, inputDir, exp, platformFlag, clearCache, }: {
|
|
71
71
|
projectDir: string;
|
|
72
72
|
inputDir: string;
|
|
73
73
|
exp: Pick<ExpoConfig, 'sdkVersion'>;
|
|
74
74
|
platformFlag: ExpoCLIExportPlatformFlag;
|
|
75
|
+
clearCache?: boolean;
|
|
75
76
|
}): Promise<void>;
|
|
76
77
|
export declare function resolveInputDirectoryAsync(inputDir: string, { skipBundler }: {
|
|
77
78
|
skipBundler?: boolean;
|
package/build/project/publish.js
CHANGED
|
@@ -118,7 +118,7 @@ async function buildUnsortedUpdateInfoGroupAsync(assets, exp) {
|
|
|
118
118
|
return updateInfoGroup;
|
|
119
119
|
}
|
|
120
120
|
exports.buildUnsortedUpdateInfoGroupAsync = buildUnsortedUpdateInfoGroupAsync;
|
|
121
|
-
async function buildBundlesAsync({ projectDir, inputDir, exp, platformFlag, }) {
|
|
121
|
+
async function buildBundlesAsync({ projectDir, inputDir, exp, platformFlag, clearCache, }) {
|
|
122
122
|
const packageJSON = json_file_1.default.read(path_1.default.resolve(projectDir, 'package.json'));
|
|
123
123
|
if (!packageJSON) {
|
|
124
124
|
throw new Error('Could not locate package.json');
|
|
@@ -132,6 +132,7 @@ async function buildBundlesAsync({ projectDir, inputDir, exp, platformFlag, }) {
|
|
|
132
132
|
'--dump-assetmap',
|
|
133
133
|
'--platform',
|
|
134
134
|
platformFlag,
|
|
135
|
+
...(clearCache ? ['--clear'] : []),
|
|
135
136
|
]);
|
|
136
137
|
}
|
|
137
138
|
else {
|
|
@@ -146,6 +147,7 @@ async function buildBundlesAsync({ projectDir, inputDir, exp, platformFlag, }) {
|
|
|
146
147
|
'--dump-assetmap',
|
|
147
148
|
'--platform',
|
|
148
149
|
platformFlag,
|
|
150
|
+
...(clearCache ? ['--clear'] : []),
|
|
149
151
|
]);
|
|
150
152
|
}
|
|
151
153
|
}
|
package/build/prompts.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { Answers, Choice, Options, PromptType
|
|
1
|
+
import { Answers, Choice, Options, PromptType } from 'prompts';
|
|
2
|
+
import { Question } from './easMultiselect';
|
|
2
3
|
export { PromptType, Question, Choice };
|
|
3
4
|
export interface ExpoChoice<T> extends Choice {
|
|
4
5
|
value: T;
|
package/build/prompts.js
CHANGED
|
@@ -3,7 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.pressAnyKeyToContinueAsync = exports.toggleConfirmAsync = exports.selectAsync = exports.confirmAsync = exports.promptAsync = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const os_1 = require("os");
|
|
6
|
-
const prompts_1 = tslib_1.
|
|
6
|
+
const prompts_1 = tslib_1.__importStar(require("prompts"));
|
|
7
|
+
const easMultiselect_1 = require("./easMultiselect");
|
|
8
|
+
if (prompts_1.prompts) {
|
|
9
|
+
prompts_1.prompts.multiselect = easMultiselect_1.easMultiselect;
|
|
10
|
+
}
|
|
7
11
|
async function promptAsync(questions, options = {}) {
|
|
8
12
|
var _a;
|
|
9
13
|
if (!process.stdin.isTTY && !global.test) {
|
|
@@ -3,11 +3,15 @@ import { AscApiKeyPath, MinimalAscApiKey } from '../../credentials/ios/credentia
|
|
|
3
3
|
import { SubmissionContext } from '../context';
|
|
4
4
|
export declare enum AscApiKeySourceType {
|
|
5
5
|
path = 0,
|
|
6
|
-
prompt = 1
|
|
6
|
+
prompt = 1,
|
|
7
|
+
credentialsService = 2
|
|
7
8
|
}
|
|
8
9
|
interface AscApiKeySourceBase {
|
|
9
10
|
sourceType: AscApiKeySourceType;
|
|
10
11
|
}
|
|
12
|
+
interface AscApiKeyCredentialsServiceSource extends AscApiKeySourceBase {
|
|
13
|
+
sourceType: AscApiKeySourceType.credentialsService;
|
|
14
|
+
}
|
|
11
15
|
interface AscApiKeyPromptSource extends AscApiKeySourceBase {
|
|
12
16
|
sourceType: AscApiKeySourceType.prompt;
|
|
13
17
|
}
|
|
@@ -15,7 +19,7 @@ interface AscApiKeyEnvVarSource extends AscApiKeySourceBase {
|
|
|
15
19
|
sourceType: AscApiKeySourceType.path;
|
|
16
20
|
path: AscApiKeyPath;
|
|
17
21
|
}
|
|
18
|
-
export type AscApiKeySource = AscApiKeyEnvVarSource | AscApiKeyPromptSource;
|
|
22
|
+
export type AscApiKeySource = AscApiKeyEnvVarSource | AscApiKeyPromptSource | AscApiKeyCredentialsServiceSource;
|
|
19
23
|
type AscApiKeySummary = {
|
|
20
24
|
source: 'local' | 'EAS servers';
|
|
21
25
|
path?: string;
|
|
@@ -29,6 +33,7 @@ export type AscApiKeyResult = {
|
|
|
29
33
|
result: MinimalAscApiKey | AscApiKeyFromExpoServers;
|
|
30
34
|
summary: AscApiKeySummary;
|
|
31
35
|
};
|
|
36
|
+
export declare function getAscApiKeyResultAsync(ctx: SubmissionContext<Platform.IOS>, source: AscApiKeySource): Promise<AscApiKeyResult>;
|
|
32
37
|
export declare function getAscApiKeyLocallyAsync(ctx: SubmissionContext<Platform.IOS>, source: AscApiKeySource): Promise<AscApiKeyResult>;
|
|
33
38
|
export declare function getAscApiKeyPathAsync(ctx: SubmissionContext<Platform.IOS>, source: AscApiKeySource): Promise<AscApiKeyPath>;
|
|
34
39
|
export {};
|
|
@@ -1,16 +1,76 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getAscApiKeyPathAsync = exports.getAscApiKeyLocallyAsync = exports.AscApiKeySourceType = void 0;
|
|
3
|
+
exports.getAscApiKeyPathAsync = exports.getAscApiKeyLocallyAsync = exports.getAscApiKeyResultAsync = exports.AscApiKeySourceType = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
|
|
6
|
+
const nullthrows_1 = tslib_1.__importDefault(require("nullthrows"));
|
|
6
7
|
const AscApiKeyUtils_1 = require("../../credentials/ios/actions/AscApiKeyUtils");
|
|
8
|
+
const SetUpAscApiKey_1 = require("../../credentials/ios/actions/SetUpAscApiKey");
|
|
7
9
|
const log_1 = tslib_1.__importDefault(require("../../log"));
|
|
10
|
+
const bundleIdentifier_1 = require("../../project/ios/bundleIdentifier");
|
|
11
|
+
const prompts_1 = require("../../prompts");
|
|
8
12
|
const files_1 = require("../utils/files");
|
|
9
13
|
var AscApiKeySourceType;
|
|
10
14
|
(function (AscApiKeySourceType) {
|
|
11
15
|
AscApiKeySourceType[AscApiKeySourceType["path"] = 0] = "path";
|
|
12
16
|
AscApiKeySourceType[AscApiKeySourceType["prompt"] = 1] = "prompt";
|
|
17
|
+
AscApiKeySourceType[AscApiKeySourceType["credentialsService"] = 2] = "credentialsService";
|
|
13
18
|
})(AscApiKeySourceType = exports.AscApiKeySourceType || (exports.AscApiKeySourceType = {}));
|
|
19
|
+
async function getAscApiKeyResultAsync(ctx, source) {
|
|
20
|
+
if (source.sourceType === AscApiKeySourceType.credentialsService) {
|
|
21
|
+
return await getAscApiKeyFromCredentialsServiceAsync(ctx);
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
return await getAscApiKeyLocallyAsync(ctx, source);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
exports.getAscApiKeyResultAsync = getAscApiKeyResultAsync;
|
|
28
|
+
async function maybeGetIosBundleIdentifierAsync(ctx) {
|
|
29
|
+
try {
|
|
30
|
+
return await (0, bundleIdentifier_1.getBundleIdentifierAsync)(ctx.projectDir, ctx.exp);
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
if (error instanceof bundleIdentifier_1.AmbiguousBundleIdentifierError) {
|
|
34
|
+
log_1.default.warn('bundleIdentifier in the Xcode project is ambiguous, specify it via "bundleIdentifier" field in the submit profile in the eas.json.');
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
throw new Error(`Failed to resolve bundleIdentifier in the Xcode project: ${error.message}.`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
async function promptForBundleIdentifierAsync() {
|
|
41
|
+
const { bundleIdentifier } = await (0, prompts_1.promptAsync)({
|
|
42
|
+
name: 'bundleIdentifier',
|
|
43
|
+
message: 'Bundle identifier:',
|
|
44
|
+
type: 'text',
|
|
45
|
+
validate: value => ((0, bundleIdentifier_1.isBundleIdentifierValid)(value) ? true : bundleIdentifier_1.INVALID_BUNDLE_IDENTIFIER_MESSAGE),
|
|
46
|
+
});
|
|
47
|
+
return bundleIdentifier;
|
|
48
|
+
}
|
|
49
|
+
async function getAscApiKeyFromCredentialsServiceAsync(ctx) {
|
|
50
|
+
var _a, _b, _c;
|
|
51
|
+
const bundleIdentifier = (_c = (_b = (_a = ctx.applicationIdentifierOverride) !== null && _a !== void 0 ? _a : ctx.profile.bundleIdentifier) !== null && _b !== void 0 ? _b : (await maybeGetIosBundleIdentifierAsync(ctx))) !== null && _c !== void 0 ? _c : (await promptForBundleIdentifierAsync());
|
|
52
|
+
log_1.default.log(`Looking up credentials configuration for ${bundleIdentifier}...`);
|
|
53
|
+
const appLookupParams = {
|
|
54
|
+
account: (0, nullthrows_1.default)(ctx.user.accounts.find(a => a.name === ctx.accountName), `You do not have access to account: ${ctx.accountName}`),
|
|
55
|
+
projectName: ctx.projectName,
|
|
56
|
+
bundleIdentifier,
|
|
57
|
+
};
|
|
58
|
+
const setupAscApiKeyAction = new SetUpAscApiKey_1.SetUpAscApiKey(appLookupParams, AscApiKeyUtils_1.AppStoreApiKeyPurpose.SUBMISSION_SERVICE);
|
|
59
|
+
const iosAppCredentials = await setupAscApiKeyAction.runAsync(ctx.credentialsCtx);
|
|
60
|
+
const ascKeyForSubmissions = (0, nullthrows_1.default)(iosAppCredentials.appStoreConnectApiKeyForSubmissions, `An EAS Submit ASC Api Key could not be found for ${iosAppCredentials.appleAppIdentifier.bundleIdentifier}`);
|
|
61
|
+
const { id, keyIdentifier, name } = ascKeyForSubmissions;
|
|
62
|
+
log_1.default.log(`Using Api Key ID: ${keyIdentifier}${name ? ` (${name})` : ''}`);
|
|
63
|
+
return {
|
|
64
|
+
result: {
|
|
65
|
+
ascApiKeyId: id,
|
|
66
|
+
},
|
|
67
|
+
summary: {
|
|
68
|
+
source: 'EAS servers',
|
|
69
|
+
keyId: keyIdentifier,
|
|
70
|
+
name: name !== null && name !== void 0 ? name : undefined,
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
}
|
|
14
74
|
async function getAscApiKeyLocallyAsync(ctx, source) {
|
|
15
75
|
const ascApiKeyPath = await getAscApiKeyPathAsync(ctx, source);
|
|
16
76
|
const { keyP8Path, keyId, issuerId } = ascApiKeyPath;
|
|
@@ -31,6 +91,8 @@ async function getAscApiKeyPathAsync(ctx, source) {
|
|
|
31
91
|
return await handlePathSourceAsync(ctx, source);
|
|
32
92
|
case AscApiKeySourceType.prompt:
|
|
33
93
|
return await handlePromptSourceAsync(ctx, source);
|
|
94
|
+
case AscApiKeySourceType.credentialsService:
|
|
95
|
+
throw new Error(`AscApiKeySourceType ${source} does not return a path.`);
|
|
34
96
|
}
|
|
35
97
|
}
|
|
36
98
|
exports.getAscApiKeyPathAsync = getAscApiKeyPathAsync;
|
|
@@ -6,7 +6,6 @@ export default class IosSubmitCommand {
|
|
|
6
6
|
constructor(ctx: SubmissionContext<Platform.IOS>);
|
|
7
7
|
runAsync(): Promise<SubmissionFragment>;
|
|
8
8
|
private resolveSubmissionOptionsAsync;
|
|
9
|
-
private maybeGetIosBundleIdentifierAsync;
|
|
10
9
|
private resolveCredentialSubmissionOptionsAsync;
|
|
11
10
|
private resolveAppSpecificPasswordSource;
|
|
12
11
|
private resolveAscApiKeySource;
|
|
@@ -7,12 +7,10 @@ const getenv_1 = tslib_1.__importDefault(require("getenv"));
|
|
|
7
7
|
const wrap_ansi_1 = tslib_1.__importDefault(require("wrap-ansi"));
|
|
8
8
|
const errors_1 = require("../../credentials/errors");
|
|
9
9
|
const log_1 = tslib_1.__importStar(require("../../log"));
|
|
10
|
-
const bundleIdentifier_1 = require("../../project/ios/bundleIdentifier");
|
|
11
10
|
const commons_1 = require("../commons");
|
|
12
11
|
const AppProduce_1 = require("./AppProduce");
|
|
13
12
|
const AppSpecificPasswordSource_1 = require("./AppSpecificPasswordSource");
|
|
14
13
|
const AscApiKeySource_1 = require("./AscApiKeySource");
|
|
15
|
-
const CredentialsServiceSource_1 = require("./CredentialsServiceSource");
|
|
16
14
|
const IosSubmitter_1 = tslib_1.__importDefault(require("./IosSubmitter"));
|
|
17
15
|
class IosSubmitCommand {
|
|
18
16
|
constructor(ctx) {
|
|
@@ -31,15 +29,11 @@ class IosSubmitCommand {
|
|
|
31
29
|
? credentialsSource.appSpecificPasswordSource
|
|
32
30
|
: null;
|
|
33
31
|
const maybeAscApiKeySource = 'ascApiKeySource' in credentialsSource ? credentialsSource.ascApiKeySource : null;
|
|
34
|
-
const maybeCredentialsServiceSource = 'credentialsServiceSource' in credentialsSource
|
|
35
|
-
? credentialsSource.credentialsServiceSource
|
|
36
|
-
: null;
|
|
37
32
|
const ascAppIdentifier = await this.resolveAscAppIdentifierAsync();
|
|
38
33
|
const errored = [
|
|
39
34
|
archiveSource,
|
|
40
35
|
...(maybeAppSpecificPasswordSource ? [maybeAppSpecificPasswordSource] : []),
|
|
41
36
|
...(maybeAscApiKeySource ? [maybeAscApiKeySource] : []),
|
|
42
|
-
...(maybeCredentialsServiceSource ? [maybeCredentialsServiceSource] : []),
|
|
43
37
|
ascAppIdentifier,
|
|
44
38
|
].filter(r => !r.ok);
|
|
45
39
|
if (errored.length > 0) {
|
|
@@ -61,57 +55,18 @@ class IosSubmitCommand {
|
|
|
61
55
|
ascApiKeySource: maybeAscApiKeySource.enforceValue(),
|
|
62
56
|
}
|
|
63
57
|
: null),
|
|
64
|
-
...(maybeCredentialsServiceSource
|
|
65
|
-
? {
|
|
66
|
-
credentialsServiceSource: maybeCredentialsServiceSource.enforceValue(),
|
|
67
|
-
}
|
|
68
|
-
: null),
|
|
69
58
|
};
|
|
70
59
|
}
|
|
71
|
-
async maybeGetIosBundleIdentifierAsync() {
|
|
72
|
-
try {
|
|
73
|
-
return (0, results_1.result)(await (0, bundleIdentifier_1.getBundleIdentifierAsync)(this.ctx.projectDir, this.ctx.exp));
|
|
74
|
-
}
|
|
75
|
-
catch (error) {
|
|
76
|
-
if (error instanceof bundleIdentifier_1.AmbiguousBundleIdentifierError) {
|
|
77
|
-
log_1.default.warn('bundleIdentifier in the Xcode project is ambiguous, specify it via "bundleIdentifier" field in the submit profile in the eas.json.');
|
|
78
|
-
return (0, results_1.result)(null);
|
|
79
|
-
}
|
|
80
|
-
return (0, results_1.result)(new Error(`Failed to resolve bundleIdentifier in the Xcode project: ${error.message}.`));
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
60
|
async resolveCredentialSubmissionOptionsAsync() {
|
|
84
|
-
var
|
|
85
|
-
const ascApiKeySource = this.resolveAscApiKeySource();
|
|
86
|
-
const shouldSkipAscApiKeySource = !ascApiKeySource.ok && ascApiKeySource.enforceError() instanceof errors_1.MissingCredentialsError;
|
|
87
|
-
if (!shouldSkipAscApiKeySource) {
|
|
88
|
-
return { ascApiKeySource };
|
|
89
|
-
}
|
|
61
|
+
// if an App Specific Password env var is not specified, use ASC Api Key
|
|
90
62
|
const appSpecificPasswordSource = this.resolveAppSpecificPasswordSource();
|
|
91
63
|
const shouldSkipAppSpecificPasswordSource = !appSpecificPasswordSource.ok &&
|
|
92
64
|
appSpecificPasswordSource.enforceError() instanceof errors_1.MissingCredentialsError;
|
|
93
65
|
if (!shouldSkipAppSpecificPasswordSource) {
|
|
94
66
|
return { appSpecificPasswordSource: this.resolveAppSpecificPasswordSource() };
|
|
95
67
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
const bundleIdentifierResult = await this.maybeGetIosBundleIdentifierAsync();
|
|
99
|
-
if (!bundleIdentifierResult.ok) {
|
|
100
|
-
return {
|
|
101
|
-
credentialsServiceSource: (0, results_1.result)(bundleIdentifierResult.reason),
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
const bundleIdentifierValue = bundleIdentifierResult.enforceValue();
|
|
105
|
-
if (bundleIdentifierValue) {
|
|
106
|
-
bundleIdentifier = bundleIdentifierValue;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
return {
|
|
110
|
-
credentialsServiceSource: (0, results_1.result)({
|
|
111
|
-
sourceType: CredentialsServiceSource_1.CREDENTIALS_SERVICE_SOURCE,
|
|
112
|
-
bundleIdentifier,
|
|
113
|
-
}),
|
|
114
|
-
};
|
|
68
|
+
const ascApiKeySource = this.resolveAscApiKeySource();
|
|
69
|
+
return { ascApiKeySource };
|
|
115
70
|
}
|
|
116
71
|
resolveAppSpecificPasswordSource() {
|
|
117
72
|
const envAppSpecificPassword = getenv_1.default.string('EXPO_APPLE_APP_SPECIFIC_PASSWORD', '');
|
|
@@ -147,7 +102,7 @@ class IosSubmitCommand {
|
|
|
147
102
|
sourceType: AscApiKeySource_1.AscApiKeySourceType.prompt,
|
|
148
103
|
});
|
|
149
104
|
}
|
|
150
|
-
return (0, results_1.result)(
|
|
105
|
+
return (0, results_1.result)({ sourceType: AscApiKeySource_1.AscApiKeySourceType.credentialsService });
|
|
151
106
|
}
|
|
152
107
|
resolveArchiveSource() {
|
|
153
108
|
try {
|
|
@@ -5,13 +5,11 @@ import BaseSubmitter, { SubmissionInput } from '../BaseSubmitter';
|
|
|
5
5
|
import { SubmissionContext } from '../context';
|
|
6
6
|
import { AppSpecificPasswordCredentials, AppSpecificPasswordSource } from './AppSpecificPasswordSource';
|
|
7
7
|
import { AscApiKeyResult, AscApiKeySource } from './AscApiKeySource';
|
|
8
|
-
import { CredentialsServiceSource } from './CredentialsServiceSource';
|
|
9
8
|
export interface IosSubmissionOptions extends Pick<IosSubmissionConfigInput, 'appleIdUsername' | 'ascAppIdentifier'> {
|
|
10
9
|
projectId: string;
|
|
11
10
|
archiveSource: ArchiveSource;
|
|
12
11
|
appSpecificPasswordSource?: AppSpecificPasswordSource;
|
|
13
12
|
ascApiKeySource?: AscApiKeySource;
|
|
14
|
-
credentialsServiceSource?: CredentialsServiceSource;
|
|
15
13
|
}
|
|
16
14
|
interface ResolvedSourceOptions {
|
|
17
15
|
archive: ResolvedArchiveSource;
|
|
@@ -11,7 +11,6 @@ const BaseSubmitter_1 = tslib_1.__importDefault(require("../BaseSubmitter"));
|
|
|
11
11
|
const summary_1 = require("../utils/summary");
|
|
12
12
|
const AppSpecificPasswordSource_1 = require("./AppSpecificPasswordSource");
|
|
13
13
|
const AscApiKeySource_1 = require("./AscApiKeySource");
|
|
14
|
-
const CredentialsServiceSource_1 = require("./CredentialsServiceSource");
|
|
15
14
|
class IosSubmitter extends BaseSubmitter_1.default {
|
|
16
15
|
constructor(ctx, options) {
|
|
17
16
|
const sourceOptionsResolver = {
|
|
@@ -28,15 +27,11 @@ class IosSubmitter extends BaseSubmitter_1.default {
|
|
|
28
27
|
? await (0, AppSpecificPasswordSource_1.getAppSpecificPasswordLocallyAsync)(this.ctx, this.options.appSpecificPasswordSource)
|
|
29
28
|
: null;
|
|
30
29
|
const maybeAppStoreConnectApiKey = this.options.ascApiKeySource
|
|
31
|
-
? await (0, AscApiKeySource_1.
|
|
32
|
-
: null;
|
|
33
|
-
const maybeAscOrAspFromCredentialsService = this.options.credentialsServiceSource
|
|
34
|
-
? await (0, CredentialsServiceSource_1.getFromCredentialsServiceAsync)(this.ctx, this.options.credentialsServiceSource)
|
|
30
|
+
? await (0, AscApiKeySource_1.getAscApiKeyResultAsync)(this.ctx, this.options.ascApiKeySource)
|
|
35
31
|
: null;
|
|
36
32
|
return {
|
|
37
33
|
...(maybeAppSpecificPassword ? { appSpecificPassword: maybeAppSpecificPassword } : null),
|
|
38
34
|
...(maybeAppStoreConnectApiKey ? { ascApiKeyResult: maybeAppStoreConnectApiKey } : null),
|
|
39
|
-
...(maybeAscOrAspFromCredentialsService ? maybeAscOrAspFromCredentialsService : null),
|
|
40
35
|
};
|
|
41
36
|
},
|
|
42
37
|
};
|
|
@@ -41,7 +41,7 @@ async function readChannelSafelyAsync(projectDir) {
|
|
|
41
41
|
try {
|
|
42
42
|
const expoPlist = await readExpoPlistAsync(projectDir);
|
|
43
43
|
const updatesRequestHeaders = expoPlist['EXUpdatesRequestHeaders'];
|
|
44
|
-
return (_a = updatesRequestHeaders['expo-channel-name']) !== null && _a !== void 0 ? _a : null;
|
|
44
|
+
return (_a = updatesRequestHeaders === null || updatesRequestHeaders === void 0 ? void 0 : updatesRequestHeaders['expo-channel-name']) !== null && _a !== void 0 ? _a : null;
|
|
45
45
|
}
|
|
46
46
|
catch {
|
|
47
47
|
return null;
|
package/build/update/utils.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { ExpoConfig } from '@expo/config';
|
|
2
|
-
import {
|
|
2
|
+
import { Robot, SsoUser, Update, UpdateBranchFragment, UpdateFragment, User } from '../graphql/generated';
|
|
3
3
|
import { RequestedPlatform } from '../platform';
|
|
4
4
|
import { ProfileData } from '../utils/profiles';
|
|
5
5
|
export type FormatUpdateParameter = Pick<Update, 'id' | 'createdAt' | 'message'> & {
|
|
6
|
-
actor?:
|
|
6
|
+
actor?: Pick<Robot, '__typename' | 'firstName'> | Pick<User, '__typename' | 'username'> | Pick<SsoUser, '__typename' | 'username'> | null;
|
|
7
7
|
};
|
|
8
8
|
export type UpdateJsonInfo = {
|
|
9
9
|
branch: string;
|
package/build/update/utils.js
CHANGED
|
@@ -94,7 +94,8 @@ function formatUpdateTitle(update) {
|
|
|
94
94
|
const { message, createdAt, actor, runtimeVersion } = update;
|
|
95
95
|
let actorName;
|
|
96
96
|
switch (actor === null || actor === void 0 ? void 0 : actor.__typename) {
|
|
97
|
-
case 'User':
|
|
97
|
+
case 'User':
|
|
98
|
+
case 'SSOUser': {
|
|
98
99
|
actorName = actor.username;
|
|
99
100
|
break;
|
|
100
101
|
}
|
|
@@ -103,8 +104,9 @@ function formatUpdateTitle(update) {
|
|
|
103
104
|
actorName = firstName !== null && firstName !== void 0 ? firstName : `robot: ${id.slice(0, 4)}...`;
|
|
104
105
|
break;
|
|
105
106
|
}
|
|
106
|
-
|
|
107
|
+
case undefined: {
|
|
107
108
|
actorName = 'unknown';
|
|
109
|
+
}
|
|
108
110
|
}
|
|
109
111
|
return `[${(0, dateformat_1.default)(createdAt, 'mmm dd HH:MM')} by ${actorName}, runtimeVersion: ${runtimeVersion}] ${message}`;
|
|
110
112
|
}
|
package/build/user/User.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { CurrentUserQuery } from '../graphql/generated';
|
|
1
|
+
import { CurrentUserQuery, Robot, SsoUser, User } from '../graphql/generated';
|
|
2
2
|
export type Actor = NonNullable<CurrentUserQuery['meActor']>;
|
|
3
3
|
/**
|
|
4
4
|
* Resolve the name of the actor, either normal user or robot user.
|
|
5
5
|
* This should be used whenever the "current user" needs to be displayed.
|
|
6
6
|
* The display name CANNOT be used as project owner.
|
|
7
7
|
*/
|
|
8
|
-
export declare function getActorDisplayName(actor?:
|
|
8
|
+
export declare function getActorDisplayName(actor?: Pick<Robot, '__typename' | 'firstName'> | Pick<User, '__typename' | 'username'> | Pick<SsoUser, '__typename' | 'username'> | null): string;
|
|
9
9
|
export declare function getActorUsername(actor?: Actor): string | null;
|
package/build/user/User.js
CHANGED
|
@@ -13,9 +13,9 @@ function getActorDisplayName(actor) {
|
|
|
13
13
|
case 'Robot':
|
|
14
14
|
return actor.firstName ? `${actor.firstName} (robot)` : 'robot';
|
|
15
15
|
case 'SSOUser':
|
|
16
|
-
return actor.username
|
|
17
|
-
|
|
18
|
-
return '
|
|
16
|
+
return actor.username;
|
|
17
|
+
case undefined:
|
|
18
|
+
return 'unknown';
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
exports.getActorDisplayName = getActorDisplayName;
|
|
@@ -24,7 +24,8 @@ function getActorUsername(actor) {
|
|
|
24
24
|
case 'User':
|
|
25
25
|
case 'SSOUser':
|
|
26
26
|
return actor.username;
|
|
27
|
-
|
|
27
|
+
case 'Robot':
|
|
28
|
+
case undefined:
|
|
28
29
|
return null;
|
|
29
30
|
}
|
|
30
31
|
}
|