@vercel/container 19.1.2 → 20.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.
Files changed (2) hide show
  1. package/dist/index.js +123 -99
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -1251,7 +1251,9 @@ var IMAGE_ID_FILE = "image-id";
1251
1251
  function buildpackCacheDir(options) {
1252
1252
  const root = (0, import_node_path4.resolve)(options.repoRootPath || options.workPath);
1253
1253
  const app = (0, import_node_path4.relative)(root, (0, import_node_path4.resolve)(options.workPath)).split(import_node_path4.sep).join("/") || ".";
1254
- const key = (0, import_node_crypto2.createHash)("sha256").update(JSON.stringify([app, options.service?.name ?? null])).digest("hex").slice(0, 32);
1254
+ const daemon = options.config?.daemon;
1255
+ const owner = daemon ? { daemon: daemon.name } : options.service?.name ?? null;
1256
+ const key = (0, import_node_crypto2.createHash)("sha256").update(JSON.stringify([app, owner])).digest("hex").slice(0, 32);
1255
1257
  return (0, import_node_path4.join)(root, BUILDPACK_CACHE_DIR, key);
1256
1258
  }
1257
1259
  async function restoreBuildpackCache(dir, cacheKey, cacheDir) {
@@ -1423,18 +1425,18 @@ var distribution_default = {
1423
1425
  buildpacks: {
1424
1426
  ruby: {
1425
1427
  id: "vercel/ruby",
1426
- version: "0.3.1",
1427
- sha256: "359615b41797247e5158c7bbcd97763322fcca6836823acd6e981d4c89d432a7"
1428
+ version: "0.3.2",
1429
+ sha256: "c0e8439800b9354f24028168869315e714650275ecdd4a8a85bd4e7659890a64"
1428
1430
  },
1429
1431
  go: {
1430
1432
  id: "vercel/go",
1431
- version: "0.2.1",
1432
- sha256: "6013ede7620734cb20885d3a6aecd7f14e364e941862a3074340cf1bbe648cc0"
1433
+ version: "0.3.0",
1434
+ sha256: "748ac1fad8164467dfee92face04b2d5bf2942d8762624625f473fb41bfa2bdb"
1433
1435
  },
1434
1436
  rust: {
1435
1437
  id: "vercel/rust",
1436
- version: "0.2.2",
1437
- sha256: "e6c1d59f759599bacdcbf5f077b6a5bba6e557481827fe23045925b9c2d39032"
1438
+ version: "0.3.0",
1439
+ sha256: "624fd0cddecd31197eef634342d3ea0e77ce0d5d8e10bbb582aa143edc88ca3e"
1438
1440
  }
1439
1441
  }
1440
1442
  };
@@ -1638,10 +1640,17 @@ async function stageWorkspace({ files, workPath }, destinationDir) {
1638
1640
  function writePlatformEnvDir(buildEnv, config, parentDir = (0, import_node_os4.tmpdir)()) {
1639
1641
  const environment = { ...buildEnv };
1640
1642
  delete environment.VERCEL_NODE_HOME;
1643
+ delete environment.VERCEL_ENTRYPOINT;
1641
1644
  delete environment.VERCEL_COMMAND;
1642
1645
  if (config.nodeHome) {
1643
1646
  environment.VERCEL_NODE_HOME = config.nodeHome;
1644
1647
  }
1648
+ if (config.entrypoint) {
1649
+ environment.VERCEL_ENTRYPOINT = config.entrypoint;
1650
+ }
1651
+ if (config.command) {
1652
+ environment.VERCEL_COMMAND = JSON.stringify(config.command);
1653
+ }
1645
1654
  const dir = (0, import_node_fs5.mkdtempSync)((0, import_node_path5.join)(parentDir, "vercel-cnb-env-"));
1646
1655
  (0, import_node_fs5.chmodSync)(dir, 493);
1647
1656
  for (const [key, value] of Object.entries(environment)) {
@@ -1668,6 +1677,7 @@ function readReportDigest(report) {
1668
1677
  }
1669
1678
  return digest;
1670
1679
  }
1680
+ var BUILDPACK_FAILED_EXIT_CODE = 51;
1671
1681
  function describeCreatorExitCode(code) {
1672
1682
  if (code === void 0)
1673
1683
  return void 0;
@@ -1682,7 +1692,7 @@ function describeCreatorExitCode(code) {
1682
1692
  return "the analyze phase failed";
1683
1693
  if (code >= 40 && code <= 49)
1684
1694
  return "the restore phase failed";
1685
- if (code === 51) {
1695
+ if (code === BUILDPACK_FAILED_EXIT_CODE) {
1686
1696
  return "a buildpack failed while building the app (e.g. installing dependencies) \u2014 its error is in the build output above";
1687
1697
  }
1688
1698
  if (code >= 50 && code <= 59)
@@ -1692,6 +1702,27 @@ function describeCreatorExitCode(code) {
1692
1702
  }
1693
1703
  return void 0;
1694
1704
  }
1705
+ function lifecycleFailure(error, context) {
1706
+ const exitCode = error.exitCode;
1707
+ const hint = describeCreatorExitCode(exitCode);
1708
+ context.span?.setAttributes({
1709
+ ...exitCode !== void 0 ? { "buildpack.lifecycle.exit_code": String(exitCode) } : {},
1710
+ ...hint ? { "buildpack.lifecycle.failure_phase": hint } : {}
1711
+ });
1712
+ return Object.assign(
1713
+ new Error(
1714
+ [
1715
+ `${context.buildpack.runtime} buildpack build failed via ${context.via} (${context.buildImage}).`,
1716
+ ...hint ? [`The lifecycle exited with code ${exitCode}: ${hint}.`] : [],
1717
+ "",
1718
+ `Underlying error: ${error.message}`,
1719
+ "",
1720
+ `Buildpack project is ${context.workPath}`
1721
+ ].join("\n")
1722
+ ),
1723
+ { exitCode }
1724
+ );
1725
+ }
1695
1726
  function writeOrderDir(buildpack, parentDir = (0, import_node_os4.tmpdir)()) {
1696
1727
  const order = {
1697
1728
  order: [
@@ -2027,7 +2058,9 @@ async function buildAndPushWithLifecycle(buildpack, params, span) {
2027
2058
  (0, import_node_fs6.chmodSync)(cnbDir, 493);
2028
2059
  orderDir = writeOrderDir(buildpack);
2029
2060
  platformEnvDir = writePlatformEnvDir(params.buildEnv, {
2030
- nodeHome: params.nodeToolchain?.home
2061
+ nodeHome: params.nodeToolchain?.home,
2062
+ entrypoint: params.entrypoint,
2063
+ command: params.command
2031
2064
  });
2032
2065
  const registrySetup = params.prepareRegistry?.();
2033
2066
  const containerReady = prepareBuildContainer(
@@ -2138,22 +2171,13 @@ async function buildAndPushWithLifecycle(buildpack, params, span) {
2138
2171
  } catch (error) {
2139
2172
  if (error instanceof RegistrySetupFailure)
2140
2173
  throw error.reason;
2141
- const exitCode = error.exitCode;
2142
- const hint = describeCreatorExitCode(exitCode);
2143
- lifecycleSpan?.setAttributes({
2144
- ...exitCode !== void 0 ? { "buildpack.lifecycle.exit_code": String(exitCode) } : {},
2145
- ...hint ? { "buildpack.lifecycle.failure_phase": hint } : {}
2174
+ throw lifecycleFailure(error, {
2175
+ buildpack,
2176
+ via: "lifecycle/creator",
2177
+ buildImage: params.image.buildImage,
2178
+ workPath: params.workPath,
2179
+ span: lifecycleSpan
2146
2180
  });
2147
- throw new Error(
2148
- [
2149
- `${buildpack.runtime} buildpack build failed via lifecycle/creator (${params.image.buildImage}).`,
2150
- ...hint ? [`The lifecycle exited with code ${exitCode}: ${hint}.`] : [],
2151
- "",
2152
- `Underlying error: ${error.message}`,
2153
- "",
2154
- `Buildpack project is ${params.workPath}`
2155
- ].join("\n")
2156
- );
2157
2181
  } finally {
2158
2182
  containerRemoval ??= removeContainerInBackground(buildContainer);
2159
2183
  for (const dir of [
@@ -2232,7 +2256,11 @@ var buildAndPushWithLifecycleDocker = async (buildpack, params, span) => {
2232
2256
  const orderDir = writeOrderDir(buildpack, stageDir);
2233
2257
  const platformEnvDir = writePlatformEnvDir(
2234
2258
  params.buildEnv,
2235
- { nodeHome: params.nodeToolchain?.home },
2259
+ {
2260
+ nodeHome: params.nodeToolchain?.home,
2261
+ entrypoint: params.entrypoint,
2262
+ command: params.command
2263
+ },
2236
2264
  stageDir
2237
2265
  );
2238
2266
  step("Fetching the CNB lifecycle and buildpacks...");
@@ -2371,22 +2399,13 @@ var buildAndPushWithLifecycleDocker = async (buildpack, params, span) => {
2371
2399
  runtimeVersion: params.image.version
2372
2400
  };
2373
2401
  } catch (error) {
2374
- const exitCode = error.exitCode;
2375
- const hint = describeCreatorExitCode(exitCode);
2376
- lifecycleSpan?.setAttributes({
2377
- ...exitCode !== void 0 ? { "buildpack.lifecycle.exit_code": String(exitCode) } : {},
2378
- ...hint ? { "buildpack.lifecycle.failure_phase": hint } : {}
2402
+ throw lifecycleFailure(error, {
2403
+ buildpack,
2404
+ via: "docker",
2405
+ buildImage: params.image.buildImage,
2406
+ workPath: params.workPath,
2407
+ span: lifecycleSpan
2379
2408
  });
2380
- throw new Error(
2381
- [
2382
- `${buildpack.runtime} buildpack build failed via docker (${params.image.buildImage}).`,
2383
- ...hint ? [`The lifecycle exited with code ${exitCode}: ${hint}.`] : [],
2384
- "",
2385
- `Underlying error: ${error.message}`,
2386
- "",
2387
- `Buildpack project is ${params.workPath}`
2388
- ].join("\n")
2389
- );
2390
2409
  } finally {
2391
2410
  for (const container of containers.reverse()) {
2392
2411
  try {
@@ -2466,7 +2485,6 @@ var GO_CANDIDATE_ENTRYPOINTS = [
2466
2485
  "cmd/api/main.go",
2467
2486
  "cmd/server/main.go"
2468
2487
  ];
2469
- var GO_TARGET_ENV = "VERCEL_GO_TARGET";
2470
2488
  var VERSION_RE = /^(0|[1-9]\d*)\.(0|[1-9]\d*)(?:\.(0|[1-9]\d*))?$/;
2471
2489
  var GO_DIRECTIVE_RE = /^\s*go[ \t]+(\S+)[ \t]*(?:\/\/[^\r\n]*)?$/m;
2472
2490
  var TOOLCHAIN_DIRECTIVE_RE = /^\s*toolchain[ \t]+go(\S+)[ \t]*(?:\/\/[^\r\n]*)?$/m;
@@ -2496,32 +2514,6 @@ function selectGoVersion(workPath) {
2496
2514
  const declared = [toolchain, minimum].filter((version2) => version2 !== void 0).sort((a, b) => compareImageVersions(b, a));
2497
2515
  return declared[0]?.tag ?? DEFAULT_GO_VERSION;
2498
2516
  }
2499
- function packageDirectory(entrypoint) {
2500
- const path4 = entrypoint.replace(/\\/g, "/");
2501
- if (import_node_path9.posix.isAbsolute(path4) || path4.split("/").includes("..")) {
2502
- throw new Error(
2503
- `Invalid Go entrypoint ${JSON.stringify(entrypoint)}: it must be a path inside the service root.`
2504
- );
2505
- }
2506
- const normalized = import_node_path9.posix.normalize(path4).replace(/\/+$/, "");
2507
- const directory = normalized.endsWith(".go") ? import_node_path9.posix.dirname(normalized) : normalized;
2508
- return directory === "." ? "." : `./${directory}`;
2509
- }
2510
- function selectGoTarget({
2511
- workPath,
2512
- config,
2513
- buildEnv
2514
- }) {
2515
- const entrypoint = readString(config?.buildpackEntrypoint);
2516
- if (entrypoint)
2517
- return packageDirectory(entrypoint);
2518
- if (buildEnv && GO_TARGET_ENV in buildEnv)
2519
- return void 0;
2520
- const candidate = GO_CANDIDATE_ENTRYPOINTS.find(
2521
- (name) => (0, import_node_fs9.existsSync)((0, import_node_path9.join)(workPath, name))
2522
- );
2523
- return candidate ? packageDirectory(candidate) : void 0;
2524
- }
2525
2517
  var go = {
2526
2518
  runtime: "go",
2527
2519
  projectMarkers: ["go.mod"],
@@ -2534,9 +2526,19 @@ var go = {
2534
2526
  runImage: GO_RUN_IMAGE
2535
2527
  };
2536
2528
  },
2537
- platformEnv(params) {
2538
- const target = selectGoTarget(params);
2539
- return target ? { [GO_TARGET_ENV]: target } : {};
2529
+ defaultEntrypoint({ workPath, zeroConfig }) {
2530
+ const candidate = GO_CANDIDATE_ENTRYPOINTS.find(
2531
+ (name) => (0, import_node_fs9.existsSync)((0, import_node_path9.join)(workPath, name))
2532
+ );
2533
+ if (candidate)
2534
+ return import_node_path9.posix.dirname(candidate);
2535
+ if (zeroConfig) {
2536
+ const last = GO_CANDIDATE_ENTRYPOINTS.length - 1;
2537
+ throw new Error(
2538
+ `Couldn't find the Go program to build. Add ${GO_CANDIDATE_ENTRYPOINTS.slice(0, last).join(", ")}, or ${GO_CANDIDATE_ENTRYPOINTS[last]}, or set the VERCEL_ENTRYPOINT environment variable to its package directory or a .go file in it.`
2539
+ );
2540
+ }
2541
+ return void 0;
2540
2542
  }
2541
2543
  };
2542
2544
 
@@ -2650,6 +2652,9 @@ var rust = {
2650
2652
  buildImage: `${RUST_IMAGE_REPOSITORY}:${version2}-${RUST_BUILD_IMAGE_DISTRO}`,
2651
2653
  runImage: RUST_RUN_IMAGE
2652
2654
  };
2655
+ },
2656
+ defaultEntrypoint({ workPath, zeroConfig }) {
2657
+ return zeroConfig && (0, import_node_fs11.existsSync)((0, import_node_path11.join)(workPath, "src/main.rs")) ? "src/main.rs" : void 0;
2653
2658
  }
2654
2659
  };
2655
2660
  function selectRustVersion(workPath) {
@@ -2705,6 +2710,14 @@ function hasProjectMarkers(buildpack, workPath) {
2705
2710
  }
2706
2711
 
2707
2712
  // src/buildpacks/build.ts
2713
+ function selectEntrypoint(params, sourceDir) {
2714
+ const configured = readString(params.config.buildpackEntrypoint);
2715
+ if (configured !== void 0)
2716
+ return configured;
2717
+ const zeroConfig = params.service === void 0;
2718
+ const fromEnv = zeroConfig ? readString(params.buildEnv?.VERCEL_ENTRYPOINT) : void 0;
2719
+ return fromEnv ?? params.buildpack.defaultEntrypoint?.({ workPath: sourceDir, zeroConfig });
2720
+ }
2708
2721
  async function buildAndPushBuildpack(params) {
2709
2722
  const sourceDir = (0, import_node_fs13.mkdtempSync)((0, import_node_path13.join)((0, import_node_os7.tmpdir)(), "vercel-cnb-source-"));
2710
2723
  try {
@@ -2720,6 +2733,12 @@ async function buildAndPushBuildpack(params) {
2720
2733
  workPath: sourceDir,
2721
2734
  buildEnv: params.buildEnv
2722
2735
  });
2736
+ const entrypoint = selectEntrypoint(params, sourceDir);
2737
+ if (entrypoint !== void 0) {
2738
+ debug(
2739
+ `Passing VERCEL_ENTRYPOINT=${entrypoint} to the ${params.buildpack.runtime} buildpack`
2740
+ );
2741
+ }
2723
2742
  const buildCommand = readString(params.config.buildCommand);
2724
2743
  if (buildCommand?.trim()) {
2725
2744
  warn(
@@ -2729,15 +2748,6 @@ async function buildAndPushBuildpack(params) {
2729
2748
  const prereleaseUrl = getPrereleaseUrl();
2730
2749
  const buildpack = prereleaseUrl ? await withPrereleaseBuildpack(params.buildpack, prereleaseUrl) : params.buildpack;
2731
2750
  const image = await buildpack.resolveImage(sourceDir);
2732
- const derivedEnv = buildpack.platformEnv?.({
2733
- workPath: sourceDir,
2734
- config: params.config,
2735
- buildEnv: params.buildEnv
2736
- }) ?? {};
2737
- for (const [key, value] of Object.entries(derivedEnv)) {
2738
- debug(`Passing ${key}=${value} to the ${buildpack.runtime} buildpack`);
2739
- }
2740
- const buildEnv = { ...params.buildEnv, ...derivedEnv };
2741
2751
  const nodeToolchain = engine.name === "buildah" ? await resolveNodeToolchain(sourceDir, params.config, params.meta) : await resolveLocalNodeToolchain(
2742
2752
  sourceDir,
2743
2753
  params.config,
@@ -2819,9 +2829,11 @@ async function buildAndPushBuildpack(params) {
2819
2829
  image,
2820
2830
  imageRef: target.imageRef,
2821
2831
  credentials,
2822
- buildEnv,
2832
+ buildEnv: params.buildEnv,
2823
2833
  nodeToolchain,
2824
- cache
2834
+ cache,
2835
+ entrypoint,
2836
+ command: params.config.daemon?.command
2825
2837
  };
2826
2838
  let result;
2827
2839
  if (engine.name === "buildah") {
@@ -2871,6 +2883,9 @@ function resolveImageSource(options, context) {
2871
2883
  "Buildpack builds are selected by Vercel from the project's framework or the service's runtime; `buildpack` is not a `builds` configuration option."
2872
2884
  );
2873
2885
  }
2886
+ if (buildpack && (config.daemon || readString(config.buildpackEntrypoint))) {
2887
+ return { kind: "buildpack", buildpack };
2888
+ }
2874
2889
  const dockerfileConfigured = entrypointRef && isDockerfileRef(entrypointRef) ? entrypointRef : findDockerfile(workPath);
2875
2890
  const dockerfileRel = dockerfileConfigured ?? "Dockerfile";
2876
2891
  const dockerfilePath = import_node_path14.default.join(workPath, dockerfileRel);
@@ -3489,6 +3504,7 @@ async function buildAndPushImage(params) {
3489
3504
  }
3490
3505
  async function resolveImageHandler(options, source, span) {
3491
3506
  const { config, meta } = options;
3507
+ const { daemon } = config;
3492
3508
  span?.setAttributes({
3493
3509
  "container.has_dockerfile": toTag(source.kind === "dockerfile"),
3494
3510
  "container.is_dev": toTag(Boolean(meta?.isDev))
@@ -3509,9 +3525,7 @@ async function resolveImageHandler(options, source, span) {
3509
3525
  });
3510
3526
  return tag3;
3511
3527
  }
3512
- const repository2 = sanitizeRepository(
3513
- options.service?.name ?? buildpack.runtime
3514
- );
3528
+ const repository2 = daemon ? (0, import_build_utils6.getDaemonImageRepository)(daemon.name) : sanitizeRepository(options.service?.name ?? buildpack.runtime);
3515
3529
  const tag2 = resolveImageTag();
3516
3530
  span?.setAttributes({
3517
3531
  "container.mode": "buildpack-build-and-push",
@@ -3519,19 +3533,28 @@ async function resolveImageHandler(options, source, span) {
3519
3533
  "container.repository": repository2,
3520
3534
  "image.tag": tag2
3521
3535
  });
3522
- return buildAndPushBuildpack({
3523
- buildpack,
3524
- files: options.files,
3525
- workPath: options.workPath,
3526
- repoRootPath: options.repoRootPath,
3527
- service: options.service,
3528
- repository: repository2,
3529
- tag: tag2,
3530
- config,
3531
- meta,
3532
- buildEnv: buildArgsFromEnv(meta?.buildEnv),
3533
- parentSpan: span
3534
- });
3536
+ try {
3537
+ return await buildAndPushBuildpack({
3538
+ buildpack,
3539
+ files: options.files,
3540
+ workPath: options.workPath,
3541
+ repoRootPath: options.repoRootPath,
3542
+ service: options.service,
3543
+ repository: repository2,
3544
+ tag: tag2,
3545
+ config,
3546
+ meta,
3547
+ buildEnv: buildArgsFromEnv(meta?.buildEnv),
3548
+ parentSpan: span
3549
+ });
3550
+ } catch (error) {
3551
+ if (daemon && error.exitCode === BUILDPACK_FAILED_EXIT_CODE) {
3552
+ throw new Error(
3553
+ `Failed to build daemon "${daemon.name}" (root "${daemon.root}") with the ${buildpack.runtime} buildpack. Its error is above.`
3554
+ );
3555
+ }
3556
+ throw error;
3557
+ }
3535
3558
  }
3536
3559
  const { dockerfileRel, dockerfilePath } = source;
3537
3560
  if (meta?.isDev) {
@@ -3547,7 +3570,6 @@ async function resolveImageHandler(options, source, span) {
3547
3570
  `Dockerfile not found at "${dockerfilePath}" for container service.`
3548
3571
  );
3549
3572
  }
3550
- const { daemon } = options.config;
3551
3573
  const repository = daemon ? (0, import_build_utils6.getDaemonImageRepository)(daemon.name) : sanitizeRepository(
3552
3574
  options.service?.name ?? import_node_path17.default.basename(dockerfileRel).split(".")[0]
3553
3575
  );
@@ -3598,7 +3620,9 @@ async function build(options) {
3598
3620
  image,
3599
3621
  // Checked by vercel.json validation: a daemon sets one of them.
3600
3622
  instances: daemon.instances ?? daemon.replicas,
3601
- ...daemon.command && { command: daemon.command },
3623
+ // A command replaces the image's entrypoint, which for a buildpack
3624
+ // image is the launcher; the buildpack bakes the command in instead.
3625
+ ...daemon.command && source.kind !== "buildpack" && { command: daemon.command },
3602
3626
  ...daemon.resources && { resources: daemon.resources },
3603
3627
  ...daemon.terminationGracePeriodSeconds !== void 0 && {
3604
3628
  terminationGracePeriodSeconds: daemon.terminationGracePeriodSeconds
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vercel/container",
3
- "version": "19.1.2",
3
+ "version": "20.0.0",
4
4
  "license": "Apache-2.0",
5
5
  "main": "./dist/index.js",
6
6
  "homepage": "https://vercel.com/docs",
@@ -17,12 +17,12 @@
17
17
  "tar": "7.5.11"
18
18
  },
19
19
  "peerDependencies": {
20
- "@vercel/build-utils": "14.21.2"
20
+ "@vercel/build-utils": "14.22.0"
21
21
  },
22
22
  "devDependencies": {
23
23
  "@types/node": "20.11.0",
24
24
  "vitest": "4.1.10",
25
- "@vercel/build-utils": "14.21.2"
25
+ "@vercel/build-utils": "14.22.0"
26
26
  },
27
27
  "publishConfig": {
28
28
  "access": "public"