eas-cli 16.32.0 → 18.0.3
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 +94 -92
- package/build/branch/queries.js +6 -1
- package/build/build/createContext.js +5 -3
- package/build/build/queries.js +13 -1
- package/build/build/runBuildAndSubmit.js +2 -0
- package/build/build/utils/devClient.d.ts +1 -0
- package/build/build/utils/devClient.js +3 -2
- package/build/build/utils/repository.js +3 -3
- package/build/build/utils/resourceClass.d.ts +1 -1
- package/build/build/utils/resourceClass.js +2 -2
- package/build/channel/queries.js +10 -1
- package/build/commandUtils/new/templates/AGENTS.md +0 -1
- package/build/commands/account/login.d.ts +1 -0
- package/build/commands/account/login.js +7 -2
- package/build/commands/env/create.js +5 -2
- package/build/commands/env/list.js +1 -5
- package/build/commands/update/index.js +2 -2
- package/build/commands/upload.js +3 -3
- package/build/credentials/ios/api/graphql/mutations/AppleDistributionCertificateMutation.js +1 -3
- package/build/devices/queries.js +23 -2
- package/build/graphql/mutations/EnvironmentVariableMutation.js +1 -4
- package/build/graphql/mutations/PublishMutation.js +1 -4
- package/build/graphql/mutations/UserPreferencesMutation.js +1 -3
- package/build/graphql/mutations/WorkflowRevisionMutation.js +2 -10
- package/build/graphql/queries/AppVersionQuery.js +1 -5
- package/build/log.js +1 -1
- package/build/ora.js +1 -1
- package/build/project/discourageExpoGoForProdAsync.d.ts +4 -0
- package/build/project/discourageExpoGoForProdAsync.js +46 -0
- package/build/rollout/actions/ManageRollout.js +5 -1
- package/build/rollout/actions/SelectRuntime.js +10 -1
- package/build/update/queries.js +28 -2
- package/build/user/SessionManager.d.ts +3 -2
- package/build/user/SessionManager.js +6 -6
- package/build/user/expoBrowserAuthFlowLauncher.d.ts +3 -0
- package/build/user/expoBrowserAuthFlowLauncher.js +129 -0
- package/build/user/fetchSessionSecretAndUserFromBrowserAuthFlow.d.ts +7 -0
- package/build/user/fetchSessionSecretAndUserFromBrowserAuthFlow.js +14 -0
- package/build/utils/prompts.js +3 -3
- package/build/utils/usage/checkForOverages.js +4 -2
- package/build/worker/mutations.js +2 -8
- package/oclif.manifest.json +8 -48
- package/package.json +61 -63
- package/build/commands/submit/upload-to-asc.d.ts +0 -12
- package/build/commands/submit/upload-to-asc.js +0 -217
- package/build/submit/ios/AscApiClient.d.ts +0 -247
- package/build/submit/ios/AscApiClient.js +0 -287
- package/build/user/expoSsoLauncher.d.ts +0 -3
- package/build/user/expoSsoLauncher.js +0 -98
- package/build/user/fetchSessionSecretAndSsoUser.d.ts +0 -5
- package/build/user/fetchSessionSecretAndSsoUser.js +0 -17
package/build/branch/queries.js
CHANGED
|
@@ -20,7 +20,12 @@ const queries_1 = require("../utils/queries");
|
|
|
20
20
|
exports.BRANCHES_LIMIT = 50;
|
|
21
21
|
async function selectBranchOnAppAsync(graphqlClient, { projectId, promptTitle, displayTextForListItem, paginatedQueryOptions, }) {
|
|
22
22
|
if (paginatedQueryOptions.nonInteractive) {
|
|
23
|
-
|
|
23
|
+
const branches = await queryBranchesOnProjectAsync(graphqlClient, paginatedQueryOptions.limit ?? exports.BRANCHES_LIMIT, paginatedQueryOptions.offset, projectId);
|
|
24
|
+
if (branches.length === 0) {
|
|
25
|
+
throw new Error(`No branches found for project "${projectId}".`);
|
|
26
|
+
}
|
|
27
|
+
const branchList = branches.map(b => b.name).join('\n ');
|
|
28
|
+
throw new Error(`Unable to select a branch in non-interactive mode. Use the --branch flag to specify the branch. Available branches:\n ${branchList}`);
|
|
24
29
|
}
|
|
25
30
|
const selectedBranch = await (0, queries_1.paginatedQueryWithSelectPromptAsync)({
|
|
26
31
|
limit: paginatedQueryOptions.limit ?? exports.BRANCHES_LIMIT,
|
|
@@ -21,8 +21,10 @@ async function createBuildContextAsync({ buildProfileName, buildProfile, easJson
|
|
|
21
21
|
env,
|
|
22
22
|
});
|
|
23
23
|
const projectName = exp.slug;
|
|
24
|
-
const account = await
|
|
25
|
-
|
|
24
|
+
const [account, workflow] = await Promise.all([
|
|
25
|
+
(0, projectUtils_1.getOwnerAccountForProjectIdAsync)(graphqlClient, projectId),
|
|
26
|
+
(0, workflow_1.resolveWorkflowAsync)(projectDir, platform, vcsClient),
|
|
27
|
+
]);
|
|
26
28
|
const accountId = account.id;
|
|
27
29
|
const runFromCI = getenv_1.default.boolish('CI', false);
|
|
28
30
|
const developmentClient = buildProfile.developmentClient ??
|
|
@@ -61,7 +63,7 @@ async function createBuildContextAsync({ buildProfileName, buildProfile, easJson
|
|
|
61
63
|
local: localBuildOptions.localBuildMode === local_1.LocalBuildMode.LOCAL_BUILD_PLUGIN,
|
|
62
64
|
};
|
|
63
65
|
analytics.logEvent(AnalyticsManager_1.BuildEvent.BUILD_COMMAND, analyticsEventProperties);
|
|
64
|
-
const resourceClass =
|
|
66
|
+
const resourceClass = (0, resourceClass_1.resolveBuildResourceClass)(buildProfile, platform, resourceClassFlag);
|
|
65
67
|
const commonContext = {
|
|
66
68
|
accountId,
|
|
67
69
|
accountName: account.name,
|
package/build/build/queries.js
CHANGED
|
@@ -45,7 +45,19 @@ async function listAndRenderBuildsOnAppAsync(graphqlClient, { projectId, project
|
|
|
45
45
|
}
|
|
46
46
|
async function listAndSelectBuildOnAppAsync(graphqlClient, { projectId, title, filter, paginatedQueryOptions, selectPromptDisabledFunction, selectPromptWarningMessage, }) {
|
|
47
47
|
if (paginatedQueryOptions.nonInteractive) {
|
|
48
|
-
|
|
48
|
+
const builds = await BuildQuery_1.BuildQuery.viewBuildsOnAppAsync(graphqlClient, {
|
|
49
|
+
appId: projectId,
|
|
50
|
+
limit: paginatedQueryOptions.limit ?? exports.BUILDS_LIMIT,
|
|
51
|
+
offset: paginatedQueryOptions.offset,
|
|
52
|
+
filter,
|
|
53
|
+
});
|
|
54
|
+
if (builds.length === 0) {
|
|
55
|
+
throw new Error('No builds found for this project.');
|
|
56
|
+
}
|
|
57
|
+
const buildList = builds
|
|
58
|
+
.map(b => `${b.id} (platform: ${b.platform}, status: ${b.status}${b.buildProfile ? `, profile: ${b.buildProfile}` : ''})`)
|
|
59
|
+
.join('\n ');
|
|
60
|
+
throw new Error(`Unable to select a build in non-interactive mode. Available builds:\n ${buildList}`);
|
|
49
61
|
}
|
|
50
62
|
else {
|
|
51
63
|
const selectedBuild = await (0, queries_1.paginatedQueryWithSelectPromptAsync)({
|
|
@@ -27,6 +27,7 @@ const AppPlatform_1 = require("../graphql/types/AppPlatform");
|
|
|
27
27
|
const log_1 = tslib_1.__importStar(require("../log"));
|
|
28
28
|
const platform_1 = require("../platform");
|
|
29
29
|
const customBuildConfig_1 = require("../project/customBuildConfig");
|
|
30
|
+
const discourageExpoGoForProdAsync_1 = require("../project/discourageExpoGoForProdAsync");
|
|
30
31
|
const expoSdk_1 = require("../project/expoSdk");
|
|
31
32
|
const metroConfig_1 = require("../project/metroConfig");
|
|
32
33
|
const projectUtils_1 = require("../project/projectUtils");
|
|
@@ -64,6 +65,7 @@ async function runBuildAndSubmitAsync({ graphqlClient, analytics, vcsClient, pro
|
|
|
64
65
|
profileName: flags.profile ?? undefined,
|
|
65
66
|
projectDir,
|
|
66
67
|
});
|
|
68
|
+
await (0, discourageExpoGoForProdAsync_1.discourageExpoGoForProdAsync)(buildProfiles, projectDir, vcsClient);
|
|
67
69
|
for (const buildProfile of buildProfiles) {
|
|
68
70
|
if (buildProfile.profile.image && ['default', 'stable'].includes(buildProfile.profile.image)) {
|
|
69
71
|
log_1.default.warn(`The "image" field in the build profile "${buildProfile.profileName}" is set to "${buildProfile.profile.image}". This tag is deprecated and will be removed in the future. Use other images or tags listed here: https://docs.expo.dev/build-reference/infrastructure/`);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ensureExpoDevClientInstalledForDevClientBuildsAsync = ensureExpoDevClientInstalledForDevClientBuildsAsync;
|
|
4
|
+
exports.isExpoDevClientInstalled = isExpoDevClientInstalled;
|
|
4
5
|
const tslib_1 = require("tslib");
|
|
5
6
|
const eas_build_job_1 = require("@expo/eas-build-job");
|
|
6
7
|
const core_1 = require("@oclif/core");
|
|
@@ -14,7 +15,7 @@ const workflow_1 = require("../../project/workflow");
|
|
|
14
15
|
const prompts_1 = require("../../prompts");
|
|
15
16
|
const expoCli_1 = require("../../utils/expoCli");
|
|
16
17
|
async function ensureExpoDevClientInstalledForDevClientBuildsAsync({ projectDir, vcsClient, nonInteractive = false, buildProfiles = [], }) {
|
|
17
|
-
if (
|
|
18
|
+
if (isExpoDevClientInstalled(projectDir)) {
|
|
18
19
|
return;
|
|
19
20
|
}
|
|
20
21
|
const buildProfilesWithDevelopmentClientRequired = buildProfiles.filter(buildProfile => buildProfile.profile.developmentClient);
|
|
@@ -71,7 +72,7 @@ async function ensureExpoDevClientInstalledForDevClientBuildsAsync({ projectDir,
|
|
|
71
72
|
}
|
|
72
73
|
}
|
|
73
74
|
}
|
|
74
|
-
|
|
75
|
+
function isExpoDevClientInstalled(projectDir) {
|
|
75
76
|
try {
|
|
76
77
|
(0, resolve_from_1.default)(projectDir, 'expo-dev-client/package.json');
|
|
77
78
|
return true;
|
|
@@ -12,7 +12,7 @@ const tslib_1 = require("tslib");
|
|
|
12
12
|
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
13
13
|
const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
|
|
14
14
|
const path_1 = tslib_1.__importDefault(require("path"));
|
|
15
|
-
const
|
|
15
|
+
const tar = tslib_1.__importStar(require("tar"));
|
|
16
16
|
const uuid_1 = require("uuid");
|
|
17
17
|
const log_1 = tslib_1.__importStar(require("../../log"));
|
|
18
18
|
const ora_1 = require("../../ora");
|
|
@@ -78,7 +78,7 @@ async function makeProjectMetadataFileAsync(archivePath) {
|
|
|
78
78
|
await fs_extra_1.default.mkdirp((0, paths_1.getTmpDirectory)());
|
|
79
79
|
const metadataLocation = path_1.default.join((0, paths_1.getTmpDirectory)(), `${(0, uuid_1.v4)()}-eas-build-metadata.json`);
|
|
80
80
|
const archiveContent = [];
|
|
81
|
-
await
|
|
81
|
+
await tar.list({
|
|
82
82
|
file: archivePath,
|
|
83
83
|
onentry: (entry) => {
|
|
84
84
|
if (entry.type === 'File' && !entry.path.includes('.git/')) {
|
|
@@ -108,7 +108,7 @@ async function makeProjectTarballAsync(vcsClient) {
|
|
|
108
108
|
(0, timer_1.startTimer)(compressTimerLabel);
|
|
109
109
|
try {
|
|
110
110
|
await vcsClient.makeShallowCopyAsync(shallowClonePath);
|
|
111
|
-
await
|
|
111
|
+
await tar.create({ cwd: shallowClonePath, file: tarPath, prefix: 'project', gzip: true }, [
|
|
112
112
|
'.',
|
|
113
113
|
]);
|
|
114
114
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { Platform } from '@expo/eas-build-job';
|
|
2
2
|
import { BuildProfile, ResourceClass } from '@expo/eas-json';
|
|
3
3
|
import { BuildResourceClass } from '../../graphql/generated';
|
|
4
|
-
export declare function
|
|
4
|
+
export declare function resolveBuildResourceClass<T extends Platform>(profile: BuildProfile<T>, platform: Platform, resourceClassFlag?: ResourceClass): BuildResourceClass;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.resolveBuildResourceClass = resolveBuildResourceClass;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const eas_build_job_1 = require("@expo/eas-build-job");
|
|
6
6
|
const eas_json_1 = require("@expo/eas-json");
|
|
@@ -20,7 +20,7 @@ const androidResourceClassToBuildResourceClassMapping = {
|
|
|
20
20
|
[eas_json_1.ResourceClass.LARGE]: generated_1.BuildResourceClass.AndroidLarge,
|
|
21
21
|
[eas_json_1.ResourceClass.MEDIUM]: generated_1.BuildResourceClass.AndroidMedium,
|
|
22
22
|
};
|
|
23
|
-
|
|
23
|
+
function resolveBuildResourceClass(profile, platform, resourceClassFlag) {
|
|
24
24
|
const profileResourceClass = profile.resourceClass;
|
|
25
25
|
if (profileResourceClass && resourceClassFlag && resourceClassFlag !== profileResourceClass) {
|
|
26
26
|
log_1.default.warn(`Build profile specifies the "${profileResourceClass}" resource class but you passed "${resourceClassFlag}" to --resource-class.\nUsing "${resourceClassFlag}" as the override.`);
|
package/build/channel/queries.js
CHANGED
|
@@ -28,7 +28,16 @@ const queries_2 = require("../utils/queries");
|
|
|
28
28
|
exports.CHANNELS_LIMIT = 25;
|
|
29
29
|
async function selectChannelOnAppAsync(graphqlClient, { projectId, selectionPromptTitle, paginatedQueryOptions, }) {
|
|
30
30
|
if (paginatedQueryOptions.nonInteractive) {
|
|
31
|
-
|
|
31
|
+
const channels = await queryChannelsOnAppAsync(graphqlClient, {
|
|
32
|
+
appId: projectId,
|
|
33
|
+
limit: paginatedQueryOptions.limit ?? exports.CHANNELS_LIMIT,
|
|
34
|
+
offset: paginatedQueryOptions.offset,
|
|
35
|
+
});
|
|
36
|
+
if (channels.length === 0) {
|
|
37
|
+
throw new Error(`No channels found for project "${projectId}".`);
|
|
38
|
+
}
|
|
39
|
+
const channelList = channels.map(c => c.name).join('\n ');
|
|
40
|
+
throw new Error(`Unable to select a channel in non-interactive mode. Use the --channel flag to specify the channel. Available channels:\n ${channelList}`);
|
|
32
41
|
}
|
|
33
42
|
const updateChannel = await (0, queries_2.paginatedQueryWithSelectPromptAsync)({
|
|
34
43
|
limit: paginatedQueryOptions.limit ?? exports.CHANNELS_LIMIT,
|
|
@@ -153,7 +153,6 @@ If there are errors in **Expo Go** or the project is not running, create a **dev
|
|
|
153
153
|
When working on this project:
|
|
154
154
|
|
|
155
155
|
1. **Always start by consulting the appropriate documentation**:
|
|
156
|
-
|
|
157
156
|
- For general Expo questions: https://docs.expo.dev/llms-full.txt
|
|
158
157
|
- For EAS/deployment questions: https://docs.expo.dev/llms-eas.txt
|
|
159
158
|
- For SDK/API questions: https://docs.expo.dev/llms-sdk.txt
|
|
@@ -4,6 +4,7 @@ export default class AccountLogin extends EasCommand {
|
|
|
4
4
|
static aliases: string[];
|
|
5
5
|
static flags: {
|
|
6
6
|
sso: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
7
|
+
browser: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
7
8
|
};
|
|
8
9
|
static contextDefinition: {
|
|
9
10
|
sessionManager: import("../../commandUtils/context/SessionManagementContextField").default;
|
|
@@ -17,13 +17,18 @@ class AccountLogin extends EasCommand_1.default {
|
|
|
17
17
|
char: 's',
|
|
18
18
|
default: false,
|
|
19
19
|
}),
|
|
20
|
+
browser: core_1.Flags.boolean({
|
|
21
|
+
description: 'Login with your browser',
|
|
22
|
+
char: 'b',
|
|
23
|
+
default: false,
|
|
24
|
+
}),
|
|
20
25
|
};
|
|
21
26
|
static contextDefinition = {
|
|
22
27
|
...this.ContextOptions.MaybeLoggedIn,
|
|
23
28
|
...this.ContextOptions.SessionManagment,
|
|
24
29
|
};
|
|
25
30
|
async runAsync() {
|
|
26
|
-
const { flags: { sso }, } = await this.parse(AccountLogin);
|
|
31
|
+
const { flags: { sso, browser }, } = await this.parse(AccountLogin);
|
|
27
32
|
const { sessionManager, maybeLoggedIn: { actor }, } = await this.getContextAsync(AccountLogin, { nonInteractive: false });
|
|
28
33
|
if (sessionManager.getAccessToken()) {
|
|
29
34
|
throw new Error('EXPO_TOKEN is set in your environment, and is being used for all EAS authentication. To use username/password authentication, unset EXPO_TOKEN in your environment and re-run the command.');
|
|
@@ -37,7 +42,7 @@ class AccountLogin extends EasCommand_1.default {
|
|
|
37
42
|
core_1.Errors.error('Aborted', { exit: 1 });
|
|
38
43
|
}
|
|
39
44
|
}
|
|
40
|
-
await sessionManager.showLoginPromptAsync({ sso });
|
|
45
|
+
await sessionManager.showLoginPromptAsync({ sso, browser });
|
|
41
46
|
log_1.default.log('Logged in');
|
|
42
47
|
}
|
|
43
48
|
}
|
|
@@ -54,7 +54,10 @@ class EnvCreate extends EasCommand_1.default {
|
|
|
54
54
|
const { projectId, loggedIn: { graphqlClient }, } = await this.getContextAsync(EnvCreate, {
|
|
55
55
|
nonInteractive: validatedFlags['non-interactive'],
|
|
56
56
|
});
|
|
57
|
-
const { name, value, scope, 'non-interactive': nonInteractive, environment: environments, visibility, force, type, fileName, } = await this.promptForMissingFlagsAsync(validatedFlags, args, {
|
|
57
|
+
const { name, value, scope, 'non-interactive': nonInteractive, environment: environments, visibility, force, type, fileName, } = await this.promptForMissingFlagsAsync(validatedFlags, args, {
|
|
58
|
+
graphqlClient,
|
|
59
|
+
projectId,
|
|
60
|
+
});
|
|
58
61
|
const [projectDisplayName, ownerAccount] = await Promise.all([
|
|
59
62
|
(0, projectUtils_1.getDisplayNameForProjectIdAsync)(graphqlClient, projectId),
|
|
60
63
|
(0, projectUtils_1.getOwnerAccountForProjectIdAsync)(graphqlClient, projectId),
|
|
@@ -186,7 +189,7 @@ class EnvCreate extends EasCommand_1.default {
|
|
|
186
189
|
fileName = path_1.default.basename(environmentFilePath);
|
|
187
190
|
}
|
|
188
191
|
value = environmentFilePath ? await fs_extra_1.default.readFile(environmentFilePath, 'base64') : value;
|
|
189
|
-
let newEnvironments = environments
|
|
192
|
+
let newEnvironments = environments ?? (environment ? [environment] : undefined);
|
|
190
193
|
if (!newEnvironments) {
|
|
191
194
|
newEnvironments = await (0, prompts_2.promptVariableEnvironmentAsync)({
|
|
192
195
|
nonInteractive,
|
|
@@ -110,11 +110,7 @@ class EnvList extends EasCommand_1.default {
|
|
|
110
110
|
});
|
|
111
111
|
}
|
|
112
112
|
sanitizeInputs(flags, { environment }) {
|
|
113
|
-
const environments = flags.environment
|
|
114
|
-
? flags.environment
|
|
115
|
-
: environment
|
|
116
|
-
? [environment]
|
|
117
|
-
: undefined;
|
|
113
|
+
const environments = flags.environment ?? (environment ? [environment] : undefined);
|
|
118
114
|
return {
|
|
119
115
|
...flags,
|
|
120
116
|
'non-interactive': flags['non-interactive'] ?? false,
|
|
@@ -313,11 +313,11 @@ class UpdatePublish extends EasCommand_1.default {
|
|
|
313
313
|
return {
|
|
314
314
|
...info,
|
|
315
315
|
expoUpdatesRuntimeFingerprintSource: info.expoUpdatesRuntimeFingerprint
|
|
316
|
-
? (await (0, maybeUploadFingerprintAsync_1.maybeUploadFingerprintAsync)({
|
|
316
|
+
? ((await (0, maybeUploadFingerprintAsync_1.maybeUploadFingerprintAsync)({
|
|
317
317
|
hash: info.runtimeVersion,
|
|
318
318
|
fingerprint: info.expoUpdatesRuntimeFingerprint,
|
|
319
319
|
graphqlClient,
|
|
320
|
-
})).fingerprintSource ?? null
|
|
320
|
+
})).fingerprintSource ?? null)
|
|
321
321
|
: null,
|
|
322
322
|
};
|
|
323
323
|
}));
|
package/build/commands/upload.js
CHANGED
|
@@ -8,7 +8,7 @@ const fast_glob_1 = tslib_1.__importDefault(require("fast-glob"));
|
|
|
8
8
|
const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
|
|
9
9
|
const node_stream_zip_1 = tslib_1.__importDefault(require("node-stream-zip"));
|
|
10
10
|
const path_1 = tslib_1.__importDefault(require("path"));
|
|
11
|
-
const
|
|
11
|
+
const tar = tslib_1.__importStar(require("tar"));
|
|
12
12
|
const uuid_1 = require("uuid");
|
|
13
13
|
const url_1 = require("../build/utils/url");
|
|
14
14
|
const EasCommand_1 = tslib_1.__importDefault(require("../commandUtils/EasCommand"));
|
|
@@ -214,7 +214,7 @@ async function uploadAppArchiveAsync(graphqlClient, originalPath) {
|
|
|
214
214
|
const tarPath = path_1.default.join((0, paths_1.getTmpDirectory)(), `${(0, uuid_1.v4)()}.tar.gz`);
|
|
215
215
|
const parentPath = path_1.default.dirname(originalPath);
|
|
216
216
|
const folderName = path_1.default.basename(originalPath);
|
|
217
|
-
await
|
|
217
|
+
await tar.create({ cwd: parentPath, file: tarPath, gzip: true }, [folderName]);
|
|
218
218
|
filePath = tarPath;
|
|
219
219
|
}
|
|
220
220
|
const fileSize = (await fs_extra_1.default.stat(filePath)).size;
|
|
@@ -306,7 +306,7 @@ async function extractAppMetadataAsync(buildPath, platform) {
|
|
|
306
306
|
try {
|
|
307
307
|
let fingerprintHashPromise;
|
|
308
308
|
let infoPlistPromise;
|
|
309
|
-
await
|
|
309
|
+
await tar.list({
|
|
310
310
|
file: buildPath,
|
|
311
311
|
// eslint-disable-next-line async-protect/async-suffix
|
|
312
312
|
onentry: entry => {
|
|
@@ -43,9 +43,7 @@ exports.AppleDistributionCertificateMutation = {
|
|
|
43
43
|
async deleteAppleDistributionCertificateAsync(graphqlClient, appleDistributionCertificateId) {
|
|
44
44
|
await (0, client_1.withErrorHandlingAsync)(graphqlClient
|
|
45
45
|
.mutation((0, graphql_tag_1.default) `
|
|
46
|
-
mutation DeleteAppleDistributionCertificateMutation(
|
|
47
|
-
$appleDistributionCertificateId: ID!
|
|
48
|
-
) {
|
|
46
|
+
mutation DeleteAppleDistributionCertificateMutation($appleDistributionCertificateId: ID!) {
|
|
49
47
|
appleDistributionCertificate {
|
|
50
48
|
deleteAppleDistributionCertificate(id: $appleDistributionCertificateId) {
|
|
51
49
|
id
|
package/build/devices/queries.js
CHANGED
|
@@ -18,7 +18,18 @@ exports.TEAMS_LIMIT = 50;
|
|
|
18
18
|
exports.DEVICES_LIMIT = 50;
|
|
19
19
|
async function selectAppleTeamOnAccountAsync(graphqlClient, { accountName, selectionPromptTitle, paginatedQueryOptions, }) {
|
|
20
20
|
if (paginatedQueryOptions.nonInteractive) {
|
|
21
|
-
|
|
21
|
+
const teams = await AppleTeamQuery_1.AppleTeamQuery.getAllForAccountAsync(graphqlClient, {
|
|
22
|
+
accountName,
|
|
23
|
+
limit: paginatedQueryOptions.limit ?? exports.TEAMS_LIMIT,
|
|
24
|
+
offset: paginatedQueryOptions.offset,
|
|
25
|
+
});
|
|
26
|
+
if (teams.length === 0) {
|
|
27
|
+
throw new Error(`No Apple teams found for account ${accountName}.`);
|
|
28
|
+
}
|
|
29
|
+
const teamList = teams
|
|
30
|
+
.map(t => t.appleTeamName ? `${t.appleTeamName} (${t.appleTeamIdentifier})` : t.appleTeamIdentifier)
|
|
31
|
+
.join('\n ');
|
|
32
|
+
throw new Error(`Unable to select an Apple team in non-interactive mode. Use the --apple-team-id flag to specify the team. Available Apple teams for account ${accountName}:\n ${teamList}`);
|
|
22
33
|
}
|
|
23
34
|
else {
|
|
24
35
|
const selectedAppleTeam = await (0, queries_1.paginatedQueryWithSelectPromptAsync)({
|
|
@@ -47,7 +58,17 @@ async function selectAppleTeamOnAccountAsync(graphqlClient, { accountName, selec
|
|
|
47
58
|
}
|
|
48
59
|
async function selectAppleDeviceOnAppleTeamAsync(graphqlClient, { accountName, appleTeamIdentifier, selectionPromptTitle, paginatedQueryOptions, }) {
|
|
49
60
|
if (paginatedQueryOptions.nonInteractive) {
|
|
50
|
-
|
|
61
|
+
const devices = await AppleDeviceQuery_1.AppleDeviceQuery.getAllForAppleTeamAsync(graphqlClient, {
|
|
62
|
+
accountName,
|
|
63
|
+
appleTeamIdentifier,
|
|
64
|
+
limit: paginatedQueryOptions.limit ?? exports.DEVICES_LIMIT,
|
|
65
|
+
offset: paginatedQueryOptions.offset,
|
|
66
|
+
});
|
|
67
|
+
if (devices.length === 0) {
|
|
68
|
+
throw new Error(`No devices found on Apple team ${appleTeamIdentifier} for account ${accountName}.`);
|
|
69
|
+
}
|
|
70
|
+
const deviceList = devices.map(d => (0, DeviceUtils_1.formatDeviceLabel)(d)).join('\n ');
|
|
71
|
+
throw new Error(`Unable to select an Apple device in non-interactive mode. Available devices on Apple team ${appleTeamIdentifier}:\n ${deviceList}`);
|
|
51
72
|
}
|
|
52
73
|
else {
|
|
53
74
|
const selectedAppleDevice = await (0, queries_1.paginatedQueryWithSelectPromptAsync)({
|
|
@@ -86,10 +86,7 @@ exports.EnvironmentVariableMutation = {
|
|
|
86
86
|
$appId: ID!
|
|
87
87
|
) {
|
|
88
88
|
environmentVariable {
|
|
89
|
-
createBulkEnvironmentVariablesForApp(
|
|
90
|
-
environmentVariablesData: $input
|
|
91
|
-
appId: $appId
|
|
92
|
-
) {
|
|
89
|
+
createBulkEnvironmentVariablesForApp(environmentVariablesData: $input, appId: $appId) {
|
|
93
90
|
id
|
|
94
91
|
}
|
|
95
92
|
}
|
|
@@ -48,10 +48,7 @@ exports.PublishMutation = {
|
|
|
48
48
|
async setCodeSigningInfoAsync(graphqlClient, updateId, codeSigningInfo) {
|
|
49
49
|
const data = await (0, client_1.withErrorHandlingAsync)(graphqlClient
|
|
50
50
|
.mutation((0, graphql_tag_1.default) `
|
|
51
|
-
mutation SetCodeSigningInfoMutation(
|
|
52
|
-
$updateId: ID!
|
|
53
|
-
$codeSigningInfo: CodeSigningInfoInput!
|
|
54
|
-
) {
|
|
51
|
+
mutation SetCodeSigningInfoMutation($updateId: ID!, $codeSigningInfo: CodeSigningInfoInput!) {
|
|
55
52
|
update {
|
|
56
53
|
setCodeSigningInfo(updateId: $updateId, codeSigningInfo: $codeSigningInfo) {
|
|
57
54
|
id
|
|
@@ -9,9 +9,7 @@ exports.UserPreferencesMutation = {
|
|
|
9
9
|
async markCliDoneInOnboardingUserPreferencesAsync(graphqlClient, userPreferencesData) {
|
|
10
10
|
const data = await (0, client_1.withErrorHandlingAsync)(graphqlClient
|
|
11
11
|
.mutation((0, graphql_tag_1.default) `
|
|
12
|
-
mutation MarkCliDoneInOnboardingUserPreferencesMutation(
|
|
13
|
-
$preferences: UserPreferencesInput!
|
|
14
|
-
) {
|
|
12
|
+
mutation MarkCliDoneInOnboardingUserPreferencesMutation($preferences: UserPreferencesInput!) {
|
|
15
13
|
me {
|
|
16
14
|
setPreferences(preferences: $preferences) {
|
|
17
15
|
onboarding {
|
|
@@ -17,17 +17,9 @@ var WorkflowRevisionMutation;
|
|
|
17
17
|
async function getOrCreateWorkflowRevisionFromGitRefAsync(graphqlClient, { appId, fileName, gitRef, }) {
|
|
18
18
|
const data = await (0, client_1.withErrorHandlingAsync)(graphqlClient
|
|
19
19
|
.mutation((0, graphql_tag_1.default) `
|
|
20
|
-
mutation GetOrCreateWorkflowRevisionFromGitRef(
|
|
21
|
-
$appId: ID!
|
|
22
|
-
$fileName: String!
|
|
23
|
-
$gitRef: String!
|
|
24
|
-
) {
|
|
20
|
+
mutation GetOrCreateWorkflowRevisionFromGitRef($appId: ID!, $fileName: String!, $gitRef: String!) {
|
|
25
21
|
workflowRevision {
|
|
26
|
-
getOrCreateWorkflowRevisionFromGitRef(
|
|
27
|
-
appId: $appId
|
|
28
|
-
fileName: $fileName
|
|
29
|
-
gitRef: $gitRef
|
|
30
|
-
) {
|
|
22
|
+
getOrCreateWorkflowRevisionFromGitRef(appId: $appId, fileName: $fileName, gitRef: $gitRef) {
|
|
31
23
|
id
|
|
32
24
|
yamlConfig
|
|
33
25
|
blobSha
|
|
@@ -8,11 +8,7 @@ exports.AppVersionQuery = {
|
|
|
8
8
|
async latestVersionAsync(graphqlClient, appId, platform, applicationIdentifier) {
|
|
9
9
|
const data = await (0, client_1.withErrorHandlingAsync)(graphqlClient
|
|
10
10
|
.query((0, graphql_tag_1.default) `
|
|
11
|
-
query LatestAppVersion(
|
|
12
|
-
$appId: String!
|
|
13
|
-
$platform: AppPlatform!
|
|
14
|
-
$applicationIdentifier: String!
|
|
15
|
-
) {
|
|
11
|
+
query LatestAppVersion($appId: String!, $platform: AppPlatform!, $applicationIdentifier: String!) {
|
|
16
12
|
app {
|
|
17
13
|
byId(appId: $appId) {
|
|
18
14
|
id
|
package/build/log.js
CHANGED
|
@@ -8,7 +8,7 @@ const figures_1 = tslib_1.__importDefault(require("figures"));
|
|
|
8
8
|
const getenv_1 = require("getenv");
|
|
9
9
|
const log_symbols_1 = tslib_1.__importDefault(require("log-symbols"));
|
|
10
10
|
const terminal_link_1 = tslib_1.__importDefault(require("terminal-link"));
|
|
11
|
-
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
11
|
+
// eslint-disable-next-line eslint-import/no-extraneous-dependencies
|
|
12
12
|
const nodeDebug = require('debug')('eas:log:debug');
|
|
13
13
|
class Log {
|
|
14
14
|
static isDebug = (0, getenv_1.boolish)('EXPO_DEBUG', false);
|
package/build/ora.js
CHANGED
|
@@ -22,7 +22,7 @@ const isCi = (0, getenv_1.boolish)('CI', false);
|
|
|
22
22
|
* @returns
|
|
23
23
|
*/
|
|
24
24
|
function ora(options) {
|
|
25
|
-
const inputOptions = typeof options === 'string' ? { text: options } : options ?? {};
|
|
25
|
+
const inputOptions = typeof options === 'string' ? { text: options } : (options ?? {});
|
|
26
26
|
const disabled = log_1.default.isDebug || !process.stdin.isTTY || isCi;
|
|
27
27
|
const spinner = (0, ora_1.default)({
|
|
28
28
|
// Ensure our non-interactive mode emulates CI mode.
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ProfileData } from '../utils/profiles';
|
|
2
|
+
import type { Client } from '../vcs/vcs';
|
|
3
|
+
export declare function discourageExpoGoForProdAsync(buildProfiles: ProfileData<'build'>[] | undefined, projectDir: string, vcsClient: Client): Promise<void>;
|
|
4
|
+
export declare function detectExpoGoProdBuildAsync(buildProfiles: ProfileData<'build'>[] | undefined, projectDir: string, vcsClient: Client): Promise<boolean>;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.discourageExpoGoForProdAsync = discourageExpoGoForProdAsync;
|
|
4
|
+
exports.detectExpoGoProdBuildAsync = detectExpoGoProdBuildAsync;
|
|
5
|
+
const tslib_1 = require("tslib");
|
|
6
|
+
const eas_build_job_1 = require("@expo/eas-build-job");
|
|
7
|
+
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
8
|
+
const getenv_1 = tslib_1.__importDefault(require("getenv"));
|
|
9
|
+
const workflow_1 = require("./workflow");
|
|
10
|
+
const devClient_1 = require("../build/utils/devClient");
|
|
11
|
+
const log_1 = tslib_1.__importStar(require("../log"));
|
|
12
|
+
const suppressionEnvVarName = 'EAS_BUILD_NO_EXPO_GO_WARNING';
|
|
13
|
+
async function discourageExpoGoForProdAsync(buildProfiles, projectDir, vcsClient) {
|
|
14
|
+
try {
|
|
15
|
+
const isExpoGoProdBuild = await detectExpoGoProdBuildAsync(buildProfiles, projectDir, vcsClient);
|
|
16
|
+
if (!isExpoGoProdBuild) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
log_1.default.newLine();
|
|
20
|
+
log_1.default.warn(`⚠️ Detected that your app uses Expo Go for development, this is not recommended when building production apps.`);
|
|
21
|
+
log_1.default.warn((0, log_1.learnMore)('https://expo.fyi/why-not-build-expo-go-for-production', {
|
|
22
|
+
dim: false,
|
|
23
|
+
}));
|
|
24
|
+
log_1.default.warn(chalk_1.default.dim(`To suppress this warning, set ${chalk_1.default.bold(`${suppressionEnvVarName}=true`)}.`));
|
|
25
|
+
log_1.default.newLine();
|
|
26
|
+
}
|
|
27
|
+
catch (err) {
|
|
28
|
+
log_1.default.isDebug && log_1.default.warn('Error detecting whether Expo Go is used:', err);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
async function detectExpoGoProdBuildAsync(buildProfiles, projectDir, vcsClient) {
|
|
32
|
+
const shouldSuppressWarning = getenv_1.default.boolish(suppressionEnvVarName, false);
|
|
33
|
+
const isProductionBuild = buildProfiles?.map(it => it.profileName).includes('production');
|
|
34
|
+
if (shouldSuppressWarning || !isProductionBuild) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
const hasExpoDevClient = (0, devClient_1.isExpoDevClientInstalled)(projectDir);
|
|
38
|
+
if (hasExpoDevClient) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
return await checkIfManagedWorkflowAsync(projectDir, vcsClient);
|
|
42
|
+
}
|
|
43
|
+
async function checkIfManagedWorkflowAsync(projectDir, vcsClient) {
|
|
44
|
+
const workflows = await (0, workflow_1.resolveWorkflowPerPlatformAsync)(projectDir, vcsClient);
|
|
45
|
+
return workflows.android === eas_build_job_1.Workflow.MANAGED && workflows.ios === eas_build_job_1.Workflow.MANAGED;
|
|
46
|
+
}
|
|
@@ -30,7 +30,11 @@ class ManageRollout {
|
|
|
30
30
|
async runAsync(ctx) {
|
|
31
31
|
const { nonInteractive } = ctx;
|
|
32
32
|
if (nonInteractive) {
|
|
33
|
-
throw new Error(`
|
|
33
|
+
throw new Error(`Rollout selection cannot be run in non-interactive mode. Available actions: ${[
|
|
34
|
+
ManageRolloutActions.EDIT,
|
|
35
|
+
ManageRolloutActions.END,
|
|
36
|
+
ManageRolloutActions.VIEW,
|
|
37
|
+
].join(', ')}.`);
|
|
34
38
|
}
|
|
35
39
|
const channelObject = await this.getChannelObjectAsync(ctx);
|
|
36
40
|
(0, utils_1.printRollout)(channelObject);
|
|
@@ -43,7 +43,16 @@ class SelectRuntime {
|
|
|
43
43
|
const { nonInteractive, graphqlClient, app } = ctx;
|
|
44
44
|
const { projectId } = app;
|
|
45
45
|
if (nonInteractive) {
|
|
46
|
-
|
|
46
|
+
const runtimes = await this.getNewestRuntimeAsync(graphqlClient, {
|
|
47
|
+
appId: projectId,
|
|
48
|
+
branchName: this.branchInfo.name,
|
|
49
|
+
anotherBranchIdToIntersectRuntimesBy: this.options.anotherBranchToIntersectRuntimesBy?.id,
|
|
50
|
+
});
|
|
51
|
+
if (runtimes.edges.length === 0) {
|
|
52
|
+
throw new utils_1.NonInteractiveError(`No ${this.printedType} versions found on branch "${this.branchInfo.name}".`);
|
|
53
|
+
}
|
|
54
|
+
const runtimeList = runtimes.edges.map(e => e.node.version).join('\n ');
|
|
55
|
+
throw new utils_1.NonInteractiveError(`Runtime selection cannot be run in non-interactive mode. Available ${this.printedType} versions on branch "${this.branchInfo.name}":\n ${runtimeList}`);
|
|
47
56
|
}
|
|
48
57
|
const newestRuntimeConnection = await this.getNewestRuntimeAsync(graphqlClient, {
|
|
49
58
|
appId: projectId,
|
package/build/update/queries.js
CHANGED
|
@@ -78,7 +78,16 @@ async function listAndRenderUpdateGroupsOnBranchAsync(graphqlClient, { projectId
|
|
|
78
78
|
}
|
|
79
79
|
async function selectRuntimeAndGetLatestUpdateGroupForEachPublishPlatformOnBranchAsync(graphqlClient, { projectId, branchName, paginatedQueryOptions, }) {
|
|
80
80
|
if (paginatedQueryOptions.nonInteractive) {
|
|
81
|
-
|
|
81
|
+
const runtimes = await RuntimeQuery_1.RuntimeQuery.getRuntimesOnBranchAsync(graphqlClient, {
|
|
82
|
+
appId: projectId,
|
|
83
|
+
name: branchName,
|
|
84
|
+
first: exports.RUNTIME_VERSIONS_LIMIT,
|
|
85
|
+
});
|
|
86
|
+
if (runtimes.edges.length === 0) {
|
|
87
|
+
throw new Error(`No runtime versions found on branch "${branchName}".`);
|
|
88
|
+
}
|
|
89
|
+
const runtimeList = runtimes.edges.map(e => e.node.version).join('\n ');
|
|
90
|
+
throw new Error(`Unable to select a runtime in non-interactive mode. Available runtime versions on branch "${branchName}":\n ${runtimeList}`);
|
|
82
91
|
}
|
|
83
92
|
const runtimeVersion = await selectRuntimeOnBranchAsync(graphqlClient, {
|
|
84
93
|
appId: projectId,
|
|
@@ -112,7 +121,24 @@ async function selectRuntimeAndGetLatestUpdateGroupForEachPublishPlatformOnBranc
|
|
|
112
121
|
}
|
|
113
122
|
async function selectUpdateGroupOnBranchAsync(graphqlClient, { projectId, branchName, paginatedQueryOptions, }) {
|
|
114
123
|
if (paginatedQueryOptions.nonInteractive) {
|
|
115
|
-
|
|
124
|
+
const updateGroups = await queryUpdateGroupsOnBranchAsync(graphqlClient, {
|
|
125
|
+
appId: projectId,
|
|
126
|
+
branchName,
|
|
127
|
+
limit: paginatedQueryOptions.limit ?? exports.UPDATE_GROUPS_LIMIT,
|
|
128
|
+
offset: paginatedQueryOptions.offset,
|
|
129
|
+
});
|
|
130
|
+
if (updateGroups.length === 0) {
|
|
131
|
+
throw new Error(`No update groups found on branch "${branchName}".`);
|
|
132
|
+
}
|
|
133
|
+
const updateList = updateGroups
|
|
134
|
+
.map(group => {
|
|
135
|
+
const first = group[0];
|
|
136
|
+
return first
|
|
137
|
+
? `${first.group} (runtime: ${first.runtimeVersion}, message: ${first.message ?? 'N/A'})`
|
|
138
|
+
: 'unknown';
|
|
139
|
+
})
|
|
140
|
+
.join('\n ');
|
|
141
|
+
throw new Error(`Unable to select an update in non-interactive mode. Use the --group flag to specify the update group. Available update groups on branch "${branchName}":\n ${updateList}`);
|
|
116
142
|
}
|
|
117
143
|
const updateGroup = await (0, queries_1.paginatedQueryWithSelectPromptAsync)({
|
|
118
144
|
limit: paginatedQueryOptions.limit ?? exports.UPDATE_GROUPS_LIMIT,
|
|
@@ -39,12 +39,13 @@ export default class SessionManager {
|
|
|
39
39
|
*
|
|
40
40
|
* @deprecated Should not be used outside of context functions, except in the AccountLogin command.
|
|
41
41
|
*/
|
|
42
|
-
showLoginPromptAsync({ nonInteractive, printNewLine, sso, }?: {
|
|
42
|
+
showLoginPromptAsync({ nonInteractive, printNewLine, sso, browser, }?: {
|
|
43
43
|
nonInteractive?: boolean | undefined;
|
|
44
44
|
printNewLine?: boolean | undefined;
|
|
45
45
|
sso?: boolean | undefined;
|
|
46
|
+
browser?: boolean | undefined;
|
|
46
47
|
}): Promise<void>;
|
|
47
|
-
private
|
|
48
|
+
private browserLoginAsync;
|
|
48
49
|
private loginAsync;
|
|
49
50
|
/**
|
|
50
51
|
* Prompt for an OTP with the option to cancel the question by answering empty (pressing return key).
|