eas-cli 2.7.1 → 2.8.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 +49 -99
- package/build/branch/queries.d.ts +1 -0
- package/build/branch/queries.js +2 -2
- package/build/build/build.js +2 -2
- package/build/build/createContext.js +1 -0
- package/build/build/graphql.js +6 -0
- package/build/build/local.js +1 -1
- package/build/build/queries.d.ts +4 -2
- package/build/build/queries.js +32 -7
- package/build/commands/build/run.js +24 -11
- package/build/commands/submit.js +1 -1
- package/build/commands/update/index.js +8 -6
- package/build/devices/utils/formatDevice.js +1 -2
- package/build/graphql/generated.d.ts +12 -0
- package/build/graphql/generated.js +9 -2
- package/build/graphql/mutations/SubmissionMutation.js +14 -2
- package/build/graphql/mutations/UploadSessionMutation.d.ts +4 -3
- package/build/run/android/aapt.d.ts +5 -0
- package/build/run/android/aapt.js +51 -0
- package/build/run/android/adb.d.ts +23 -0
- package/build/run/android/adb.js +120 -0
- package/build/run/android/emulator.d.ts +7 -0
- package/build/run/android/emulator.js +109 -0
- package/build/run/android/run.d.ts +1 -1
- package/build/run/android/run.js +10 -3
- package/build/run/android/sdk.d.ts +3 -0
- package/build/run/android/sdk.js +29 -0
- package/build/run/android/systemRequirements.d.ts +1 -0
- package/build/run/android/systemRequirements.js +24 -0
- package/build/submit/ArchiveSource.d.ts +20 -10
- package/build/submit/ArchiveSource.js +59 -60
- package/build/submit/BaseSubmitter.d.ts +4 -1
- package/build/submit/BaseSubmitter.js +20 -0
- package/build/submit/android/AndroidSubmitCommand.js +1 -2
- package/build/submit/android/AndroidSubmitter.d.ts +3 -3
- package/build/submit/android/AndroidSubmitter.js +12 -7
- package/build/submit/commons.d.ts +1 -1
- package/build/submit/commons.js +1 -16
- package/build/submit/ios/IosSubmitCommand.js +1 -2
- package/build/submit/ios/IosSubmitter.d.ts +3 -3
- package/build/submit/ios/IosSubmitter.js +11 -6
- package/build/submit/utils/files.js +2 -2
- package/build/submit/utils/summary.d.ts +2 -2
- package/build/submit/utils/summary.js +7 -8
- package/build/uploads.d.ts +4 -10
- package/build/uploads.js +16 -36
- package/build/utils/download.d.ts +3 -2
- package/build/utils/download.js +37 -30
- package/build/utils/progress.d.ts +1 -1
- package/build/utils/progress.js +6 -4
- package/oclif.manifest.json +1 -1
- package/package.json +3 -3
|
@@ -6,7 +6,6 @@ const core_1 = require("@oclif/core");
|
|
|
6
6
|
const fs_extra_1 = require("fs-extra");
|
|
7
7
|
const node_assert_1 = tslib_1.__importDefault(require("node:assert"));
|
|
8
8
|
const queries_1 = require("../../build/queries");
|
|
9
|
-
const types_1 = require("../../build/types");
|
|
10
9
|
const EasCommand_1 = tslib_1.__importDefault(require("../../commandUtils/EasCommand"));
|
|
11
10
|
const pagination_1 = require("../../commandUtils/pagination");
|
|
12
11
|
const generated_1 = require("../../graphql/generated");
|
|
@@ -14,7 +13,6 @@ const BuildQuery_1 = require("../../graphql/queries/BuildQuery");
|
|
|
14
13
|
const projectUtils_1 = require("../../project/projectUtils");
|
|
15
14
|
const prompts_1 = require("../../prompts");
|
|
16
15
|
const run_1 = require("../../run/run");
|
|
17
|
-
const buildDistribution_1 = require("../../utils/buildDistribution");
|
|
18
16
|
const download_1 = require("../../utils/download");
|
|
19
17
|
class Run extends EasCommand_1.default {
|
|
20
18
|
async runAsync() {
|
|
@@ -30,11 +28,16 @@ class Run extends EasCommand_1.default {
|
|
|
30
28
|
async sanitizeFlagsAsync(flags) {
|
|
31
29
|
const { platform, limit, offset, ...runArchiveFlags } = flags;
|
|
32
30
|
const selectedPlatform = await resolvePlatformAsync(platform);
|
|
31
|
+
if (platform === 'ios' && process.platform !== 'darwin') {
|
|
32
|
+
core_1.Errors.error('You can only use an iOS simulator to run apps on macOS devices', {
|
|
33
|
+
exit: 1,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
33
36
|
if (runArchiveFlags.path &&
|
|
34
37
|
!((runArchiveFlags.path.endsWith('.tar.gz') ||
|
|
35
38
|
runArchiveFlags.path.endsWith('.app') ||
|
|
36
39
|
runArchiveFlags.path.endsWith('.apk')) &&
|
|
37
|
-
(0, fs_extra_1.
|
|
40
|
+
(await (0, fs_extra_1.pathExists)(runArchiveFlags.path)))) {
|
|
38
41
|
core_1.Errors.error('The path must point to a .tar.gz archive, .apk file, or .app directory', {
|
|
39
42
|
exit: 1,
|
|
40
43
|
});
|
|
@@ -61,7 +64,7 @@ Run.flags = {
|
|
|
61
64
|
exclusive: ['latest', 'id', 'path'],
|
|
62
65
|
}),
|
|
63
66
|
path: core_1.Flags.string({
|
|
64
|
-
description: 'Path to the simulator/emulator build archive or
|
|
67
|
+
description: 'Path to the simulator/emulator build archive or app',
|
|
65
68
|
exclusive: ['latest', 'id', 'url'],
|
|
66
69
|
}),
|
|
67
70
|
id: core_1.Flags.string({
|
|
@@ -80,6 +83,9 @@ Run.contextDefinition = {
|
|
|
80
83
|
..._a.ContextOptions.ProjectDir,
|
|
81
84
|
};
|
|
82
85
|
async function resolvePlatformAsync(platform) {
|
|
86
|
+
if (process.platform !== 'darwin') {
|
|
87
|
+
return generated_1.AppPlatform.Android;
|
|
88
|
+
}
|
|
83
89
|
if (platform && Object.values(generated_1.AppPlatform).includes(platform.toUpperCase())) {
|
|
84
90
|
return platform.toUpperCase();
|
|
85
91
|
}
|
|
@@ -95,6 +101,7 @@ async function resolvePlatformAsync(platform) {
|
|
|
95
101
|
return selectedPlatform;
|
|
96
102
|
}
|
|
97
103
|
async function maybeGetBuildAsync(graphqlClient, flags, projectId, paginatedQueryOptions) {
|
|
104
|
+
const distributionType = flags.selectedPlatform === generated_1.AppPlatform.Ios ? generated_1.DistributionType.Simulator : undefined;
|
|
98
105
|
if (flags.runArchiveFlags.id) {
|
|
99
106
|
return BuildQuery_1.BuildQuery.byIdAsync(graphqlClient, flags.runArchiveFlags.id);
|
|
100
107
|
}
|
|
@@ -102,15 +109,22 @@ async function maybeGetBuildAsync(graphqlClient, flags, projectId, paginatedQuer
|
|
|
102
109
|
!flags.runArchiveFlags.path &&
|
|
103
110
|
!flags.runArchiveFlags.url &&
|
|
104
111
|
!flags.runArchiveFlags.latest) {
|
|
105
|
-
return await (0, queries_1.listAndSelectBuildsOnAppAsync)(graphqlClient, {
|
|
112
|
+
return await (0, queries_1.listAndSelectBuildsOnAppAsync)(graphqlClient, flags.selectedPlatform, {
|
|
106
113
|
projectId,
|
|
107
114
|
projectDisplayName: await (0, projectUtils_1.getDisplayNameForProjectIdAsync)(graphqlClient, projectId),
|
|
108
115
|
filter: {
|
|
109
116
|
platform: flags.selectedPlatform,
|
|
110
|
-
distribution:
|
|
117
|
+
distribution: distributionType,
|
|
111
118
|
status: generated_1.BuildStatus.Finished,
|
|
112
119
|
},
|
|
113
120
|
queryOptions: paginatedQueryOptions,
|
|
121
|
+
selectPromptDisabledFunction: build => {
|
|
122
|
+
var _b, _c, _d;
|
|
123
|
+
return build.platform === generated_1.AppPlatform.Ios
|
|
124
|
+
? false
|
|
125
|
+
: (_d = !((_c = (_b = build.artifacts) === null || _b === void 0 ? void 0 : _b.applicationArchiveUrl) === null || _c === void 0 ? void 0 : _c.endsWith('.apk'))) !== null && _d !== void 0 ? _d : false;
|
|
126
|
+
},
|
|
127
|
+
warningMessage: 'This is not a simulator/emulator build',
|
|
114
128
|
});
|
|
115
129
|
}
|
|
116
130
|
else if (flags.runArchiveFlags.latest) {
|
|
@@ -118,7 +132,7 @@ async function maybeGetBuildAsync(graphqlClient, flags, projectId, paginatedQuer
|
|
|
118
132
|
projectId,
|
|
119
133
|
filter: {
|
|
120
134
|
platform: flags.selectedPlatform,
|
|
121
|
-
distribution:
|
|
135
|
+
distribution: distributionType,
|
|
122
136
|
status: generated_1.BuildStatus.Finished,
|
|
123
137
|
},
|
|
124
138
|
});
|
|
@@ -130,18 +144,17 @@ async function maybeGetBuildAsync(graphqlClient, flags, projectId, paginatedQuer
|
|
|
130
144
|
async function getPathToSimulatorBuildAppAsync(graphqlClient, projectId, flags, queryOptions) {
|
|
131
145
|
var _b, _c;
|
|
132
146
|
const maybeBuild = await maybeGetBuildAsync(graphqlClient, flags, projectId, queryOptions);
|
|
133
|
-
const appExtension = flags.selectedPlatform === generated_1.AppPlatform.Ios ? 'app' : 'apk';
|
|
134
147
|
if (maybeBuild) {
|
|
135
148
|
if (!((_b = maybeBuild.artifacts) === null || _b === void 0 ? void 0 : _b.applicationArchiveUrl)) {
|
|
136
149
|
throw new Error('Build does not have an application archive url');
|
|
137
150
|
}
|
|
138
|
-
return await (0, download_1.
|
|
151
|
+
return await (0, download_1.downloadAndMaybeExtractAppAsync)(maybeBuild.artifacts.applicationArchiveUrl, flags.selectedPlatform);
|
|
139
152
|
}
|
|
140
153
|
if (flags.runArchiveFlags.url) {
|
|
141
|
-
return await (0, download_1.
|
|
154
|
+
return await (0, download_1.downloadAndMaybeExtractAppAsync)(flags.runArchiveFlags.url, flags.selectedPlatform);
|
|
142
155
|
}
|
|
143
156
|
if ((_c = flags.runArchiveFlags.path) === null || _c === void 0 ? void 0 : _c.endsWith('.tar.gz')) {
|
|
144
|
-
return await (0, download_1.extractAppFromLocalArchiveAsync)(flags.runArchiveFlags.path,
|
|
157
|
+
return await (0, download_1.extractAppFromLocalArchiveAsync)(flags.runArchiveFlags.path, flags.selectedPlatform);
|
|
145
158
|
}
|
|
146
159
|
// this should never fail, due to the validation in sanitizeFlagsAsync
|
|
147
160
|
(0, node_assert_1.default)(flags.runArchiveFlags.path);
|
package/build/commands/submit.js
CHANGED
|
@@ -124,7 +124,7 @@ Submit.flags = {
|
|
|
124
124
|
exclusive: ['latest', 'id', 'path'],
|
|
125
125
|
}),
|
|
126
126
|
verbose: core_1.Flags.boolean({
|
|
127
|
-
description: 'Always print logs from
|
|
127
|
+
description: 'Always print logs from EAS Submit',
|
|
128
128
|
default: false,
|
|
129
129
|
}),
|
|
130
130
|
wait: core_1.Flags.boolean({
|
|
@@ -248,15 +248,17 @@ class UpdatePublish extends EasCommand_1.default {
|
|
|
248
248
|
runtimeToPlatformMapping.push({ runtimeVersion: runtime.runtimeVersion, platforms });
|
|
249
249
|
}
|
|
250
250
|
}
|
|
251
|
-
const { branchId } = await (0, queries_1.ensureBranchExistsAsync)(graphqlClient, {
|
|
251
|
+
const { branchId, createdBranch } = await (0, queries_1.ensureBranchExistsAsync)(graphqlClient, {
|
|
252
252
|
appId: projectId,
|
|
253
253
|
branchName,
|
|
254
254
|
});
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
255
|
+
if (createdBranch) {
|
|
256
|
+
await (0, queries_2.ensureChannelExistsAsync)(graphqlClient, {
|
|
257
|
+
appId: projectId,
|
|
258
|
+
branchId,
|
|
259
|
+
channelName: branchName,
|
|
260
|
+
});
|
|
261
|
+
}
|
|
260
262
|
log_1.default.withTick(`Channel: ${chalk_1.default.bold(branchName)} pointed at branch: ${chalk_1.default.bold(branchName)}`);
|
|
261
263
|
const gitCommitHash = await (0, vcs_1.getVcsClient)().getCommitHashAsync();
|
|
262
264
|
// Sort the updates into different groups based on their platform specific runtime versions
|
|
@@ -19,13 +19,12 @@ function formatDeviceClass(device) {
|
|
|
19
19
|
function formatDevice(device, team) {
|
|
20
20
|
var _a, _b;
|
|
21
21
|
const fields = [
|
|
22
|
-
{ label: '
|
|
22
|
+
{ label: 'UDID', value: device.identifier },
|
|
23
23
|
{ label: 'Name', value: (_a = device.name) !== null && _a !== void 0 ? _a : 'Unknown' },
|
|
24
24
|
{
|
|
25
25
|
label: 'Class',
|
|
26
26
|
value: formatDeviceClass(device),
|
|
27
27
|
},
|
|
28
|
-
{ label: 'UDID', value: device.identifier },
|
|
29
28
|
];
|
|
30
29
|
if (team) {
|
|
31
30
|
fields.push({ label: 'Apple Team ID', value: team.appleTeamIdentifier }, { label: 'Apple Team Name', value: (_b = team.appleTeamName) !== null && _b !== void 0 ? _b : 'Unknown' });
|
|
@@ -2114,6 +2114,11 @@ export declare type GetSignedAssetUploadSpecificationsResult = {
|
|
|
2114
2114
|
__typename?: 'GetSignedAssetUploadSpecificationsResult';
|
|
2115
2115
|
specifications: Array<Scalars['String']>;
|
|
2116
2116
|
};
|
|
2117
|
+
export declare enum GitHubAppEnvironment {
|
|
2118
|
+
Development = "DEVELOPMENT",
|
|
2119
|
+
Production = "PRODUCTION",
|
|
2120
|
+
Staging = "STAGING"
|
|
2121
|
+
}
|
|
2117
2122
|
export declare type GitHubAppInstallation = {
|
|
2118
2123
|
__typename?: 'GitHubAppInstallation';
|
|
2119
2124
|
accessibleRepositories: GitHubRepositoryPaginationResult;
|
|
@@ -2166,7 +2171,9 @@ export declare type GitHubAppQuery = {
|
|
|
2166
2171
|
__typename?: 'GitHubAppQuery';
|
|
2167
2172
|
appIdentifier: Scalars['String'];
|
|
2168
2173
|
clientIdentifier: Scalars['String'];
|
|
2174
|
+
environment: GitHubAppEnvironment;
|
|
2169
2175
|
installation: GitHubAppInstallation;
|
|
2176
|
+
name: Scalars['String'];
|
|
2170
2177
|
searchRepositories: GitHubRepositoryPaginationResult;
|
|
2171
2178
|
};
|
|
2172
2179
|
export declare type GitHubAppQueryInstallationArgs = {
|
|
@@ -2187,12 +2194,14 @@ export declare type GitHubRepository = {
|
|
|
2187
2194
|
};
|
|
2188
2195
|
export declare type GitHubRepositoryMetadata = {
|
|
2189
2196
|
__typename?: 'GitHubRepositoryMetadata';
|
|
2197
|
+
defaultBranch?: Maybe<Scalars['String']>;
|
|
2190
2198
|
githubRepoDescription?: Maybe<Scalars['String']>;
|
|
2191
2199
|
githubRepoName: Scalars['String'];
|
|
2192
2200
|
githubRepoOwnerName: Scalars['String'];
|
|
2193
2201
|
githubRepoUrl: Scalars['String'];
|
|
2194
2202
|
lastPushed: Scalars['DateTime'];
|
|
2195
2203
|
lastUpdated: Scalars['DateTime'];
|
|
2204
|
+
openGraphImageUrl?: Maybe<Scalars['String']>;
|
|
2196
2205
|
private: Scalars['Boolean'];
|
|
2197
2206
|
};
|
|
2198
2207
|
export declare type GitHubRepositoryMutation = {
|
|
@@ -2735,6 +2744,7 @@ export declare type ProjectArchiveSourceInput = {
|
|
|
2735
2744
|
url?: InputMaybe<Scalars['String']>;
|
|
2736
2745
|
};
|
|
2737
2746
|
export declare enum ProjectArchiveSourceType {
|
|
2747
|
+
Gcs = "GCS",
|
|
2738
2748
|
S3 = "S3",
|
|
2739
2749
|
Url = "URL"
|
|
2740
2750
|
}
|
|
@@ -6939,6 +6949,7 @@ export declare type CreateAndroidSubmissionMutationVariables = Exact<{
|
|
|
6939
6949
|
appId: Scalars['ID'];
|
|
6940
6950
|
config: AndroidSubmissionConfigInput;
|
|
6941
6951
|
submittedBuildId?: InputMaybe<Scalars['ID']>;
|
|
6952
|
+
archiveSource?: InputMaybe<SubmissionArchiveSourceInput>;
|
|
6942
6953
|
}>;
|
|
6943
6954
|
export declare type CreateAndroidSubmissionMutation = {
|
|
6944
6955
|
__typename?: 'RootMutation';
|
|
@@ -6987,6 +6998,7 @@ export declare type CreateIosSubmissionMutationVariables = Exact<{
|
|
|
6987
6998
|
appId: Scalars['ID'];
|
|
6988
6999
|
config: IosSubmissionConfigInput;
|
|
6989
7000
|
submittedBuildId?: InputMaybe<Scalars['ID']>;
|
|
7001
|
+
archiveSource?: InputMaybe<SubmissionArchiveSourceInput>;
|
|
6990
7002
|
}>;
|
|
6991
7003
|
export declare type CreateIosSubmissionMutation = {
|
|
6992
7004
|
__typename?: 'RootMutation';
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
* For more info and docs, visit https://graphql-code-generator.com/
|
|
7
7
|
*/
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.
|
|
10
|
-
exports.WebhookType = exports.UsageMetricsGranularity = exports.UsageMetricType = exports.UploadSessionType = void 0;
|
|
9
|
+
exports.SubmissionArchiveSourceType = exports.SubmissionAndroidTrack = exports.SubmissionAndroidReleaseStatus = exports.SubmissionAndroidArchiveType = exports.StatuspageServiceStatus = exports.StatuspageServiceName = exports.StatuspageIncidentStatus = exports.StatuspageIncidentImpact = exports.StandardOffer = exports.SecondFactorMethod = exports.Role = exports.ProjectArchiveSourceType = exports.Permission = exports.Order = exports.OfferType = exports.MailchimpTag = exports.MailchimpAudience = exports.IosSchemeBuildConfiguration = exports.IosManagedBuildType = exports.IosDistributionType = exports.IosBuildType = exports.InvoiceDiscountType = exports.GitHubAppInstallationStatus = exports.GitHubAppEnvironment = exports.Feature = exports.EnvironmentSecretType = exports.EasServiceMetric = exports.EasBuildDeprecationInfoType = exports.DistributionType = exports.CacheControlScope = exports.BuildWorkflow = exports.BuildStatus = exports.BuildResourceClass = exports.BuildPriority = exports.BuildJobStatus = exports.BuildJobLogsFormat = exports.BuildIosEnterpriseProvisioning = exports.BuildCredentialsSource = exports.AuthProtocolType = exports.AssetMetadataStatus = exports.AppsFilter = exports.AppleDeviceClass = exports.AppStoreConnectUserRole = exports.AppSort = exports.AppPrivacy = exports.AppPlatform = exports.AndroidKeystoreType = exports.AndroidFcmVersion = exports.AndroidBuildType = exports.ActivityTimelineProjectActivityType = void 0;
|
|
10
|
+
exports.WebhookType = exports.UsageMetricsGranularity = exports.UsageMetricType = exports.UploadSessionType = exports.SubmissionStatus = void 0;
|
|
11
11
|
var ActivityTimelineProjectActivityType;
|
|
12
12
|
(function (ActivityTimelineProjectActivityType) {
|
|
13
13
|
ActivityTimelineProjectActivityType["Build"] = "BUILD";
|
|
@@ -186,6 +186,12 @@ var Feature;
|
|
|
186
186
|
/** Share access to projects */
|
|
187
187
|
Feature["Teams"] = "TEAMS";
|
|
188
188
|
})(Feature = exports.Feature || (exports.Feature = {}));
|
|
189
|
+
var GitHubAppEnvironment;
|
|
190
|
+
(function (GitHubAppEnvironment) {
|
|
191
|
+
GitHubAppEnvironment["Development"] = "DEVELOPMENT";
|
|
192
|
+
GitHubAppEnvironment["Production"] = "PRODUCTION";
|
|
193
|
+
GitHubAppEnvironment["Staging"] = "STAGING";
|
|
194
|
+
})(GitHubAppEnvironment = exports.GitHubAppEnvironment || (exports.GitHubAppEnvironment = {}));
|
|
189
195
|
var GitHubAppInstallationStatus;
|
|
190
196
|
(function (GitHubAppInstallationStatus) {
|
|
191
197
|
GitHubAppInstallationStatus["Active"] = "ACTIVE";
|
|
@@ -253,6 +259,7 @@ var Permission;
|
|
|
253
259
|
})(Permission = exports.Permission || (exports.Permission = {}));
|
|
254
260
|
var ProjectArchiveSourceType;
|
|
255
261
|
(function (ProjectArchiveSourceType) {
|
|
262
|
+
ProjectArchiveSourceType["Gcs"] = "GCS";
|
|
256
263
|
ProjectArchiveSourceType["S3"] = "S3";
|
|
257
264
|
ProjectArchiveSourceType["Url"] = "URL";
|
|
258
265
|
})(ProjectArchiveSourceType = exports.ProjectArchiveSourceType || (exports.ProjectArchiveSourceType = {}));
|
|
@@ -15,10 +15,16 @@ exports.SubmissionMutation = {
|
|
|
15
15
|
$appId: ID!
|
|
16
16
|
$config: AndroidSubmissionConfigInput!
|
|
17
17
|
$submittedBuildId: ID
|
|
18
|
+
$archiveSource: SubmissionArchiveSourceInput
|
|
18
19
|
) {
|
|
19
20
|
submission {
|
|
20
21
|
createAndroidSubmission(
|
|
21
|
-
input: {
|
|
22
|
+
input: {
|
|
23
|
+
appId: $appId
|
|
24
|
+
config: $config
|
|
25
|
+
submittedBuildId: $submittedBuildId
|
|
26
|
+
archiveSource: $archiveSource
|
|
27
|
+
}
|
|
22
28
|
) {
|
|
23
29
|
submission {
|
|
24
30
|
id
|
|
@@ -39,10 +45,16 @@ exports.SubmissionMutation = {
|
|
|
39
45
|
$appId: ID!
|
|
40
46
|
$config: IosSubmissionConfigInput!
|
|
41
47
|
$submittedBuildId: ID
|
|
48
|
+
$archiveSource: SubmissionArchiveSourceInput
|
|
42
49
|
) {
|
|
43
50
|
submission {
|
|
44
51
|
createIosSubmission(
|
|
45
|
-
input: {
|
|
52
|
+
input: {
|
|
53
|
+
appId: $appId
|
|
54
|
+
config: $config
|
|
55
|
+
submittedBuildId: $submittedBuildId
|
|
56
|
+
archiveSource: $archiveSource
|
|
57
|
+
}
|
|
46
58
|
) {
|
|
47
59
|
submission {
|
|
48
60
|
id
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
|
|
2
2
|
import { UploadSessionType } from '../generated';
|
|
3
|
-
export interface
|
|
3
|
+
export interface SignedUrl {
|
|
4
4
|
url: string;
|
|
5
|
-
|
|
5
|
+
headers: Record<string, string>;
|
|
6
|
+
bucketKey: string;
|
|
6
7
|
}
|
|
7
8
|
export declare const UploadSessionMutation: {
|
|
8
|
-
createUploadSessionAsync(graphqlClient: ExpoGraphqlClient, type: UploadSessionType): Promise<
|
|
9
|
+
createUploadSessionAsync(graphqlClient: ExpoGraphqlClient, type: UploadSessionType): Promise<SignedUrl>;
|
|
9
10
|
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getAptParametersAsync = exports.getAaptExecutableAsync = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const spawn_async_1 = tslib_1.__importDefault(require("@expo/spawn-async"));
|
|
6
|
+
const fast_glob_1 = tslib_1.__importDefault(require("fast-glob"));
|
|
7
|
+
const path_1 = tslib_1.__importDefault(require("path"));
|
|
8
|
+
const log_1 = tslib_1.__importDefault(require("../../log"));
|
|
9
|
+
const sdk_1 = require("./sdk");
|
|
10
|
+
async function aaptAsync(...options) {
|
|
11
|
+
try {
|
|
12
|
+
return await (0, spawn_async_1.default)(await getAaptExecutableAsync(), options);
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
if (error.stderr) {
|
|
16
|
+
log_1.default.error(error.stderr);
|
|
17
|
+
}
|
|
18
|
+
throw error;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
async function getAaptExecutableAsync() {
|
|
22
|
+
const sdkRoot = await (0, sdk_1.getAndroidSdkRootAsync)();
|
|
23
|
+
if (!sdkRoot) {
|
|
24
|
+
log_1.default.debug('Failed to resolve the Android SDK path, falling back to global aapt executable');
|
|
25
|
+
return 'aapt';
|
|
26
|
+
}
|
|
27
|
+
const aaptPaths = await (0, fast_glob_1.default)(path_1.default.posix.join('build-tools/**', process.platform === 'win32' ? 'aapt.exe' : 'aapt'), { cwd: sdkRoot, absolute: true });
|
|
28
|
+
if (aaptPaths.length === 0) {
|
|
29
|
+
throw new Error('Failed to resolve the Android aapt path');
|
|
30
|
+
}
|
|
31
|
+
const sorted = aaptPaths.sort();
|
|
32
|
+
return sorted[sorted.length - 1];
|
|
33
|
+
}
|
|
34
|
+
exports.getAaptExecutableAsync = getAaptExecutableAsync;
|
|
35
|
+
async function getAptParametersAsync(appPath) {
|
|
36
|
+
const { stdout } = await aaptAsync('dump', 'badging', appPath);
|
|
37
|
+
const packageNameMatch = stdout.match(/package: name='([^']+)'/);
|
|
38
|
+
if (!packageNameMatch) {
|
|
39
|
+
throw new Error(`Could not read package name from ${appPath}`);
|
|
40
|
+
}
|
|
41
|
+
// get activity name
|
|
42
|
+
const activityNameMatch = stdout.match(/launchable-activity: name='([^']+)'/);
|
|
43
|
+
if (!activityNameMatch) {
|
|
44
|
+
throw new Error(`Could not read activity name from ${appPath}`);
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
packageName: packageNameMatch[1],
|
|
48
|
+
activityName: activityNameMatch[1],
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
exports.getAptParametersAsync = getAptParametersAsync;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { SpawnResult } from '@expo/spawn-async';
|
|
2
|
+
export interface AndroidEmulator {
|
|
3
|
+
pid?: string;
|
|
4
|
+
name: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function adbAsync(...args: string[]): Promise<SpawnResult>;
|
|
7
|
+
export declare function getAdbExecutableAsync(): Promise<string>;
|
|
8
|
+
export declare function sanitizeAdbDeviceName(deviceName: string): string | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* Return the Emulator name for an emulator ID, this can be used to determine if an emulator is booted.
|
|
11
|
+
*
|
|
12
|
+
* @param devicePid a value like `emulator-5554` from `abd devices`
|
|
13
|
+
*/
|
|
14
|
+
export declare function getAdbNameForDeviceIdAsync(emulatorPid: string): Promise<string | null>;
|
|
15
|
+
export declare function getRunningEmulatorsAsync(): Promise<AndroidEmulator[]>;
|
|
16
|
+
export declare function getFirstRunningEmulatorAsync(): Promise<AndroidEmulator | null>;
|
|
17
|
+
/**
|
|
18
|
+
* Returns true if emulator is booted
|
|
19
|
+
*
|
|
20
|
+
* @param emulatorPid
|
|
21
|
+
*/
|
|
22
|
+
export declare function isEmulatorBootedAsync(emulatorPid: string): Promise<boolean>;
|
|
23
|
+
export declare function waitForEmulatorToBeBootedAsync(maxWaitTimeMs: number, intervalMs: number): Promise<AndroidEmulator>;
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.waitForEmulatorToBeBootedAsync = exports.isEmulatorBootedAsync = exports.getFirstRunningEmulatorAsync = exports.getRunningEmulatorsAsync = exports.getAdbNameForDeviceIdAsync = exports.sanitizeAdbDeviceName = exports.getAdbExecutableAsync = exports.adbAsync = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const spawn_async_1 = tslib_1.__importDefault(require("@expo/spawn-async"));
|
|
6
|
+
const os_1 = tslib_1.__importDefault(require("os"));
|
|
7
|
+
const path_1 = tslib_1.__importDefault(require("path"));
|
|
8
|
+
const log_1 = tslib_1.__importDefault(require("../../log"));
|
|
9
|
+
const filter_1 = require("../../utils/expodash/filter");
|
|
10
|
+
const promise_1 = require("../../utils/promise");
|
|
11
|
+
const sdk_1 = require("./sdk");
|
|
12
|
+
const BEGINNING_OF_ADB_ERROR_MESSAGE = 'error: ';
|
|
13
|
+
async function adbAsync(...args) {
|
|
14
|
+
const adbExecutable = await getAdbExecutableAsync();
|
|
15
|
+
try {
|
|
16
|
+
return await (0, spawn_async_1.default)(adbExecutable, args);
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
let errorMessage = (error.stderr || error.stdout || error.message).trim();
|
|
20
|
+
if (errorMessage.startsWith(BEGINNING_OF_ADB_ERROR_MESSAGE)) {
|
|
21
|
+
errorMessage = errorMessage.substring(BEGINNING_OF_ADB_ERROR_MESSAGE.length);
|
|
22
|
+
}
|
|
23
|
+
error.message = errorMessage;
|
|
24
|
+
throw error;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
exports.adbAsync = adbAsync;
|
|
28
|
+
async function getAdbExecutableAsync() {
|
|
29
|
+
const sdkRoot = await (0, sdk_1.getAndroidSdkRootAsync)();
|
|
30
|
+
if (!sdkRoot) {
|
|
31
|
+
log_1.default.debug('Failed to resolve the Android SDK path, falling back to global adb executable');
|
|
32
|
+
return 'adb';
|
|
33
|
+
}
|
|
34
|
+
return path_1.default.join(sdkRoot, 'platform-tools/adb');
|
|
35
|
+
}
|
|
36
|
+
exports.getAdbExecutableAsync = getAdbExecutableAsync;
|
|
37
|
+
function sanitizeAdbDeviceName(deviceName) {
|
|
38
|
+
return deviceName.trim().split(/[\r\n]+/)[0];
|
|
39
|
+
}
|
|
40
|
+
exports.sanitizeAdbDeviceName = sanitizeAdbDeviceName;
|
|
41
|
+
/**
|
|
42
|
+
* Return the Emulator name for an emulator ID, this can be used to determine if an emulator is booted.
|
|
43
|
+
*
|
|
44
|
+
* @param devicePid a value like `emulator-5554` from `abd devices`
|
|
45
|
+
*/
|
|
46
|
+
async function getAdbNameForDeviceIdAsync(emulatorPid) {
|
|
47
|
+
var _a;
|
|
48
|
+
const { stdout } = await adbAsync('-s', emulatorPid, 'emu', 'avd', 'name');
|
|
49
|
+
if (stdout.match(/could not connect to TCP port .*: Connection refused/)) {
|
|
50
|
+
// Can also occur when the emulator does not exist.
|
|
51
|
+
throw new Error(`Emulator not found: ${stdout}`);
|
|
52
|
+
}
|
|
53
|
+
return (_a = sanitizeAdbDeviceName(stdout)) !== null && _a !== void 0 ? _a : null;
|
|
54
|
+
}
|
|
55
|
+
exports.getAdbNameForDeviceIdAsync = getAdbNameForDeviceIdAsync;
|
|
56
|
+
// TODO: This is very expensive for some operations.
|
|
57
|
+
async function getRunningEmulatorsAsync() {
|
|
58
|
+
const { stdout } = await adbAsync('devices', '-l');
|
|
59
|
+
const splitItems = stdout.trim().split(os_1.default.EOL);
|
|
60
|
+
const attachedDevices = splitItems
|
|
61
|
+
// First line is `"List of devices attached"`, remove it
|
|
62
|
+
.slice(1, splitItems.length)
|
|
63
|
+
.map(line => {
|
|
64
|
+
// unauthorized: ['FA8251A00719', 'unauthorized', 'usb:338690048X', 'transport_id:5']
|
|
65
|
+
// authorized: ['FA8251A00719', 'device', 'usb:336592896X', 'product:walleye', 'model:Pixel_2', 'device:walleye', 'transport_id:4']
|
|
66
|
+
// emulator: ['emulator-5554', 'offline', 'transport_id:1']
|
|
67
|
+
const [pid] = line.split(' ').filter(filter_1.truthy);
|
|
68
|
+
const type = line.includes('emulator') ? 'emulator' : 'device';
|
|
69
|
+
return { pid, type };
|
|
70
|
+
})
|
|
71
|
+
.filter(({ pid, type }) => !!pid && type === 'emulator');
|
|
72
|
+
const devicePromises = attachedDevices.map(async ({ pid }) => {
|
|
73
|
+
var _a;
|
|
74
|
+
const name = (_a = (await getAdbNameForDeviceIdAsync(pid))) !== null && _a !== void 0 ? _a : '';
|
|
75
|
+
return {
|
|
76
|
+
pid,
|
|
77
|
+
name,
|
|
78
|
+
};
|
|
79
|
+
});
|
|
80
|
+
return Promise.all(devicePromises);
|
|
81
|
+
}
|
|
82
|
+
exports.getRunningEmulatorsAsync = getRunningEmulatorsAsync;
|
|
83
|
+
async function getFirstRunningEmulatorAsync() {
|
|
84
|
+
var _a;
|
|
85
|
+
const emulators = await getRunningEmulatorsAsync();
|
|
86
|
+
return (_a = emulators[0]) !== null && _a !== void 0 ? _a : null;
|
|
87
|
+
}
|
|
88
|
+
exports.getFirstRunningEmulatorAsync = getFirstRunningEmulatorAsync;
|
|
89
|
+
/**
|
|
90
|
+
* Returns true if emulator is booted
|
|
91
|
+
*
|
|
92
|
+
* @param emulatorPid
|
|
93
|
+
*/
|
|
94
|
+
async function isEmulatorBootedAsync(emulatorPid) {
|
|
95
|
+
try {
|
|
96
|
+
const { stdout } = await adbAsync('-s', emulatorPid, 'shell', 'getprop', 'sys.boot_completed');
|
|
97
|
+
if (stdout.trim() === '1') {
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
exports.isEmulatorBootedAsync = isEmulatorBootedAsync;
|
|
107
|
+
async function waitForEmulatorToBeBootedAsync(maxWaitTimeMs, intervalMs) {
|
|
108
|
+
log_1.default.newLine();
|
|
109
|
+
log_1.default.log('Waiting for the Android emulator to start...');
|
|
110
|
+
const startTime = Date.now();
|
|
111
|
+
while (Date.now() - startTime < maxWaitTimeMs) {
|
|
112
|
+
const emulator = await getFirstRunningEmulatorAsync();
|
|
113
|
+
if ((emulator === null || emulator === void 0 ? void 0 : emulator.pid) && (await isEmulatorBootedAsync(emulator.pid))) {
|
|
114
|
+
return emulator;
|
|
115
|
+
}
|
|
116
|
+
await (0, promise_1.sleepAsync)(intervalMs);
|
|
117
|
+
}
|
|
118
|
+
throw new Error('Timed out waiting for the Android emulator to start.');
|
|
119
|
+
}
|
|
120
|
+
exports.waitForEmulatorToBeBootedAsync = waitForEmulatorToBeBootedAsync;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { AndroidEmulator } from './adb';
|
|
2
|
+
export declare const EMULATOR_MAX_WAIT_TIMEOUT_MS: number;
|
|
3
|
+
export declare function getEmulatorExecutableAsync(): Promise<string>;
|
|
4
|
+
export declare function selectEmulatorAsync(): Promise<AndroidEmulator>;
|
|
5
|
+
export declare function ensureEmulatorBootedAsync(emulator: AndroidEmulator): Promise<AndroidEmulator>;
|
|
6
|
+
export declare function installAppAsync(emulator: AndroidEmulator, apkFilePath: string): Promise<void>;
|
|
7
|
+
export declare function startAppAsync(emulator: AndroidEmulator, packageName: string, activityName: string): Promise<void>;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.startAppAsync = exports.installAppAsync = exports.ensureEmulatorBootedAsync = exports.selectEmulatorAsync = exports.getEmulatorExecutableAsync = exports.EMULATOR_MAX_WAIT_TIMEOUT_MS = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const spawn_async_1 = tslib_1.__importDefault(require("@expo/spawn-async"));
|
|
6
|
+
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
7
|
+
const node_assert_1 = tslib_1.__importDefault(require("node:assert"));
|
|
8
|
+
const os_1 = tslib_1.__importDefault(require("os"));
|
|
9
|
+
const path_1 = tslib_1.__importDefault(require("path"));
|
|
10
|
+
const log_1 = tslib_1.__importDefault(require("../../log"));
|
|
11
|
+
const prompts_1 = require("../../prompts");
|
|
12
|
+
const filter_1 = require("../../utils/expodash/filter");
|
|
13
|
+
const adb_1 = require("./adb");
|
|
14
|
+
const sdk_1 = require("./sdk");
|
|
15
|
+
exports.EMULATOR_MAX_WAIT_TIMEOUT_MS = 60 * 1000 * 3;
|
|
16
|
+
async function getEmulatorExecutableAsync() {
|
|
17
|
+
const sdkRoot = await (0, sdk_1.getAndroidSdkRootAsync)();
|
|
18
|
+
if (sdkRoot) {
|
|
19
|
+
return path_1.default.join(sdkRoot, 'emulator', 'emulator');
|
|
20
|
+
}
|
|
21
|
+
return 'emulator';
|
|
22
|
+
}
|
|
23
|
+
exports.getEmulatorExecutableAsync = getEmulatorExecutableAsync;
|
|
24
|
+
async function emulatorAsync(...options) {
|
|
25
|
+
const emulatorExecutable = await getEmulatorExecutableAsync();
|
|
26
|
+
try {
|
|
27
|
+
return await (0, spawn_async_1.default)(emulatorExecutable, options);
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
if (error.stderr) {
|
|
31
|
+
log_1.default.error(error.stderr);
|
|
32
|
+
}
|
|
33
|
+
throw error;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
async function getAvaliableAndroidEmulatorsAsync() {
|
|
37
|
+
try {
|
|
38
|
+
const { stdout } = await emulatorAsync('-list-avds');
|
|
39
|
+
return stdout
|
|
40
|
+
.split(os_1.default.EOL)
|
|
41
|
+
.filter(filter_1.truthy)
|
|
42
|
+
.map(name => ({
|
|
43
|
+
name,
|
|
44
|
+
}));
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return [];
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/** Start an Android device and wait until it is booted. */
|
|
51
|
+
async function bootEmulatorAsync(emulator, { timeout = exports.EMULATOR_MAX_WAIT_TIMEOUT_MS, interval = 1000, } = {}) {
|
|
52
|
+
log_1.default.newLine();
|
|
53
|
+
log_1.default.log(`Opening emulator ${chalk_1.default.bold(emulator.name)}`);
|
|
54
|
+
const emulatorExecutable = await getEmulatorExecutableAsync();
|
|
55
|
+
// Start a process to open an emulator
|
|
56
|
+
const emulatorProcess = (0, spawn_async_1.default)(emulatorExecutable, [`@${emulator.name}`], {
|
|
57
|
+
stdio: 'ignore',
|
|
58
|
+
detached: true,
|
|
59
|
+
});
|
|
60
|
+
// we don't want to wait for the emulator process to exit before we can finish `eas build:run` command
|
|
61
|
+
// https://github.com/expo/eas-cli/pull/1485#discussion_r1007935871
|
|
62
|
+
emulatorProcess.child.unref();
|
|
63
|
+
return await (0, adb_1.waitForEmulatorToBeBootedAsync)(timeout, interval);
|
|
64
|
+
}
|
|
65
|
+
async function selectEmulatorAsync() {
|
|
66
|
+
const runningEmulator = await (0, adb_1.getFirstRunningEmulatorAsync)();
|
|
67
|
+
if (runningEmulator) {
|
|
68
|
+
log_1.default.newLine();
|
|
69
|
+
log_1.default.log(`Using open emulator: ${chalk_1.default.bold(runningEmulator.name)}`);
|
|
70
|
+
return runningEmulator;
|
|
71
|
+
}
|
|
72
|
+
const emulators = await getAvaliableAndroidEmulatorsAsync();
|
|
73
|
+
log_1.default.newLine();
|
|
74
|
+
const { selectedEmulator } = await (0, prompts_1.promptAsync)({
|
|
75
|
+
type: 'select',
|
|
76
|
+
message: `Select an emulator to run your app on`,
|
|
77
|
+
name: 'selectedEmulator',
|
|
78
|
+
choices: emulators.map(emulator => ({
|
|
79
|
+
title: emulator.name,
|
|
80
|
+
value: emulator,
|
|
81
|
+
})),
|
|
82
|
+
});
|
|
83
|
+
return selectedEmulator;
|
|
84
|
+
}
|
|
85
|
+
exports.selectEmulatorAsync = selectEmulatorAsync;
|
|
86
|
+
async function ensureEmulatorBootedAsync(emulator) {
|
|
87
|
+
if (!emulator.pid || !(await (0, adb_1.isEmulatorBootedAsync)(emulator.pid))) {
|
|
88
|
+
return await bootEmulatorAsync(emulator);
|
|
89
|
+
}
|
|
90
|
+
return emulator;
|
|
91
|
+
}
|
|
92
|
+
exports.ensureEmulatorBootedAsync = ensureEmulatorBootedAsync;
|
|
93
|
+
async function installAppAsync(emulator, apkFilePath) {
|
|
94
|
+
log_1.default.newLine();
|
|
95
|
+
log_1.default.log('Installing your app...');
|
|
96
|
+
(0, node_assert_1.default)(emulator.pid);
|
|
97
|
+
await (0, adb_1.adbAsync)('-s', emulator.pid, 'install', '-r', '-d', apkFilePath);
|
|
98
|
+
log_1.default.succeed('Successfully installed your app!');
|
|
99
|
+
}
|
|
100
|
+
exports.installAppAsync = installAppAsync;
|
|
101
|
+
async function startAppAsync(emulator, packageName, activityName) {
|
|
102
|
+
log_1.default.newLine();
|
|
103
|
+
log_1.default.log('Starting your app...');
|
|
104
|
+
(0, node_assert_1.default)(emulator.pid);
|
|
105
|
+
await (0, adb_1.adbAsync)('-s', emulator.pid, 'shell', 'am', 'start', '-a', 'android.intent.action.RUN', '-f', '0x20000000', // FLAG_ACTIVITY_SINGLE_TOP -- If set, the activity will not be launched if it is already running at the top of the history stack.
|
|
106
|
+
'-n', `${packageName}/${activityName}`);
|
|
107
|
+
log_1.default.succeed('Successfully started your app!');
|
|
108
|
+
}
|
|
109
|
+
exports.startAppAsync = startAppAsync;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare function runAppOnAndroidEmulatorAsync(
|
|
1
|
+
export declare function runAppOnAndroidEmulatorAsync(appPath: string): Promise<void>;
|