@expo/build-tools 18.12.1 → 18.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -1
- package/dist/ios/pod.js +5 -11
- package/dist/sentry.d.ts +19 -0
- package/dist/sentry.js +102 -0
- package/dist/steps/functions/startAgentDeviceRemoteSession.js +19 -3
- package/dist/steps/functions/startServeSimRemoteSession.js +2 -29
- package/dist/steps/utils/ios/xcactivitylog.d.ts +3 -5
- package/dist/steps/utils/ios/xcactivitylog.js +11 -6
- package/dist/steps/utils/remoteDeviceRunSession.d.ts +8 -0
- package/dist/steps/utils/remoteDeviceRunSession.js +37 -0
- package/package.json +5 -4
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -39,7 +39,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
39
39
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
40
40
|
};
|
|
41
41
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
-
exports.runHookIfPresent = exports.Hook = exports.findAndUploadXcodeBuildLogsAsync = exports.PackageManager = exports.SkipNativeBuildError = exports.BuildContext = exports.GCSLoggerStream = exports.GCS = exports.Builders = void 0;
|
|
42
|
+
exports.Sentry = exports.runHookIfPresent = exports.Hook = exports.findAndUploadXcodeBuildLogsAsync = exports.PackageManager = exports.SkipNativeBuildError = exports.BuildContext = exports.GCSLoggerStream = exports.GCS = exports.Builders = void 0;
|
|
43
43
|
const Builders = __importStar(require("./builders"));
|
|
44
44
|
exports.Builders = Builders;
|
|
45
45
|
const LoggerStream_1 = __importDefault(require("./gcs/LoggerStream"));
|
|
@@ -57,3 +57,5 @@ var hooks_1 = require("./utils/hooks");
|
|
|
57
57
|
Object.defineProperty(exports, "Hook", { enumerable: true, get: function () { return hooks_1.Hook; } });
|
|
58
58
|
Object.defineProperty(exports, "runHookIfPresent", { enumerable: true, get: function () { return hooks_1.runHookIfPresent; } });
|
|
59
59
|
__exportStar(require("./generic"), exports);
|
|
60
|
+
var sentry_1 = require("./sentry");
|
|
61
|
+
Object.defineProperty(exports, "Sentry", { enumerable: true, get: function () { return sentry_1.Sentry; } });
|
package/dist/ios/pod.js
CHANGED
|
@@ -4,8 +4,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.installPods = installPods;
|
|
7
|
+
const eas_build_job_1 = require("@expo/eas-build-job");
|
|
7
8
|
const turtle_spawn_1 = __importDefault(require("@expo/turtle-spawn"));
|
|
8
|
-
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
9
9
|
const path_1 = __importDefault(require("path"));
|
|
10
10
|
const semver_1 = __importDefault(require("semver"));
|
|
11
11
|
const MIN_PRECOMPILED_MODULES_EXPO_VERSION = '55.0.21';
|
|
@@ -43,7 +43,10 @@ async function resolvePrecompiledModulesPodInstallEnvAsync(ctx) {
|
|
|
43
43
|
}
|
|
44
44
|
let expoPackageVersion;
|
|
45
45
|
try {
|
|
46
|
-
expoPackageVersion = await getInstalledExpoPackageVersionAsync(
|
|
46
|
+
expoPackageVersion = await (0, eas_build_job_1.getInstalledExpoPackageVersionAsync)({
|
|
47
|
+
env: ctx.env,
|
|
48
|
+
projectDir: ctx.getReactNativeProjectDirectory(),
|
|
49
|
+
});
|
|
47
50
|
}
|
|
48
51
|
catch (err) {
|
|
49
52
|
ctx.logger.info({ err }, 'Failed to detect installed Expo package version; not enabling precompiled modules use.');
|
|
@@ -67,15 +70,6 @@ async function resolvePrecompiledModulesPodInstallEnvAsync(ctx) {
|
|
|
67
70
|
.join('\n')}\nPrecompiled modules pod install environment is configured.`);
|
|
68
71
|
return env;
|
|
69
72
|
}
|
|
70
|
-
async function getInstalledExpoPackageVersionAsync(ctx) {
|
|
71
|
-
const { stdout } = await (0, turtle_spawn_1.default)('node', ['--print', "require.resolve('expo/package.json')"], {
|
|
72
|
-
cwd: ctx.getReactNativeProjectDirectory(),
|
|
73
|
-
env: ctx.env,
|
|
74
|
-
stdio: 'pipe',
|
|
75
|
-
});
|
|
76
|
-
const expoPackageJsonPath = stdout.toString().trim();
|
|
77
|
-
return (await fs_extra_1.default.readJson(expoPackageJsonPath)).version;
|
|
78
|
-
}
|
|
79
73
|
function getPrecompiledModulesBaseUrl(ctx) {
|
|
80
74
|
if (!ctx.env.EAS_BUILD_COCOAPODS_CACHE_URL) {
|
|
81
75
|
return PRECOMPILED_MODULES_BASE_URL;
|
package/dist/sentry.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as sentryNode from '@sentry/node';
|
|
2
|
+
type CaptureOptions = {
|
|
3
|
+
tags?: Record<string, string>;
|
|
4
|
+
extras?: Record<string, unknown>;
|
|
5
|
+
level?: sentryNode.SeverityLevel;
|
|
6
|
+
};
|
|
7
|
+
type SentryAPI = {
|
|
8
|
+
setup(opts: {
|
|
9
|
+
dsn: string | null;
|
|
10
|
+
environment: string;
|
|
11
|
+
tags?: Record<string, string>;
|
|
12
|
+
}): void;
|
|
13
|
+
capture(msg: string, options?: CaptureOptions): void;
|
|
14
|
+
capture(msg: string, err: Error | undefined, options?: CaptureOptions): void;
|
|
15
|
+
capture(err: Error, options?: CaptureOptions): void;
|
|
16
|
+
flush(timeoutMs?: number): Promise<boolean>;
|
|
17
|
+
};
|
|
18
|
+
export declare const Sentry: SentryAPI;
|
|
19
|
+
export {};
|
package/dist/sentry.js
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.Sentry = void 0;
|
|
37
|
+
const sentryNode = __importStar(require("@sentry/node"));
|
|
38
|
+
exports.Sentry = {
|
|
39
|
+
setup({ dsn, environment, tags }) {
|
|
40
|
+
if (dsn) {
|
|
41
|
+
sentryNode.init({
|
|
42
|
+
dsn,
|
|
43
|
+
environment,
|
|
44
|
+
...(tags ? { initialScope: { tags } } : {}),
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
capture(arg1, arg2, arg3) {
|
|
49
|
+
let msg;
|
|
50
|
+
let err;
|
|
51
|
+
let options = {};
|
|
52
|
+
if (arg1 instanceof Error) {
|
|
53
|
+
err = arg1;
|
|
54
|
+
options = arg2 ?? {};
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
msg = arg1;
|
|
58
|
+
if (arg3 !== undefined) {
|
|
59
|
+
// 3-arg form: arg2 unambiguously means err (null/undefined → no err)
|
|
60
|
+
options = arg3;
|
|
61
|
+
if (arg2 !== undefined && arg2 !== null) {
|
|
62
|
+
err = arg2 instanceof Error ? arg2 : new Error(String(arg2));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
else if (arg2 instanceof Error) {
|
|
66
|
+
err = arg2;
|
|
67
|
+
}
|
|
68
|
+
else if (arg2 !== undefined && arg2 !== null) {
|
|
69
|
+
// 2-arg form: non-Error object → options; primitive → coerced err
|
|
70
|
+
if (typeof arg2 === 'object') {
|
|
71
|
+
options = arg2;
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
err = new Error(String(arg2));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
sentryNode.withScope(scope => {
|
|
79
|
+
if (options.tags) {
|
|
80
|
+
scope.setTags(options.tags);
|
|
81
|
+
}
|
|
82
|
+
if (options.extras) {
|
|
83
|
+
scope.setExtras(options.extras);
|
|
84
|
+
}
|
|
85
|
+
if (options.level) {
|
|
86
|
+
scope.setLevel(options.level);
|
|
87
|
+
}
|
|
88
|
+
if (err) {
|
|
89
|
+
if (msg && err.message !== msg) {
|
|
90
|
+
scope.setExtra('message', msg);
|
|
91
|
+
}
|
|
92
|
+
sentryNode.captureException(err);
|
|
93
|
+
}
|
|
94
|
+
else if (msg) {
|
|
95
|
+
sentryNode.captureMessage(msg);
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
},
|
|
99
|
+
flush(timeoutMs = 2000) {
|
|
100
|
+
return sentryNode.flush(timeoutMs);
|
|
101
|
+
},
|
|
102
|
+
};
|
|
@@ -81,17 +81,33 @@ function createStartAgentDeviceRemoteSessionBuildFunction(ctx) {
|
|
|
81
81
|
env,
|
|
82
82
|
});
|
|
83
83
|
logger.info('Waiting for a public tunnel URL.');
|
|
84
|
-
const
|
|
84
|
+
const agentDeviceRemoteSessionUrl = await waitForMatchInOutputAsync({
|
|
85
85
|
process: cloudflared,
|
|
86
86
|
pattern: /https:\/\/[a-z0-9-]+\.trycloudflare\.com/,
|
|
87
87
|
timeoutMs: STARTUP_TIMEOUT_MS,
|
|
88
88
|
description: 'cloudflared tunnel',
|
|
89
89
|
});
|
|
90
|
-
logger.info(`Tunnel is ready at ${
|
|
90
|
+
logger.info(`Tunnel is ready at ${agentDeviceRemoteSessionUrl}.`);
|
|
91
|
+
// serve-sim is iOS-only — only launch it (and report a webPreviewUrl)
|
|
92
|
+
// on Darwin. Android sessions go without a preview URL.
|
|
93
|
+
let webPreviewUrl;
|
|
94
|
+
if (runtimePlatform === steps_1.BuildRuntimePlatform.DARWIN) {
|
|
95
|
+
const { previewUrl } = await (0, remoteDeviceRunSession_1.startServeSimWithTunnelAsync)({
|
|
96
|
+
env,
|
|
97
|
+
logger,
|
|
98
|
+
timeoutMs: STARTUP_TIMEOUT_MS,
|
|
99
|
+
});
|
|
100
|
+
webPreviewUrl = previewUrl;
|
|
101
|
+
logger.info(`Web preview URL: ${webPreviewUrl}`);
|
|
102
|
+
}
|
|
91
103
|
await (0, remoteDeviceRunSession_1.uploadRemoteSessionConfigAsync)({
|
|
92
104
|
ctx,
|
|
93
105
|
deviceRunSessionId,
|
|
94
|
-
remoteConfig: {
|
|
106
|
+
remoteConfig: {
|
|
107
|
+
agentDeviceRemoteSessionUrl,
|
|
108
|
+
agentDeviceRemoteSessionToken: daemonToken,
|
|
109
|
+
...(webPreviewUrl ? { webPreviewUrl } : {}),
|
|
110
|
+
},
|
|
95
111
|
logger,
|
|
96
112
|
});
|
|
97
113
|
logger.info('Remote session is live. Keeping the job alive until the session is stopped.');
|
|
@@ -4,14 +4,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.createStartServeSimRemoteSessionBuildFunction = createStartServeSimRemoteSessionBuildFunction;
|
|
7
|
-
const eas_build_job_1 = require("@expo/eas-build-job");
|
|
8
7
|
const steps_1 = require("@expo/steps");
|
|
9
8
|
const turtle_spawn_1 = __importDefault(require("@expo/turtle-spawn"));
|
|
10
|
-
const retry_1 = require("../../utils/retry");
|
|
11
9
|
const remoteDeviceRunSession_1 = require("../utils/remoteDeviceRunSession");
|
|
12
10
|
const XCODE_DEVELOPER_DIR = '/Applications/Xcode.app/Contents/Developer';
|
|
13
11
|
const STARTUP_TIMEOUT_MS = 60_000;
|
|
14
|
-
const TRYCLOUDFLARE_URL_PATTERN = /https:\/\/[a-z0-9-]+\.trycloudflare\.com/;
|
|
15
12
|
function createStartServeSimRemoteSessionBuildFunction(ctx) {
|
|
16
13
|
return new steps_1.BuildFunction({
|
|
17
14
|
namespace: 'eas',
|
|
@@ -26,15 +23,9 @@ function createStartServeSimRemoteSessionBuildFunction(ctx) {
|
|
|
26
23
|
await (0, turtle_spawn_1.default)('sudo', ['xcode-select', '-s', XCODE_DEVELOPER_DIR], { env, logger });
|
|
27
24
|
logger.info('Ensuring cloudflared is installed.');
|
|
28
25
|
await (0, remoteDeviceRunSession_1.ensureBrewPackageInstalledAsync)({ name: 'cloudflared', env, logger });
|
|
29
|
-
|
|
30
|
-
const serveSim = (0, remoteDeviceRunSession_1.spawnDetached)({
|
|
31
|
-
command: 'npx',
|
|
32
|
-
args: ['serve-sim-szdziedzic@latest', '--tunnel'],
|
|
26
|
+
const { previewUrl, streamUrl } = await (0, remoteDeviceRunSession_1.startServeSimWithTunnelAsync)({
|
|
33
27
|
env,
|
|
34
|
-
|
|
35
|
-
logger.info('Waiting for serve-sim to report tunnel and stream URLs.');
|
|
36
|
-
const { previewUrl, streamUrl } = await waitForServeSimUrlsAsync({
|
|
37
|
-
serveSim,
|
|
28
|
+
logger,
|
|
38
29
|
timeoutMs: STARTUP_TIMEOUT_MS,
|
|
39
30
|
});
|
|
40
31
|
logger.info(`Preview URL: ${previewUrl}`);
|
|
@@ -52,21 +43,3 @@ function createStartServeSimRemoteSessionBuildFunction(ctx) {
|
|
|
52
43
|
},
|
|
53
44
|
});
|
|
54
45
|
}
|
|
55
|
-
async function waitForServeSimUrlsAsync({ serveSim, timeoutMs, }) {
|
|
56
|
-
const deadline = Date.now() + timeoutMs;
|
|
57
|
-
while (Date.now() < deadline) {
|
|
58
|
-
const output = serveSim.getOutput();
|
|
59
|
-
const previewUrl = matchLabeledUrl(output, 'Tunnel');
|
|
60
|
-
const streamUrl = matchLabeledUrl(output, 'Stream');
|
|
61
|
-
if (previewUrl && streamUrl) {
|
|
62
|
-
return { previewUrl, streamUrl };
|
|
63
|
-
}
|
|
64
|
-
await (0, retry_1.sleepAsync)(1_000);
|
|
65
|
-
}
|
|
66
|
-
throw new eas_build_job_1.SystemError(`Timed out waiting for serve-sim to report Tunnel and Stream URLs. Last output:\n${serveSim.getOutput() || '<empty>'}`);
|
|
67
|
-
}
|
|
68
|
-
function matchLabeledUrl(content, label) {
|
|
69
|
-
const labelPattern = new RegExp(`${label}:\\s*(${TRYCLOUDFLARE_URL_PATTERN.source})`);
|
|
70
|
-
const match = labelPattern.exec(content);
|
|
71
|
-
return match ? match[1] : null;
|
|
72
|
-
}
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { bunyan } from '@expo/logger';
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* Can be called from both the step-based flow (BuildFunction) and the
|
|
8
|
-
* traditional builder flow (runBuildPhase).
|
|
4
|
+
* Never throws — best-effort observability that does not affect build status.
|
|
5
|
+
* Failures route to Sentry via `Sentry.capture` for engineering triage;
|
|
6
|
+
* users see only a generic skip message.
|
|
9
7
|
*/
|
|
10
8
|
export declare function parseAndReportXcactivitylog({ derivedDataPath, workspacePath, xclogparserVersion, logger, proxyBaseUrl, }: {
|
|
11
9
|
derivedDataPath: string;
|
|
@@ -15,33 +15,38 @@ const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
|
15
15
|
const os_1 = __importDefault(require("os"));
|
|
16
16
|
const path_1 = __importDefault(require("path"));
|
|
17
17
|
const zod_1 = require("zod");
|
|
18
|
+
const sentry_1 = require("../../../sentry");
|
|
18
19
|
const DEFAULT_XCLOGPARSER_VERSION = 'v0.2.47';
|
|
19
20
|
const XCLOGPARSER_DOWNLOAD_URL = 'https://storage.googleapis.com/turtle-v2/xclogparser';
|
|
20
21
|
const XCLOGPARSER_DOWNLOAD_TIMEOUT_MS = 20_000;
|
|
21
22
|
const XCLOGPARSER_OUTPUT_FILENAME = 'xcactivitylog.json';
|
|
22
23
|
/**
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* Can be called from both the step-based flow (BuildFunction) and the
|
|
27
|
-
* traditional builder flow (runBuildPhase).
|
|
24
|
+
* Never throws — best-effort observability that does not affect build status.
|
|
25
|
+
* Failures route to Sentry via `Sentry.capture` for engineering triage;
|
|
26
|
+
* users see only a generic skip message.
|
|
28
27
|
*/
|
|
29
28
|
async function parseAndReportXcactivitylog({ derivedDataPath, workspacePath, xclogparserVersion = DEFAULT_XCLOGPARSER_VERSION, logger, proxyBaseUrl, }) {
|
|
30
29
|
let tempDir;
|
|
30
|
+
let phase = 'creating_temp_directory';
|
|
31
31
|
try {
|
|
32
32
|
tempDir = await fs_extra_1.default.mkdtemp(path_1.default.join(os_1.default.tmpdir(), 'xclogparser-'));
|
|
33
|
+
phase = 'downloading_xclogparser';
|
|
33
34
|
const xclogparserPath = await downloadXclogparser(tempDir, xclogparserVersion, logger, proxyBaseUrl);
|
|
35
|
+
phase = 'running_xclogparser';
|
|
34
36
|
const jsonOutputPath = await runXclogparser({
|
|
35
37
|
binaryPath: xclogparserPath,
|
|
36
38
|
derivedDataPath,
|
|
37
39
|
workspacePath,
|
|
38
40
|
outputDir: tempDir,
|
|
39
41
|
});
|
|
42
|
+
phase = 'parsing_xclogparser_output';
|
|
40
43
|
const data = XcactivitylogDataSchemaZ.parse(JSON.parse(await fs_extra_1.default.readFile(jsonOutputPath, 'utf8')));
|
|
41
44
|
logger.info(formatReport(data));
|
|
42
45
|
}
|
|
43
46
|
catch (err) {
|
|
44
|
-
logger.
|
|
47
|
+
logger.info('Build performance analysis skipped.');
|
|
48
|
+
const msg = `Build performance analysis failed during "${phase}"`;
|
|
49
|
+
sentry_1.Sentry.capture(msg, err, { tags: { phase } });
|
|
45
50
|
}
|
|
46
51
|
finally {
|
|
47
52
|
if (tempDir) {
|
|
@@ -22,3 +22,11 @@ export declare function spawnDetached({ command, args, cwd, env, }: {
|
|
|
22
22
|
cwd?: string;
|
|
23
23
|
env: BuildStepEnv;
|
|
24
24
|
}): DetachedProcessHandle;
|
|
25
|
+
export declare function startServeSimWithTunnelAsync({ env, logger, timeoutMs, }: {
|
|
26
|
+
env: BuildStepEnv;
|
|
27
|
+
logger: bunyan;
|
|
28
|
+
timeoutMs: number;
|
|
29
|
+
}): Promise<{
|
|
30
|
+
previewUrl: string;
|
|
31
|
+
streamUrl: string;
|
|
32
|
+
}>;
|
|
@@ -7,9 +7,12 @@ exports.getDeviceRunSessionIdOrThrow = getDeviceRunSessionIdOrThrow;
|
|
|
7
7
|
exports.uploadRemoteSessionConfigAsync = uploadRemoteSessionConfigAsync;
|
|
8
8
|
exports.ensureBrewPackageInstalledAsync = ensureBrewPackageInstalledAsync;
|
|
9
9
|
exports.spawnDetached = spawnDetached;
|
|
10
|
+
exports.startServeSimWithTunnelAsync = startServeSimWithTunnelAsync;
|
|
10
11
|
const eas_build_job_1 = require("@expo/eas-build-job");
|
|
11
12
|
const turtle_spawn_1 = __importDefault(require("@expo/turtle-spawn"));
|
|
12
13
|
const gql_tada_1 = require("gql.tada");
|
|
14
|
+
const retry_1 = require("../../utils/retry");
|
|
15
|
+
const TRYCLOUDFLARE_URL_PATTERN = /https:\/\/[a-z0-9-]+\.trycloudflare\.com/;
|
|
13
16
|
const START_DEVICE_RUN_SESSION_MUTATION = (0, gql_tada_1.graphql)(`
|
|
14
17
|
mutation StartDeviceRunSession($deviceRunSessionId: ID!, $remoteConfig: JSONObject!) {
|
|
15
18
|
deviceRunSession {
|
|
@@ -63,3 +66,37 @@ function spawnDetached({ command, args, cwd, env, }) {
|
|
|
63
66
|
promise.child.stderr?.on('data', appendChunk);
|
|
64
67
|
return { getOutput: () => output };
|
|
65
68
|
}
|
|
69
|
+
async function startServeSimWithTunnelAsync({ env, logger, timeoutMs, }) {
|
|
70
|
+
logger.info('Launching serve-sim with tunnel.');
|
|
71
|
+
const serveSim = spawnDetached({
|
|
72
|
+
command: 'npx',
|
|
73
|
+
args: [
|
|
74
|
+
'serve-sim-szdziedzic@latest',
|
|
75
|
+
'--tunnel',
|
|
76
|
+
'--tunnel-protocol',
|
|
77
|
+
'quic',
|
|
78
|
+
'--stream-max-dimension',
|
|
79
|
+
'1280',
|
|
80
|
+
'--stream-quality',
|
|
81
|
+
'0.55',
|
|
82
|
+
],
|
|
83
|
+
env,
|
|
84
|
+
});
|
|
85
|
+
logger.info('Waiting for serve-sim to report tunnel and stream URLs.');
|
|
86
|
+
const deadline = Date.now() + timeoutMs;
|
|
87
|
+
while (Date.now() < deadline) {
|
|
88
|
+
const output = serveSim.getOutput();
|
|
89
|
+
const previewUrl = matchLabeledUrl(output, 'Tunnel');
|
|
90
|
+
const streamUrl = matchLabeledUrl(output, 'Stream');
|
|
91
|
+
if (previewUrl && streamUrl) {
|
|
92
|
+
return { previewUrl, streamUrl };
|
|
93
|
+
}
|
|
94
|
+
await (0, retry_1.sleepAsync)(1_000);
|
|
95
|
+
}
|
|
96
|
+
throw new eas_build_job_1.SystemError(`Timed out waiting for serve-sim to report Tunnel and Stream URLs. Last output:\n${serveSim.getOutput() || '<empty>'}`);
|
|
97
|
+
}
|
|
98
|
+
function matchLabeledUrl(content, label) {
|
|
99
|
+
const labelPattern = new RegExp(`${label}:\\s*(${TRYCLOUDFLARE_URL_PATTERN.source})`);
|
|
100
|
+
const match = labelPattern.exec(content);
|
|
101
|
+
return match ? match[1] : null;
|
|
102
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@expo/build-tools",
|
|
3
|
-
"version": "18.
|
|
3
|
+
"version": "18.13.1",
|
|
4
4
|
"bugs": "https://github.com/expo/eas-cli/issues",
|
|
5
5
|
"license": "BUSL-1.1",
|
|
6
6
|
"author": "Expo <support@expo.io>",
|
|
@@ -38,18 +38,19 @@
|
|
|
38
38
|
"@expo/config": "55.0.10",
|
|
39
39
|
"@expo/config-plugins": "55.0.7",
|
|
40
40
|
"@expo/downloader": "18.5.0",
|
|
41
|
-
"@expo/eas-build-job": "18.
|
|
41
|
+
"@expo/eas-build-job": "18.13.1",
|
|
42
42
|
"@expo/env": "^0.4.0",
|
|
43
43
|
"@expo/logger": "18.5.0",
|
|
44
44
|
"@expo/package-manager": "1.9.10",
|
|
45
45
|
"@expo/plist": "^0.2.0",
|
|
46
46
|
"@expo/results": "^1.0.0",
|
|
47
47
|
"@expo/spawn-async": "1.7.2",
|
|
48
|
-
"@expo/steps": "18.
|
|
48
|
+
"@expo/steps": "18.13.1",
|
|
49
49
|
"@expo/template-file": "18.5.0",
|
|
50
50
|
"@expo/turtle-spawn": "18.5.0",
|
|
51
51
|
"@expo/xcpretty": "^4.3.1",
|
|
52
52
|
"@google-cloud/storage": "^7.11.2",
|
|
53
|
+
"@sentry/node": "7.77.0",
|
|
53
54
|
"@urql/core": "^6.0.1",
|
|
54
55
|
"bplist-parser": "0.3.2",
|
|
55
56
|
"fast-glob": "^3.3.2",
|
|
@@ -98,5 +99,5 @@
|
|
|
98
99
|
"typescript": "^5.5.4",
|
|
99
100
|
"uuid": "^9.0.1"
|
|
100
101
|
},
|
|
101
|
-
"gitHead": "
|
|
102
|
+
"gitHead": "dbf597957dc93133d15e99298c55c0ad31b994c1"
|
|
102
103
|
}
|