@vercel/container 10.0.0 → 10.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/index.js +394 -159
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -62,8 +62,8 @@ async function generateProjectManifest({
|
|
|
62
62
|
var diagnostics = (0, import_build_utils.createDiagnostics)("container");
|
|
63
63
|
|
|
64
64
|
// src/index.ts
|
|
65
|
-
var
|
|
66
|
-
var
|
|
65
|
+
var import_node_fs15 = require("fs");
|
|
66
|
+
var import_node_path15 = __toESM(require("path"));
|
|
67
67
|
|
|
68
68
|
// src/util.ts
|
|
69
69
|
var import_build_utils2 = require("@vercel/build-utils");
|
|
@@ -106,7 +106,7 @@ function shortDigest(digest) {
|
|
|
106
106
|
return digest.startsWith("sha256:") ? `${digest.slice(0, 19)}\u2026` : digest;
|
|
107
107
|
}
|
|
108
108
|
function delay(ms) {
|
|
109
|
-
return new Promise((
|
|
109
|
+
return new Promise((resolve4) => setTimeout(resolve4, ms));
|
|
110
110
|
}
|
|
111
111
|
async function withSpan(parent, name, attrs, fn) {
|
|
112
112
|
if (!parent) {
|
|
@@ -136,7 +136,7 @@ function devImageTag(serviceName) {
|
|
|
136
136
|
return `vercel-dev/${safe || "service"}:dev`;
|
|
137
137
|
}
|
|
138
138
|
function run(cmd, args, opts = {}) {
|
|
139
|
-
return new Promise((
|
|
139
|
+
return new Promise((resolve4, reject) => {
|
|
140
140
|
const child = (0, import_node_child_process.spawn)(cmd, args, {
|
|
141
141
|
cwd: opts.cwd,
|
|
142
142
|
env: opts.env,
|
|
@@ -171,7 +171,7 @@ function run(cmd, args, opts = {}) {
|
|
|
171
171
|
});
|
|
172
172
|
child.on("close", (code) => {
|
|
173
173
|
if (code === 0) {
|
|
174
|
-
|
|
174
|
+
resolve4({ stdout, stderr });
|
|
175
175
|
} else {
|
|
176
176
|
const detail = stderr.trim().split("\n").slice(-5).join("\n");
|
|
177
177
|
const error = new Error(
|
|
@@ -746,7 +746,7 @@ var buildahEngine = {
|
|
|
746
746
|
});
|
|
747
747
|
const imageCount = stdout2.trim() ? stdout2.trim().split("\n").length : 0;
|
|
748
748
|
info(
|
|
749
|
-
imageCount > 0 ? `layer store: warm (${imageCount} image(s) present before build)` : "layer store: cold (no
|
|
749
|
+
imageCount > 0 ? `layer store: warm (${imageCount} image(s) present before build)` : "layer store: cold (no images present before build)"
|
|
750
750
|
);
|
|
751
751
|
} catch (err) {
|
|
752
752
|
debug(`could not read store warmth: ${err.message}`);
|
|
@@ -990,7 +990,7 @@ async function startDockerDaemon(span) {
|
|
|
990
990
|
].join("\n")
|
|
991
991
|
);
|
|
992
992
|
}
|
|
993
|
-
await new Promise((
|
|
993
|
+
await new Promise((resolve4) => setTimeout(resolve4, 500));
|
|
994
994
|
}
|
|
995
995
|
}
|
|
996
996
|
async function stopDockerDaemon(daemon, span) {
|
|
@@ -1000,12 +1000,12 @@ async function stopDockerDaemon(daemon, span) {
|
|
|
1000
1000
|
}
|
|
1001
1001
|
step("Stopping Docker daemon");
|
|
1002
1002
|
const stopTimeoutMs = Number(process.env.VERCEL_VCR_DOCKERD_STOP_TIMEOUT_MS) || 1e4;
|
|
1003
|
-
await new Promise((
|
|
1003
|
+
await new Promise((resolve4) => {
|
|
1004
1004
|
let settled = false;
|
|
1005
1005
|
const finish = () => {
|
|
1006
1006
|
if (!settled) {
|
|
1007
1007
|
settled = true;
|
|
1008
|
-
|
|
1008
|
+
resolve4();
|
|
1009
1009
|
}
|
|
1010
1010
|
};
|
|
1011
1011
|
child.once("exit", finish);
|
|
@@ -1206,16 +1206,155 @@ function selectContainerEngine() {
|
|
|
1206
1206
|
}
|
|
1207
1207
|
|
|
1208
1208
|
// src/buildpacks/build.ts
|
|
1209
|
-
var
|
|
1209
|
+
var import_node_fs11 = require("fs");
|
|
1210
1210
|
var import_node_os7 = require("os");
|
|
1211
|
-
var
|
|
1211
|
+
var import_node_path11 = require("path");
|
|
1212
1212
|
|
|
1213
|
-
// src/buildpacks/
|
|
1214
|
-
var import_build_utils3 = require("@vercel/build-utils");
|
|
1213
|
+
// src/buildpacks/cache.ts
|
|
1215
1214
|
var import_node_crypto2 = require("crypto");
|
|
1216
1215
|
var import_node_fs4 = require("fs");
|
|
1217
|
-
var import_node_os4 = require("os");
|
|
1218
1216
|
var import_node_path4 = require("path");
|
|
1217
|
+
var BUILDPACK_CACHE_DIR = ".vercel/cache/buildpacks";
|
|
1218
|
+
var CNB_COMMITTED_DIR = "committed";
|
|
1219
|
+
var CNB_CACHE_METADATA_FILE = "io.buildpacks.lifecycle.cache.metadata";
|
|
1220
|
+
var IMAGE_ID_FILE = "image-id";
|
|
1221
|
+
function buildpackCacheEnabled() {
|
|
1222
|
+
return readString(process.env.VERCEL_ENABLE_BUILDPACK_CACHE) === "1";
|
|
1223
|
+
}
|
|
1224
|
+
function buildpackCacheDir(options) {
|
|
1225
|
+
const root = (0, import_node_path4.resolve)(options.repoRootPath || options.workPath);
|
|
1226
|
+
const app = (0, import_node_path4.relative)(root, (0, import_node_path4.resolve)(options.workPath)).split(import_node_path4.sep).join("/") || ".";
|
|
1227
|
+
const key = (0, import_node_crypto2.createHash)("sha256").update(JSON.stringify([app, options.service?.name ?? null])).digest("hex").slice(0, 32);
|
|
1228
|
+
return (0, import_node_path4.join)(root, BUILDPACK_CACHE_DIR, key);
|
|
1229
|
+
}
|
|
1230
|
+
function restoreBuildpackCache(dir, imageId, cacheDir) {
|
|
1231
|
+
try {
|
|
1232
|
+
if (readRegularFile((0, import_node_path4.join)(dir, IMAGE_ID_FILE)) !== imageId) {
|
|
1233
|
+
return { status: "miss", reason: "base_image_changed" };
|
|
1234
|
+
}
|
|
1235
|
+
copyCommitted(dir, cacheDir);
|
|
1236
|
+
return { status: "hit", bytes: sizeOf((0, import_node_path4.join)(cacheDir, CNB_COMMITTED_DIR)) };
|
|
1237
|
+
} catch (error) {
|
|
1238
|
+
(0, import_node_fs4.rmSync)((0, import_node_path4.join)(cacheDir, CNB_COMMITTED_DIR), { recursive: true, force: true });
|
|
1239
|
+
const cold = error.code === "ENOENT";
|
|
1240
|
+
return { status: "miss", reason: cold ? "no_cache" : firstLine(error) };
|
|
1241
|
+
}
|
|
1242
|
+
}
|
|
1243
|
+
function saveBuildpackCache(dir, imageId, cacheDir) {
|
|
1244
|
+
const committed = (0, import_node_path4.join)(cacheDir, CNB_COMMITTED_DIR);
|
|
1245
|
+
let metadata;
|
|
1246
|
+
try {
|
|
1247
|
+
assertDirectory(committed);
|
|
1248
|
+
metadata = readRegularFile((0, import_node_path4.join)(committed, CNB_CACHE_METADATA_FILE));
|
|
1249
|
+
} catch (error) {
|
|
1250
|
+
const missing = error.code === "ENOENT";
|
|
1251
|
+
return {
|
|
1252
|
+
status: "skipped",
|
|
1253
|
+
reason: missing ? "no_cache_written" : firstLine(error)
|
|
1254
|
+
};
|
|
1255
|
+
}
|
|
1256
|
+
try {
|
|
1257
|
+
if (isSaved(dir, imageId, metadata))
|
|
1258
|
+
return { status: "unchanged" };
|
|
1259
|
+
const bytes = sizeOf(committed);
|
|
1260
|
+
(0, import_node_fs4.rmSync)(dir, { recursive: true, force: true });
|
|
1261
|
+
copyCommitted(cacheDir, dir);
|
|
1262
|
+
(0, import_node_fs4.writeFileSync)((0, import_node_path4.join)(dir, IMAGE_ID_FILE), imageId);
|
|
1263
|
+
return { status: "saved", bytes };
|
|
1264
|
+
} catch (error) {
|
|
1265
|
+
(0, import_node_fs4.rmSync)(dir, { recursive: true, force: true });
|
|
1266
|
+
return { status: "skipped", reason: firstLine(error) };
|
|
1267
|
+
}
|
|
1268
|
+
}
|
|
1269
|
+
function isSaved(dir, imageId, metadata) {
|
|
1270
|
+
try {
|
|
1271
|
+
const committed = (0, import_node_path4.join)(dir, CNB_COMMITTED_DIR);
|
|
1272
|
+
assertDirectory(committed);
|
|
1273
|
+
return readRegularFile((0, import_node_path4.join)(dir, IMAGE_ID_FILE)) === imageId && readRegularFile((0, import_node_path4.join)(committed, CNB_CACHE_METADATA_FILE)) === metadata;
|
|
1274
|
+
} catch {
|
|
1275
|
+
return false;
|
|
1276
|
+
}
|
|
1277
|
+
}
|
|
1278
|
+
function copyCommitted(from, to) {
|
|
1279
|
+
const source = (0, import_node_path4.join)(from, CNB_COMMITTED_DIR);
|
|
1280
|
+
const target = (0, import_node_path4.join)(to, CNB_COMMITTED_DIR);
|
|
1281
|
+
assertDirectory(source);
|
|
1282
|
+
(0, import_node_fs4.mkdirSync)(target, { recursive: true });
|
|
1283
|
+
for (const entry of (0, import_node_fs4.readdirSync)(source, { withFileTypes: true })) {
|
|
1284
|
+
if (!entry.isFile())
|
|
1285
|
+
throw notRegularFile(entry.name);
|
|
1286
|
+
(0, import_node_fs4.copyFileSync)((0, import_node_path4.join)(source, entry.name), (0, import_node_path4.join)(target, entry.name));
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
function assertDirectory(path4) {
|
|
1290
|
+
if (!(0, import_node_fs4.lstatSync)(path4).isDirectory()) {
|
|
1291
|
+
throw new Error(`${(0, import_node_path4.basename)(path4)} is not a directory`);
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
1294
|
+
function readRegularFile(path4) {
|
|
1295
|
+
if (!(0, import_node_fs4.lstatSync)(path4).isFile())
|
|
1296
|
+
throw notRegularFile((0, import_node_path4.basename)(path4));
|
|
1297
|
+
return (0, import_node_fs4.readFileSync)(path4, "utf8");
|
|
1298
|
+
}
|
|
1299
|
+
function notRegularFile(name) {
|
|
1300
|
+
return new Error(`${JSON.stringify(name)} is not a regular file`);
|
|
1301
|
+
}
|
|
1302
|
+
function sizeOf(dir) {
|
|
1303
|
+
return (0, import_node_fs4.readdirSync)(dir).reduce(
|
|
1304
|
+
(bytes, name) => bytes + (0, import_node_fs4.lstatSync)((0, import_node_path4.join)(dir, name)).size,
|
|
1305
|
+
0
|
|
1306
|
+
);
|
|
1307
|
+
}
|
|
1308
|
+
function firstLine(error) {
|
|
1309
|
+
return error.message.split("\n")[0];
|
|
1310
|
+
}
|
|
1311
|
+
function formatBytes(bytes) {
|
|
1312
|
+
if (bytes < 1024)
|
|
1313
|
+
return `${bytes} B`;
|
|
1314
|
+
const units = ["KiB", "MiB", "GiB"];
|
|
1315
|
+
let value = bytes / 1024;
|
|
1316
|
+
let unit = 0;
|
|
1317
|
+
while (value >= 1024 && unit < units.length - 1) {
|
|
1318
|
+
value /= 1024;
|
|
1319
|
+
unit += 1;
|
|
1320
|
+
}
|
|
1321
|
+
return `${value.toFixed(value >= 10 ? 0 : 1)} ${units[unit]}`;
|
|
1322
|
+
}
|
|
1323
|
+
function describeRestore(outcome) {
|
|
1324
|
+
return outcome.status === "hit" ? `restored buildpack cache (${formatBytes(outcome.bytes)})` : `no buildpack cache to restore (${outcome.reason})`;
|
|
1325
|
+
}
|
|
1326
|
+
function describeSave(outcome) {
|
|
1327
|
+
switch (outcome.status) {
|
|
1328
|
+
case "saved":
|
|
1329
|
+
return `saved buildpack cache (${formatBytes(outcome.bytes)})`;
|
|
1330
|
+
case "unchanged":
|
|
1331
|
+
return "buildpack cache unchanged";
|
|
1332
|
+
default:
|
|
1333
|
+
return `buildpack cache not saved (${outcome.reason})`;
|
|
1334
|
+
}
|
|
1335
|
+
}
|
|
1336
|
+
function recordRestore(span, outcome, durationMs) {
|
|
1337
|
+
span?.setAttributes({
|
|
1338
|
+
"buildpack.cache.restore": outcome.status,
|
|
1339
|
+
"buildpack.cache.restore_ms": String(durationMs),
|
|
1340
|
+
...outcome.status === "hit" ? { "buildpack.cache.restore_bytes": String(outcome.bytes) } : { "buildpack.cache.miss_reason": outcome.reason }
|
|
1341
|
+
});
|
|
1342
|
+
}
|
|
1343
|
+
function recordSave(span, outcome, durationMs) {
|
|
1344
|
+
span?.setAttributes({
|
|
1345
|
+
"buildpack.cache.save": outcome.status,
|
|
1346
|
+
"buildpack.cache.save_ms": String(durationMs),
|
|
1347
|
+
...outcome.status === "saved" ? { "buildpack.cache.save_bytes": String(outcome.bytes) } : {},
|
|
1348
|
+
...outcome.status === "skipped" ? { "buildpack.cache.skip_reason": outcome.reason } : {}
|
|
1349
|
+
});
|
|
1350
|
+
}
|
|
1351
|
+
|
|
1352
|
+
// src/buildpacks/lifecycle/lifecycle.ts
|
|
1353
|
+
var import_build_utils3 = require("@vercel/build-utils");
|
|
1354
|
+
var import_node_crypto3 = require("crypto");
|
|
1355
|
+
var import_node_fs5 = require("fs");
|
|
1356
|
+
var import_node_os4 = require("os");
|
|
1357
|
+
var import_node_path5 = require("path");
|
|
1219
1358
|
var import_smol_toml = require("smol-toml");
|
|
1220
1359
|
var import_tar = require("tar");
|
|
1221
1360
|
|
|
@@ -1230,8 +1369,8 @@ var distribution_default = {
|
|
|
1230
1369
|
buildpacks: {
|
|
1231
1370
|
ruby: {
|
|
1232
1371
|
id: "vercel/ruby",
|
|
1233
|
-
version: "0.
|
|
1234
|
-
sha256: "
|
|
1372
|
+
version: "0.3.0",
|
|
1373
|
+
sha256: "7ee871c18ac1616658793d3d25639d7a1f65ade618f84c6596ef9e3f515b7202"
|
|
1235
1374
|
}
|
|
1236
1375
|
}
|
|
1237
1376
|
};
|
|
@@ -1314,7 +1453,7 @@ async function withPrereleaseBuildpack(buildpack, archiveUrl) {
|
|
|
1314
1453
|
);
|
|
1315
1454
|
if (!entry) {
|
|
1316
1455
|
throw new Error(
|
|
1317
|
-
`Pre-release archive ${archive.
|
|
1456
|
+
`Pre-release archive ${archive.fileName} does not match a buildpack in the ${buildpack.runtime} runtime.`
|
|
1318
1457
|
);
|
|
1319
1458
|
}
|
|
1320
1459
|
const checksumUrlObj = new URL(archive.url);
|
|
@@ -1323,17 +1462,17 @@ async function withPrereleaseBuildpack(buildpack, archiveUrl) {
|
|
|
1323
1462
|
const response = await fetch(checksumUrl);
|
|
1324
1463
|
if (!response.ok) {
|
|
1325
1464
|
throw new Error(
|
|
1326
|
-
`Failed to fetch pre-release checksum ${
|
|
1465
|
+
`Failed to fetch pre-release checksum for ${archive.fileName}: HTTP ${response.status} ${response.statusText}`
|
|
1327
1466
|
);
|
|
1328
1467
|
}
|
|
1329
1468
|
const fields = (await response.text()).trim().split(/\s+/);
|
|
1330
1469
|
const [sha256, fileName] = fields;
|
|
1331
1470
|
if (fields.length !== 2 || !SHA256_RE.test(sha256) || fileName !== archive.fileName) {
|
|
1332
1471
|
throw new Error(
|
|
1333
|
-
`Invalid pre-release checksum
|
|
1472
|
+
`Invalid pre-release checksum: expected a SHA-256 checksum for ${archive.fileName}.`
|
|
1334
1473
|
);
|
|
1335
1474
|
}
|
|
1336
|
-
info(`Using pre-release ${entry.id}@${archive.version}
|
|
1475
|
+
info(`Using pre-release ${entry.id}@${archive.version}`);
|
|
1337
1476
|
return {
|
|
1338
1477
|
...buildpack,
|
|
1339
1478
|
buildpacks: buildpack.buildpacks.map(
|
|
@@ -1346,17 +1485,18 @@ async function withPrereleaseBuildpack(buildpack, archiveUrl) {
|
|
|
1346
1485
|
var BUILD_USER_ID = 1001;
|
|
1347
1486
|
var BUILD_GROUP_ID = 1001;
|
|
1348
1487
|
var BUILD_USER = `${BUILD_USER_ID}:${BUILD_GROUP_ID}`;
|
|
1349
|
-
var CNB_PLATFORM_API = "0.
|
|
1488
|
+
var CNB_PLATFORM_API = "0.15";
|
|
1350
1489
|
var ORDER_MOUNT_DIR = "/platform/order";
|
|
1351
1490
|
var ORDER_FILE = `${ORDER_MOUNT_DIR}/order.toml`;
|
|
1491
|
+
var CACHE_MOUNT_DIR = "/cache";
|
|
1352
1492
|
var ENV_NAME_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
1353
1493
|
async function stageWorkspace({ files, workPath }, destinationDir) {
|
|
1354
1494
|
const staged = /* @__PURE__ */ Object.create(null);
|
|
1355
1495
|
const symlinks = /* @__PURE__ */ new Set();
|
|
1356
1496
|
for (const [name, file] of Object.entries(files)) {
|
|
1357
1497
|
const portable = name.replace(/\\/g, "/");
|
|
1358
|
-
const normalized =
|
|
1359
|
-
if (!normalized || normalized === "." ||
|
|
1498
|
+
const normalized = import_node_path5.posix.normalize(portable).replace(/\/$/, "");
|
|
1499
|
+
if (!normalized || normalized === "." || import_node_path5.win32.isAbsolute(name) || import_node_path5.posix.isAbsolute(portable) || portable.split("/").includes("..") || normalized in staged) {
|
|
1360
1500
|
throw new Error(`Invalid buildpack source path ${JSON.stringify(name)}.`);
|
|
1361
1501
|
}
|
|
1362
1502
|
staged[normalized] = file;
|
|
@@ -1369,15 +1509,15 @@ async function stageWorkspace({ files, workPath }, destinationDir) {
|
|
|
1369
1509
|
if (!target) {
|
|
1370
1510
|
throw new Error(`Cannot read buildpack source symlink ${name}.`);
|
|
1371
1511
|
}
|
|
1372
|
-
if ((0,
|
|
1373
|
-
target = (0,
|
|
1374
|
-
} else if (
|
|
1512
|
+
if ((0, import_node_path5.isAbsolute)(target)) {
|
|
1513
|
+
target = (0, import_node_path5.relative)((0, import_node_path5.resolve)(workPath, import_node_path5.posix.dirname(normalized)), target) || ".";
|
|
1514
|
+
} else if (import_node_path5.win32.isAbsolute(target)) {
|
|
1375
1515
|
throw new Error(
|
|
1376
1516
|
`Buildpack source symlink ${name} has an absolute target.`
|
|
1377
1517
|
);
|
|
1378
1518
|
}
|
|
1379
1519
|
target = target.replace(/\\/g, "/");
|
|
1380
|
-
const resolved =
|
|
1520
|
+
const resolved = import_node_path5.posix.join(import_node_path5.posix.dirname(normalized), target);
|
|
1381
1521
|
if (resolved === ".." || resolved.startsWith("../")) {
|
|
1382
1522
|
throw new Error(
|
|
1383
1523
|
`Buildpack source symlink ${name} escapes the service root. Ruby buildpack services must be self-contained.`
|
|
@@ -1387,7 +1527,7 @@ async function stageWorkspace({ files, workPath }, destinationDir) {
|
|
|
1387
1527
|
symlinks.add(normalized);
|
|
1388
1528
|
}
|
|
1389
1529
|
for (const name of Object.keys(staged)) {
|
|
1390
|
-
for (let parent =
|
|
1530
|
+
for (let parent = import_node_path5.posix.dirname(name); parent !== "."; parent = import_node_path5.posix.dirname(parent)) {
|
|
1391
1531
|
if (symlinks.has(parent)) {
|
|
1392
1532
|
throw new Error(
|
|
1393
1533
|
`Buildpack source ${name} is inside symlink ${parent}.`
|
|
@@ -1396,16 +1536,16 @@ async function stageWorkspace({ files, workPath }, destinationDir) {
|
|
|
1396
1536
|
}
|
|
1397
1537
|
const file = staged[name];
|
|
1398
1538
|
if (file.type === "FileFsRef" && !(0, import_build_utils3.isSymbolicLink)(file.mode)) {
|
|
1399
|
-
const sourcePath = (0,
|
|
1400
|
-
const sourceRelative = (0,
|
|
1401
|
-
if (sourceRelative.startsWith(`..${
|
|
1539
|
+
const sourcePath = (0, import_node_path5.resolve)(file.fsPath);
|
|
1540
|
+
const sourceRelative = (0, import_node_path5.relative)((0, import_node_path5.resolve)(workPath), sourcePath);
|
|
1541
|
+
if (sourceRelative.startsWith(`..${import_node_path5.sep}`) || sourceRelative === ".." || (0, import_node_path5.isAbsolute)(sourceRelative)) {
|
|
1402
1542
|
continue;
|
|
1403
1543
|
}
|
|
1404
|
-
const sourceRoot =
|
|
1405
|
-
const sourceTarget =
|
|
1406
|
-
if (sourceTarget !== (0,
|
|
1407
|
-
const target = (0,
|
|
1408
|
-
if (target === ".." || target.startsWith("../") || (0,
|
|
1544
|
+
const sourceRoot = import_node_fs5.realpathSync.native(workPath);
|
|
1545
|
+
const sourceTarget = import_node_fs5.realpathSync.native(sourcePath);
|
|
1546
|
+
if (sourceTarget !== (0, import_node_path5.resolve)(sourceRoot, sourceRelative)) {
|
|
1547
|
+
const target = (0, import_node_path5.relative)(sourceRoot, sourceTarget).split(import_node_path5.sep).join("/");
|
|
1548
|
+
if (target === ".." || target.startsWith("../") || (0, import_node_path5.isAbsolute)(target) || !(target in staged)) {
|
|
1409
1549
|
throw new Error(
|
|
1410
1550
|
`Buildpack source ${name} follows a symlink to an excluded or outside-root file. Ruby buildpack services must be self-contained.`
|
|
1411
1551
|
);
|
|
@@ -1414,17 +1554,17 @@ async function stageWorkspace({ files, workPath }, destinationDir) {
|
|
|
1414
1554
|
}
|
|
1415
1555
|
}
|
|
1416
1556
|
await (0, import_build_utils3.download)(staged, destinationDir);
|
|
1417
|
-
const root =
|
|
1557
|
+
const root = import_node_fs5.realpathSync.native(destinationDir);
|
|
1418
1558
|
for (const name of symlinks) {
|
|
1419
1559
|
let target;
|
|
1420
1560
|
try {
|
|
1421
|
-
target = (0,
|
|
1561
|
+
target = (0, import_node_path5.relative)(root, import_node_fs5.realpathSync.native((0, import_node_path5.join)(destinationDir, name)));
|
|
1422
1562
|
} catch {
|
|
1423
1563
|
throw new Error(
|
|
1424
1564
|
`Buildpack source symlink ${name} has no target in the staged service.`
|
|
1425
1565
|
);
|
|
1426
1566
|
}
|
|
1427
|
-
if (target === ".." || target.startsWith(`..${
|
|
1567
|
+
if (target === ".." || target.startsWith(`..${import_node_path5.sep}`) || (0, import_node_path5.isAbsolute)(target)) {
|
|
1428
1568
|
throw new Error(
|
|
1429
1569
|
`Buildpack source symlink ${name} escapes the staged service.`
|
|
1430
1570
|
);
|
|
@@ -1438,16 +1578,16 @@ function writePlatformEnvDir(buildEnv, config, parentDir = (0, import_node_os4.t
|
|
|
1438
1578
|
if (config.nodeHome) {
|
|
1439
1579
|
environment.VERCEL_NODE_HOME = config.nodeHome;
|
|
1440
1580
|
}
|
|
1441
|
-
const dir = (0,
|
|
1442
|
-
(0,
|
|
1581
|
+
const dir = (0, import_node_fs5.mkdtempSync)((0, import_node_path5.join)(parentDir, "vercel-cnb-env-"));
|
|
1582
|
+
(0, import_node_fs5.chmodSync)(dir, 493);
|
|
1443
1583
|
for (const [key, value] of Object.entries(environment)) {
|
|
1444
1584
|
if (!ENV_NAME_RE.test(key)) {
|
|
1445
1585
|
debug(`skipping build env var with an unsupported name: ${key}`);
|
|
1446
1586
|
continue;
|
|
1447
1587
|
}
|
|
1448
|
-
const file = (0,
|
|
1449
|
-
(0,
|
|
1450
|
-
(0,
|
|
1588
|
+
const file = (0, import_node_path5.join)(dir, key);
|
|
1589
|
+
(0, import_node_fs5.writeFileSync)(file, value);
|
|
1590
|
+
(0, import_node_fs5.chmodSync)(file, 420);
|
|
1451
1591
|
}
|
|
1452
1592
|
return dir;
|
|
1453
1593
|
}
|
|
@@ -1499,11 +1639,11 @@ function writeOrderDir(buildpack, parentDir = (0, import_node_os4.tmpdir)()) {
|
|
|
1499
1639
|
}
|
|
1500
1640
|
]
|
|
1501
1641
|
};
|
|
1502
|
-
const dir = (0,
|
|
1503
|
-
(0,
|
|
1504
|
-
const file = (0,
|
|
1505
|
-
(0,
|
|
1506
|
-
(0,
|
|
1642
|
+
const dir = (0, import_node_fs5.mkdtempSync)((0, import_node_path5.join)(parentDir, "vercel-cnb-order-"));
|
|
1643
|
+
(0, import_node_fs5.chmodSync)(dir, 493);
|
|
1644
|
+
const file = (0, import_node_path5.join)(dir, "order.toml");
|
|
1645
|
+
(0, import_node_fs5.writeFileSync)(file, (0, import_smol_toml.stringify)(order));
|
|
1646
|
+
(0, import_node_fs5.chmodSync)(file, 420);
|
|
1507
1647
|
return dir;
|
|
1508
1648
|
}
|
|
1509
1649
|
function cnbRegistryAuth(credentials) {
|
|
@@ -1519,74 +1659,78 @@ function distributionUrls(buildpack) {
|
|
|
1519
1659
|
)
|
|
1520
1660
|
};
|
|
1521
1661
|
}
|
|
1662
|
+
function archiveName(archive) {
|
|
1663
|
+
return new URL(archive.url).pathname.split("/").at(-1) || "archive";
|
|
1664
|
+
}
|
|
1522
1665
|
async function downloadPinnedArchive(archive, destinationPath) {
|
|
1523
1666
|
const response = await fetch(archive.url);
|
|
1524
1667
|
if (!response.ok) {
|
|
1525
1668
|
throw new Error(
|
|
1526
|
-
`Failed to fetch ${archive
|
|
1669
|
+
`Failed to fetch ${archiveName(archive)}: HTTP ${response.status} ${response.statusText}`
|
|
1527
1670
|
);
|
|
1528
1671
|
}
|
|
1529
1672
|
const contents = new Uint8Array(await response.arrayBuffer());
|
|
1530
|
-
const checksum = (0,
|
|
1673
|
+
const checksum = (0, import_node_crypto3.createHash)("sha256").update(contents).digest("hex");
|
|
1531
1674
|
if (checksum !== archive.sha256) {
|
|
1532
1675
|
throw new Error(
|
|
1533
|
-
`Checksum mismatch for ${archive
|
|
1676
|
+
`Checksum mismatch for ${archiveName(archive)}: expected ${archive.sha256}, received ${checksum}.`
|
|
1534
1677
|
);
|
|
1535
1678
|
}
|
|
1536
|
-
(0,
|
|
1679
|
+
(0, import_node_fs5.writeFileSync)(destinationPath, contents);
|
|
1537
1680
|
}
|
|
1538
1681
|
async function fetchPinnedArchive(archive, destinationDir) {
|
|
1539
|
-
const archivePath = (0,
|
|
1682
|
+
const archivePath = (0, import_node_path5.join)(destinationDir, `${archive.sha256}.tgz`);
|
|
1540
1683
|
try {
|
|
1541
1684
|
await downloadPinnedArchive(archive, archivePath);
|
|
1542
1685
|
(0, import_tar.extract)({ file: archivePath, cwd: destinationDir, sync: true });
|
|
1543
1686
|
} finally {
|
|
1544
|
-
(0,
|
|
1687
|
+
(0, import_node_fs5.rmSync)(archivePath, { force: true });
|
|
1545
1688
|
}
|
|
1546
1689
|
}
|
|
1547
1690
|
var LAYER_MEDIA_TYPE_RE = /(\.tar\.gzip|\.tar\+gzip|\.tar)$/;
|
|
1548
1691
|
function readOciJson(path4) {
|
|
1549
|
-
return JSON.parse((0,
|
|
1692
|
+
return JSON.parse((0, import_node_fs5.readFileSync)(path4, "utf8"));
|
|
1550
1693
|
}
|
|
1551
1694
|
function blobPath(layoutDir, digest) {
|
|
1552
1695
|
const match = digest.match(/^sha256:([0-9a-f]{64})$/);
|
|
1553
1696
|
if (!match) {
|
|
1554
1697
|
throw new Error(`Unsupported OCI digest ${JSON.stringify(digest)}.`);
|
|
1555
1698
|
}
|
|
1556
|
-
return (0,
|
|
1699
|
+
return (0, import_node_path5.join)(layoutDir, "blobs", "sha256", match[1]);
|
|
1557
1700
|
}
|
|
1558
1701
|
async function fetchBuildpackage(archive, cnbDir) {
|
|
1559
|
-
const layoutDir = (0,
|
|
1560
|
-
const archivePath = (0,
|
|
1702
|
+
const layoutDir = (0, import_node_fs5.mkdtempSync)((0, import_node_path5.join)((0, import_node_os4.tmpdir)(), "vercel-cnb-buildpackage-"));
|
|
1703
|
+
const archivePath = (0, import_node_path5.join)(layoutDir, "buildpackage.cnb");
|
|
1561
1704
|
try {
|
|
1562
1705
|
await downloadPinnedArchive(archive, archivePath);
|
|
1563
1706
|
await (0, import_tar.extract)({ file: archivePath, cwd: layoutDir });
|
|
1564
1707
|
const index = readOciJson(
|
|
1565
|
-
(0,
|
|
1708
|
+
(0, import_node_path5.join)(layoutDir, "index.json")
|
|
1566
1709
|
);
|
|
1710
|
+
const name = archiveName(archive);
|
|
1567
1711
|
const manifestDigest = index.manifests?.[0]?.digest;
|
|
1568
1712
|
if (!manifestDigest) {
|
|
1569
|
-
throw new Error(`${
|
|
1713
|
+
throw new Error(`${name} has no image manifest in index.json.`);
|
|
1570
1714
|
}
|
|
1571
1715
|
const manifest = readOciJson(
|
|
1572
1716
|
blobPath(layoutDir, manifestDigest)
|
|
1573
1717
|
);
|
|
1574
1718
|
if (!manifest.layers?.length) {
|
|
1575
|
-
throw new Error(`${
|
|
1719
|
+
throw new Error(`${name} has an image manifest with no layers.`);
|
|
1576
1720
|
}
|
|
1577
1721
|
for (const layer of manifest.layers) {
|
|
1578
1722
|
if (!layer.digest || !LAYER_MEDIA_TYPE_RE.test(layer.mediaType ?? "")) {
|
|
1579
1723
|
throw new Error(
|
|
1580
|
-
`${
|
|
1724
|
+
`${name} has an unsupported layer media type ${JSON.stringify(
|
|
1581
1725
|
layer.mediaType
|
|
1582
1726
|
)}.`
|
|
1583
1727
|
);
|
|
1584
1728
|
}
|
|
1585
1729
|
const layerPath = blobPath(layoutDir, layer.digest);
|
|
1586
|
-
const actual = (0,
|
|
1730
|
+
const actual = (0, import_node_crypto3.createHash)("sha256").update(new Uint8Array((0, import_node_fs5.readFileSync)(layerPath))).digest("hex");
|
|
1587
1731
|
if (`sha256:${actual}` !== layer.digest) {
|
|
1588
1732
|
throw new Error(
|
|
1589
|
-
`${
|
|
1733
|
+
`${name} layer ${layer.digest} hashes to sha256:${actual}.`
|
|
1590
1734
|
);
|
|
1591
1735
|
}
|
|
1592
1736
|
await (0, import_tar.extract)({
|
|
@@ -1609,7 +1753,7 @@ async function fetchBuildpackage(archive, cnbDir) {
|
|
|
1609
1753
|
});
|
|
1610
1754
|
}
|
|
1611
1755
|
} finally {
|
|
1612
|
-
(0,
|
|
1756
|
+
(0, import_node_fs5.rmSync)(layoutDir, { recursive: true, force: true });
|
|
1613
1757
|
}
|
|
1614
1758
|
}
|
|
1615
1759
|
async function fetchDistribution(buildpack, cnbDir) {
|
|
@@ -1620,14 +1764,14 @@ async function fetchDistribution(buildpack, cnbDir) {
|
|
|
1620
1764
|
)
|
|
1621
1765
|
]);
|
|
1622
1766
|
for (const entry of buildpack.buildpacks) {
|
|
1623
|
-
const directory = (0,
|
|
1767
|
+
const directory = (0, import_node_path5.join)(
|
|
1624
1768
|
cnbDir,
|
|
1625
1769
|
"buildpacks",
|
|
1626
1770
|
entry.id.replace("/", "_"),
|
|
1627
1771
|
entry.version
|
|
1628
1772
|
);
|
|
1629
1773
|
for (const file of ["buildpack.toml", "bin/detect", "bin/build"]) {
|
|
1630
|
-
if (!(0,
|
|
1774
|
+
if (!(0, import_node_fs5.statSync)((0, import_node_path5.join)(directory, file), { throwIfNoEntry: false })?.isFile()) {
|
|
1631
1775
|
throw new Error(
|
|
1632
1776
|
`Buildpack ${entry.id}@${entry.version} is missing ${file}.`
|
|
1633
1777
|
);
|
|
@@ -1635,11 +1779,11 @@ async function fetchDistribution(buildpack, cnbDir) {
|
|
|
1635
1779
|
}
|
|
1636
1780
|
}
|
|
1637
1781
|
}
|
|
1638
|
-
function creatorArgs(image, imageRef) {
|
|
1782
|
+
function creatorArgs(image, imageRef, options = {}) {
|
|
1639
1783
|
return [
|
|
1640
1784
|
"-app=/workspace",
|
|
1641
1785
|
`-order=${ORDER_FILE}`,
|
|
1642
|
-
"-skip-restore",
|
|
1786
|
+
...options.cacheDir ? [`-cache-dir=${options.cacheDir}`] : ["-skip-restore"],
|
|
1643
1787
|
`-run-image=${image.runImage}`,
|
|
1644
1788
|
"-report=/platform-output/report.toml",
|
|
1645
1789
|
imageRef
|
|
@@ -1647,13 +1791,13 @@ function creatorArgs(image, imageRef) {
|
|
|
1647
1791
|
}
|
|
1648
1792
|
|
|
1649
1793
|
// src/buildpacks/lifecycle/buildah.ts
|
|
1650
|
-
var
|
|
1651
|
-
var
|
|
1794
|
+
var import_node_fs6 = require("fs");
|
|
1795
|
+
var import_node_crypto4 = require("crypto");
|
|
1652
1796
|
var import_node_os5 = require("os");
|
|
1653
|
-
var
|
|
1654
|
-
async function runBuildah2(args, env) {
|
|
1797
|
+
var import_node_path6 = require("path");
|
|
1798
|
+
async function runBuildah2(args, env, quiet) {
|
|
1655
1799
|
const storageArgs = await buildahStorageArgs();
|
|
1656
|
-
return run("buildah", [...storageArgs, ...args], { env });
|
|
1800
|
+
return run("buildah", [...storageArgs, ...args], { env, quiet });
|
|
1657
1801
|
}
|
|
1658
1802
|
async function removeContainer(name) {
|
|
1659
1803
|
try {
|
|
@@ -1664,6 +1808,47 @@ async function removeContainer(name) {
|
|
|
1664
1808
|
);
|
|
1665
1809
|
}
|
|
1666
1810
|
}
|
|
1811
|
+
async function inspectBaseImageId(container) {
|
|
1812
|
+
const { stdout } = await runBuildah2(
|
|
1813
|
+
["inspect", "--type", "container", container],
|
|
1814
|
+
void 0,
|
|
1815
|
+
true
|
|
1816
|
+
);
|
|
1817
|
+
const inspected = JSON.parse(stdout);
|
|
1818
|
+
const id = inspected.FromImageID || inspected.FromImageDigest;
|
|
1819
|
+
if (!id) {
|
|
1820
|
+
throw new Error(
|
|
1821
|
+
`buildah inspect did not report the base image of ${container}.`
|
|
1822
|
+
);
|
|
1823
|
+
}
|
|
1824
|
+
return id;
|
|
1825
|
+
}
|
|
1826
|
+
function cacheScratchParent() {
|
|
1827
|
+
if (isBuildContainer()) {
|
|
1828
|
+
const dir = "/vercel/.cnb";
|
|
1829
|
+
try {
|
|
1830
|
+
(0, import_node_fs6.mkdirSync)(dir, { recursive: true });
|
|
1831
|
+
return dir;
|
|
1832
|
+
} catch (error) {
|
|
1833
|
+
debug(
|
|
1834
|
+
`cannot use ${dir} for the buildpack cache: ${error.message}`
|
|
1835
|
+
);
|
|
1836
|
+
}
|
|
1837
|
+
}
|
|
1838
|
+
return (0, import_node_os5.tmpdir)();
|
|
1839
|
+
}
|
|
1840
|
+
function chownTree(root, uid, gid) {
|
|
1841
|
+
const stat = (0, import_node_fs6.lstatSync)(root);
|
|
1842
|
+
if (stat.isDirectory()) {
|
|
1843
|
+
(0, import_node_fs6.chmodSync)(root, 493);
|
|
1844
|
+
for (const entry of (0, import_node_fs6.readdirSync)(root)) {
|
|
1845
|
+
chownTree((0, import_node_path6.join)(root, entry), uid, gid);
|
|
1846
|
+
}
|
|
1847
|
+
} else if (stat.isFile()) {
|
|
1848
|
+
(0, import_node_fs6.chmodSync)(root, 420);
|
|
1849
|
+
}
|
|
1850
|
+
(0, import_node_fs6.lchownSync)(root, uid, gid);
|
|
1851
|
+
}
|
|
1667
1852
|
var buildAndPushWithLifecycle = async (buildpack, params, span) => {
|
|
1668
1853
|
const urls = distributionUrls(buildpack);
|
|
1669
1854
|
return withSpan(
|
|
@@ -1680,19 +1865,20 @@ var buildAndPushWithLifecycle = async (buildpack, params, span) => {
|
|
|
1680
1865
|
"image.ref": params.imageRef
|
|
1681
1866
|
},
|
|
1682
1867
|
async (lifecycleSpan) => {
|
|
1683
|
-
const suffix = `${process.pid}-${(0,
|
|
1868
|
+
const suffix = `${process.pid}-${(0, import_node_crypto4.randomBytes)(4).toString("hex")}`;
|
|
1684
1869
|
const buildContainer = `vercel-cnb-${buildpack.runtime}-${suffix}`;
|
|
1685
1870
|
let cnbDir;
|
|
1686
1871
|
let reportDir;
|
|
1687
1872
|
let orderDir;
|
|
1688
1873
|
let platformEnvDir;
|
|
1874
|
+
let cacheScratch;
|
|
1689
1875
|
try {
|
|
1690
|
-
reportDir = (0,
|
|
1691
|
-
const reportPath = (0,
|
|
1692
|
-
(0,
|
|
1693
|
-
(0,
|
|
1694
|
-
cnbDir = (0,
|
|
1695
|
-
(0,
|
|
1876
|
+
reportDir = (0, import_node_fs6.mkdtempSync)((0, import_node_path6.join)((0, import_node_os5.tmpdir)(), "vercel-cnb-report-"));
|
|
1877
|
+
const reportPath = (0, import_node_path6.join)(reportDir, "report.toml");
|
|
1878
|
+
(0, import_node_fs6.chownSync)(reportDir, BUILD_USER_ID, BUILD_GROUP_ID);
|
|
1879
|
+
(0, import_node_fs6.chmodSync)(reportDir, 493);
|
|
1880
|
+
cnbDir = (0, import_node_fs6.mkdtempSync)((0, import_node_path6.join)((0, import_node_os5.tmpdir)(), "vercel-cnb-"));
|
|
1881
|
+
(0, import_node_fs6.chmodSync)(cnbDir, 493);
|
|
1696
1882
|
orderDir = writeOrderDir(buildpack);
|
|
1697
1883
|
platformEnvDir = writePlatformEnvDir(params.buildEnv, {
|
|
1698
1884
|
nodeHome: params.nodeToolchain?.home
|
|
@@ -1730,6 +1916,36 @@ var buildAndPushWithLifecycle = async (buildpack, params, span) => {
|
|
|
1730
1916
|
params.workPath,
|
|
1731
1917
|
"/workspace"
|
|
1732
1918
|
]);
|
|
1919
|
+
let imageId;
|
|
1920
|
+
let cacheDir;
|
|
1921
|
+
if (params.cache) {
|
|
1922
|
+
const restoreStart = Date.now();
|
|
1923
|
+
step("Restoring the buildpack cache");
|
|
1924
|
+
let restored;
|
|
1925
|
+
try {
|
|
1926
|
+
imageId = await inspectBaseImageId(buildContainer);
|
|
1927
|
+
cacheScratch = (0, import_node_fs6.mkdtempSync)(
|
|
1928
|
+
(0, import_node_path6.join)(cacheScratchParent(), "vercel-cnb-cache-")
|
|
1929
|
+
);
|
|
1930
|
+
(0, import_node_fs6.chmodSync)(cacheScratch, 493);
|
|
1931
|
+
cacheDir = (0, import_node_path6.join)(cacheScratch, "cache");
|
|
1932
|
+
(0, import_node_fs6.mkdirSync)(cacheDir, { mode: 493 });
|
|
1933
|
+
restored = restoreBuildpackCache(
|
|
1934
|
+
params.cache.dir,
|
|
1935
|
+
imageId,
|
|
1936
|
+
cacheDir
|
|
1937
|
+
);
|
|
1938
|
+
chownTree(cacheDir, BUILD_USER_ID, BUILD_GROUP_ID);
|
|
1939
|
+
} catch (error) {
|
|
1940
|
+
cacheDir = void 0;
|
|
1941
|
+
restored = {
|
|
1942
|
+
status: "miss",
|
|
1943
|
+
reason: `setup_failed:${error.message.split("\n")[0]}`
|
|
1944
|
+
};
|
|
1945
|
+
}
|
|
1946
|
+
done(describeRestore(restored));
|
|
1947
|
+
recordRestore(lifecycleSpan, restored, Date.now() - restoreStart);
|
|
1948
|
+
}
|
|
1733
1949
|
const platformEnvMount = [
|
|
1734
1950
|
"--volume",
|
|
1735
1951
|
`${platformEnvDir}:/platform/env:ro`
|
|
@@ -1738,6 +1954,7 @@ var buildAndPushWithLifecycle = async (buildpack, params, span) => {
|
|
|
1738
1954
|
"--volume",
|
|
1739
1955
|
`${params.nodeToolchain.home}:${params.nodeToolchain.home}:ro`
|
|
1740
1956
|
] : [];
|
|
1957
|
+
const cacheMount = cacheDir ? ["--volume", `${cacheDir}:${CACHE_MOUNT_DIR}`] : [];
|
|
1741
1958
|
const lifecycleEnv = {
|
|
1742
1959
|
...process.env,
|
|
1743
1960
|
CNB_REGISTRY_AUTH: cnbRegistryAuth(params.credentials)
|
|
@@ -1770,14 +1987,17 @@ var buildAndPushWithLifecycle = async (buildpack, params, span) => {
|
|
|
1770
1987
|
`${orderDir}:${ORDER_MOUNT_DIR}:ro`,
|
|
1771
1988
|
...nodeToolchainMount,
|
|
1772
1989
|
...platformEnvMount,
|
|
1990
|
+
...cacheMount,
|
|
1773
1991
|
buildContainer,
|
|
1774
1992
|
"--",
|
|
1775
1993
|
"/cnb/lifecycle/creator",
|
|
1776
|
-
...creatorArgs(params.image, params.imageRef
|
|
1994
|
+
...creatorArgs(params.image, params.imageRef, {
|
|
1995
|
+
cacheDir: cacheDir ? CACHE_MOUNT_DIR : void 0
|
|
1996
|
+
})
|
|
1777
1997
|
],
|
|
1778
1998
|
lifecycleEnv
|
|
1779
1999
|
);
|
|
1780
|
-
const digest = readReportDigest((0,
|
|
2000
|
+
const digest = readReportDigest((0, import_node_fs6.readFileSync)(reportPath, "utf8"));
|
|
1781
2001
|
if (!digest) {
|
|
1782
2002
|
throw new Error(
|
|
1783
2003
|
`${buildpack.runtime} buildpack lifecycle did not report a digest.`
|
|
@@ -1785,6 +2005,12 @@ var buildAndPushWithLifecycle = async (buildpack, params, span) => {
|
|
|
1785
2005
|
}
|
|
1786
2006
|
done(`built and published ${params.imageRef}@${digest}`);
|
|
1787
2007
|
lifecycleSpan?.setAttributes({ "image.digest": digest });
|
|
2008
|
+
if (params.cache && imageId && cacheDir) {
|
|
2009
|
+
const saveStart = Date.now();
|
|
2010
|
+
const save = saveBuildpackCache(params.cache.dir, imageId, cacheDir);
|
|
2011
|
+
done(`${describeSave(save)} in ${elapsed(saveStart)}`);
|
|
2012
|
+
recordSave(lifecycleSpan, save, Date.now() - saveStart);
|
|
2013
|
+
}
|
|
1788
2014
|
return {
|
|
1789
2015
|
imageRef: params.imageRef,
|
|
1790
2016
|
digest,
|
|
@@ -1802,8 +2028,6 @@ var buildAndPushWithLifecycle = async (buildpack, params, span) => {
|
|
|
1802
2028
|
throw new Error(
|
|
1803
2029
|
[
|
|
1804
2030
|
`${buildpack.runtime} buildpack build failed via lifecycle/creator (${params.image.buildImage}).`,
|
|
1805
|
-
`Lifecycle archive: ${urls.lifecycle}`,
|
|
1806
|
-
...urls.buildpacks.map((url) => `Buildpack archive: ${url}`),
|
|
1807
2031
|
...hint ? [`The lifecycle exited with code ${exitCode}: ${hint}.`] : [],
|
|
1808
2032
|
"",
|
|
1809
2033
|
`Underlying error: ${error.message}`,
|
|
@@ -1813,10 +2037,16 @@ var buildAndPushWithLifecycle = async (buildpack, params, span) => {
|
|
|
1813
2037
|
);
|
|
1814
2038
|
} finally {
|
|
1815
2039
|
await removeContainer(buildContainer);
|
|
1816
|
-
for (const dir of [
|
|
2040
|
+
for (const dir of [
|
|
2041
|
+
cnbDir,
|
|
2042
|
+
reportDir,
|
|
2043
|
+
orderDir,
|
|
2044
|
+
platformEnvDir,
|
|
2045
|
+
cacheScratch
|
|
2046
|
+
]) {
|
|
1817
2047
|
if (dir) {
|
|
1818
2048
|
try {
|
|
1819
|
-
(0,
|
|
2049
|
+
(0, import_node_fs6.rmSync)(dir, { recursive: true, force: true });
|
|
1820
2050
|
} catch {
|
|
1821
2051
|
debug(`Could not remove Buildah build scratch directory ${dir}.`);
|
|
1822
2052
|
}
|
|
@@ -1828,10 +2058,10 @@ var buildAndPushWithLifecycle = async (buildpack, params, span) => {
|
|
|
1828
2058
|
};
|
|
1829
2059
|
|
|
1830
2060
|
// src/buildpacks/lifecycle/docker.ts
|
|
1831
|
-
var
|
|
1832
|
-
var
|
|
2061
|
+
var import_node_crypto5 = require("crypto");
|
|
2062
|
+
var import_node_fs7 = require("fs");
|
|
1833
2063
|
var import_node_os6 = require("os");
|
|
1834
|
-
var
|
|
2064
|
+
var import_node_path7 = require("path");
|
|
1835
2065
|
function localBuildImageDockerfile(buildImage, nodeMajor) {
|
|
1836
2066
|
const lines = [];
|
|
1837
2067
|
if (nodeMajor !== void 0) {
|
|
@@ -1850,7 +2080,7 @@ function localBuildImageDockerfile(buildImage, nodeMajor) {
|
|
|
1850
2080
|
`;
|
|
1851
2081
|
}
|
|
1852
2082
|
function localBuildImageTag(dockerfile) {
|
|
1853
|
-
const hash = (0,
|
|
2083
|
+
const hash = (0, import_node_crypto5.createHash)("sha256").update(dockerfile).digest("hex");
|
|
1854
2084
|
return `vercel-cnb-build:${hash.slice(0, 16)}`;
|
|
1855
2085
|
}
|
|
1856
2086
|
async function runDocker2(args, opts = {}) {
|
|
@@ -1876,9 +2106,9 @@ var buildAndPushWithLifecycleDocker = async (buildpack, params, span) => {
|
|
|
1876
2106
|
let stageDir;
|
|
1877
2107
|
const containers = [];
|
|
1878
2108
|
try {
|
|
1879
|
-
stageDir = (0,
|
|
1880
|
-
const cnbDir = (0,
|
|
1881
|
-
(0,
|
|
2109
|
+
stageDir = (0, import_node_fs7.mkdtempSync)((0, import_node_path7.join)((0, import_node_os6.tmpdir)(), "vercel-cnb-"));
|
|
2110
|
+
const cnbDir = (0, import_node_path7.join)(stageDir, "cnb");
|
|
2111
|
+
(0, import_node_fs7.mkdirSync)(cnbDir, { mode: 493 });
|
|
1882
2112
|
const orderDir = writeOrderDir(buildpack, stageDir);
|
|
1883
2113
|
const platformEnvDir = writePlatformEnvDir(
|
|
1884
2114
|
params.buildEnv,
|
|
@@ -1893,7 +2123,7 @@ var buildAndPushWithLifecycleDocker = async (buildpack, params, span) => {
|
|
|
1893
2123
|
params.nodeToolchain?.major
|
|
1894
2124
|
);
|
|
1895
2125
|
const buildImageTag = localBuildImageTag(dockerfile);
|
|
1896
|
-
const buildImageIdPath = (0,
|
|
2126
|
+
const buildImageIdPath = (0, import_node_path7.join)(stageDir, "build-image.id");
|
|
1897
2127
|
step(
|
|
1898
2128
|
`Preparing ${buildpack.runtime} ${params.image.version} build image` + (params.nodeToolchain ? ` with Node.js ${params.nodeToolchain.major}` : "")
|
|
1899
2129
|
);
|
|
@@ -1911,11 +2141,11 @@ var buildAndPushWithLifecycleDocker = async (buildpack, params, span) => {
|
|
|
1911
2141
|
],
|
|
1912
2142
|
{ input: dockerfile }
|
|
1913
2143
|
);
|
|
1914
|
-
const buildImageId = (0,
|
|
2144
|
+
const buildImageId = (0, import_node_fs7.readFileSync)(buildImageIdPath, "utf8").trim();
|
|
1915
2145
|
if (!/^sha256:[a-f0-9]{64}$/.test(buildImageId)) {
|
|
1916
2146
|
throw new Error("Docker build did not report a valid image ID.");
|
|
1917
2147
|
}
|
|
1918
|
-
const containerName = `vercel-cnb-${buildpack.runtime}-${process.pid}-${(0,
|
|
2148
|
+
const containerName = `vercel-cnb-${buildpack.runtime}-${process.pid}-${(0, import_node_crypto5.randomBytes)(8).toString("hex")}`;
|
|
1919
2149
|
const initContainerName = `${containerName}-init`;
|
|
1920
2150
|
containers.push(initContainerName);
|
|
1921
2151
|
await runDocker2([
|
|
@@ -1999,13 +2229,13 @@ var buildAndPushWithLifecycleDocker = async (buildpack, params, span) => {
|
|
|
1999
2229
|
`Building and publishing ${params.imageRef} via Vercel ${buildpack.runtime} buildpacks`
|
|
2000
2230
|
);
|
|
2001
2231
|
await runDocker2(["start", "--attach", containerName]);
|
|
2002
|
-
const reportPath = (0,
|
|
2232
|
+
const reportPath = (0, import_node_path7.join)(stageDir, "report.toml");
|
|
2003
2233
|
await runDocker2([
|
|
2004
2234
|
"cp",
|
|
2005
2235
|
`${containerName}:/platform-output/report.toml`,
|
|
2006
2236
|
reportPath
|
|
2007
2237
|
]);
|
|
2008
|
-
const digest = readReportDigest((0,
|
|
2238
|
+
const digest = readReportDigest((0, import_node_fs7.readFileSync)(reportPath, "utf8"));
|
|
2009
2239
|
if (!digest) {
|
|
2010
2240
|
throw new Error(
|
|
2011
2241
|
`${buildpack.runtime} buildpack lifecycle did not report a digest.`
|
|
@@ -2049,7 +2279,7 @@ var buildAndPushWithLifecycleDocker = async (buildpack, params, span) => {
|
|
|
2049
2279
|
}
|
|
2050
2280
|
if (stageDir) {
|
|
2051
2281
|
try {
|
|
2052
|
-
(0,
|
|
2282
|
+
(0, import_node_fs7.rmSync)(stageDir, { recursive: true, force: true });
|
|
2053
2283
|
} catch {
|
|
2054
2284
|
debug(
|
|
2055
2285
|
`Could not remove Docker build scratch directory ${stageDir}.`
|
|
@@ -2063,10 +2293,10 @@ var buildAndPushWithLifecycleDocker = async (buildpack, params, span) => {
|
|
|
2063
2293
|
|
|
2064
2294
|
// src/buildpacks/node-toolchain.ts
|
|
2065
2295
|
var import_build_utils4 = require("@vercel/build-utils");
|
|
2066
|
-
var
|
|
2067
|
-
var
|
|
2296
|
+
var import_node_fs8 = require("fs");
|
|
2297
|
+
var import_node_path8 = require("path");
|
|
2068
2298
|
async function selectNodeMajor(workPath, config, meta) {
|
|
2069
|
-
if (!(0,
|
|
2299
|
+
if (!(0, import_node_fs8.existsSync)((0, import_node_path8.join)(workPath, "package.json"))) {
|
|
2070
2300
|
return void 0;
|
|
2071
2301
|
}
|
|
2072
2302
|
const version2 = await (0, import_build_utils4.getNodeVersion)(workPath, void 0, config, meta);
|
|
@@ -2087,7 +2317,7 @@ async function resolveNodeToolchain(workPath, config, meta) {
|
|
|
2087
2317
|
return void 0;
|
|
2088
2318
|
}
|
|
2089
2319
|
for (const executable of ["node", "npm"]) {
|
|
2090
|
-
if (!(0,
|
|
2320
|
+
if (!(0, import_node_fs8.existsSync)((0, import_node_path8.join)(toolchain.home, "bin", executable))) {
|
|
2091
2321
|
throw new Error(
|
|
2092
2322
|
`The selected Node.js ${toolchain.version} installation is missing ${toolchain.home}/bin/${executable} in the build environment.`
|
|
2093
2323
|
);
|
|
@@ -2100,12 +2330,12 @@ async function resolveLocalNodeToolchain(workPath, config, meta) {
|
|
|
2100
2330
|
}
|
|
2101
2331
|
|
|
2102
2332
|
// src/buildpacks/registry.ts
|
|
2103
|
-
var
|
|
2104
|
-
var
|
|
2333
|
+
var import_node_fs10 = require("fs");
|
|
2334
|
+
var import_node_path10 = require("path");
|
|
2105
2335
|
|
|
2106
2336
|
// src/buildpacks/ruby.ts
|
|
2107
|
-
var
|
|
2108
|
-
var
|
|
2337
|
+
var import_node_fs9 = require("fs");
|
|
2338
|
+
var import_node_path9 = require("path");
|
|
2109
2339
|
var import_smol_toml2 = require("smol-toml");
|
|
2110
2340
|
var DEFAULT_RUBY_VERSION = "3.4";
|
|
2111
2341
|
var RUBY_IMAGE_REPOSITORY = "docker.io/library/ruby";
|
|
@@ -2130,10 +2360,10 @@ var ruby = {
|
|
|
2130
2360
|
return { version: version2, buildImage: image, runImage: image };
|
|
2131
2361
|
},
|
|
2132
2362
|
validate({ workPath, buildEnv }) {
|
|
2133
|
-
const gemfile = (0,
|
|
2134
|
-
if (!(0,
|
|
2363
|
+
const gemfile = (0, import_node_path9.join)(workPath, "Gemfile");
|
|
2364
|
+
if (!(0, import_node_fs9.existsSync)(gemfile))
|
|
2135
2365
|
return;
|
|
2136
|
-
if (!GEMFILE_RAILS_GEM_RE.test((0,
|
|
2366
|
+
if (!GEMFILE_RAILS_GEM_RE.test((0, import_node_fs9.readFileSync)(gemfile, "utf8")))
|
|
2137
2367
|
return;
|
|
2138
2368
|
if (buildEnv?.SECRET_KEY_BASE)
|
|
2139
2369
|
return;
|
|
@@ -2147,13 +2377,13 @@ function isValidVersion(version2) {
|
|
|
2147
2377
|
}
|
|
2148
2378
|
function selectRubyVersion(workPath) {
|
|
2149
2379
|
for (const name of RUBY_VERSION_FILES) {
|
|
2150
|
-
const file = (0,
|
|
2151
|
-
if ((0,
|
|
2152
|
-
return parseVersionFile(name, (0,
|
|
2380
|
+
const file = (0, import_node_path9.join)(workPath, name);
|
|
2381
|
+
if ((0, import_node_fs9.existsSync)(file)) {
|
|
2382
|
+
return parseVersionFile(name, (0, import_node_fs9.readFileSync)(file, "utf8"));
|
|
2153
2383
|
}
|
|
2154
2384
|
}
|
|
2155
|
-
const gemfile = (0,
|
|
2156
|
-
return (0,
|
|
2385
|
+
const gemfile = (0, import_node_path9.join)(workPath, "Gemfile");
|
|
2386
|
+
return (0, import_node_fs9.existsSync)(gemfile) ? parseGemfileRubyVersion((0, import_node_fs9.readFileSync)(gemfile, "utf8")) : void 0;
|
|
2157
2387
|
}
|
|
2158
2388
|
function parseVersionFile(name, contents) {
|
|
2159
2389
|
let version2;
|
|
@@ -2198,13 +2428,13 @@ function requestedBuildpack(config) {
|
|
|
2198
2428
|
}
|
|
2199
2429
|
function hasProjectMarkers(buildpack, workPath) {
|
|
2200
2430
|
return buildpack.projectMarkers.some(
|
|
2201
|
-
(name) => (0,
|
|
2431
|
+
(name) => (0, import_node_fs10.existsSync)((0, import_node_path10.join)(workPath, name))
|
|
2202
2432
|
);
|
|
2203
2433
|
}
|
|
2204
2434
|
|
|
2205
2435
|
// src/buildpacks/build.ts
|
|
2206
2436
|
async function buildAndPushBuildpack(params) {
|
|
2207
|
-
const sourceDir = (0,
|
|
2437
|
+
const sourceDir = (0, import_node_fs11.mkdtempSync)((0, import_node_path11.join)((0, import_node_os7.tmpdir)(), "vercel-cnb-source-"));
|
|
2208
2438
|
try {
|
|
2209
2439
|
step("Staging buildpack source files");
|
|
2210
2440
|
await stageWorkspace(params, sourceDir);
|
|
@@ -2249,6 +2479,12 @@ async function buildAndPushBuildpack(params) {
|
|
|
2249
2479
|
"image.ref": target.imageRef,
|
|
2250
2480
|
"registry.username": target.username
|
|
2251
2481
|
});
|
|
2482
|
+
const cache = params.cache && engine.name === "buildah" ? { dir: buildpackCacheDir(params) } : void 0;
|
|
2483
|
+
if (cache)
|
|
2484
|
+
debug(`buildpack cache: ${cache.dir}`);
|
|
2485
|
+
buildSpan?.setAttributes({
|
|
2486
|
+
"buildpack.cache.enabled": String(Boolean(cache))
|
|
2487
|
+
});
|
|
2252
2488
|
return engine.withRuntime(buildSpan, async () => {
|
|
2253
2489
|
await withSpan(
|
|
2254
2490
|
buildSpan,
|
|
@@ -2298,7 +2534,8 @@ async function buildAndPushBuildpack(params) {
|
|
|
2298
2534
|
imageRef: target.imageRef,
|
|
2299
2535
|
credentials,
|
|
2300
2536
|
buildEnv: params.buildEnv,
|
|
2301
|
-
nodeToolchain
|
|
2537
|
+
nodeToolchain,
|
|
2538
|
+
cache
|
|
2302
2539
|
},
|
|
2303
2540
|
buildSpan
|
|
2304
2541
|
);
|
|
@@ -2314,7 +2551,7 @@ async function buildAndPushBuildpack(params) {
|
|
|
2314
2551
|
);
|
|
2315
2552
|
} finally {
|
|
2316
2553
|
try {
|
|
2317
|
-
(0,
|
|
2554
|
+
(0, import_node_fs11.rmSync)(sourceDir, { recursive: true, force: true });
|
|
2318
2555
|
} catch {
|
|
2319
2556
|
debug(`Could not remove buildpack source snapshot ${sourceDir}.`);
|
|
2320
2557
|
}
|
|
@@ -2322,8 +2559,8 @@ async function buildAndPushBuildpack(params) {
|
|
|
2322
2559
|
}
|
|
2323
2560
|
|
|
2324
2561
|
// src/image-source.ts
|
|
2325
|
-
var
|
|
2326
|
-
var
|
|
2562
|
+
var import_node_fs12 = require("fs");
|
|
2563
|
+
var import_node_path12 = __toESM(require("path"));
|
|
2327
2564
|
var DETECT_SENTINEL = "<detect>";
|
|
2328
2565
|
function resolveImageSource(options, context) {
|
|
2329
2566
|
const { config, workPath, entrypoint } = options;
|
|
@@ -2337,8 +2574,8 @@ function resolveImageSource(options, context) {
|
|
|
2337
2574
|
}
|
|
2338
2575
|
const dockerfileConfigured = entrypointRef && isDockerfileRef(entrypointRef) ? entrypointRef : findDockerfile(workPath);
|
|
2339
2576
|
const dockerfileRel = dockerfileConfigured ?? "Dockerfile";
|
|
2340
|
-
const dockerfilePath =
|
|
2341
|
-
const hasDockerfile = dockerfileConfigured !== void 0 || !buildpack && (0,
|
|
2577
|
+
const dockerfilePath = import_node_path12.default.join(workPath, dockerfileRel);
|
|
2578
|
+
const hasDockerfile = dockerfileConfigured !== void 0 || !buildpack && (0, import_node_fs12.existsSync)(dockerfilePath);
|
|
2342
2579
|
if (hasDockerfile) {
|
|
2343
2580
|
return { kind: "dockerfile", dockerfileRel, dockerfilePath };
|
|
2344
2581
|
}
|
|
@@ -2356,9 +2593,9 @@ function resolveImageSource(options, context) {
|
|
|
2356
2593
|
|
|
2357
2594
|
// src/dev.ts
|
|
2358
2595
|
var import_node_child_process3 = require("child_process");
|
|
2359
|
-
var
|
|
2596
|
+
var import_node_fs13 = require("fs");
|
|
2360
2597
|
var import_node_os8 = require("os");
|
|
2361
|
-
var
|
|
2598
|
+
var import_node_path13 = __toESM(require("path"));
|
|
2362
2599
|
var HOST_ONLY_ENV = /* @__PURE__ */ new Set([
|
|
2363
2600
|
"TMPDIR",
|
|
2364
2601
|
"TMP",
|
|
@@ -2388,8 +2625,8 @@ function isHostOnlyEnvVar(key) {
|
|
|
2388
2625
|
return HOST_ONLY_ENV.has(key) || key.startsWith("__") || key.startsWith("XPC_") || key.startsWith("SSH_") || key.startsWith("Apple");
|
|
2389
2626
|
}
|
|
2390
2627
|
function writeEnvFile(env) {
|
|
2391
|
-
const dir = (0,
|
|
2392
|
-
const file =
|
|
2628
|
+
const dir = (0, import_node_fs13.mkdtempSync)(import_node_path13.default.join((0, import_node_os8.tmpdir)(), "vercel-container-dev-env-"));
|
|
2629
|
+
const file = import_node_path13.default.join(dir, "env");
|
|
2393
2630
|
const lines = [];
|
|
2394
2631
|
for (const [key, value] of Object.entries(env)) {
|
|
2395
2632
|
if (value.includes("\n")) {
|
|
@@ -2397,7 +2634,7 @@ function writeEnvFile(env) {
|
|
|
2397
2634
|
}
|
|
2398
2635
|
lines.push(`${key}=${value}`);
|
|
2399
2636
|
}
|
|
2400
|
-
(0,
|
|
2637
|
+
(0, import_node_fs13.writeFileSync)(file, `${lines.join("\n")}
|
|
2401
2638
|
`);
|
|
2402
2639
|
return file;
|
|
2403
2640
|
}
|
|
@@ -2422,7 +2659,7 @@ function emit(out, line) {
|
|
|
2422
2659
|
}
|
|
2423
2660
|
}
|
|
2424
2661
|
function runForwarded(cmd, args, out, opts = {}) {
|
|
2425
|
-
return new Promise((
|
|
2662
|
+
return new Promise((resolve4, reject) => {
|
|
2426
2663
|
const child = (0, import_node_child_process3.spawn)(cmd, args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
2427
2664
|
let stdout = "";
|
|
2428
2665
|
let stderr = "";
|
|
@@ -2459,7 +2696,7 @@ function runForwarded(cmd, args, out, opts = {}) {
|
|
|
2459
2696
|
});
|
|
2460
2697
|
child.on("close", (code) => {
|
|
2461
2698
|
if (code === 0) {
|
|
2462
|
-
|
|
2699
|
+
resolve4({ stdout });
|
|
2463
2700
|
} else {
|
|
2464
2701
|
const detail = stderr.trim().split("\n").slice(-5).join("\n");
|
|
2465
2702
|
reject(
|
|
@@ -2488,14 +2725,14 @@ async function resolveDevImage(options, out, span) {
|
|
|
2488
2725
|
);
|
|
2489
2726
|
}
|
|
2490
2727
|
const { dockerfilePath } = source;
|
|
2491
|
-
if (!(0,
|
|
2728
|
+
if (!(0, import_node_fs13.existsSync)(dockerfilePath)) {
|
|
2492
2729
|
throw new Error(
|
|
2493
2730
|
`Dockerfile not found at "${dockerfilePath}" for container service.`
|
|
2494
2731
|
);
|
|
2495
2732
|
}
|
|
2496
2733
|
const serviceName = options.service?.name ?? "service";
|
|
2497
2734
|
const tag = devImageTag(serviceName);
|
|
2498
|
-
const contextDir =
|
|
2735
|
+
const contextDir = import_node_path13.default.dirname(dockerfilePath);
|
|
2499
2736
|
const buildArgFlags2 = [];
|
|
2500
2737
|
const buildEnv = options.meta?.buildEnv ?? {};
|
|
2501
2738
|
for (const [key, value] of Object.entries(buildEnv)) {
|
|
@@ -2700,7 +2937,7 @@ async function startContainer(options, reuseKey) {
|
|
|
2700
2937
|
}
|
|
2701
2938
|
});
|
|
2702
2939
|
const cleanupEnvFile = () => {
|
|
2703
|
-
(0,
|
|
2940
|
+
(0, import_node_fs13.rmSync)(import_node_path13.default.dirname(envFilePath), { recursive: true, force: true });
|
|
2704
2941
|
};
|
|
2705
2942
|
const shutdown = async () => {
|
|
2706
2943
|
runningContainers.delete(reuseKey);
|
|
@@ -2733,7 +2970,7 @@ async function startContainer(options, reuseKey) {
|
|
|
2733
2970
|
break;
|
|
2734
2971
|
} catch (err) {
|
|
2735
2972
|
lastErr = err;
|
|
2736
|
-
await new Promise((
|
|
2973
|
+
await new Promise((resolve4) => setTimeout(resolve4, 250));
|
|
2737
2974
|
}
|
|
2738
2975
|
}
|
|
2739
2976
|
if (hostPort === void 0) {
|
|
@@ -2777,29 +3014,24 @@ async function startContainer(options, reuseKey) {
|
|
|
2777
3014
|
|
|
2778
3015
|
// src/prepare-cache.ts
|
|
2779
3016
|
var import_build_utils5 = require("@vercel/build-utils");
|
|
2780
|
-
var
|
|
2781
|
-
var
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
debug("layer cache disabled (VERCEL_VCR_DISABLE_LAYER_CACHE)");
|
|
2787
|
-
return {};
|
|
2788
|
-
}
|
|
2789
|
-
if (!isBuildContainer()) {
|
|
2790
|
-
debug("skipping container layer cache (not in build container)");
|
|
2791
|
-
return {};
|
|
2792
|
-
}
|
|
2793
|
-
if (!(0, import_node_fs13.existsSync)(BUILDAH_GRAPH_ROOT)) {
|
|
2794
|
-
debug(`no buildah store to cache at ${BUILDAH_GRAPH_ROOT}`);
|
|
3017
|
+
var import_node_fs14 = require("fs");
|
|
3018
|
+
var import_node_path14 = require("path");
|
|
3019
|
+
async function prepareCache(options) {
|
|
3020
|
+
const root = (0, import_node_path14.resolve)(options.repoRootPath || options.workPath);
|
|
3021
|
+
if (!buildpackCacheEnabled()) {
|
|
3022
|
+
(0, import_node_fs14.rmSync)((0, import_node_path14.join)(root, BUILDPACK_CACHE_DIR), { recursive: true, force: true });
|
|
2795
3023
|
return {};
|
|
2796
3024
|
}
|
|
2797
3025
|
const start = Date.now();
|
|
2798
|
-
const files = await (0, import_build_utils5.glob)(`${
|
|
3026
|
+
const files = await (0, import_build_utils5.glob)(`${BUILDPACK_CACHE_DIR}/**`, root);
|
|
2799
3027
|
const count = Object.keys(files).length;
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
3028
|
+
if (count > 0) {
|
|
3029
|
+
info(
|
|
3030
|
+
`cached buildpack layers: ${count} file${count === 1 ? "" : "s"} under ${BUILDPACK_CACHE_DIR} in ${Date.now() - start}ms`
|
|
3031
|
+
);
|
|
3032
|
+
} else {
|
|
3033
|
+
debug("no buildpack cache to persist");
|
|
3034
|
+
}
|
|
2803
3035
|
return files;
|
|
2804
3036
|
}
|
|
2805
3037
|
|
|
@@ -2997,11 +3229,14 @@ async function resolveImageHandler(options, source, span) {
|
|
|
2997
3229
|
buildpack,
|
|
2998
3230
|
files: options.files,
|
|
2999
3231
|
workPath: options.workPath,
|
|
3232
|
+
repoRootPath: options.repoRootPath,
|
|
3233
|
+
service: options.service,
|
|
3000
3234
|
repository: repository2,
|
|
3001
3235
|
tag: tag2,
|
|
3002
3236
|
config,
|
|
3003
3237
|
meta,
|
|
3004
3238
|
buildEnv: buildArgsFromEnv(meta?.buildEnv),
|
|
3239
|
+
cache: buildpackCacheEnabled(),
|
|
3005
3240
|
parentSpan: span
|
|
3006
3241
|
});
|
|
3007
3242
|
}
|
|
@@ -3009,22 +3244,22 @@ async function resolveImageHandler(options, source, span) {
|
|
|
3009
3244
|
if (meta?.isDev) {
|
|
3010
3245
|
const serviceName2 = options.service?.name;
|
|
3011
3246
|
const tag2 = devImageTag(
|
|
3012
|
-
serviceName2 ??
|
|
3247
|
+
serviceName2 ?? import_node_path15.default.basename(dockerfileRel).split(".")[0]
|
|
3013
3248
|
);
|
|
3014
3249
|
span?.setAttributes({ "container.mode": "dev", "image.tag": tag2 });
|
|
3015
3250
|
return tag2;
|
|
3016
3251
|
}
|
|
3017
|
-
if (!(0,
|
|
3252
|
+
if (!(0, import_node_fs15.existsSync)(dockerfilePath)) {
|
|
3018
3253
|
throw new Error(
|
|
3019
3254
|
`Dockerfile not found at "${dockerfilePath}" for container service.`
|
|
3020
3255
|
);
|
|
3021
3256
|
}
|
|
3022
3257
|
const serviceName = options.service?.name;
|
|
3023
3258
|
const repository = sanitizeRepository(
|
|
3024
|
-
serviceName ??
|
|
3259
|
+
serviceName ?? import_node_path15.default.basename(dockerfileRel).split(".")[0]
|
|
3025
3260
|
);
|
|
3026
3261
|
const tag = resolveImageTag();
|
|
3027
|
-
const contextDir =
|
|
3262
|
+
const contextDir = import_node_path15.default.dirname(dockerfilePath);
|
|
3028
3263
|
const buildArgs = buildArgsFromEnv(meta?.buildEnv);
|
|
3029
3264
|
span?.setAttributes({
|
|
3030
3265
|
"container.mode": "build_and_push",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vercel/container",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.1.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"homepage": "https://vercel.com/docs",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"build": "node ../../utils/build-builder.mjs",
|
|
32
32
|
"type-check": "tsc --noEmit",
|
|
33
33
|
"test": "vitest run --config ../../vitest.config.mts",
|
|
34
|
-
"test-unit": "vitest run --config ../../vitest.config.mts test/unit.test.ts test/diagnostics.test.ts test/workspace.test.ts test/lifecycle-docker.test.ts test/ruby-version.test.ts test/docker-push.test.ts",
|
|
34
|
+
"test-unit": "vitest run --config ../../vitest.config.mts test/unit.test.ts test/diagnostics.test.ts test/workspace.test.ts test/lifecycle-docker.test.ts test/ruby-version.test.ts test/docker-push.test.ts test/cache.test.ts",
|
|
35
35
|
"test-e2e": "vitest run --config ../../vitest.config.mts test/e2e.test.ts"
|
|
36
36
|
}
|
|
37
37
|
}
|