@enclave-run/sdk 0.0.0-dev.4 → 0.0.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 +51 -18
- package/dist/index.d.mts +372 -17
- package/dist/index.d.ts +372 -17
- package/dist/index.js +592 -114
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +590 -114
- package/dist/index.mjs.map +1 -1
- package/package.json +25 -24
package/dist/index.mjs
CHANGED
|
@@ -60,7 +60,7 @@ import createClient from "openapi-fetch";
|
|
|
60
60
|
import platform2 from "platform";
|
|
61
61
|
|
|
62
62
|
// package.json
|
|
63
|
-
var version = "0.0.0
|
|
63
|
+
var version = "0.0.0";
|
|
64
64
|
|
|
65
65
|
// src/utils.ts
|
|
66
66
|
import platform from "platform";
|
|
@@ -244,6 +244,21 @@ var TemplateError = class extends SandboxError {
|
|
|
244
244
|
this.name = "TemplateError";
|
|
245
245
|
}
|
|
246
246
|
};
|
|
247
|
+
var TemplateTagConflictError = class extends TemplateError {
|
|
248
|
+
constructor(options) {
|
|
249
|
+
var _a3;
|
|
250
|
+
super(
|
|
251
|
+
(_a3 = options.message) != null ? _a3 : `Template tag "${options.tag}" conflicted with another mutation. Fetch its current head with Template.getTagHead() before retrying.`
|
|
252
|
+
);
|
|
253
|
+
this.name = "TemplateTagConflictError";
|
|
254
|
+
this.templateId = options.templateId;
|
|
255
|
+
this.tag = options.tag;
|
|
256
|
+
this.candidateBuildId = options.candidateBuildId;
|
|
257
|
+
this.expectedBuildId = options.expectedBuildId;
|
|
258
|
+
this.expectedVersion = options.expectedVersion;
|
|
259
|
+
this.reason = options.reason;
|
|
260
|
+
}
|
|
261
|
+
};
|
|
247
262
|
var RateLimitError = class extends SandboxError {
|
|
248
263
|
constructor(message) {
|
|
249
264
|
super(message);
|
|
@@ -271,11 +286,11 @@ function formatLog(log) {
|
|
|
271
286
|
return JSON.parse(JSON.stringify(log));
|
|
272
287
|
}
|
|
273
288
|
function createRpcLogger(logger) {
|
|
274
|
-
function logEach(
|
|
289
|
+
function logEach(stream2) {
|
|
275
290
|
return __asyncGenerator(this, null, function* () {
|
|
276
291
|
var _a3;
|
|
277
292
|
try {
|
|
278
|
-
for (var iter = __forAwait(
|
|
293
|
+
for (var iter = __forAwait(stream2), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
|
|
279
294
|
const m = temp.value;
|
|
280
295
|
(_a3 = logger.debug) == null ? void 0 : _a3.call(logger, "Response stream:", formatLog(m));
|
|
281
296
|
yield m;
|
|
@@ -1653,9 +1668,9 @@ var ALL_TRAFFIC = "0.0.0.0/0";
|
|
|
1653
1668
|
function shellEscape(value) {
|
|
1654
1669
|
return `'${value.replace(/'/g, `'"'"'`)}'`;
|
|
1655
1670
|
}
|
|
1656
|
-
function withCredentials(
|
|
1671
|
+
function withCredentials(url2, username, password) {
|
|
1657
1672
|
if (!username && !password) {
|
|
1658
|
-
return
|
|
1673
|
+
return url2;
|
|
1659
1674
|
}
|
|
1660
1675
|
if (!username || !password) {
|
|
1661
1676
|
throw new InvalidArgumentError(
|
|
@@ -1664,9 +1679,9 @@ function withCredentials(url, username, password) {
|
|
|
1664
1679
|
}
|
|
1665
1680
|
let parsed;
|
|
1666
1681
|
try {
|
|
1667
|
-
parsed = new URL(
|
|
1682
|
+
parsed = new URL(url2);
|
|
1668
1683
|
} catch (e) {
|
|
1669
|
-
throw new InvalidArgumentError(`Invalid Git URL: ${
|
|
1684
|
+
throw new InvalidArgumentError(`Invalid Git URL: ${url2}`);
|
|
1670
1685
|
}
|
|
1671
1686
|
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
1672
1687
|
throw new InvalidArgumentError(
|
|
@@ -1677,27 +1692,27 @@ function withCredentials(url, username, password) {
|
|
|
1677
1692
|
parsed.password = password;
|
|
1678
1693
|
return parsed.toString();
|
|
1679
1694
|
}
|
|
1680
|
-
function stripCredentials(
|
|
1695
|
+
function stripCredentials(url2) {
|
|
1681
1696
|
let parsed;
|
|
1682
1697
|
try {
|
|
1683
|
-
parsed = new URL(
|
|
1698
|
+
parsed = new URL(url2);
|
|
1684
1699
|
} catch (e) {
|
|
1685
|
-
return
|
|
1700
|
+
return url2;
|
|
1686
1701
|
}
|
|
1687
1702
|
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
1688
|
-
return
|
|
1703
|
+
return url2;
|
|
1689
1704
|
}
|
|
1690
1705
|
if (!parsed.username && !parsed.password) {
|
|
1691
|
-
return
|
|
1706
|
+
return url2;
|
|
1692
1707
|
}
|
|
1693
1708
|
parsed.username = "";
|
|
1694
1709
|
parsed.password = "";
|
|
1695
1710
|
return parsed.toString();
|
|
1696
1711
|
}
|
|
1697
|
-
function deriveRepoDirFromUrl(
|
|
1712
|
+
function deriveRepoDirFromUrl(url2) {
|
|
1698
1713
|
let parsed;
|
|
1699
1714
|
try {
|
|
1700
|
-
parsed = new URL(
|
|
1715
|
+
parsed = new URL(url2);
|
|
1701
1716
|
} catch (e) {
|
|
1702
1717
|
return void 0;
|
|
1703
1718
|
}
|
|
@@ -1984,7 +1999,7 @@ var Git = class {
|
|
|
1984
1999
|
* @param opts Clone options.
|
|
1985
2000
|
* @returns Command result from the command runner.
|
|
1986
2001
|
*/
|
|
1987
|
-
async clone(
|
|
2002
|
+
async clone(url2, opts) {
|
|
1988
2003
|
const _a3 = opts != null ? opts : {}, {
|
|
1989
2004
|
username,
|
|
1990
2005
|
password,
|
|
@@ -2006,10 +2021,10 @@ var Git = class {
|
|
|
2006
2021
|
);
|
|
2007
2022
|
}
|
|
2008
2023
|
const attemptClone = async (authUsername, authPassword) => {
|
|
2009
|
-
const urlWithCreds = authUsername && authPassword ? withCredentials(
|
|
2024
|
+
const urlWithCreds = authUsername && authPassword ? withCredentials(url2, authUsername, authPassword) : url2;
|
|
2010
2025
|
const sanitizedUrl = stripCredentials(urlWithCreds);
|
|
2011
2026
|
const stripInlineCreds = !dangerouslyStoreCredentials && sanitizedUrl !== urlWithCreds;
|
|
2012
|
-
const repoPath = stripInlineCreds ? path2 != null ? path2 : deriveRepoDirFromUrl(
|
|
2027
|
+
const repoPath = stripInlineCreds ? path2 != null ? path2 : deriveRepoDirFromUrl(url2) : path2;
|
|
2013
2028
|
if (stripInlineCreds && !repoPath) {
|
|
2014
2029
|
throw new InvalidArgumentError(
|
|
2015
2030
|
"A destination path is required when using credentials without storing them."
|
|
@@ -2068,8 +2083,8 @@ var Git = class {
|
|
|
2068
2083
|
* @param opts Remote add options.
|
|
2069
2084
|
* @returns Command result from the command runner.
|
|
2070
2085
|
*/
|
|
2071
|
-
async remoteAdd(path2, name,
|
|
2072
|
-
if (!name || !
|
|
2086
|
+
async remoteAdd(path2, name, url2, opts) {
|
|
2087
|
+
if (!name || !url2) {
|
|
2073
2088
|
throw new InvalidArgumentError(
|
|
2074
2089
|
"Both remote name and URL are required to add a git remote."
|
|
2075
2090
|
);
|
|
@@ -2079,12 +2094,12 @@ var Git = class {
|
|
|
2079
2094
|
if (fetch2) {
|
|
2080
2095
|
addArgs.push("-f");
|
|
2081
2096
|
}
|
|
2082
|
-
addArgs.push(name,
|
|
2097
|
+
addArgs.push(name, url2);
|
|
2083
2098
|
if (!overwrite) {
|
|
2084
2099
|
return this.runGit(addArgs, path2, rest);
|
|
2085
2100
|
}
|
|
2086
2101
|
const addCmd = buildGitCommand(addArgs, path2);
|
|
2087
|
-
const setUrlCmd = buildGitCommand(["remote", "set-url", name,
|
|
2102
|
+
const setUrlCmd = buildGitCommand(["remote", "set-url", name, url2], path2);
|
|
2088
2103
|
let cmd = `${addCmd} || ${setUrlCmd}`;
|
|
2089
2104
|
if (fetch2) {
|
|
2090
2105
|
const fetchCmd = buildGitCommand(["fetch", name], path2);
|
|
@@ -2529,13 +2544,13 @@ var Git = class {
|
|
|
2529
2544
|
}
|
|
2530
2545
|
async getRemoteUrl(path2, remote, opts) {
|
|
2531
2546
|
const result = await this.runGit(["remote", "get-url", remote], path2, opts);
|
|
2532
|
-
const
|
|
2533
|
-
if (!
|
|
2547
|
+
const url2 = result.stdout.trim();
|
|
2548
|
+
if (!url2) {
|
|
2534
2549
|
throw new InvalidArgumentError(
|
|
2535
2550
|
`Remote "${remote}" URL not found in repository.`
|
|
2536
2551
|
);
|
|
2537
2552
|
}
|
|
2538
|
-
return
|
|
2553
|
+
return url2;
|
|
2539
2554
|
}
|
|
2540
2555
|
async resolveRemoteName(path2, remote, opts) {
|
|
2541
2556
|
if (remote) {
|
|
@@ -3068,6 +3083,26 @@ function getLifecycle(opts) {
|
|
|
3068
3083
|
var _a3;
|
|
3069
3084
|
return (_a3 = opts == null ? void 0 : opts.lifecycle) != null ? _a3 : { onTimeout: "kill", autoResume: false };
|
|
3070
3085
|
}
|
|
3086
|
+
function resolveSandboxTarget(target, opts) {
|
|
3087
|
+
if (typeof target === "string") {
|
|
3088
|
+
return {
|
|
3089
|
+
sandboxId: target,
|
|
3090
|
+
config: ConnectionConfig.forSandbox(opts)
|
|
3091
|
+
};
|
|
3092
|
+
}
|
|
3093
|
+
const referenceRegion = ConnectionConfig.resolveRegion(target.region);
|
|
3094
|
+
if ((opts == null ? void 0 : opts.region) && ConnectionConfig.resolveRegion(opts.region) !== referenceRegion) {
|
|
3095
|
+
throw new Error(
|
|
3096
|
+
`Sandbox ${target.sandboxId} belongs to region "${referenceRegion}", not "${opts.region}"`
|
|
3097
|
+
);
|
|
3098
|
+
}
|
|
3099
|
+
return {
|
|
3100
|
+
sandboxId: target.sandboxId,
|
|
3101
|
+
config: ConnectionConfig.forSandbox(__spreadProps(__spreadValues({}, opts), {
|
|
3102
|
+
region: referenceRegion
|
|
3103
|
+
}))
|
|
3104
|
+
};
|
|
3105
|
+
}
|
|
3071
3106
|
var SandboxApi = class {
|
|
3072
3107
|
constructor() {
|
|
3073
3108
|
}
|
|
@@ -3079,9 +3114,9 @@ var SandboxApi = class {
|
|
|
3079
3114
|
*
|
|
3080
3115
|
* @returns `true` if the sandbox was found and killed, `false` otherwise.
|
|
3081
3116
|
*/
|
|
3082
|
-
static async kill(
|
|
3117
|
+
static async kill(target, opts) {
|
|
3083
3118
|
var _a3;
|
|
3084
|
-
const config =
|
|
3119
|
+
const { sandboxId, config } = resolveSandboxTarget(target, opts);
|
|
3085
3120
|
const client = new ApiClient(config);
|
|
3086
3121
|
const res = await client.api.DELETE("/sandboxes/{sandboxID}", {
|
|
3087
3122
|
params: {
|
|
@@ -3108,8 +3143,8 @@ var SandboxApi = class {
|
|
|
3108
3143
|
*
|
|
3109
3144
|
* @returns sandbox information.
|
|
3110
3145
|
*/
|
|
3111
|
-
static async getInfo(
|
|
3112
|
-
const fullInfo = await this.getFullInfo(
|
|
3146
|
+
static async getInfo(target, opts) {
|
|
3147
|
+
const fullInfo = await this.getFullInfo(target, opts);
|
|
3113
3148
|
delete fullInfo.envdAccessToken;
|
|
3114
3149
|
delete fullInfo.sandboxDomain;
|
|
3115
3150
|
return fullInfo;
|
|
@@ -3122,9 +3157,9 @@ var SandboxApi = class {
|
|
|
3122
3157
|
*
|
|
3123
3158
|
* @returns List of sandbox metrics containing CPU, memory and disk usage information.
|
|
3124
3159
|
*/
|
|
3125
|
-
static async getMetrics(
|
|
3160
|
+
static async getMetrics(target, opts) {
|
|
3126
3161
|
var _a3, _b;
|
|
3127
|
-
const config =
|
|
3162
|
+
const { sandboxId, config } = resolveSandboxTarget(target, opts);
|
|
3128
3163
|
const client = new ApiClient(config);
|
|
3129
3164
|
const start = (opts == null ? void 0 : opts.start) ? opts.start.getTime() : void 0;
|
|
3130
3165
|
const end = (opts == null ? void 0 : opts.end) ? opts.end.getTime() : void 0;
|
|
@@ -3167,9 +3202,9 @@ var SandboxApi = class {
|
|
|
3167
3202
|
* @param timeoutMs timeout in **milliseconds**.
|
|
3168
3203
|
* @param opts connection options.
|
|
3169
3204
|
*/
|
|
3170
|
-
static async setTimeout(
|
|
3205
|
+
static async setTimeout(target, timeoutMs, opts) {
|
|
3171
3206
|
var _a3;
|
|
3172
|
-
const config =
|
|
3207
|
+
const { sandboxId, config } = resolveSandboxTarget(target, opts);
|
|
3173
3208
|
const client = new ApiClient(config);
|
|
3174
3209
|
const res = await client.api.POST("/sandboxes/{sandboxID}/timeout", {
|
|
3175
3210
|
params: {
|
|
@@ -3190,9 +3225,9 @@ var SandboxApi = class {
|
|
|
3190
3225
|
throw err;
|
|
3191
3226
|
}
|
|
3192
3227
|
}
|
|
3193
|
-
static async getFullInfo(
|
|
3228
|
+
static async getFullInfo(target, opts) {
|
|
3194
3229
|
var _a3, _b;
|
|
3195
|
-
const config =
|
|
3230
|
+
const { sandboxId, config } = resolveSandboxTarget(target, opts);
|
|
3196
3231
|
const client = new ApiClient(config);
|
|
3197
3232
|
const res = await client.api.GET("/sandboxes/{sandboxID}", {
|
|
3198
3233
|
params: {
|
|
@@ -3214,6 +3249,7 @@ var SandboxApi = class {
|
|
|
3214
3249
|
}
|
|
3215
3250
|
return __spreadProps(__spreadValues({
|
|
3216
3251
|
sandboxId: res.data.sandboxID,
|
|
3252
|
+
buildId: res.data.buildID,
|
|
3217
3253
|
templateId: res.data.templateID
|
|
3218
3254
|
}, res.data.alias && { name: res.data.alias }), {
|
|
3219
3255
|
metadata: (_b = res.data.metadata) != null ? _b : {},
|
|
@@ -3236,9 +3272,9 @@ var SandboxApi = class {
|
|
|
3236
3272
|
*
|
|
3237
3273
|
* @returns `true` if the sandbox got paused, `false` if the sandbox was already paused.
|
|
3238
3274
|
*/
|
|
3239
|
-
static async pause(
|
|
3275
|
+
static async pause(target, opts) {
|
|
3240
3276
|
var _a3, _b;
|
|
3241
|
-
const config =
|
|
3277
|
+
const { sandboxId, config } = resolveSandboxTarget(target, opts);
|
|
3242
3278
|
const client = new ApiClient(config);
|
|
3243
3279
|
const res = await client.api.POST("/sandboxes/{sandboxID}/pause", {
|
|
3244
3280
|
params: {
|
|
@@ -3272,9 +3308,9 @@ var SandboxApi = class {
|
|
|
3272
3308
|
*
|
|
3273
3309
|
* @returns snapshot information including the snapshot name that can be used with Sandbox.create().
|
|
3274
3310
|
*/
|
|
3275
|
-
static async createSnapshot(
|
|
3311
|
+
static async createSnapshot(target, opts) {
|
|
3276
3312
|
var _a3;
|
|
3277
|
-
const config =
|
|
3313
|
+
const { sandboxId, config } = resolveSandboxTarget(target, opts);
|
|
3278
3314
|
const client = new ApiClient(config);
|
|
3279
3315
|
const res = await client.api.POST("/sandboxes/{sandboxID}/snapshots", {
|
|
3280
3316
|
params: {
|
|
@@ -3393,14 +3429,51 @@ var SandboxApi = class {
|
|
|
3393
3429
|
}
|
|
3394
3430
|
sandbox = res.data;
|
|
3395
3431
|
}
|
|
3432
|
+
return this.sandboxInfoFromCreate(sandbox, config, opts);
|
|
3433
|
+
}
|
|
3434
|
+
static async recoverSandboxCreate(recovery, opts) {
|
|
3435
|
+
if (!recovery.idempotencyKey.trim()) {
|
|
3436
|
+
throw new InvalidArgumentError(
|
|
3437
|
+
"Sandbox create recovery requires an idempotency key"
|
|
3438
|
+
);
|
|
3439
|
+
}
|
|
3440
|
+
const recoveryRegion = recovery.region ? ConnectionConfig.resolveRegion(recovery.region) : void 0;
|
|
3441
|
+
if (recoveryRegion && (opts == null ? void 0 : opts.region) && ConnectionConfig.resolveRegion(opts.region) !== recoveryRegion) {
|
|
3442
|
+
throw new InvalidArgumentError(
|
|
3443
|
+
`Sandbox create recovery belongs to region "${recoveryRegion}", not "${opts.region}"`
|
|
3444
|
+
);
|
|
3445
|
+
}
|
|
3446
|
+
const config = ConnectionConfig.forSandbox(__spreadProps(__spreadValues({}, opts), {
|
|
3447
|
+
region: recoveryRegion != null ? recoveryRegion : opts == null ? void 0 : opts.region
|
|
3448
|
+
}));
|
|
3449
|
+
const signal = config.getSignal(opts == null ? void 0 : opts.requestTimeoutMs);
|
|
3450
|
+
const sandbox = await this.waitForSandboxCreate(
|
|
3451
|
+
new ApiClient(config),
|
|
3452
|
+
__spreadProps(__spreadValues({}, recovery), {
|
|
3453
|
+
region: config.region
|
|
3454
|
+
}),
|
|
3455
|
+
signal
|
|
3456
|
+
);
|
|
3457
|
+
return this.sandboxInfoFromCreate(sandbox, config, opts);
|
|
3458
|
+
}
|
|
3459
|
+
static async sandboxInfoFromCreate(sandbox, config, opts) {
|
|
3396
3460
|
if (compareVersions4(sandbox.envdVersion, "0.1.0") < 0) {
|
|
3397
|
-
await this.kill(
|
|
3461
|
+
await this.kill(
|
|
3462
|
+
{
|
|
3463
|
+
sandboxId: sandbox.sandboxID,
|
|
3464
|
+
region: sandbox.region
|
|
3465
|
+
},
|
|
3466
|
+
__spreadProps(__spreadValues({}, opts), {
|
|
3467
|
+
region: sandbox.region
|
|
3468
|
+
})
|
|
3469
|
+
);
|
|
3398
3470
|
throw new TemplateError(
|
|
3399
3471
|
"You need to update the template to use the new SDK. You can do this by running `enclave template build` in the directory with the template."
|
|
3400
3472
|
);
|
|
3401
3473
|
}
|
|
3402
3474
|
return {
|
|
3403
3475
|
sandboxId: sandbox.sandboxID,
|
|
3476
|
+
buildId: sandbox.buildID,
|
|
3404
3477
|
sandboxDomain: sandbox.domain || void 0,
|
|
3405
3478
|
sandboxRegion: sandbox.region,
|
|
3406
3479
|
capacityTier: sandbox.capacityTier,
|
|
@@ -3414,7 +3487,13 @@ var SandboxApi = class {
|
|
|
3414
3487
|
};
|
|
3415
3488
|
}
|
|
3416
3489
|
static async waitForSandboxCreate(client, recovery, signal) {
|
|
3417
|
-
var _a3, _b;
|
|
3490
|
+
var _a3, _b, _c;
|
|
3491
|
+
let lastRecoveryError;
|
|
3492
|
+
let recoveryRetryDelayMs = 25;
|
|
3493
|
+
const waitToRetryRecovery = async () => {
|
|
3494
|
+
await new Promise((resolve) => setTimeout(resolve, recoveryRetryDelayMs));
|
|
3495
|
+
recoveryRetryDelayMs = Math.min(recoveryRetryDelayMs * 2, 1e3);
|
|
3496
|
+
};
|
|
3418
3497
|
while (!(signal == null ? void 0 : signal.aborted)) {
|
|
3419
3498
|
let res;
|
|
3420
3499
|
try {
|
|
@@ -3430,12 +3509,17 @@ var SandboxApi = class {
|
|
|
3430
3509
|
}
|
|
3431
3510
|
);
|
|
3432
3511
|
} catch (cause) {
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
cause
|
|
3437
|
-
);
|
|
3512
|
+
lastRecoveryError = cause;
|
|
3513
|
+
await waitToRetryRecovery();
|
|
3514
|
+
continue;
|
|
3438
3515
|
}
|
|
3516
|
+
const status = res.response.status;
|
|
3517
|
+
if (status === 404 || status === 408 || status === 425 || status >= 500) {
|
|
3518
|
+
lastRecoveryError = handleApiError(res);
|
|
3519
|
+
await waitToRetryRecovery();
|
|
3520
|
+
continue;
|
|
3521
|
+
}
|
|
3522
|
+
recoveryRetryDelayMs = 25;
|
|
3439
3523
|
const err = handleApiError(res);
|
|
3440
3524
|
if (err) {
|
|
3441
3525
|
throw err;
|
|
@@ -3454,13 +3538,13 @@ var SandboxApi = class {
|
|
|
3454
3538
|
throw new OutcomeUnknownError(
|
|
3455
3539
|
"Sandbox admission committed, but waiting for its terminal result timed out.",
|
|
3456
3540
|
recovery,
|
|
3457
|
-
signal == null ? void 0 : signal.reason
|
|
3541
|
+
(_c = signal == null ? void 0 : signal.reason) != null ? _c : lastRecoveryError
|
|
3458
3542
|
);
|
|
3459
3543
|
}
|
|
3460
|
-
static async connectSandbox(
|
|
3544
|
+
static async connectSandbox(target, opts) {
|
|
3461
3545
|
var _a3, _b;
|
|
3462
3546
|
const timeoutMs = (_a3 = opts == null ? void 0 : opts.timeoutMs) != null ? _a3 : DEFAULT_SANDBOX_TIMEOUT_MS;
|
|
3463
|
-
const config =
|
|
3547
|
+
const { sandboxId, config } = resolveSandboxTarget(target, opts);
|
|
3464
3548
|
const client = new ApiClient(config);
|
|
3465
3549
|
const res = await client.api.POST("/sandboxes/{sandboxID}/connect", {
|
|
3466
3550
|
params: {
|
|
@@ -3482,6 +3566,7 @@ var SandboxApi = class {
|
|
|
3482
3566
|
}
|
|
3483
3567
|
return {
|
|
3484
3568
|
sandboxId: res.data.sandboxID,
|
|
3569
|
+
buildId: res.data.buildID,
|
|
3485
3570
|
sandboxDomain: res.data.domain || void 0,
|
|
3486
3571
|
sandboxRegion: res.data.region,
|
|
3487
3572
|
capacityTier: res.data.capacityTier,
|
|
@@ -3562,6 +3647,7 @@ var SandboxPaginator = class extends BasePaginator {
|
|
|
3562
3647
|
var _a4;
|
|
3563
3648
|
return __spreadProps(__spreadValues({
|
|
3564
3649
|
sandboxId: sandbox.sandboxID,
|
|
3650
|
+
buildId: sandbox.buildID,
|
|
3565
3651
|
templateId: sandbox.templateID
|
|
3566
3652
|
}, sandbox.alias && { name: sandbox.alias }), {
|
|
3567
3653
|
metadata: (_a4 = sandbox.metadata) != null ? _a4 : {},
|
|
@@ -3628,8 +3714,14 @@ var Sandbox = class extends SandboxApi {
|
|
|
3628
3714
|
this.mcpPort = 50005;
|
|
3629
3715
|
this.connectionConfig = ConnectionConfig.forSandbox(opts);
|
|
3630
3716
|
this.sandboxId = opts.sandboxId;
|
|
3717
|
+
this.buildId = opts.buildId;
|
|
3631
3718
|
this.sandboxDomain = (_a3 = opts.sandboxDomain) != null ? _a3 : this.connectionConfig.domain;
|
|
3632
|
-
this.sandboxRegion = opts.sandboxRegion;
|
|
3719
|
+
this.sandboxRegion = this.connectionConfig.debug ? opts.sandboxRegion : ConnectionConfig.resolveRegion(opts.sandboxRegion);
|
|
3720
|
+
if (!this.connectionConfig.debug && this.connectionConfig.region !== this.sandboxRegion) {
|
|
3721
|
+
throw new Error(
|
|
3722
|
+
`Sandbox ${opts.sandboxId} belongs to region "${this.sandboxRegion}", not "${this.connectionConfig.region}"`
|
|
3723
|
+
);
|
|
3724
|
+
}
|
|
3633
3725
|
this.capacityTier = opts.capacityTier;
|
|
3634
3726
|
this.envdAccessToken = opts.envdAccessToken;
|
|
3635
3727
|
this.trafficAccessToken = opts.trafficAccessToken;
|
|
@@ -3646,7 +3738,7 @@ var Sandbox = class extends SandboxApi {
|
|
|
3646
3738
|
baseUrl: this.envdApiUrl,
|
|
3647
3739
|
useBinaryFormat: false,
|
|
3648
3740
|
interceptors: (opts == null ? void 0 : opts.logger) ? [createRpcLogger(opts.logger)] : void 0,
|
|
3649
|
-
fetch: (
|
|
3741
|
+
fetch: (url2, options) => {
|
|
3650
3742
|
const headers = new Headers(this.connectionConfig.headers);
|
|
3651
3743
|
new Headers(options == null ? void 0 : options.headers).forEach(
|
|
3652
3744
|
(value, key) => headers.append(key, value)
|
|
@@ -3661,7 +3753,7 @@ var Sandbox = class extends SandboxApi {
|
|
|
3661
3753
|
headers,
|
|
3662
3754
|
redirect: "follow"
|
|
3663
3755
|
});
|
|
3664
|
-
return fetch(
|
|
3756
|
+
return fetch(url2, options);
|
|
3665
3757
|
}
|
|
3666
3758
|
});
|
|
3667
3759
|
this.envdApi = new EnvdApiClient(
|
|
@@ -3690,6 +3782,33 @@ var Sandbox = class extends SandboxApi {
|
|
|
3690
3782
|
});
|
|
3691
3783
|
this.git = new Git(this.commands);
|
|
3692
3784
|
}
|
|
3785
|
+
/**
|
|
3786
|
+
* Serializable regional reference for reconnecting to this sandbox.
|
|
3787
|
+
*/
|
|
3788
|
+
get ref() {
|
|
3789
|
+
if (this.connectionConfig.debug) {
|
|
3790
|
+
throw new Error("Sandbox references are unavailable in debug mode");
|
|
3791
|
+
}
|
|
3792
|
+
return {
|
|
3793
|
+
sandboxId: this.sandboxId,
|
|
3794
|
+
region: this.sandboxRegion
|
|
3795
|
+
};
|
|
3796
|
+
}
|
|
3797
|
+
connectionOptions(opts) {
|
|
3798
|
+
const ownerRegion = this.connectionConfig.debug ? this.connectionConfig.region : this.sandboxRegion;
|
|
3799
|
+
if (!this.connectionConfig.debug && (opts == null ? void 0 : opts.region) && ConnectionConfig.resolveRegion(opts.region) !== ownerRegion) {
|
|
3800
|
+
throw new Error(
|
|
3801
|
+
`Sandbox ${this.sandboxId} belongs to region "${ownerRegion}", not "${opts.region}"`
|
|
3802
|
+
);
|
|
3803
|
+
}
|
|
3804
|
+
return __spreadProps(__spreadValues(__spreadValues({}, this.connectionConfig), opts), {
|
|
3805
|
+
apiUrl: this.connectionConfig.apiUrl,
|
|
3806
|
+
sandboxUrl: this.connectionConfig.sandboxUrl,
|
|
3807
|
+
domain: this.connectionConfig.domain,
|
|
3808
|
+
debug: this.connectionConfig.debug,
|
|
3809
|
+
region: ownerRegion
|
|
3810
|
+
});
|
|
3811
|
+
}
|
|
3693
3812
|
/**
|
|
3694
3813
|
* List all sandboxes.
|
|
3695
3814
|
*
|
|
@@ -3700,6 +3819,20 @@ var Sandbox = class extends SandboxApi {
|
|
|
3700
3819
|
static list(opts) {
|
|
3701
3820
|
return new SandboxPaginator(opts);
|
|
3702
3821
|
}
|
|
3822
|
+
/**
|
|
3823
|
+
* Create an immutable regional scope so repeated sandbox operations do not
|
|
3824
|
+
* need to repeat the same region option.
|
|
3825
|
+
*
|
|
3826
|
+
* @example
|
|
3827
|
+
* ```ts
|
|
3828
|
+
* const yyz = Sandbox.inRegion("yyz")
|
|
3829
|
+
* const sandbox = await yyz.create()
|
|
3830
|
+
* const sameSandbox = await yyz.connect(sandbox.sandboxId)
|
|
3831
|
+
* ```
|
|
3832
|
+
*/
|
|
3833
|
+
static inRegion(region) {
|
|
3834
|
+
return new SandboxRegionScope(this, region);
|
|
3835
|
+
}
|
|
3703
3836
|
static async create(templateOrOpts, opts) {
|
|
3704
3837
|
var _a3, _b;
|
|
3705
3838
|
const { template, sandboxOpts } = typeof templateOrOpts === "string" ? {
|
|
@@ -3713,6 +3846,7 @@ var Sandbox = class extends SandboxApi {
|
|
|
3713
3846
|
if (config.debug) {
|
|
3714
3847
|
return new this(__spreadValues({
|
|
3715
3848
|
sandboxId: "debug_sandbox_id",
|
|
3849
|
+
buildId: "debug_build_id",
|
|
3716
3850
|
sandboxRegion: "debug",
|
|
3717
3851
|
capacityTier: "shared",
|
|
3718
3852
|
envdVersion: ENVD_DEBUG_FALLBACK
|
|
@@ -3723,7 +3857,9 @@ var Sandbox = class extends SandboxApi {
|
|
|
3723
3857
|
(_a3 = sandboxOpts == null ? void 0 : sandboxOpts.timeoutMs) != null ? _a3 : this.defaultSandboxTimeoutMs,
|
|
3724
3858
|
sandboxOpts
|
|
3725
3859
|
);
|
|
3726
|
-
const sandbox = new this(__spreadValues(__spreadValues({}, config), sandboxInfo)
|
|
3860
|
+
const sandbox = new this(__spreadProps(__spreadValues(__spreadValues({}, config), sandboxInfo), {
|
|
3861
|
+
region: sandboxInfo.sandboxRegion
|
|
3862
|
+
}));
|
|
3727
3863
|
if (sandboxOpts == null ? void 0 : sandboxOpts.mcp) {
|
|
3728
3864
|
sandbox.mcpToken = crypto.randomUUID();
|
|
3729
3865
|
const res = await sandbox.commands.run(
|
|
@@ -3741,6 +3877,51 @@ var Sandbox = class extends SandboxApi {
|
|
|
3741
3877
|
}
|
|
3742
3878
|
return sandbox;
|
|
3743
3879
|
}
|
|
3880
|
+
/**
|
|
3881
|
+
* Recover a create whose authoritative response was lost without resending
|
|
3882
|
+
* the original create payload.
|
|
3883
|
+
*
|
|
3884
|
+
* Pass `OutcomeUnknownError.recovery`. Recovery is pinned to the operation's
|
|
3885
|
+
* owning region and cannot create a second sandbox with different options.
|
|
3886
|
+
*
|
|
3887
|
+
* @example
|
|
3888
|
+
* ```ts
|
|
3889
|
+
* try {
|
|
3890
|
+
* return await Sandbox.create("base", { idempotencyKey: "job-123" })
|
|
3891
|
+
* } catch (error) {
|
|
3892
|
+
* if (error instanceof OutcomeUnknownError) {
|
|
3893
|
+
* return Sandbox.recoverCreate(error.recovery)
|
|
3894
|
+
* }
|
|
3895
|
+
* throw error
|
|
3896
|
+
* }
|
|
3897
|
+
* ```
|
|
3898
|
+
*/
|
|
3899
|
+
static async recoverCreate(recovery, opts) {
|
|
3900
|
+
var _a3;
|
|
3901
|
+
const config = ConnectionConfig.forSandbox(__spreadProps(__spreadValues({}, opts), {
|
|
3902
|
+
region: (_a3 = recovery.region) != null ? _a3 : opts == null ? void 0 : opts.region
|
|
3903
|
+
}));
|
|
3904
|
+
const sandboxInfo = await SandboxApi.recoverSandboxCreate(recovery, opts);
|
|
3905
|
+
const sandbox = new this(__spreadProps(__spreadValues(__spreadValues({}, config), sandboxInfo), {
|
|
3906
|
+
region: sandboxInfo.sandboxRegion
|
|
3907
|
+
}));
|
|
3908
|
+
if (opts == null ? void 0 : opts.mcp) {
|
|
3909
|
+
sandbox.mcpToken = crypto.randomUUID();
|
|
3910
|
+
const res = await sandbox.commands.run(
|
|
3911
|
+
`mcp-gateway --config '${JSON.stringify(opts.mcp)}'`,
|
|
3912
|
+
{
|
|
3913
|
+
user: "root",
|
|
3914
|
+
envs: {
|
|
3915
|
+
GATEWAY_ACCESS_TOKEN: sandbox.mcpToken
|
|
3916
|
+
}
|
|
3917
|
+
}
|
|
3918
|
+
);
|
|
3919
|
+
if (res.exitCode !== 0) {
|
|
3920
|
+
throw new Error(`Failed to start MCP gateway: ${res.stderr}`);
|
|
3921
|
+
}
|
|
3922
|
+
}
|
|
3923
|
+
return sandbox;
|
|
3924
|
+
}
|
|
3744
3925
|
static async betaCreate(templateOrOpts, opts) {
|
|
3745
3926
|
var _a3, _b;
|
|
3746
3927
|
const { template, sandboxOpts } = typeof templateOrOpts === "string" ? {
|
|
@@ -3754,6 +3935,7 @@ var Sandbox = class extends SandboxApi {
|
|
|
3754
3935
|
if (config.debug) {
|
|
3755
3936
|
return new this(__spreadValues({
|
|
3756
3937
|
sandboxId: "debug_sandbox_id",
|
|
3938
|
+
buildId: "debug_build_id",
|
|
3757
3939
|
sandboxRegion: "debug",
|
|
3758
3940
|
capacityTier: "shared",
|
|
3759
3941
|
envdVersion: ENVD_DEBUG_FALLBACK
|
|
@@ -3764,7 +3946,9 @@ var Sandbox = class extends SandboxApi {
|
|
|
3764
3946
|
(_a3 = sandboxOpts == null ? void 0 : sandboxOpts.timeoutMs) != null ? _a3 : this.defaultSandboxTimeoutMs,
|
|
3765
3947
|
sandboxOpts
|
|
3766
3948
|
);
|
|
3767
|
-
const sandbox = new this(__spreadValues(__spreadValues({}, config), sandboxInfo)
|
|
3949
|
+
const sandbox = new this(__spreadProps(__spreadValues(__spreadValues({}, config), sandboxInfo), {
|
|
3950
|
+
region: sandboxInfo.sandboxRegion
|
|
3951
|
+
}));
|
|
3768
3952
|
if (sandboxOpts == null ? void 0 : sandboxOpts.mcp) {
|
|
3769
3953
|
sandbox.mcpToken = crypto.randomUUID();
|
|
3770
3954
|
const res = await sandbox.commands.run(
|
|
@@ -3786,9 +3970,11 @@ var Sandbox = class extends SandboxApi {
|
|
|
3786
3970
|
* Connect to a sandbox. If the sandbox is paused, it will be automatically resumed.
|
|
3787
3971
|
* Sandbox must be either running or be paused.
|
|
3788
3972
|
*
|
|
3789
|
-
*
|
|
3973
|
+
* Persist {@link Sandbox.ref} to reconnect through the sandbox's owning
|
|
3974
|
+
* regional API from another process or environment.
|
|
3790
3975
|
*
|
|
3791
|
-
* @param
|
|
3976
|
+
* @param target sandbox ID, or a serializable reference containing its ID
|
|
3977
|
+
* and owning region.
|
|
3792
3978
|
* @param opts connection options.
|
|
3793
3979
|
*
|
|
3794
3980
|
* @returns A running sandbox instance
|
|
@@ -3802,13 +3988,15 @@ var Sandbox = class extends SandboxApi {
|
|
|
3802
3988
|
* const sameSandbox = await Sandbox.connect(sandboxId)
|
|
3803
3989
|
* ```
|
|
3804
3990
|
*/
|
|
3805
|
-
static async connect(
|
|
3806
|
-
const sandbox = await SandboxApi.connectSandbox(
|
|
3807
|
-
const config = ConnectionConfig.forSandbox(opts);
|
|
3991
|
+
static async connect(target, opts) {
|
|
3992
|
+
const sandbox = await SandboxApi.connectSandbox(target, opts);
|
|
3993
|
+
const config = ConnectionConfig.forSandbox(__spreadValues(__spreadValues({}, opts), typeof target === "string" ? {} : { region: target.region }));
|
|
3808
3994
|
return new this(__spreadProps(__spreadValues({}, config), {
|
|
3809
|
-
sandboxId,
|
|
3995
|
+
sandboxId: sandbox.sandboxId,
|
|
3996
|
+
buildId: sandbox.buildId,
|
|
3810
3997
|
sandboxDomain: sandbox.sandboxDomain,
|
|
3811
3998
|
sandboxRegion: sandbox.sandboxRegion,
|
|
3999
|
+
region: sandbox.sandboxRegion,
|
|
3812
4000
|
capacityTier: sandbox.capacityTier,
|
|
3813
4001
|
apiUrl: sandbox.apiUrl,
|
|
3814
4002
|
envdAccessToken: sandbox.envdAccessToken,
|
|
@@ -3836,7 +4024,10 @@ var Sandbox = class extends SandboxApi {
|
|
|
3836
4024
|
* ```
|
|
3837
4025
|
*/
|
|
3838
4026
|
async connect(opts) {
|
|
3839
|
-
await SandboxApi.connectSandbox(
|
|
4027
|
+
await SandboxApi.connectSandbox(
|
|
4028
|
+
this.sandboxId,
|
|
4029
|
+
this.connectionOptions(opts)
|
|
4030
|
+
);
|
|
3840
4031
|
return this;
|
|
3841
4032
|
}
|
|
3842
4033
|
/**
|
|
@@ -3905,7 +4096,11 @@ var Sandbox = class extends SandboxApi {
|
|
|
3905
4096
|
if (this.connectionConfig.debug) {
|
|
3906
4097
|
return;
|
|
3907
4098
|
}
|
|
3908
|
-
await SandboxApi.setTimeout(
|
|
4099
|
+
await SandboxApi.setTimeout(
|
|
4100
|
+
this.sandboxId,
|
|
4101
|
+
timeoutMs,
|
|
4102
|
+
this.connectionOptions(opts)
|
|
4103
|
+
);
|
|
3909
4104
|
}
|
|
3910
4105
|
/**
|
|
3911
4106
|
* Kill the sandbox.
|
|
@@ -3916,7 +4111,7 @@ var Sandbox = class extends SandboxApi {
|
|
|
3916
4111
|
if (this.connectionConfig.debug) {
|
|
3917
4112
|
return;
|
|
3918
4113
|
}
|
|
3919
|
-
await SandboxApi.kill(this.sandboxId,
|
|
4114
|
+
await SandboxApi.kill(this.sandboxId, this.connectionOptions(opts));
|
|
3920
4115
|
}
|
|
3921
4116
|
/**
|
|
3922
4117
|
* Pause a sandbox by its ID.
|
|
@@ -3932,7 +4127,7 @@ var Sandbox = class extends SandboxApi {
|
|
|
3932
4127
|
* ```
|
|
3933
4128
|
*/
|
|
3934
4129
|
async pause(opts) {
|
|
3935
|
-
return await SandboxApi.pause(this.sandboxId,
|
|
4130
|
+
return await SandboxApi.pause(this.sandboxId, this.connectionOptions(opts));
|
|
3936
4131
|
}
|
|
3937
4132
|
/**
|
|
3938
4133
|
* Create a snapshot of the sandbox's current state.
|
|
@@ -3960,7 +4155,10 @@ var Sandbox = class extends SandboxApi {
|
|
|
3960
4155
|
* ```
|
|
3961
4156
|
*/
|
|
3962
4157
|
async createSnapshot(opts) {
|
|
3963
|
-
return await SandboxApi.createSnapshot(
|
|
4158
|
+
return await SandboxApi.createSnapshot(
|
|
4159
|
+
this.sandboxId,
|
|
4160
|
+
this.connectionOptions(opts)
|
|
4161
|
+
);
|
|
3964
4162
|
}
|
|
3965
4163
|
/**
|
|
3966
4164
|
* List all snapshots created from this sandbox.
|
|
@@ -3970,7 +4168,7 @@ var Sandbox = class extends SandboxApi {
|
|
|
3970
4168
|
* @returns paginator for listing snapshots from this sandbox.
|
|
3971
4169
|
*/
|
|
3972
4170
|
listSnapshots(opts) {
|
|
3973
|
-
return SandboxApi.listSnapshots(__spreadProps(__spreadValues(
|
|
4171
|
+
return SandboxApi.listSnapshots(__spreadProps(__spreadValues({}, this.connectionOptions(opts)), {
|
|
3974
4172
|
sandboxId: this.sandboxId
|
|
3975
4173
|
}));
|
|
3976
4174
|
}
|
|
@@ -4022,7 +4220,7 @@ var Sandbox = class extends SandboxApi {
|
|
|
4022
4220
|
const filePath = path2 != null ? path2 : "";
|
|
4023
4221
|
const fileUrl = this.fileUrl(filePath, username);
|
|
4024
4222
|
if (useSignature) {
|
|
4025
|
-
const
|
|
4223
|
+
const url2 = new URL(fileUrl);
|
|
4026
4224
|
const sig = await getSignature({
|
|
4027
4225
|
path: filePath,
|
|
4028
4226
|
operation: "write",
|
|
@@ -4030,11 +4228,11 @@ var Sandbox = class extends SandboxApi {
|
|
|
4030
4228
|
expirationInSeconds: opts.useSignatureExpiration,
|
|
4031
4229
|
envdAccessToken: this.envdAccessToken
|
|
4032
4230
|
});
|
|
4033
|
-
|
|
4231
|
+
url2.searchParams.set("signature", sig.signature);
|
|
4034
4232
|
if (sig.expiration) {
|
|
4035
|
-
|
|
4233
|
+
url2.searchParams.set("signature_expiration", sig.expiration.toString());
|
|
4036
4234
|
}
|
|
4037
|
-
return
|
|
4235
|
+
return url2.toString();
|
|
4038
4236
|
}
|
|
4039
4237
|
return fileUrl;
|
|
4040
4238
|
}
|
|
@@ -4061,7 +4259,7 @@ var Sandbox = class extends SandboxApi {
|
|
|
4061
4259
|
}
|
|
4062
4260
|
const fileUrl = this.fileUrl(path2, username);
|
|
4063
4261
|
if (useSignature) {
|
|
4064
|
-
const
|
|
4262
|
+
const url2 = new URL(fileUrl);
|
|
4065
4263
|
const sig = await getSignature({
|
|
4066
4264
|
path: path2,
|
|
4067
4265
|
operation: "read",
|
|
@@ -4069,11 +4267,11 @@ var Sandbox = class extends SandboxApi {
|
|
|
4069
4267
|
expirationInSeconds: opts.useSignatureExpiration,
|
|
4070
4268
|
envdAccessToken: this.envdAccessToken
|
|
4071
4269
|
});
|
|
4072
|
-
|
|
4270
|
+
url2.searchParams.set("signature", sig.signature);
|
|
4073
4271
|
if (sig.expiration) {
|
|
4074
|
-
|
|
4272
|
+
url2.searchParams.set("signature_expiration", sig.expiration.toString());
|
|
4075
4273
|
}
|
|
4076
|
-
return
|
|
4274
|
+
return url2.toString();
|
|
4077
4275
|
}
|
|
4078
4276
|
return fileUrl;
|
|
4079
4277
|
}
|
|
@@ -4085,7 +4283,10 @@ var Sandbox = class extends SandboxApi {
|
|
|
4085
4283
|
* @returns information about the sandbox
|
|
4086
4284
|
*/
|
|
4087
4285
|
async getInfo(opts) {
|
|
4088
|
-
return await SandboxApi.getInfo(
|
|
4286
|
+
return await SandboxApi.getInfo(
|
|
4287
|
+
this.sandboxId,
|
|
4288
|
+
this.connectionOptions(opts)
|
|
4289
|
+
);
|
|
4089
4290
|
}
|
|
4090
4291
|
/**
|
|
4091
4292
|
* Get the metrics of the sandbox.
|
|
@@ -4109,7 +4310,10 @@ var Sandbox = class extends SandboxApi {
|
|
|
4109
4310
|
);
|
|
4110
4311
|
}
|
|
4111
4312
|
}
|
|
4112
|
-
return await SandboxApi.getMetrics(
|
|
4313
|
+
return await SandboxApi.getMetrics(
|
|
4314
|
+
this.sandboxId,
|
|
4315
|
+
this.connectionOptions(opts)
|
|
4316
|
+
);
|
|
4113
4317
|
}
|
|
4114
4318
|
fileUrl(path2, username) {
|
|
4115
4319
|
const externalUrl = this.connectionConfig.getSandboxExternalUrl(
|
|
@@ -4120,19 +4324,109 @@ var Sandbox = class extends SandboxApi {
|
|
|
4120
4324
|
port: this.envdPort
|
|
4121
4325
|
}
|
|
4122
4326
|
);
|
|
4123
|
-
const
|
|
4327
|
+
const url2 = new URL("/files", externalUrl);
|
|
4124
4328
|
if (username) {
|
|
4125
|
-
|
|
4329
|
+
url2.searchParams.set("username", username);
|
|
4126
4330
|
}
|
|
4127
4331
|
if (path2) {
|
|
4128
|
-
|
|
4332
|
+
url2.searchParams.set("path", path2);
|
|
4129
4333
|
}
|
|
4130
|
-
return
|
|
4334
|
+
return url2.toString();
|
|
4131
4335
|
}
|
|
4132
4336
|
};
|
|
4133
4337
|
Sandbox.defaultTemplate = "base";
|
|
4134
4338
|
Sandbox.defaultMcpTemplate = "mcp-gateway";
|
|
4135
4339
|
Sandbox.defaultSandboxTimeoutMs = DEFAULT_SANDBOX_TIMEOUT_MS;
|
|
4340
|
+
var SandboxRegionScope = class {
|
|
4341
|
+
constructor(sandboxClass, region) {
|
|
4342
|
+
this.sandboxClass = sandboxClass;
|
|
4343
|
+
this.selectedRegion = ConnectionConfig.resolveRegion(region);
|
|
4344
|
+
}
|
|
4345
|
+
get region() {
|
|
4346
|
+
return this.selectedRegion;
|
|
4347
|
+
}
|
|
4348
|
+
options(opts) {
|
|
4349
|
+
const requestedRegion = opts == null ? void 0 : opts.region;
|
|
4350
|
+
if (requestedRegion && ConnectionConfig.resolveRegion(requestedRegion) !== this.region) {
|
|
4351
|
+
throw new Error(
|
|
4352
|
+
`Regional sandbox scope is pinned to "${this.region}", not "${requestedRegion}"`
|
|
4353
|
+
);
|
|
4354
|
+
}
|
|
4355
|
+
return __spreadProps(__spreadValues({}, opts), {
|
|
4356
|
+
region: this.region
|
|
4357
|
+
});
|
|
4358
|
+
}
|
|
4359
|
+
list(opts) {
|
|
4360
|
+
return this.sandboxClass.list(this.options(opts));
|
|
4361
|
+
}
|
|
4362
|
+
async create(templateOrOpts, opts) {
|
|
4363
|
+
if (typeof templateOrOpts === "string") {
|
|
4364
|
+
return this.sandboxClass.create(
|
|
4365
|
+
templateOrOpts,
|
|
4366
|
+
this.options(opts)
|
|
4367
|
+
);
|
|
4368
|
+
}
|
|
4369
|
+
return this.sandboxClass.create(this.options(templateOrOpts));
|
|
4370
|
+
}
|
|
4371
|
+
recoverCreate(recovery, opts) {
|
|
4372
|
+
if (recovery.region && ConnectionConfig.resolveRegion(recovery.region) !== this.region) {
|
|
4373
|
+
throw new Error(
|
|
4374
|
+
`Sandbox create recovery belongs to region "${recovery.region}", not "${this.region}"`
|
|
4375
|
+
);
|
|
4376
|
+
}
|
|
4377
|
+
return this.sandboxClass.recoverCreate(
|
|
4378
|
+
__spreadProps(__spreadValues({}, recovery), {
|
|
4379
|
+
region: this.region
|
|
4380
|
+
}),
|
|
4381
|
+
this.options(opts)
|
|
4382
|
+
);
|
|
4383
|
+
}
|
|
4384
|
+
async betaCreate(templateOrOpts, opts) {
|
|
4385
|
+
if (typeof templateOrOpts === "string") {
|
|
4386
|
+
return this.sandboxClass.betaCreate(
|
|
4387
|
+
templateOrOpts,
|
|
4388
|
+
this.options(opts)
|
|
4389
|
+
);
|
|
4390
|
+
}
|
|
4391
|
+
return this.sandboxClass.betaCreate(
|
|
4392
|
+
this.options(templateOrOpts)
|
|
4393
|
+
);
|
|
4394
|
+
}
|
|
4395
|
+
connect(target, opts) {
|
|
4396
|
+
return this.sandboxClass.connect(target, this.options(opts));
|
|
4397
|
+
}
|
|
4398
|
+
kill(target, opts) {
|
|
4399
|
+
return this.sandboxClass.kill(target, this.options(opts));
|
|
4400
|
+
}
|
|
4401
|
+
getInfo(target, opts) {
|
|
4402
|
+
return this.sandboxClass.getInfo(target, this.options(opts));
|
|
4403
|
+
}
|
|
4404
|
+
getFullInfo(target, opts) {
|
|
4405
|
+
return this.sandboxClass.getFullInfo(target, this.options(opts));
|
|
4406
|
+
}
|
|
4407
|
+
getMetrics(target, opts) {
|
|
4408
|
+
return this.sandboxClass.getMetrics(target, this.options(opts));
|
|
4409
|
+
}
|
|
4410
|
+
setTimeout(target, timeoutMs, opts) {
|
|
4411
|
+
return this.sandboxClass.setTimeout(target, timeoutMs, this.options(opts));
|
|
4412
|
+
}
|
|
4413
|
+
pause(target, opts) {
|
|
4414
|
+
return this.sandboxClass.pause(target, this.options(opts));
|
|
4415
|
+
}
|
|
4416
|
+
createSnapshot(target, opts) {
|
|
4417
|
+
return this.sandboxClass.createSnapshot(target, this.options(opts));
|
|
4418
|
+
}
|
|
4419
|
+
listSnapshots(opts) {
|
|
4420
|
+
return this.sandboxClass.listSnapshots(this.options(opts));
|
|
4421
|
+
}
|
|
4422
|
+
deleteSnapshot(snapshotId, opts) {
|
|
4423
|
+
return this.sandboxClass.deleteSnapshot(snapshotId, this.options(opts));
|
|
4424
|
+
}
|
|
4425
|
+
};
|
|
4426
|
+
|
|
4427
|
+
// src/template/buildApi.ts
|
|
4428
|
+
import fs2 from "fs";
|
|
4429
|
+
import stream from "stream";
|
|
4136
4430
|
|
|
4137
4431
|
// src/template/logger.ts
|
|
4138
4432
|
import chalk from "chalk";
|
|
@@ -4255,11 +4549,13 @@ function defaultBuildLogger(options) {
|
|
|
4255
4549
|
// src/template/utils.ts
|
|
4256
4550
|
import crypto2 from "crypto";
|
|
4257
4551
|
import fs from "fs";
|
|
4552
|
+
import os from "os";
|
|
4258
4553
|
import path from "path";
|
|
4259
|
-
import
|
|
4554
|
+
import url from "url";
|
|
4260
4555
|
|
|
4261
4556
|
// src/template/consts.ts
|
|
4262
4557
|
var FINALIZE_STEP_NAME = "finalize";
|
|
4558
|
+
var FILE_UPLOAD_TIMEOUT_MS = 36e5;
|
|
4263
4559
|
var BASE_STEP_NAME = "base";
|
|
4264
4560
|
var STACK_TRACE_DEPTH = 3;
|
|
4265
4561
|
var RESOLVE_SYMLINKS = false;
|
|
@@ -4404,14 +4700,14 @@ function getCallerDirectory(depth) {
|
|
|
4404
4700
|
return void 0;
|
|
4405
4701
|
}
|
|
4406
4702
|
if (fileName.startsWith("file:")) {
|
|
4407
|
-
fileName = fileURLToPath(fileName);
|
|
4703
|
+
fileName = url.fileURLToPath(fileName);
|
|
4408
4704
|
}
|
|
4409
4705
|
return path.dirname(fileName);
|
|
4410
4706
|
}
|
|
4411
4707
|
function padOctal(mode) {
|
|
4412
4708
|
return mode.toString(8).padStart(4, "0");
|
|
4413
4709
|
}
|
|
4414
|
-
async function
|
|
4710
|
+
async function getTarArchiveInputs(fileName, fileContextPath, ignorePatterns) {
|
|
4415
4711
|
const { create } = await dynamicImport("tar");
|
|
4416
4712
|
const allFiles = await getAllFilesInPath(
|
|
4417
4713
|
fileName,
|
|
@@ -4419,24 +4715,40 @@ async function tarFileStream(fileName, fileContextPath, ignorePatterns, resolveS
|
|
|
4419
4715
|
ignorePatterns,
|
|
4420
4716
|
true
|
|
4421
4717
|
);
|
|
4422
|
-
|
|
4423
|
-
|
|
4424
|
-
|
|
4425
|
-
|
|
4426
|
-
cwd: fileContextPath,
|
|
4427
|
-
follow: resolveSymlinks,
|
|
4428
|
-
noDirRecurse: true
|
|
4429
|
-
},
|
|
4430
|
-
filePaths
|
|
4431
|
-
);
|
|
4718
|
+
return {
|
|
4719
|
+
create,
|
|
4720
|
+
filePaths: allFiles.map((file) => file.relativePosix())
|
|
4721
|
+
};
|
|
4432
4722
|
}
|
|
4433
|
-
async function
|
|
4434
|
-
|
|
4723
|
+
async function spoolTarArchive(fileName, fileContextPath, ignorePatterns, resolveSymlinks) {
|
|
4724
|
+
const { create, filePaths } = await getTarArchiveInputs(
|
|
4435
4725
|
fileName,
|
|
4436
4726
|
fileContextPath,
|
|
4437
|
-
ignorePatterns
|
|
4438
|
-
|
|
4727
|
+
ignorePatterns
|
|
4728
|
+
);
|
|
4729
|
+
const tmpDir = await fs.promises.mkdtemp(
|
|
4730
|
+
path.join(os.tmpdir(), "enclave-template-")
|
|
4439
4731
|
);
|
|
4732
|
+
const tarPath = path.join(tmpDir, "context.tar.gz");
|
|
4733
|
+
const cleanup = () => fs.promises.rm(tmpDir, { recursive: true, force: true }).catch(() => {
|
|
4734
|
+
});
|
|
4735
|
+
try {
|
|
4736
|
+
await create(
|
|
4737
|
+
{
|
|
4738
|
+
gzip: true,
|
|
4739
|
+
cwd: fileContextPath,
|
|
4740
|
+
follow: resolveSymlinks,
|
|
4741
|
+
noDirRecurse: true,
|
|
4742
|
+
file: tarPath
|
|
4743
|
+
},
|
|
4744
|
+
filePaths
|
|
4745
|
+
);
|
|
4746
|
+
const { size } = await fs.promises.stat(tarPath);
|
|
4747
|
+
return { path: tarPath, size, cleanup };
|
|
4748
|
+
} catch (error) {
|
|
4749
|
+
await cleanup();
|
|
4750
|
+
throw error;
|
|
4751
|
+
}
|
|
4440
4752
|
}
|
|
4441
4753
|
function getBuildStepIndex(step, stackTracesLength) {
|
|
4442
4754
|
if (step === BASE_STEP_NAME) {
|
|
@@ -4495,23 +4807,35 @@ async function getFileUploadLink(client, { templateID, filesHash }, stackTrace)
|
|
|
4495
4807
|
return fileUploadLinkRes.data;
|
|
4496
4808
|
}
|
|
4497
4809
|
async function uploadFile(options, stackTrace) {
|
|
4498
|
-
const { fileName, url, fileContextPath, ignorePatterns, resolveSymlinks } = options;
|
|
4810
|
+
const { fileName, url: url2, fileContextPath, ignorePatterns, resolveSymlinks } = options;
|
|
4811
|
+
let cleanup;
|
|
4812
|
+
let bodyStream;
|
|
4499
4813
|
try {
|
|
4500
|
-
const
|
|
4814
|
+
const archive = await spoolTarArchive(
|
|
4501
4815
|
fileName,
|
|
4502
4816
|
fileContextPath,
|
|
4503
4817
|
ignorePatterns,
|
|
4504
4818
|
resolveSymlinks
|
|
4505
4819
|
);
|
|
4506
|
-
|
|
4820
|
+
cleanup = archive.cleanup;
|
|
4821
|
+
bodyStream = fs2.createReadStream(archive.path);
|
|
4822
|
+
const res = await fetch(url2, {
|
|
4507
4823
|
method: "PUT",
|
|
4508
|
-
|
|
4509
|
-
|
|
4824
|
+
body: stream.Readable.toWeb(bodyStream),
|
|
4825
|
+
headers: {
|
|
4826
|
+
"Content-Length": archive.size.toString()
|
|
4827
|
+
},
|
|
4828
|
+
signal: AbortSignal.timeout(FILE_UPLOAD_TIMEOUT_MS),
|
|
4829
|
+
// Node fetch requires duplex for a streaming request body, but the DOM
|
|
4830
|
+
// RequestInit type does not expose it.
|
|
4831
|
+
// @ts-expect-error Node fetch extension
|
|
4510
4832
|
duplex: "half"
|
|
4511
4833
|
});
|
|
4512
4834
|
if (!res.ok) {
|
|
4835
|
+
const responseDetails = (await res.text().catch(() => "")).slice(0, 4096);
|
|
4836
|
+
const status = `${res.status} ${res.statusText}`.trim();
|
|
4513
4837
|
throw new FileUploadError(
|
|
4514
|
-
`Failed to upload file: ${
|
|
4838
|
+
`Failed to upload file: ${status}${responseDetails ? ` - ${responseDetails}` : ""}`,
|
|
4515
4839
|
stackTrace
|
|
4516
4840
|
);
|
|
4517
4841
|
}
|
|
@@ -4520,6 +4844,14 @@ async function uploadFile(options, stackTrace) {
|
|
|
4520
4844
|
throw error;
|
|
4521
4845
|
}
|
|
4522
4846
|
throw new FileUploadError(`Failed to upload file: ${error}`, stackTrace);
|
|
4847
|
+
} finally {
|
|
4848
|
+
if (bodyStream && !bodyStream.closed) {
|
|
4849
|
+
await new Promise((resolve) => {
|
|
4850
|
+
bodyStream == null ? void 0 : bodyStream.once("close", resolve);
|
|
4851
|
+
bodyStream == null ? void 0 : bodyStream.destroy();
|
|
4852
|
+
});
|
|
4853
|
+
}
|
|
4854
|
+
await (cleanup == null ? void 0 : cleanup());
|
|
4523
4855
|
}
|
|
4524
4856
|
}
|
|
4525
4857
|
async function triggerBuild(client, { templateID, buildID, template }) {
|
|
@@ -4708,7 +5040,7 @@ async function getTemplateTags(client, { templateID }) {
|
|
|
4708
5040
|
import {
|
|
4709
5041
|
DockerfileParser
|
|
4710
5042
|
} from "dockerfile-ast";
|
|
4711
|
-
import
|
|
5043
|
+
import fs3 from "fs";
|
|
4712
5044
|
|
|
4713
5045
|
// src/template/readycmd.ts
|
|
4714
5046
|
var ReadyCmd = class {
|
|
@@ -4723,8 +5055,8 @@ function waitForPort(port) {
|
|
|
4723
5055
|
const cmd = `ss -tuln | grep :${port}`;
|
|
4724
5056
|
return new ReadyCmd(cmd);
|
|
4725
5057
|
}
|
|
4726
|
-
function waitForURL(
|
|
4727
|
-
const cmd = `curl -s -o /dev/null -w "%{http_code}" ${
|
|
5058
|
+
function waitForURL(url2, statusCode = 200) {
|
|
5059
|
+
const cmd = `curl -s -o /dev/null -w "%{http_code}" ${url2} | grep -q "${statusCode}"`;
|
|
4728
5060
|
return new ReadyCmd(cmd);
|
|
4729
5061
|
}
|
|
4730
5062
|
function waitForProcess(processName) {
|
|
@@ -4745,8 +5077,8 @@ function waitForTimeout(timeout) {
|
|
|
4745
5077
|
function parseDockerfile(dockerfileContentOrPath, templateBuilder) {
|
|
4746
5078
|
let dockerfileContent;
|
|
4747
5079
|
try {
|
|
4748
|
-
if (
|
|
4749
|
-
dockerfileContent =
|
|
5080
|
+
if (fs3.existsSync(dockerfileContentOrPath) && fs3.statSync(dockerfileContentOrPath).isFile()) {
|
|
5081
|
+
dockerfileContent = fs3.readFileSync(dockerfileContentOrPath, "utf-8");
|
|
4750
5082
|
} else {
|
|
4751
5083
|
dockerfileContent = dockerfileContentOrPath;
|
|
4752
5084
|
}
|
|
@@ -4929,6 +5261,7 @@ function handleCmdEntrypointInstruction(instruction, templateBuilder) {
|
|
|
4929
5261
|
// src/template/activationApi.ts
|
|
4930
5262
|
async function activateTemplate(build, options = {}) {
|
|
4931
5263
|
assertBuildIdentity(build);
|
|
5264
|
+
assertExpectedVersion(options.expectedVersion);
|
|
4932
5265
|
const region = resolveRegion(options.region);
|
|
4933
5266
|
const config = ConnectionConfig.forGlobal(options);
|
|
4934
5267
|
const client = new ApiClient(config);
|
|
@@ -4945,7 +5278,8 @@ async function activateTemplate(build, options = {}) {
|
|
|
4945
5278
|
buildID: build.buildId,
|
|
4946
5279
|
active: true,
|
|
4947
5280
|
requiredReadyNodes: options.requiredReadyNodes,
|
|
4948
|
-
allowRemoteFallback: options.allowRemoteFallback
|
|
5281
|
+
allowRemoteFallback: options.allowRemoteFallback,
|
|
5282
|
+
expectedVersion: options.expectedVersion
|
|
4949
5283
|
},
|
|
4950
5284
|
signal: config.getSignal(options.requestTimeoutMs)
|
|
4951
5285
|
}
|
|
@@ -4954,6 +5288,7 @@ async function activateTemplate(build, options = {}) {
|
|
|
4954
5288
|
}
|
|
4955
5289
|
async function deactivateTemplate(build, options = {}) {
|
|
4956
5290
|
assertBuildIdentity(build);
|
|
5291
|
+
assertExpectedVersion(options.expectedVersion);
|
|
4957
5292
|
const region = resolveRegion(options.region);
|
|
4958
5293
|
const config = ConnectionConfig.forGlobal(options);
|
|
4959
5294
|
const client = new ApiClient(config);
|
|
@@ -4968,7 +5303,8 @@ async function deactivateTemplate(build, options = {}) {
|
|
|
4968
5303
|
},
|
|
4969
5304
|
body: {
|
|
4970
5305
|
buildID: build.buildId,
|
|
4971
|
-
active: false
|
|
5306
|
+
active: false,
|
|
5307
|
+
expectedVersion: options.expectedVersion
|
|
4972
5308
|
},
|
|
4973
5309
|
signal: config.getSignal(options.requestTimeoutMs)
|
|
4974
5310
|
}
|
|
@@ -4979,6 +5315,9 @@ async function getTemplateActivation(templateId, options = {}) {
|
|
|
4979
5315
|
if (!templateId.trim()) {
|
|
4980
5316
|
throw new InvalidArgumentError("templateId is required");
|
|
4981
5317
|
}
|
|
5318
|
+
if (options.buildId !== void 0 && !options.buildId.trim()) {
|
|
5319
|
+
throw new InvalidArgumentError("buildId must not be empty");
|
|
5320
|
+
}
|
|
4982
5321
|
const region = resolveRegion(options.region);
|
|
4983
5322
|
const config = ConnectionConfig.forSandbox(__spreadProps(__spreadValues({}, options), { region }));
|
|
4984
5323
|
const client = new ApiClient(config);
|
|
@@ -4989,6 +5328,9 @@ async function getTemplateActivation(templateId, options = {}) {
|
|
|
4989
5328
|
path: {
|
|
4990
5329
|
templateID: templateId,
|
|
4991
5330
|
region
|
|
5331
|
+
},
|
|
5332
|
+
query: {
|
|
5333
|
+
buildID: options.buildId
|
|
4992
5334
|
}
|
|
4993
5335
|
},
|
|
4994
5336
|
signal: config.getSignal(options.requestTimeoutMs)
|
|
@@ -5004,6 +5346,100 @@ function assertBuildIdentity(build) {
|
|
|
5004
5346
|
function resolveRegion(region) {
|
|
5005
5347
|
return ConnectionConfig.resolveRegion(region);
|
|
5006
5348
|
}
|
|
5349
|
+
function assertExpectedVersion(expectedVersion) {
|
|
5350
|
+
if (expectedVersion !== void 0 && (!Number.isSafeInteger(expectedVersion) || expectedVersion < 0)) {
|
|
5351
|
+
throw new InvalidArgumentError(
|
|
5352
|
+
"expectedVersion must be a non-negative safe integer"
|
|
5353
|
+
);
|
|
5354
|
+
}
|
|
5355
|
+
}
|
|
5356
|
+
|
|
5357
|
+
// src/template/tagHeadApi.ts
|
|
5358
|
+
async function getTemplateTagHead(client, templateId, tag, signal) {
|
|
5359
|
+
assertTemplateAndTag(templateId, tag);
|
|
5360
|
+
const response = await client.api.GET("/templates/{templateID}/tags/{tag}", {
|
|
5361
|
+
params: {
|
|
5362
|
+
path: {
|
|
5363
|
+
templateID: templateId,
|
|
5364
|
+
tag
|
|
5365
|
+
}
|
|
5366
|
+
},
|
|
5367
|
+
signal
|
|
5368
|
+
});
|
|
5369
|
+
const error = handleApiError(response, TemplateError);
|
|
5370
|
+
if (error) {
|
|
5371
|
+
throw error;
|
|
5372
|
+
}
|
|
5373
|
+
if (!response.data) {
|
|
5374
|
+
throw new TemplateError("Enclave API returned no template tag head");
|
|
5375
|
+
}
|
|
5376
|
+
return mapTagHead(response.data);
|
|
5377
|
+
}
|
|
5378
|
+
async function promoteTemplateTag(client, candidate, tag, expected, signal) {
|
|
5379
|
+
var _a3, _b, _c, _d, _e, _f;
|
|
5380
|
+
assertBuildIdentity2(candidate);
|
|
5381
|
+
assertTemplateAndTag(candidate.templateId, tag);
|
|
5382
|
+
assertExpectation(expected);
|
|
5383
|
+
const response = await client.api.PUT("/templates/{templateID}/tags/{tag}", {
|
|
5384
|
+
params: {
|
|
5385
|
+
path: {
|
|
5386
|
+
templateID: candidate.templateId,
|
|
5387
|
+
tag
|
|
5388
|
+
}
|
|
5389
|
+
},
|
|
5390
|
+
body: {
|
|
5391
|
+
buildID: candidate.buildId,
|
|
5392
|
+
expectedBuildID: expected == null ? void 0 : expected.buildId,
|
|
5393
|
+
expectedVersion: (_a3 = expected == null ? void 0 : expected.version) != null ? _a3 : 0
|
|
5394
|
+
},
|
|
5395
|
+
signal
|
|
5396
|
+
});
|
|
5397
|
+
if (response.response.status === 409 && (((_b = response.error) == null ? void 0 : _b.code) === "tag_changed" || ((_c = response.error) == null ? void 0 : _c.code) === "concurrent_mutation")) {
|
|
5398
|
+
const message = (_e = (_d = response.error) == null ? void 0 : _d.message) != null ? _e : "The template tag changed after it was read";
|
|
5399
|
+
throw new TemplateTagConflictError({
|
|
5400
|
+
templateId: candidate.templateId,
|
|
5401
|
+
tag,
|
|
5402
|
+
candidateBuildId: candidate.buildId,
|
|
5403
|
+
expectedBuildId: expected == null ? void 0 : expected.buildId,
|
|
5404
|
+
expectedVersion: (_f = expected == null ? void 0 : expected.version) != null ? _f : 0,
|
|
5405
|
+
reason: response.error.code,
|
|
5406
|
+
message: `409: ${message}. Fetch its current head with Template.getTagHead() before retrying.`
|
|
5407
|
+
});
|
|
5408
|
+
}
|
|
5409
|
+
const error = handleApiError(response, TemplateError);
|
|
5410
|
+
if (error) {
|
|
5411
|
+
throw error;
|
|
5412
|
+
}
|
|
5413
|
+
if (!response.data) {
|
|
5414
|
+
throw new TemplateError("Enclave API returned no promoted template tag");
|
|
5415
|
+
}
|
|
5416
|
+
return mapTagHead(response.data);
|
|
5417
|
+
}
|
|
5418
|
+
function mapTagHead(head) {
|
|
5419
|
+
return {
|
|
5420
|
+
tag: head.tag,
|
|
5421
|
+
buildId: head.buildID,
|
|
5422
|
+
version: head.version,
|
|
5423
|
+
createdAt: new Date(head.createdAt)
|
|
5424
|
+
};
|
|
5425
|
+
}
|
|
5426
|
+
function assertTemplateAndTag(templateId, tag) {
|
|
5427
|
+
if (!templateId.trim() || !tag.trim()) {
|
|
5428
|
+
throw new InvalidArgumentError("templateId and tag are required");
|
|
5429
|
+
}
|
|
5430
|
+
}
|
|
5431
|
+
function assertBuildIdentity2(candidate) {
|
|
5432
|
+
if (!candidate.templateId.trim() || !candidate.buildId.trim()) {
|
|
5433
|
+
throw new InvalidArgumentError("templateId and buildId are required");
|
|
5434
|
+
}
|
|
5435
|
+
}
|
|
5436
|
+
function assertExpectation(expected) {
|
|
5437
|
+
if (expected !== null && (!expected.buildId.trim() || !Number.isSafeInteger(expected.version) || expected.version < 1)) {
|
|
5438
|
+
throw new InvalidArgumentError(
|
|
5439
|
+
"expected tag head must include a buildId and a positive safe-integer version"
|
|
5440
|
+
);
|
|
5441
|
+
}
|
|
5442
|
+
}
|
|
5007
5443
|
|
|
5008
5444
|
// src/template/index.ts
|
|
5009
5445
|
var _a2;
|
|
@@ -5255,6 +5691,42 @@ var TemplateBase = class {
|
|
|
5255
5691
|
const client = new ApiClient(config);
|
|
5256
5692
|
return getTemplateTags(client, { templateID: templateId });
|
|
5257
5693
|
}
|
|
5694
|
+
/**
|
|
5695
|
+
* Get the authoritative traffic-selection token for one template tag.
|
|
5696
|
+
*
|
|
5697
|
+
* Pass the returned head directly to {@link promoteTag}; its monotonic
|
|
5698
|
+
* version prevents concurrent releasers from silently overwriting each
|
|
5699
|
+
* other.
|
|
5700
|
+
*/
|
|
5701
|
+
static async getTagHead(templateId, tag, options) {
|
|
5702
|
+
const config = ConnectionConfig.forGlobal(options);
|
|
5703
|
+
const client = new ApiClient(config);
|
|
5704
|
+
return getTemplateTagHead(
|
|
5705
|
+
client,
|
|
5706
|
+
templateId,
|
|
5707
|
+
tag,
|
|
5708
|
+
config.getSignal(options == null ? void 0 : options.requestTimeoutMs)
|
|
5709
|
+
);
|
|
5710
|
+
}
|
|
5711
|
+
/**
|
|
5712
|
+
* Atomically move one template tag to an exact ready, durable build.
|
|
5713
|
+
*
|
|
5714
|
+
* Use a head returned by {@link getTagHead} as `expected`. Pass `null` only
|
|
5715
|
+
* when creating a tag that must not already exist. A concurrent change throws
|
|
5716
|
+
* `TemplateTagConflictError`; fetch the head again before deciding whether to
|
|
5717
|
+
* retry.
|
|
5718
|
+
*/
|
|
5719
|
+
static async promoteTag(candidate, tag, expected, options) {
|
|
5720
|
+
const config = ConnectionConfig.forGlobal(options);
|
|
5721
|
+
const client = new ApiClient(config);
|
|
5722
|
+
return promoteTemplateTag(
|
|
5723
|
+
client,
|
|
5724
|
+
candidate,
|
|
5725
|
+
tag,
|
|
5726
|
+
expected,
|
|
5727
|
+
config.getSignal(options == null ? void 0 : options.requestTimeoutMs)
|
|
5728
|
+
);
|
|
5729
|
+
}
|
|
5258
5730
|
fromDebianImage(variant = "stable") {
|
|
5259
5731
|
return this.fromImage(`debian:${variant}`);
|
|
5260
5732
|
}
|
|
@@ -5552,8 +6024,8 @@ var TemplateBase = class {
|
|
|
5552
6024
|
})
|
|
5553
6025
|
);
|
|
5554
6026
|
}
|
|
5555
|
-
gitClone(
|
|
5556
|
-
const args = ["git", "clone",
|
|
6027
|
+
gitClone(url2, path2, options) {
|
|
6028
|
+
const args = ["git", "clone", url2];
|
|
5557
6029
|
if (options == null ? void 0 : options.branch) {
|
|
5558
6030
|
args.push(`--branch ${options.branch}`);
|
|
5559
6031
|
args.push("--single-branch");
|
|
@@ -5805,7 +6277,7 @@ var TemplateBase = class {
|
|
|
5805
6277
|
if (index + 1 >= 0 && index + 1 < this.stackTraces.length) {
|
|
5806
6278
|
stackTrace = this.stackTraces[index + 1];
|
|
5807
6279
|
}
|
|
5808
|
-
const { present, url } = await getFileUploadLink(
|
|
6280
|
+
const { present, url: url2 } = await getFileUploadLink(
|
|
5809
6281
|
client,
|
|
5810
6282
|
{
|
|
5811
6283
|
templateID,
|
|
@@ -5813,12 +6285,12 @@ var TemplateBase = class {
|
|
|
5813
6285
|
},
|
|
5814
6286
|
stackTrace
|
|
5815
6287
|
);
|
|
5816
|
-
if (forceUpload &&
|
|
6288
|
+
if (forceUpload && url2 != null || present === false && url2 != null) {
|
|
5817
6289
|
await uploadFile(
|
|
5818
6290
|
{
|
|
5819
6291
|
fileName: src,
|
|
5820
6292
|
fileContextPath: this.fileContextPath.toString(),
|
|
5821
|
-
url,
|
|
6293
|
+
url: url2,
|
|
5822
6294
|
ignorePatterns: [
|
|
5823
6295
|
...this.fileIgnorePatterns,
|
|
5824
6296
|
...readDockerignore(this.fileContextPath.toString())
|
|
@@ -5939,6 +6411,8 @@ Template.exists = TemplateBase.exists;
|
|
|
5939
6411
|
Template.assignTags = TemplateBase.assignTags;
|
|
5940
6412
|
Template.removeTags = TemplateBase.removeTags;
|
|
5941
6413
|
Template.getTags = TemplateBase.getTags;
|
|
6414
|
+
Template.getTagHead = TemplateBase.getTagHead;
|
|
6415
|
+
Template.promoteTag = TemplateBase.promoteTag;
|
|
5942
6416
|
Template.toJSON = TemplateBase.toJSON;
|
|
5943
6417
|
Template.toDockerfile = TemplateBase.toDockerfile;
|
|
5944
6418
|
|
|
@@ -5972,9 +6446,11 @@ export {
|
|
|
5972
6446
|
Sandbox,
|
|
5973
6447
|
SandboxCreateRejectedError,
|
|
5974
6448
|
SandboxError,
|
|
6449
|
+
SandboxRegionScope,
|
|
5975
6450
|
Template,
|
|
5976
6451
|
TemplateBase,
|
|
5977
6452
|
TemplateError,
|
|
6453
|
+
TemplateTagConflictError,
|
|
5978
6454
|
TimeoutError,
|
|
5979
6455
|
src_default as default,
|
|
5980
6456
|
defaultBuildLogger,
|