@expo/build-tools 1.0.182 → 1.0.184
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/dist/common/git.d.ts +10 -0
- package/dist/common/git.js +85 -0
- package/dist/common/git.js.map +1 -0
- package/dist/common/projectSources.js +46 -74
- package/dist/common/projectSources.js.map +1 -1
- package/dist/steps/functions/startAndroidEmulator.js +34 -1
- package/dist/steps/functions/startAndroidEmulator.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/// <reference types="bunyan" />
|
|
2
|
+
import { ArchiveSource, ArchiveSourceType } from '@expo/eas-build-job';
|
|
3
|
+
import { bunyan } from '@expo/logger';
|
|
4
|
+
export declare function shallowCloneRepositoryAsync({ logger, archiveSource, destinationDirectory, }: {
|
|
5
|
+
logger: bunyan;
|
|
6
|
+
archiveSource: ArchiveSource & {
|
|
7
|
+
type: ArchiveSourceType.GIT;
|
|
8
|
+
};
|
|
9
|
+
destinationDirectory: string;
|
|
10
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.shallowCloneRepositoryAsync = void 0;
|
|
7
|
+
const turtle_spawn_1 = __importDefault(require("@expo/turtle-spawn"));
|
|
8
|
+
async function shallowCloneRepositoryAsync({ logger, archiveSource, destinationDirectory, }) {
|
|
9
|
+
const { repositoryUrl } = archiveSource;
|
|
10
|
+
try {
|
|
11
|
+
await (0, turtle_spawn_1.default)('git', ['init'], { cwd: destinationDirectory });
|
|
12
|
+
await (0, turtle_spawn_1.default)('git', ['remote', 'add', 'origin', repositoryUrl], { cwd: destinationDirectory });
|
|
13
|
+
const { gitRef, gitCommitHash } = archiveSource;
|
|
14
|
+
await (0, turtle_spawn_1.default)('git', ['fetch', 'origin', '--depth', '1', '--no-tags', gitCommitHash], {
|
|
15
|
+
cwd: destinationDirectory,
|
|
16
|
+
});
|
|
17
|
+
await (0, turtle_spawn_1.default)('git', ['checkout', gitCommitHash], { cwd: destinationDirectory });
|
|
18
|
+
// If we have a gitRef, we try to add it to the repo.
|
|
19
|
+
if (gitRef) {
|
|
20
|
+
const { name, type } = getStrippedBranchOrTagName(gitRef);
|
|
21
|
+
switch (type) {
|
|
22
|
+
// If the gitRef is for a tag, we add a lightweight tag to current commit.
|
|
23
|
+
case 'tag': {
|
|
24
|
+
await (0, turtle_spawn_1.default)('git', ['tag', name], { cwd: destinationDirectory });
|
|
25
|
+
break;
|
|
26
|
+
}
|
|
27
|
+
// gitRef for a branch may come as:
|
|
28
|
+
// - qualified ref (e.g. refs/heads/feature/add-icon), detected as "branch" for a push,
|
|
29
|
+
// - unqualified ref (e.g. feature/add-icon), detected as "other" for a pull request.
|
|
30
|
+
case 'branch':
|
|
31
|
+
case 'other': {
|
|
32
|
+
await (0, turtle_spawn_1.default)('git', ['checkout', '-b', name], { cwd: destinationDirectory });
|
|
33
|
+
break;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
const sanitizedUrl = getSanitizedGitUrl(repositoryUrl);
|
|
40
|
+
if (sanitizedUrl) {
|
|
41
|
+
logger.error(`Failed to clone git repository: ${sanitizedUrl}.`);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
logger.error('Failed to clone git repository.');
|
|
45
|
+
}
|
|
46
|
+
logger.error(err.stderr);
|
|
47
|
+
throw err;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
exports.shallowCloneRepositoryAsync = shallowCloneRepositoryAsync;
|
|
51
|
+
function getSanitizedGitUrl(maybeGitUrl) {
|
|
52
|
+
try {
|
|
53
|
+
const url = new URL(maybeGitUrl);
|
|
54
|
+
if (url.password) {
|
|
55
|
+
url.password = '*******';
|
|
56
|
+
}
|
|
57
|
+
return url.toString();
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function getStrippedBranchOrTagName(ref) {
|
|
64
|
+
const branchRegex = /(\/?refs)?\/?heads\/(.+)/;
|
|
65
|
+
const branchMatch = ref.match(branchRegex);
|
|
66
|
+
if (branchMatch) {
|
|
67
|
+
return {
|
|
68
|
+
name: branchMatch[2],
|
|
69
|
+
type: 'branch',
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
const tagRegex = /(\/?refs)?\/?tags\/(.+)/;
|
|
73
|
+
const tagMatch = ref.match(tagRegex);
|
|
74
|
+
if (tagMatch) {
|
|
75
|
+
return {
|
|
76
|
+
name: tagMatch[2],
|
|
77
|
+
type: 'tag',
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
name: ref,
|
|
82
|
+
type: 'other',
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=git.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/common/git.ts"],"names":[],"mappings":"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","sourcesContent":["import { ArchiveSource, ArchiveSourceType } from '@expo/eas-build-job';\nimport { bunyan } from '@expo/logger';\nimport spawn from '@expo/turtle-spawn';\n\nexport async function shallowCloneRepositoryAsync({\n logger,\n archiveSource,\n destinationDirectory,\n}: {\n logger: bunyan;\n archiveSource: ArchiveSource & { type: ArchiveSourceType.GIT };\n destinationDirectory: string;\n}): Promise<void> {\n const { repositoryUrl } = archiveSource;\n try {\n await spawn('git', ['init'], { cwd: destinationDirectory });\n await spawn('git', ['remote', 'add', 'origin', repositoryUrl], { cwd: destinationDirectory });\n\n const { gitRef, gitCommitHash } = archiveSource;\n\n await spawn('git', ['fetch', 'origin', '--depth', '1', '--no-tags', gitCommitHash], {\n cwd: destinationDirectory,\n });\n\n await spawn('git', ['checkout', gitCommitHash], { cwd: destinationDirectory });\n\n // If we have a gitRef, we try to add it to the repo.\n if (gitRef) {\n const { name, type } = getStrippedBranchOrTagName(gitRef);\n switch (type) {\n // If the gitRef is for a tag, we add a lightweight tag to current commit.\n case 'tag': {\n await spawn('git', ['tag', name], { cwd: destinationDirectory });\n break;\n }\n // gitRef for a branch may come as:\n // - qualified ref (e.g. refs/heads/feature/add-icon), detected as \"branch\" for a push,\n // - unqualified ref (e.g. feature/add-icon), detected as \"other\" for a pull request.\n case 'branch':\n case 'other': {\n await spawn('git', ['checkout', '-b', name], { cwd: destinationDirectory });\n break;\n }\n }\n }\n } catch (err: any) {\n const sanitizedUrl = getSanitizedGitUrl(repositoryUrl);\n if (sanitizedUrl) {\n logger.error(`Failed to clone git repository: ${sanitizedUrl}.`);\n } else {\n logger.error('Failed to clone git repository.');\n }\n logger.error(err.stderr);\n throw err;\n }\n}\n\nfunction getSanitizedGitUrl(maybeGitUrl: string): string | null {\n try {\n const url = new URL(maybeGitUrl);\n if (url.password) {\n url.password = '*******';\n }\n return url.toString();\n } catch {\n return null;\n }\n}\n\nfunction getStrippedBranchOrTagName(ref: string): {\n name: string;\n type: 'branch' | 'tag' | 'other';\n} {\n const branchRegex = /(\\/?refs)?\\/?heads\\/(.+)/;\n const branchMatch = ref.match(branchRegex);\n\n if (branchMatch) {\n return {\n name: branchMatch[2],\n type: 'branch',\n };\n }\n\n const tagRegex = /(\\/?refs)?\\/?tags\\/(.+)/;\n const tagMatch = ref.match(tagRegex);\n\n if (tagMatch) {\n return {\n name: tagMatch[2],\n type: 'tag',\n };\n }\n\n return {\n name: ref,\n type: 'other',\n };\n}\n"]}
|
|
@@ -9,6 +9,11 @@ const turtle_spawn_1 = __importDefault(require("@expo/turtle-spawn"));
|
|
|
9
9
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
10
10
|
const eas_build_job_1 = require("@expo/eas-build-job");
|
|
11
11
|
const downloader_1 = __importDefault(require("@expo/downloader"));
|
|
12
|
+
const zod_1 = require("zod");
|
|
13
|
+
const results_1 = require("@expo/results");
|
|
14
|
+
const nullthrows_1 = __importDefault(require("nullthrows"));
|
|
15
|
+
const turtleFetch_1 = require("../utils/turtleFetch");
|
|
16
|
+
const git_1 = require("./git");
|
|
12
17
|
async function prepareProjectSourcesAsync(ctx, destinationDirectory = ctx.buildDirectory) {
|
|
13
18
|
if (ctx.job.projectArchive.type === eas_build_job_1.ArchiveSourceType.GCS) {
|
|
14
19
|
throw new Error('GCS project sources should be resolved earlier to url');
|
|
@@ -20,67 +25,56 @@ async function prepareProjectSourcesAsync(ctx, destinationDirectory = ctx.buildD
|
|
|
20
25
|
await downloadAndUnpackProjectFromTarGzAsync(ctx, ctx.job.projectArchive.url, destinationDirectory);
|
|
21
26
|
}
|
|
22
27
|
else if (ctx.job.projectArchive.type === eas_build_job_1.ArchiveSourceType.GIT) {
|
|
23
|
-
|
|
28
|
+
let repositoryUrl = ctx.job.projectArchive.repositoryUrl;
|
|
29
|
+
try {
|
|
30
|
+
repositoryUrl = await fetchRepositoryUrlAsync(ctx);
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
ctx.logger.error('Failed to refresh clone URL, falling back to the original one', err);
|
|
34
|
+
}
|
|
35
|
+
await (0, git_1.shallowCloneRepositoryAsync)({
|
|
24
36
|
logger: ctx.logger,
|
|
25
|
-
archiveSource:
|
|
37
|
+
archiveSource: {
|
|
38
|
+
...ctx.job.projectArchive,
|
|
39
|
+
repositoryUrl,
|
|
40
|
+
},
|
|
26
41
|
destinationDirectory,
|
|
27
42
|
});
|
|
28
43
|
}
|
|
29
44
|
}
|
|
30
45
|
exports.prepareProjectSourcesAsync = prepareProjectSourcesAsync;
|
|
31
|
-
async function
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
await (0, turtle_spawn_1.default)('git', ['tag', name], { cwd: destinationDirectory });
|
|
48
|
-
break;
|
|
49
|
-
}
|
|
50
|
-
// gitRef for a branch may come as:
|
|
51
|
-
// - qualified ref (e.g. refs/heads/feature/add-icon), detected as "branch" for a push,
|
|
52
|
-
// - unqualified ref (e.g. feature/add-icon), detected as "other" for a pull request.
|
|
53
|
-
case 'branch':
|
|
54
|
-
case 'other': {
|
|
55
|
-
await (0, turtle_spawn_1.default)('git', ['checkout', '-b', name], { cwd: destinationDirectory });
|
|
56
|
-
break;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
catch (err) {
|
|
62
|
-
const sanitizedUrl = getSanitizedGitUrl(repositoryUrl);
|
|
63
|
-
if (sanitizedUrl) {
|
|
64
|
-
logger.error(`Failed to clone git repository: ${sanitizedUrl}.`);
|
|
65
|
-
}
|
|
66
|
-
else {
|
|
67
|
-
logger.error('Failed to clone git repository.');
|
|
68
|
-
}
|
|
69
|
-
logger.error(err.stderr);
|
|
70
|
-
throw err;
|
|
46
|
+
async function fetchRepositoryUrlAsync(ctx) {
|
|
47
|
+
const taskId = (0, nullthrows_1.default)(ctx.env.EAS_BUILD_ID, 'EAS_BUILD_ID is not set');
|
|
48
|
+
const expoApiServerURL = (0, nullthrows_1.default)(ctx.env.__API_SERVER_URL, '__API_SERVER_URL is not set');
|
|
49
|
+
const expoToken = (0, nullthrows_1.default)(ctx.env.EXPO_TOKEN, 'EXPO_TOKEN is not set');
|
|
50
|
+
const response = await (0, turtleFetch_1.turtleFetch)(new URL(`/v2/github/fetch-github-repository-url`, expoApiServerURL).toString(), 'POST', {
|
|
51
|
+
json: { taskId },
|
|
52
|
+
headers: {
|
|
53
|
+
Authorization: `Bearer ${expoToken}`,
|
|
54
|
+
},
|
|
55
|
+
timeout: 20000,
|
|
56
|
+
retries: 3,
|
|
57
|
+
logger: ctx.logger,
|
|
58
|
+
});
|
|
59
|
+
if (!response.ok) {
|
|
60
|
+
const textResult = await (0, results_1.asyncResult)(response.text());
|
|
61
|
+
throw new Error(`Unexpected response from server (${response.status}): ${textResult.value}`);
|
|
71
62
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
const url = new URL(maybeGitUrl);
|
|
76
|
-
if (url.password) {
|
|
77
|
-
url.password = '*******';
|
|
78
|
-
}
|
|
79
|
-
return url.toString();
|
|
63
|
+
const jsonResult = await (0, results_1.asyncResult)(response.json());
|
|
64
|
+
if (!jsonResult.ok) {
|
|
65
|
+
throw new Error(`Expected JSON response from server (${response.status}): ${jsonResult.reason}`);
|
|
80
66
|
}
|
|
81
|
-
|
|
82
|
-
|
|
67
|
+
const dataResult = zod_1.z
|
|
68
|
+
.object({
|
|
69
|
+
data: zod_1.z.object({
|
|
70
|
+
repositoryUrl: zod_1.z.string().url(),
|
|
71
|
+
}),
|
|
72
|
+
})
|
|
73
|
+
.safeParse(jsonResult.value);
|
|
74
|
+
if (!dataResult.success) {
|
|
75
|
+
throw new Error(`Unexpected response from server (${response.status}): ${dataResult.error}`);
|
|
83
76
|
}
|
|
77
|
+
return dataResult.data.data.repositoryUrl;
|
|
84
78
|
}
|
|
85
79
|
async function downloadAndUnpackProjectFromTarGzAsync(ctx, projectArchiveUrl, destinationDirectory) {
|
|
86
80
|
var _a;
|
|
@@ -115,26 +109,4 @@ async function unpackTarGzAsync({ logger, source, destination, }) {
|
|
|
115
109
|
logger,
|
|
116
110
|
});
|
|
117
111
|
}
|
|
118
|
-
function getStrippedBranchOrTagName(ref) {
|
|
119
|
-
const branchRegex = /(\/?refs)?\/?heads\/(.+)/;
|
|
120
|
-
const branchMatch = ref.match(branchRegex);
|
|
121
|
-
if (branchMatch) {
|
|
122
|
-
return {
|
|
123
|
-
name: branchMatch[2],
|
|
124
|
-
type: 'branch',
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
const tagRegex = /(\/?refs)?\/?tags\/(.+)/;
|
|
128
|
-
const tagMatch = ref.match(tagRegex);
|
|
129
|
-
if (tagMatch) {
|
|
130
|
-
return {
|
|
131
|
-
name: tagMatch[2],
|
|
132
|
-
type: 'tag',
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
return {
|
|
136
|
-
name: ref,
|
|
137
|
-
type: 'other',
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
112
|
//# sourceMappingURL=projectSources.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"projectSources.js","sourceRoot":"","sources":["../../src/common/projectSources.ts"],"names":[],"mappings":";;;;;;AAAA,gDAAwB;AAExB,sEAAuC;AACvC,wDAA0B;AAC1B,
|
|
1
|
+
{"version":3,"file":"projectSources.js","sourceRoot":"","sources":["../../src/common/projectSources.ts"],"names":[],"mappings":"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","sourcesContent":["import path from 'path';\n\nimport spawn from '@expo/turtle-spawn';\nimport fs from 'fs-extra';\nimport { ArchiveSourceType, Job } from '@expo/eas-build-job';\nimport { bunyan } from '@expo/logger';\nimport downloadFile from '@expo/downloader';\nimport { z } from 'zod';\nimport { asyncResult } from '@expo/results';\nimport nullthrows from 'nullthrows';\n\nimport { BuildContext } from '../context';\nimport { turtleFetch } from '../utils/turtleFetch';\n\nimport { shallowCloneRepositoryAsync } from './git';\n\nexport async function prepareProjectSourcesAsync<TJob extends Job>(\n ctx: BuildContext<TJob>,\n destinationDirectory = ctx.buildDirectory\n): Promise<void> {\n if (ctx.job.projectArchive.type === ArchiveSourceType.GCS) {\n throw new Error('GCS project sources should be resolved earlier to url');\n } else if (ctx.job.projectArchive.type === ArchiveSourceType.PATH) {\n await prepareProjectSourcesLocallyAsync(ctx, ctx.job.projectArchive.path, destinationDirectory); // used in eas build --local\n } else if (ctx.job.projectArchive.type === ArchiveSourceType.URL) {\n await downloadAndUnpackProjectFromTarGzAsync(\n ctx,\n ctx.job.projectArchive.url,\n destinationDirectory\n );\n } else if (ctx.job.projectArchive.type === ArchiveSourceType.GIT) {\n let repositoryUrl = ctx.job.projectArchive.repositoryUrl;\n try {\n repositoryUrl = await fetchRepositoryUrlAsync(ctx);\n } catch (err) {\n ctx.logger.error('Failed to refresh clone URL, falling back to the original one', err);\n }\n\n await shallowCloneRepositoryAsync({\n logger: ctx.logger,\n archiveSource: {\n ...ctx.job.projectArchive,\n repositoryUrl,\n },\n destinationDirectory,\n });\n }\n}\n\nasync function fetchRepositoryUrlAsync(ctx: BuildContext<Job>): Promise<string> {\n const taskId = nullthrows(ctx.env.EAS_BUILD_ID, 'EAS_BUILD_ID is not set');\n const expoApiServerURL = nullthrows(ctx.env.__API_SERVER_URL, '__API_SERVER_URL is not set');\n const expoToken = nullthrows(ctx.env.EXPO_TOKEN, 'EXPO_TOKEN is not set');\n\n const response = await turtleFetch(\n new URL(`/v2/github/fetch-github-repository-url`, expoApiServerURL).toString(),\n 'POST',\n {\n json: { taskId },\n headers: {\n Authorization: `Bearer ${expoToken}`,\n },\n timeout: 20000,\n retries: 3,\n logger: ctx.logger,\n }\n );\n\n if (!response.ok) {\n const textResult = await asyncResult(response.text());\n throw new Error(`Unexpected response from server (${response.status}): ${textResult.value}`);\n }\n\n const jsonResult = await asyncResult(response.json());\n if (!jsonResult.ok) {\n throw new Error(\n `Expected JSON response from server (${response.status}): ${jsonResult.reason}`\n );\n }\n\n const dataResult = z\n .object({\n data: z.object({\n repositoryUrl: z.string().url(),\n }),\n })\n .safeParse(jsonResult.value);\n if (!dataResult.success) {\n throw new Error(`Unexpected response from server (${response.status}): ${dataResult.error}`);\n }\n\n return dataResult.data.data.repositoryUrl;\n}\n\nexport async function downloadAndUnpackProjectFromTarGzAsync<TJob extends Job>(\n ctx: BuildContext<TJob>,\n projectArchiveUrl: string,\n destinationDirectory: string\n): Promise<void> {\n const projectTarball = path.join(ctx.workingdir, 'project.tar.gz');\n try {\n await downloadFile(projectArchiveUrl, projectTarball, { retry: 3 });\n } catch (err: any) {\n ctx.reportError?.('Failed to download project archive', err, {\n extras: { buildId: ctx.env.EAS_BUILD_ID },\n });\n throw err;\n }\n\n await unpackTarGzAsync({\n destination: destinationDirectory,\n source: projectTarball,\n logger: ctx.logger,\n });\n}\n\nasync function prepareProjectSourcesLocallyAsync<TJob extends Job>(\n ctx: BuildContext<TJob>,\n projectArchivePath: string,\n destinationDirectory: string\n): Promise<void> {\n const projectTarball = path.join(ctx.workingdir, 'project.tar.gz');\n await fs.copy(projectArchivePath, projectTarball);\n\n await unpackTarGzAsync({\n destination: destinationDirectory,\n source: projectTarball,\n logger: ctx.logger,\n });\n}\n\nasync function unpackTarGzAsync({\n logger,\n source,\n destination,\n}: {\n logger: bunyan;\n source: string;\n destination: string;\n}): Promise<void> {\n await spawn('tar', ['-C', destination, '--strip-components', '1', '-zxf', source], {\n logger,\n });\n}\n"]}
|
|
@@ -23,6 +23,11 @@ function createStartAndroidEmulatorBuildFunction() {
|
|
|
23
23
|
defaultValue: 'EasAndroidDevice01',
|
|
24
24
|
allowedValueTypeName: steps_1.BuildStepInputValueTypeName.STRING,
|
|
25
25
|
}),
|
|
26
|
+
steps_1.BuildStepInput.createProvider({
|
|
27
|
+
id: 'device_identifier',
|
|
28
|
+
required: false,
|
|
29
|
+
allowedValueTypeName: steps_1.BuildStepInputValueTypeName.STRING,
|
|
30
|
+
}),
|
|
26
31
|
steps_1.BuildStepInput.createProvider({
|
|
27
32
|
id: 'system_image_package',
|
|
28
33
|
required: false,
|
|
@@ -38,8 +43,20 @@ function createStartAndroidEmulatorBuildFunction() {
|
|
|
38
43
|
],
|
|
39
44
|
fn: async ({ logger }, { inputs, env }) => {
|
|
40
45
|
var _a, _b, _c;
|
|
46
|
+
try {
|
|
47
|
+
const availableDevices = await getAvailableEmulatorDevices({ env });
|
|
48
|
+
logger.info(`Available Android devices:\n- ${availableDevices.join(`\n- `)}`);
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
logger.info('Failed to list available Android devices.', error);
|
|
52
|
+
}
|
|
53
|
+
finally {
|
|
54
|
+
logger.info('');
|
|
55
|
+
}
|
|
41
56
|
const deviceName = `${inputs.device_name.value}`;
|
|
42
57
|
const systemImagePackage = `${inputs.system_image_package.value}`;
|
|
58
|
+
// We can cast because allowedValueTypeName validated this is a string.
|
|
59
|
+
const deviceIdentifier = inputs.device_identifier.value;
|
|
43
60
|
logger.info('Making sure system image is installed');
|
|
44
61
|
await (0, retry_1.retryAsync)(async () => {
|
|
45
62
|
await (0, turtle_spawn_1.default)('sdkmanager', [systemImagePackage], {
|
|
@@ -54,7 +71,16 @@ function createStartAndroidEmulatorBuildFunction() {
|
|
|
54
71
|
},
|
|
55
72
|
});
|
|
56
73
|
logger.info('Creating emulator device');
|
|
57
|
-
const avdManager = (0, turtle_spawn_1.default)('avdmanager', [
|
|
74
|
+
const avdManager = (0, turtle_spawn_1.default)('avdmanager', [
|
|
75
|
+
'create',
|
|
76
|
+
'avd',
|
|
77
|
+
'--name',
|
|
78
|
+
deviceName,
|
|
79
|
+
'--package',
|
|
80
|
+
systemImagePackage,
|
|
81
|
+
'--force',
|
|
82
|
+
...(deviceIdentifier ? ['--device', deviceIdentifier] : []),
|
|
83
|
+
], {
|
|
58
84
|
env,
|
|
59
85
|
stdio: 'pipe',
|
|
60
86
|
});
|
|
@@ -205,4 +231,11 @@ async function ensureEmulatorIsReadyAsync({ deviceName, env, logger, }) {
|
|
|
205
231
|
});
|
|
206
232
|
return { serialId };
|
|
207
233
|
}
|
|
234
|
+
async function getAvailableEmulatorDevices({ env }) {
|
|
235
|
+
const result = await (0, turtle_spawn_1.default)('avdmanager', ['list', 'device', '--compact', '--null'], {
|
|
236
|
+
env,
|
|
237
|
+
mode: logger_1.PipeMode.COMBINED_AS_STDOUT,
|
|
238
|
+
});
|
|
239
|
+
return result.stdout.split('\0').filter((line) => line !== '');
|
|
240
|
+
}
|
|
208
241
|
//# sourceMappingURL=startAndroidEmulator.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"startAndroidEmulator.js","sourceRoot":"","sources":["../../../src/steps/functions/startAndroidEmulator.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from 'assert';\nimport fs from 'fs/promises';\n\nimport { PipeMode, bunyan } from '@expo/logger';\nimport {\n BuildFunction,\n BuildStepEnv,\n BuildStepInput,\n BuildStepInputValueTypeName,\n spawnAsync,\n} from '@expo/steps';\nimport spawn, { SpawnPromise, SpawnResult } from '@expo/turtle-spawn';\n\nimport { retryAsync } from '../../utils/retry';\n\nconst defaultSystemImagePackage = `system-images;android-30;default;${\n process.arch === 'arm64' ? 'arm64-v8a' : 'x86_64'\n}`;\n\nexport function createStartAndroidEmulatorBuildFunction(): BuildFunction {\n return new BuildFunction({\n namespace: 'eas',\n id: 'start_android_emulator',\n name: 'Start Android Emulator',\n inputProviders: [\n BuildStepInput.createProvider({\n id: 'device_name',\n required: false,\n defaultValue: 'EasAndroidDevice01',\n allowedValueTypeName: BuildStepInputValueTypeName.STRING,\n }),\n BuildStepInput.createProvider({\n id: 'system_image_package',\n required: false,\n defaultValue: defaultSystemImagePackage,\n allowedValueTypeName: BuildStepInputValueTypeName.STRING,\n }),\n BuildStepInput.createProvider({\n id: 'count',\n required: false,\n defaultValue: 1,\n allowedValueTypeName: BuildStepInputValueTypeName.NUMBER,\n }),\n ],\n fn: async ({ logger }, { inputs, env }) => {\n const deviceName = `${inputs.device_name.value}`;\n const systemImagePackage = `${inputs.system_image_package.value}`;\n logger.info('Making sure system image is installed');\n await retryAsync(\n async () => {\n await spawn('sdkmanager', [systemImagePackage], {\n env,\n logger,\n });\n },\n {\n logger,\n retryOptions: {\n retries: 3, // Retry 3 times\n retryIntervalMs: 1_000,\n },\n }\n );\n\n logger.info('Creating emulator device');\n const avdManager = spawn(\n 'avdmanager',\n ['create', 'avd', '--name', deviceName, '--package', systemImagePackage, '--force'],\n {\n env,\n stdio: 'pipe',\n }\n );\n // `avdmanager create` always asks about creating a custom hardware profile.\n // > Do you wish to create a custom hardware profile? [no]\n // We answer \"no\".\n avdManager.child.stdin?.write('no');\n avdManager.child.stdin?.end();\n await avdManager;\n\n logger.info('Starting emulator device');\n const { emulatorPromise } = await startAndroidSimulator({ deviceName, env });\n\n logger.info('Waiting for emulator to become ready');\n const { serialId } = await ensureEmulatorIsReadyAsync({\n deviceName,\n env,\n logger,\n });\n\n logger.info(`${deviceName} is ready.`);\n\n const count = Number(inputs.count.value ?? 1);\n if (count > 1) {\n logger.info(`Requested ${count} emulators, shutting down ${deviceName} for cloning.`);\n await spawn('adb', ['-s', serialId, 'shell', 'reboot', '-p'], {\n logger,\n env,\n });\n // Waiting for source emulator to shutdown.\n await emulatorPromise;\n\n for (let i = 0; i < count; i++) {\n const cloneIdentifier = `eas-simulator-${i + 1}`;\n logger.info(`Cloning ${deviceName} to ${cloneIdentifier}...`);\n const cloneIniFile = `${process.env.HOME}/.android/avd/${cloneIdentifier}.ini`;\n\n await fs.rm(`${process.env.HOME}/.android/avd/${cloneIdentifier}.avd`, {\n recursive: true,\n force: true,\n });\n await fs.rm(cloneIniFile, { force: true });\n\n await fs.cp(\n `${process.env.HOME}/.android/avd/${deviceName}.avd`,\n `${process.env.HOME}/.android/avd/${cloneIdentifier}.avd`,\n { recursive: true, verbatimSymlinks: true, force: true }\n );\n\n await fs.cp(`${process.env.HOME}/.android/avd/${deviceName}.ini`, cloneIniFile, {\n verbatimSymlinks: true,\n force: true,\n });\n\n const filesToReplaceDeviceNameIn = (\n await spawnAsync('grep', [\n '--binary-files=without-match',\n '--recursive',\n '--files-with-matches',\n `${deviceName}`,\n `${process.env.HOME}/.android/avd/${cloneIdentifier}.avd`,\n ])\n ).stdout\n .split('\\n')\n .filter((file) => file !== '');\n\n for (const file of [...filesToReplaceDeviceNameIn, cloneIniFile]) {\n const txtFile = await fs.readFile(file, 'utf-8');\n const replaceRegex = new RegExp(`${deviceName}`, 'g');\n const updatedTxtFile = txtFile.replace(replaceRegex, cloneIdentifier);\n await fs.writeFile(file, updatedTxtFile);\n }\n\n logger.info('Starting emulator device');\n await startAndroidSimulator({ deviceName: cloneIdentifier, env });\n\n logger.info('Waiting for emulator to become ready');\n await ensureEmulatorIsReadyAsync({\n deviceName: cloneIdentifier,\n env,\n logger,\n });\n\n logger.info(`${cloneIdentifier} is ready.`);\n }\n }\n },\n });\n}\n\nasync function startAndroidSimulator({\n deviceName,\n env,\n}: {\n deviceName: string;\n env: BuildStepEnv;\n}): Promise<{ emulatorPromise: SpawnPromise<SpawnResult> }> {\n const emulatorPromise = spawn(\n `${process.env.ANDROID_HOME}/emulator/emulator`,\n [\n '-no-window',\n '-no-boot-anim',\n '-writable-system',\n '-noaudio',\n '-memory',\n '8192',\n '-no-snapshot-save',\n '-avd',\n deviceName,\n ],\n {\n detached: true,\n stdio: 'inherit',\n env,\n }\n );\n // If emulator fails to start, throw its error.\n if (!emulatorPromise.child.pid) {\n await emulatorPromise;\n }\n emulatorPromise.child.unref();\n\n // We don't want to await the SpawnPromise here.\n // eslint-disable-next-line @typescript-eslint/return-await\n return { emulatorPromise };\n}\n\nasync function getEmulatorSerialId({\n deviceName,\n env,\n}: {\n deviceName: string;\n env: BuildStepEnv;\n}): Promise<string | null> {\n const adbDevices = await spawn('adb', ['devices'], { mode: PipeMode.COMBINED, env });\n for (const adbDeviceLine of adbDevices.stdout.split('\\n')) {\n if (!adbDeviceLine.startsWith('emulator')) {\n continue;\n }\n\n const matches = adbDeviceLine.match(/^(\\S+)/);\n if (!matches) {\n continue;\n }\n\n const [, serialId] = matches;\n // Previously we were using `qemu.uuid` to identify the emulator,\n // but this does not work for newer emulators, because there is\n // a limit on properties and custom properties get ignored.\n // See https://stackoverflow.com/questions/2214377/how-to-get-serial-number-or-id-of-android-emulator-after-it-runs#comment98259121_42038655\n const adbEmuAvdName = await spawn('adb', ['-s', serialId, 'emu', 'avd', 'name'], {\n mode: PipeMode.COMBINED,\n env,\n });\n if (adbEmuAvdName.stdout.replace(/\\r\\n/g, '\\n').split('\\n')[0] === deviceName) {\n return serialId;\n }\n }\n\n return null;\n}\n\nasync function ensureEmulatorIsReadyAsync({\n deviceName,\n env,\n logger,\n}: {\n deviceName: string;\n env: BuildStepEnv;\n logger: bunyan;\n}): Promise<{ serialId: string }> {\n const serialId = await retryAsync(\n async () => {\n const serialId = await getEmulatorSerialId({ deviceName, env });\n assert(\n serialId,\n `Failed to configure emulator (${deviceName}): emulator with required ID not found.`\n );\n return serialId;\n },\n {\n logger,\n retryOptions: {\n retries: 3 * 60,\n retryIntervalMs: 1_000,\n },\n }\n );\n\n await retryAsync(\n async () => {\n const { stdout } = await spawn(\n 'adb',\n ['-s', serialId, 'shell', 'getprop', 'sys.boot_completed'],\n {\n env,\n mode: PipeMode.COMBINED,\n }\n );\n\n if (!stdout.startsWith('1')) {\n throw new Error(`Emulator (${deviceName}) boot has not completed.`);\n }\n },\n {\n // Retry every second for 3 minutes.\n retryOptions: {\n retries: 3 * 60,\n retryIntervalMs: 1_000,\n },\n }\n );\n\n return { serialId };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"startAndroidEmulator.js","sourceRoot":"","sources":["../../../src/steps/functions/startAndroidEmulator.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from 'assert';\nimport fs from 'fs/promises';\n\nimport { PipeMode, bunyan } from '@expo/logger';\nimport {\n BuildFunction,\n BuildStepEnv,\n BuildStepInput,\n BuildStepInputValueTypeName,\n spawnAsync,\n} from '@expo/steps';\nimport spawn, { SpawnPromise, SpawnResult } from '@expo/turtle-spawn';\n\nimport { retryAsync } from '../../utils/retry';\n\nconst defaultSystemImagePackage = `system-images;android-30;default;${\n process.arch === 'arm64' ? 'arm64-v8a' : 'x86_64'\n}`;\n\nexport function createStartAndroidEmulatorBuildFunction(): BuildFunction {\n return new BuildFunction({\n namespace: 'eas',\n id: 'start_android_emulator',\n name: 'Start Android Emulator',\n inputProviders: [\n BuildStepInput.createProvider({\n id: 'device_name',\n required: false,\n defaultValue: 'EasAndroidDevice01',\n allowedValueTypeName: BuildStepInputValueTypeName.STRING,\n }),\n BuildStepInput.createProvider({\n id: 'device_identifier',\n required: false,\n allowedValueTypeName: BuildStepInputValueTypeName.STRING,\n }),\n BuildStepInput.createProvider({\n id: 'system_image_package',\n required: false,\n defaultValue: defaultSystemImagePackage,\n allowedValueTypeName: BuildStepInputValueTypeName.STRING,\n }),\n BuildStepInput.createProvider({\n id: 'count',\n required: false,\n defaultValue: 1,\n allowedValueTypeName: BuildStepInputValueTypeName.NUMBER,\n }),\n ],\n fn: async ({ logger }, { inputs, env }) => {\n try {\n const availableDevices = await getAvailableEmulatorDevices({ env });\n logger.info(`Available Android devices:\\n- ${availableDevices.join(`\\n- `)}`);\n } catch (error) {\n logger.info('Failed to list available Android devices.', error);\n } finally {\n logger.info('');\n }\n\n const deviceName = `${inputs.device_name.value}`;\n const systemImagePackage = `${inputs.system_image_package.value}`;\n // We can cast because allowedValueTypeName validated this is a string.\n const deviceIdentifier = inputs.device_identifier.value as string | undefined;\n\n logger.info('Making sure system image is installed');\n await retryAsync(\n async () => {\n await spawn('sdkmanager', [systemImagePackage], {\n env,\n logger,\n });\n },\n {\n logger,\n retryOptions: {\n retries: 3, // Retry 3 times\n retryIntervalMs: 1_000,\n },\n }\n );\n\n logger.info('Creating emulator device');\n const avdManager = spawn(\n 'avdmanager',\n [\n 'create',\n 'avd',\n '--name',\n deviceName,\n '--package',\n systemImagePackage,\n '--force',\n ...(deviceIdentifier ? ['--device', deviceIdentifier] : []),\n ],\n {\n env,\n stdio: 'pipe',\n }\n );\n // `avdmanager create` always asks about creating a custom hardware profile.\n // > Do you wish to create a custom hardware profile? [no]\n // We answer \"no\".\n avdManager.child.stdin?.write('no');\n avdManager.child.stdin?.end();\n await avdManager;\n\n logger.info('Starting emulator device');\n const { emulatorPromise } = await startAndroidSimulator({ deviceName, env });\n\n logger.info('Waiting for emulator to become ready');\n const { serialId } = await ensureEmulatorIsReadyAsync({\n deviceName,\n env,\n logger,\n });\n\n logger.info(`${deviceName} is ready.`);\n\n const count = Number(inputs.count.value ?? 1);\n if (count > 1) {\n logger.info(`Requested ${count} emulators, shutting down ${deviceName} for cloning.`);\n await spawn('adb', ['-s', serialId, 'shell', 'reboot', '-p'], {\n logger,\n env,\n });\n // Waiting for source emulator to shutdown.\n await emulatorPromise;\n\n for (let i = 0; i < count; i++) {\n const cloneIdentifier = `eas-simulator-${i + 1}`;\n logger.info(`Cloning ${deviceName} to ${cloneIdentifier}...`);\n const cloneIniFile = `${process.env.HOME}/.android/avd/${cloneIdentifier}.ini`;\n\n await fs.rm(`${process.env.HOME}/.android/avd/${cloneIdentifier}.avd`, {\n recursive: true,\n force: true,\n });\n await fs.rm(cloneIniFile, { force: true });\n\n await fs.cp(\n `${process.env.HOME}/.android/avd/${deviceName}.avd`,\n `${process.env.HOME}/.android/avd/${cloneIdentifier}.avd`,\n { recursive: true, verbatimSymlinks: true, force: true }\n );\n\n await fs.cp(`${process.env.HOME}/.android/avd/${deviceName}.ini`, cloneIniFile, {\n verbatimSymlinks: true,\n force: true,\n });\n\n const filesToReplaceDeviceNameIn = (\n await spawnAsync('grep', [\n '--binary-files=without-match',\n '--recursive',\n '--files-with-matches',\n `${deviceName}`,\n `${process.env.HOME}/.android/avd/${cloneIdentifier}.avd`,\n ])\n ).stdout\n .split('\\n')\n .filter((file) => file !== '');\n\n for (const file of [...filesToReplaceDeviceNameIn, cloneIniFile]) {\n const txtFile = await fs.readFile(file, 'utf-8');\n const replaceRegex = new RegExp(`${deviceName}`, 'g');\n const updatedTxtFile = txtFile.replace(replaceRegex, cloneIdentifier);\n await fs.writeFile(file, updatedTxtFile);\n }\n\n logger.info('Starting emulator device');\n await startAndroidSimulator({ deviceName: cloneIdentifier, env });\n\n logger.info('Waiting for emulator to become ready');\n await ensureEmulatorIsReadyAsync({\n deviceName: cloneIdentifier,\n env,\n logger,\n });\n\n logger.info(`${cloneIdentifier} is ready.`);\n }\n }\n },\n });\n}\n\nasync function startAndroidSimulator({\n deviceName,\n env,\n}: {\n deviceName: string;\n env: BuildStepEnv;\n}): Promise<{ emulatorPromise: SpawnPromise<SpawnResult> }> {\n const emulatorPromise = spawn(\n `${process.env.ANDROID_HOME}/emulator/emulator`,\n [\n '-no-window',\n '-no-boot-anim',\n '-writable-system',\n '-noaudio',\n '-memory',\n '8192',\n '-no-snapshot-save',\n '-avd',\n deviceName,\n ],\n {\n detached: true,\n stdio: 'inherit',\n env,\n }\n );\n // If emulator fails to start, throw its error.\n if (!emulatorPromise.child.pid) {\n await emulatorPromise;\n }\n emulatorPromise.child.unref();\n\n // We don't want to await the SpawnPromise here.\n // eslint-disable-next-line @typescript-eslint/return-await\n return { emulatorPromise };\n}\n\nasync function getEmulatorSerialId({\n deviceName,\n env,\n}: {\n deviceName: string;\n env: BuildStepEnv;\n}): Promise<string | null> {\n const adbDevices = await spawn('adb', ['devices'], { mode: PipeMode.COMBINED, env });\n for (const adbDeviceLine of adbDevices.stdout.split('\\n')) {\n if (!adbDeviceLine.startsWith('emulator')) {\n continue;\n }\n\n const matches = adbDeviceLine.match(/^(\\S+)/);\n if (!matches) {\n continue;\n }\n\n const [, serialId] = matches;\n // Previously we were using `qemu.uuid` to identify the emulator,\n // but this does not work for newer emulators, because there is\n // a limit on properties and custom properties get ignored.\n // See https://stackoverflow.com/questions/2214377/how-to-get-serial-number-or-id-of-android-emulator-after-it-runs#comment98259121_42038655\n const adbEmuAvdName = await spawn('adb', ['-s', serialId, 'emu', 'avd', 'name'], {\n mode: PipeMode.COMBINED,\n env,\n });\n if (adbEmuAvdName.stdout.replace(/\\r\\n/g, '\\n').split('\\n')[0] === deviceName) {\n return serialId;\n }\n }\n\n return null;\n}\n\nasync function ensureEmulatorIsReadyAsync({\n deviceName,\n env,\n logger,\n}: {\n deviceName: string;\n env: BuildStepEnv;\n logger: bunyan;\n}): Promise<{ serialId: string }> {\n const serialId = await retryAsync(\n async () => {\n const serialId = await getEmulatorSerialId({ deviceName, env });\n assert(\n serialId,\n `Failed to configure emulator (${deviceName}): emulator with required ID not found.`\n );\n return serialId;\n },\n {\n logger,\n retryOptions: {\n retries: 3 * 60,\n retryIntervalMs: 1_000,\n },\n }\n );\n\n await retryAsync(\n async () => {\n const { stdout } = await spawn(\n 'adb',\n ['-s', serialId, 'shell', 'getprop', 'sys.boot_completed'],\n {\n env,\n mode: PipeMode.COMBINED,\n }\n );\n\n if (!stdout.startsWith('1')) {\n throw new Error(`Emulator (${deviceName}) boot has not completed.`);\n }\n },\n {\n // Retry every second for 3 minutes.\n retryOptions: {\n retries: 3 * 60,\n retryIntervalMs: 1_000,\n },\n }\n );\n\n return { serialId };\n}\n\nasync function getAvailableEmulatorDevices({ env }: { env: BuildStepEnv }): Promise<string[]> {\n const result = await spawn('avdmanager', ['list', 'device', '--compact', '--null'], {\n env,\n mode: PipeMode.COMBINED_AS_STDOUT,\n });\n return result.stdout.split('\\0').filter((line) => line !== '');\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@expo/build-tools",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.184",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"files": [
|
|
@@ -76,5 +76,5 @@
|
|
|
76
76
|
"node": "20.14.0",
|
|
77
77
|
"yarn": "1.22.21"
|
|
78
78
|
},
|
|
79
|
-
"gitHead": "
|
|
79
|
+
"gitHead": "ee08739c4be2187e5ba7f457563014c656bff88e"
|
|
80
80
|
}
|