@expo/build-tools 21.0.2 → 21.1.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/dist/builders/android.js +12 -1
- package/dist/builders/ios.js +13 -1
- package/dist/common/easBuildInternal.js +3 -0
- package/dist/common/hookableBuildPhase.d.ts +18 -0
- package/dist/common/hookableBuildPhase.js +72 -0
- package/dist/common/jobHooks.d.ts +16 -0
- package/dist/common/jobHooks.js +95 -0
- package/dist/common/setup.d.ts +14 -2
- package/dist/common/setup.js +40 -21
- package/dist/index.d.ts +4 -3
- package/dist/index.js +5 -5
- package/dist/{gcs/LoggerStream.d.ts → logging/RemoteLoggerStream.d.ts} +6 -6
- package/dist/{gcs/LoggerStream.js → logging/RemoteLoggerStream.js} +10 -10
- package/dist/steps/functions/maestroResultParser.d.ts +1 -0
- package/dist/steps/functions/maestroResultParser.js +12 -0
- package/dist/steps/functions/maestroScreenshots.d.ts +1 -0
- package/dist/steps/functions/maestroScreenshots.js +167 -34
- package/dist/steps/functions/maestroTests.js +4 -0
- package/dist/steps/functions/startAgentDeviceRemoteSession.d.ts +8 -0
- package/dist/steps/functions/startAgentDeviceRemoteSession.js +35 -3
- package/dist/steps/utils/deviceRunSessionEvents.d.ts +23 -0
- package/dist/steps/utils/deviceRunSessionEvents.js +311 -0
- package/dist/{gcs → storage}/retry.d.ts +1 -1
- package/dist/{gcs → storage}/retry.js +2 -2
- package/dist/storage/uploadWithSignedUrl.d.ts +12 -0
- package/dist/{gcs/client.js → storage/uploadWithSignedUrl.js} +27 -31
- package/package.json +4 -4
- package/dist/gcs/client.d.ts +0 -15
|
@@ -0,0 +1,311 @@
|
|
|
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.startAgentDeviceEventCollectionAsync = startAgentDeviceEventCollectionAsync;
|
|
7
|
+
const eas_build_job_1 = require("@expo/eas-build-job");
|
|
8
|
+
const gql_tada_1 = require("gql.tada");
|
|
9
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
10
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
11
|
+
const node_string_decoder_1 = require("node:string_decoder");
|
|
12
|
+
const promises_1 = require("node:timers/promises");
|
|
13
|
+
const zod_1 = require("zod");
|
|
14
|
+
const RemoteLoggerStream_1 = __importDefault(require("../../logging/RemoteLoggerStream"));
|
|
15
|
+
const sentry_1 = require("../../sentry");
|
|
16
|
+
const POLL_INTERVAL_MS = 1_000;
|
|
17
|
+
const UPLOAD_INTERVAL_MS = 5_000;
|
|
18
|
+
const AGENT_DEVICE_EVENT_KIND_TO_TYPE = {
|
|
19
|
+
'request.started': 'operation.started',
|
|
20
|
+
'request.finished': 'operation.completed',
|
|
21
|
+
'action.recorded': 'interaction.recorded',
|
|
22
|
+
};
|
|
23
|
+
const AgentDeviceEventSchema = zod_1.z
|
|
24
|
+
.object({
|
|
25
|
+
version: zod_1.z.number(),
|
|
26
|
+
ts: zod_1.z.string(),
|
|
27
|
+
session: zod_1.z.string(),
|
|
28
|
+
kind: zod_1.z.string(),
|
|
29
|
+
requestId: zod_1.z.string().optional().catch(undefined),
|
|
30
|
+
command: zod_1.z.string().optional().catch(undefined),
|
|
31
|
+
status: zod_1.z.string().optional().catch(undefined),
|
|
32
|
+
summary: zod_1.z.string().optional().catch(undefined),
|
|
33
|
+
details: zod_1.z.record(zod_1.z.string(), zod_1.z.unknown()).optional().catch(undefined),
|
|
34
|
+
})
|
|
35
|
+
.passthrough();
|
|
36
|
+
const CREATE_DEVICE_RUN_SESSION_EVENT_LOG_UPLOAD_SESSION_MUTATION = (0, gql_tada_1.graphql)(`
|
|
37
|
+
mutation CreateDeviceRunSessionEventLogUploadSession($deviceRunSessionId: ID!) {
|
|
38
|
+
deviceRunSession {
|
|
39
|
+
createEventLogUploadSession(deviceRunSessionId: $deviceRunSessionId) {
|
|
40
|
+
uploadSession {
|
|
41
|
+
url
|
|
42
|
+
headers
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
`);
|
|
48
|
+
async function startAgentDeviceEventCollectionAsync({ ctx, deviceRunSessionId, stateDir, logger, pollIntervalMs = POLL_INTERVAL_MS, }) {
|
|
49
|
+
let didReportEventLogFailure = false;
|
|
50
|
+
const reportEventLogFailure = (error, operation) => {
|
|
51
|
+
if (didReportEventLogFailure) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
didReportEventLogFailure = true;
|
|
55
|
+
sentry_1.Sentry.capture('Could not persist device run session events', error, {
|
|
56
|
+
level: 'warning',
|
|
57
|
+
tags: { phase: 'device-run-session-event-collection', operation },
|
|
58
|
+
extras: { deviceRunSessionId },
|
|
59
|
+
});
|
|
60
|
+
};
|
|
61
|
+
let eventLogStream;
|
|
62
|
+
try {
|
|
63
|
+
const uploadSession = await createEventLogUploadSessionAsync(ctx, deviceRunSessionId);
|
|
64
|
+
eventLogStream = new RemoteLoggerStream_1.default({
|
|
65
|
+
logger,
|
|
66
|
+
uploadMethod: { signedUrl: uploadSession },
|
|
67
|
+
options: {
|
|
68
|
+
uploadIntervalMs: UPLOAD_INTERVAL_MS,
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
await eventLogStream.init();
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
75
|
+
logger.warn({ err: error }, 'Could not start device run session event collection.');
|
|
76
|
+
reportEventLogFailure(error, 'setup');
|
|
77
|
+
return { stopAsync: async () => { } };
|
|
78
|
+
}
|
|
79
|
+
const states = new Map();
|
|
80
|
+
const controller = new AbortController();
|
|
81
|
+
let parseFailureCount = 0;
|
|
82
|
+
const parseFailureCounts = {
|
|
83
|
+
'invalid-json': 0,
|
|
84
|
+
'invalid-event': 0,
|
|
85
|
+
};
|
|
86
|
+
let didReportCollectionFailure = false;
|
|
87
|
+
const collectAsync = async () => {
|
|
88
|
+
const eventFiles = await findAgentDeviceEventFilesAsync(stateDir);
|
|
89
|
+
await Promise.all(eventFiles.map(async (eventFile) => {
|
|
90
|
+
const state = states.get(eventFile) ?? {
|
|
91
|
+
offset: 0,
|
|
92
|
+
nextSequenceNumber: 1,
|
|
93
|
+
nextLineNumber: 1,
|
|
94
|
+
pending: '',
|
|
95
|
+
decoder: new node_string_decoder_1.StringDecoder('utf8'),
|
|
96
|
+
};
|
|
97
|
+
states.set(eventFile, state);
|
|
98
|
+
await collectEventFileAsync({
|
|
99
|
+
eventFile,
|
|
100
|
+
state,
|
|
101
|
+
deviceRunSessionId,
|
|
102
|
+
writeEvent: event => eventLogStream.write(event),
|
|
103
|
+
onParseFailure: ({ failure, lineNumber }) => {
|
|
104
|
+
parseFailureCount += 1;
|
|
105
|
+
parseFailureCounts[failure] += 1;
|
|
106
|
+
if (parseFailureCount !== 1) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
logger.warn({ agentDeviceEventParseFailure: failure, lineNumber }, 'Could not parse an agent-device event log record.');
|
|
110
|
+
sentry_1.Sentry.capture('Could not parse an agent-device event log record', {
|
|
111
|
+
level: 'warning',
|
|
112
|
+
tags: { phase: 'agent-device-event-collection', reason: failure },
|
|
113
|
+
extras: { deviceRunSessionId, lineNumber },
|
|
114
|
+
});
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
}));
|
|
118
|
+
};
|
|
119
|
+
const collectSafelyAsync = async () => {
|
|
120
|
+
try {
|
|
121
|
+
await collectAsync();
|
|
122
|
+
didReportCollectionFailure = false;
|
|
123
|
+
}
|
|
124
|
+
catch (err) {
|
|
125
|
+
if (didReportCollectionFailure) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
didReportCollectionFailure = true;
|
|
129
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
130
|
+
logger.warn({ err: error }, 'Could not collect agent-device events.');
|
|
131
|
+
sentry_1.Sentry.capture('Could not collect agent-device events', error, {
|
|
132
|
+
level: 'warning',
|
|
133
|
+
tags: { phase: 'agent-device-event-collection' },
|
|
134
|
+
extras: { deviceRunSessionId },
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
const pollingPromise = (async () => {
|
|
139
|
+
while (!controller.signal.aborted) {
|
|
140
|
+
await collectSafelyAsync();
|
|
141
|
+
try {
|
|
142
|
+
await (0, promises_1.setTimeout)(pollIntervalMs, undefined, { signal: controller.signal });
|
|
143
|
+
}
|
|
144
|
+
catch (err) {
|
|
145
|
+
if (!controller.signal.aborted) {
|
|
146
|
+
throw err;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
})()
|
|
151
|
+
.catch(err => {
|
|
152
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
153
|
+
logger.warn({ err: error }, 'Agent-device event collection poller failed.');
|
|
154
|
+
sentry_1.Sentry.capture('Agent-device event collection poller failed', error, {
|
|
155
|
+
level: 'warning',
|
|
156
|
+
tags: { phase: 'agent-device-event-collection', operation: 'poll' },
|
|
157
|
+
extras: { deviceRunSessionId },
|
|
158
|
+
});
|
|
159
|
+
})
|
|
160
|
+
.catch(() => {
|
|
161
|
+
// A diagnostics failure must not recreate an unhandled rejection in this best-effort poller.
|
|
162
|
+
});
|
|
163
|
+
return {
|
|
164
|
+
stopAsync: async () => {
|
|
165
|
+
controller.abort();
|
|
166
|
+
await pollingPromise;
|
|
167
|
+
await collectSafelyAsync();
|
|
168
|
+
if (parseFailureCount > 1) {
|
|
169
|
+
logger.warn({ agentDeviceEventParseFailures: parseFailureCounts, parseFailureCount }, `Could not parse ${parseFailureCount} agent-device event log records.`);
|
|
170
|
+
sentry_1.Sentry.capture('Could not parse multiple agent-device event log records', {
|
|
171
|
+
level: 'warning',
|
|
172
|
+
tags: { phase: 'agent-device-event-collection' },
|
|
173
|
+
extras: { deviceRunSessionId, parseFailureCount, parseFailureCounts },
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
try {
|
|
177
|
+
await eventLogStream.cleanUp();
|
|
178
|
+
}
|
|
179
|
+
catch (err) {
|
|
180
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
181
|
+
logger.warn({ err: error }, 'Could not finish device run session event collection.');
|
|
182
|
+
reportEventLogFailure(error, 'cleanup');
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
async function createEventLogUploadSessionAsync(ctx, deviceRunSessionId) {
|
|
188
|
+
const result = await ctx.graphqlClient
|
|
189
|
+
.mutation(CREATE_DEVICE_RUN_SESSION_EVENT_LOG_UPLOAD_SESSION_MUTATION, {
|
|
190
|
+
deviceRunSessionId,
|
|
191
|
+
})
|
|
192
|
+
.toPromise();
|
|
193
|
+
if (result.error) {
|
|
194
|
+
throw new eas_build_job_1.SystemError(`Failed to create device run session event log upload session: ${result.error.message}`, { cause: result.error });
|
|
195
|
+
}
|
|
196
|
+
const uploadSession = result.data.deviceRunSession.createEventLogUploadSession.uploadSession;
|
|
197
|
+
return {
|
|
198
|
+
url: uploadSession.url,
|
|
199
|
+
headers: uploadSession.headers,
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
async function findAgentDeviceEventFilesAsync(stateDir) {
|
|
203
|
+
const sessionsDir = node_path_1.default.join(stateDir, 'sessions');
|
|
204
|
+
let entries;
|
|
205
|
+
try {
|
|
206
|
+
entries = await node_fs_1.default.promises.readdir(sessionsDir, { withFileTypes: true });
|
|
207
|
+
}
|
|
208
|
+
catch (err) {
|
|
209
|
+
if (err.code === 'ENOENT') {
|
|
210
|
+
return [];
|
|
211
|
+
}
|
|
212
|
+
throw err;
|
|
213
|
+
}
|
|
214
|
+
return entries
|
|
215
|
+
.filter(entry => entry.isDirectory())
|
|
216
|
+
.map(entry => node_path_1.default.join(sessionsDir, entry.name, 'events.ndjson'));
|
|
217
|
+
}
|
|
218
|
+
async function collectEventFileAsync({ eventFile, state, deviceRunSessionId, writeEvent, onParseFailure, }) {
|
|
219
|
+
let fileSize;
|
|
220
|
+
try {
|
|
221
|
+
fileSize = (await node_fs_1.default.promises.stat(eventFile)).size;
|
|
222
|
+
}
|
|
223
|
+
catch (err) {
|
|
224
|
+
if (err.code === 'ENOENT') {
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
throw err;
|
|
228
|
+
}
|
|
229
|
+
if (fileSize < state.offset) {
|
|
230
|
+
state.offset = 0;
|
|
231
|
+
state.pending = '';
|
|
232
|
+
state.decoder = new node_string_decoder_1.StringDecoder('utf8');
|
|
233
|
+
}
|
|
234
|
+
if (fileSize === state.offset) {
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
const handle = await node_fs_1.default.promises.open(eventFile, 'r');
|
|
238
|
+
try {
|
|
239
|
+
const buffer = new Uint8Array(new ArrayBuffer(fileSize - state.offset));
|
|
240
|
+
const { bytesRead } = await handle.read(buffer, 0, buffer.length, state.offset);
|
|
241
|
+
state.offset += bytesRead;
|
|
242
|
+
const text = state.decoder.write(buffer.subarray(0, bytesRead));
|
|
243
|
+
const lines = `${state.pending}${text}`.split('\n');
|
|
244
|
+
state.pending = lines.pop() ?? '';
|
|
245
|
+
for (const line of lines) {
|
|
246
|
+
const lineNumber = state.nextLineNumber++;
|
|
247
|
+
const sequenceNumber = state.nextSequenceNumber++;
|
|
248
|
+
const { event, failure } = parseAgentDeviceEvent(line);
|
|
249
|
+
if (failure) {
|
|
250
|
+
onParseFailure({ failure, lineNumber });
|
|
251
|
+
}
|
|
252
|
+
if (!event) {
|
|
253
|
+
continue;
|
|
254
|
+
}
|
|
255
|
+
const deviceRunSessionEvent = normalizeAgentDeviceEvent({
|
|
256
|
+
event,
|
|
257
|
+
sequenceNumber,
|
|
258
|
+
sourceSessionDirectory: node_path_1.default.basename(node_path_1.default.dirname(eventFile)),
|
|
259
|
+
deviceRunSessionId,
|
|
260
|
+
});
|
|
261
|
+
writeEvent(deviceRunSessionEvent);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
finally {
|
|
265
|
+
await handle.close();
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
function parseAgentDeviceEvent(line) {
|
|
269
|
+
if (!line.trim()) {
|
|
270
|
+
return {};
|
|
271
|
+
}
|
|
272
|
+
try {
|
|
273
|
+
const result = AgentDeviceEventSchema.safeParse(JSON.parse(line));
|
|
274
|
+
return result.success ? { event: result.data } : { failure: 'invalid-event' };
|
|
275
|
+
}
|
|
276
|
+
catch {
|
|
277
|
+
return { failure: 'invalid-json' };
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
function normalizeAgentDeviceEvent({ event, sequenceNumber, sourceSessionDirectory, deviceRunSessionId, }) {
|
|
281
|
+
const type = AGENT_DEVICE_EVENT_KIND_TO_TYPE[event.kind] ?? event.kind;
|
|
282
|
+
const durationMs = event.details?.durationMs;
|
|
283
|
+
const outcome = event.status === 'ok' ? 'success' : event.status === 'error' ? 'failure' : undefined;
|
|
284
|
+
const summary = event.summary ??
|
|
285
|
+
(event.kind === 'request.started'
|
|
286
|
+
? `Started ${event.command ?? 'activity'}`
|
|
287
|
+
: event.kind === 'request.finished'
|
|
288
|
+
? `Finished ${event.command ?? 'activity'}`
|
|
289
|
+
: event.kind === 'action.recorded'
|
|
290
|
+
? `Recorded ${event.command ?? 'activity'}`
|
|
291
|
+
: `${event.kind}${event.command ? `: ${event.command}` : ''}`);
|
|
292
|
+
return {
|
|
293
|
+
v: 1,
|
|
294
|
+
// Consumers use eventId to deduplicate events across polls. Keep the per-file sequence
|
|
295
|
+
// monotonic across source-file truncations so an ID is never reused during collection.
|
|
296
|
+
eventId: `agent-device:${deviceRunSessionId}:${sourceSessionDirectory}:${sequenceNumber}`,
|
|
297
|
+
ts: event.ts,
|
|
298
|
+
producer: 'agent-device',
|
|
299
|
+
type,
|
|
300
|
+
...(event.requestId ? { operationId: event.requestId } : {}),
|
|
301
|
+
...(outcome ? { outcome } : {}),
|
|
302
|
+
...(typeof durationMs === 'number' ? { durationMs } : {}),
|
|
303
|
+
summary,
|
|
304
|
+
data: {
|
|
305
|
+
...event.details,
|
|
306
|
+
session: event.session,
|
|
307
|
+
sourceVersion: event.version,
|
|
308
|
+
...(event.status ? { sourceStatus: event.status } : {}),
|
|
309
|
+
},
|
|
310
|
+
};
|
|
311
|
+
}
|
|
@@ -5,7 +5,7 @@ type RetryOptions = {
|
|
|
5
5
|
shouldRetryOnError: (error: unknown) => boolean;
|
|
6
6
|
shouldRetryOnResponse: (response: Response) => boolean;
|
|
7
7
|
};
|
|
8
|
-
export declare function
|
|
8
|
+
export declare function retryOnUploadFailure(fn: (attemptCount: number) => Promise<Response>, { retries, retryIntervalMs, }: {
|
|
9
9
|
retries: RetryOptions['retries'];
|
|
10
10
|
retryIntervalMs: RetryOptions['retryIntervalMs'];
|
|
11
11
|
}): Promise<Response>;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.retryOnUploadFailure = retryOnUploadFailure;
|
|
4
4
|
// based on https://github.com/googleapis/nodejs-storage/blob/8ab50804fc7bae3bbd159bbb4adf65c02215b11b/src/storage.ts#L284-L320
|
|
5
|
-
async function
|
|
5
|
+
async function retryOnUploadFailure(fn, { retries, retryIntervalMs, }) {
|
|
6
6
|
return await retry(fn, {
|
|
7
7
|
retries,
|
|
8
8
|
retryIntervalMs,
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Readable } from 'stream';
|
|
2
|
+
export type SignedUrl = {
|
|
3
|
+
url: string;
|
|
4
|
+
headers: Record<string, string>;
|
|
5
|
+
};
|
|
6
|
+
export type UploadWithSignedUrlParams = {
|
|
7
|
+
signedUrl: SignedUrl;
|
|
8
|
+
srcGeneratorAsync: () => Promise<Readable>;
|
|
9
|
+
retryIntervalMs?: number;
|
|
10
|
+
retries?: number;
|
|
11
|
+
};
|
|
12
|
+
export declare function uploadWithSignedUrl({ signedUrl, srcGeneratorAsync, retries, retryIntervalMs, }: UploadWithSignedUrlParams): Promise<string>;
|
|
@@ -33,40 +33,36 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.
|
|
36
|
+
exports.uploadWithSignedUrl = uploadWithSignedUrl;
|
|
37
37
|
const node_fetch_1 = __importStar(require("node-fetch"));
|
|
38
38
|
const url_1 = require("url");
|
|
39
39
|
const retry_1 = require("./retry");
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
if (err instanceof node_fetch_1.FetchError) {
|
|
56
|
-
throw new Error(`Failed to upload the file, reason: ${err.code}`);
|
|
57
|
-
}
|
|
58
|
-
throw err;
|
|
40
|
+
async function uploadWithSignedUrl({ signedUrl, srcGeneratorAsync, retries = 2, retryIntervalMs = 30_000, }) {
|
|
41
|
+
let resp;
|
|
42
|
+
try {
|
|
43
|
+
resp = await (0, retry_1.retryOnUploadFailure)(async () => {
|
|
44
|
+
const src = await srcGeneratorAsync();
|
|
45
|
+
return await (0, node_fetch_1.default)(signedUrl.url, {
|
|
46
|
+
method: 'PUT',
|
|
47
|
+
headers: signedUrl.headers,
|
|
48
|
+
body: src,
|
|
49
|
+
});
|
|
50
|
+
}, { retries, retryIntervalMs });
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
if (err instanceof node_fetch_1.FetchError) {
|
|
54
|
+
throw new Error(`Failed to upload the file, reason: ${err.code}`);
|
|
59
55
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
throw new Error(`Failed to upload file: status: ${resp.status} status text: ${resp.statusText}, body: ${body}`);
|
|
56
|
+
throw err;
|
|
57
|
+
}
|
|
58
|
+
if (!resp.ok) {
|
|
59
|
+
let body;
|
|
60
|
+
try {
|
|
61
|
+
body = await resp.text();
|
|
67
62
|
}
|
|
68
|
-
|
|
69
|
-
|
|
63
|
+
catch { }
|
|
64
|
+
throw new Error(`Failed to upload file: status: ${resp.status} status text: ${resp.statusText}, body: ${body}`);
|
|
70
65
|
}
|
|
71
|
-
|
|
72
|
-
|
|
66
|
+
const url = new url_1.URL(signedUrl.url);
|
|
67
|
+
return `${url.protocol}//${url.host}${url.pathname}`;
|
|
68
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@expo/build-tools",
|
|
3
|
-
"version": "21.0
|
|
3
|
+
"version": "21.1.0",
|
|
4
4
|
"bugs": "https://github.com/expo/eas-cli/issues",
|
|
5
5
|
"license": "BUSL-1.1",
|
|
6
6
|
"author": "Expo <support@expo.io>",
|
|
@@ -39,14 +39,14 @@
|
|
|
39
39
|
"@expo/config": "55.0.10",
|
|
40
40
|
"@expo/config-plugins": "55.0.7",
|
|
41
41
|
"@expo/downloader": "21.0.0",
|
|
42
|
-
"@expo/eas-build-job": "21.0
|
|
42
|
+
"@expo/eas-build-job": "21.1.0",
|
|
43
43
|
"@expo/env": "^0.4.0",
|
|
44
44
|
"@expo/logger": "21.0.0",
|
|
45
45
|
"@expo/package-manager": "1.9.10",
|
|
46
46
|
"@expo/plist": "^0.3.5",
|
|
47
47
|
"@expo/results": "^1.0.0",
|
|
48
48
|
"@expo/spawn-async": "1.7.2",
|
|
49
|
-
"@expo/steps": "21.0
|
|
49
|
+
"@expo/steps": "21.1.0",
|
|
50
50
|
"@expo/template-file": "21.0.2",
|
|
51
51
|
"@expo/turtle-spawn": "21.0.0",
|
|
52
52
|
"@expo/xcpretty": "^4.3.1",
|
|
@@ -100,5 +100,5 @@
|
|
|
100
100
|
"typescript": "^5.5.4",
|
|
101
101
|
"uuid": "^9.0.1"
|
|
102
102
|
},
|
|
103
|
-
"gitHead": "
|
|
103
|
+
"gitHead": "24272d8a5f080584f9688d19c2a4a4d06f9448ac"
|
|
104
104
|
}
|
package/dist/gcs/client.d.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { Readable } from 'stream';
|
|
2
|
-
interface UploadWithSignedUrlParams {
|
|
3
|
-
signedUrl: GCS.SignedUrl;
|
|
4
|
-
srcGeneratorAsync: () => Promise<Readable>;
|
|
5
|
-
retryIntervalMs?: number;
|
|
6
|
-
retries?: number;
|
|
7
|
-
}
|
|
8
|
-
export declare namespace GCS {
|
|
9
|
-
type SignedUrl = {
|
|
10
|
-
url: string;
|
|
11
|
-
headers: Record<string, string>;
|
|
12
|
-
};
|
|
13
|
-
function uploadWithSignedUrl({ signedUrl, srcGeneratorAsync, retries, retryIntervalMs, }: UploadWithSignedUrlParams): Promise<string>;
|
|
14
|
-
}
|
|
15
|
-
export {};
|