feat(core,cli): add node-24 and node-26 runtimes, deprecate experimental aliases (#4337)
## Summary
Adds `node-24` and `node-26` as first-class `runtime` options in
`trigger.config.ts`. Previously these Node versions were only reachable
via the `experimental-node-24` / `experimental-node-26` names.
Those experimental names are now **deprecated aliases**: they still
resolve to `node-24` / `node-26` for backwards compatibility, but
loading a config that uses them prints a deprecation warning pointing at
the new name.
```ts
export default defineConfig({
runtime: "node-24",
project: "<your-project-ref>",
});
```
## Details
- `ConfigRuntime` (the public config schema) now accepts `node-24` and
`node-26` directly; the internal `BuildRuntime` already supported them,
so base images and the deploy path are unchanged.
- `resolveBuildRuntime` passes the new names straight through and keeps
mapping the experimental aliases to their replacements.
- Renamed the runtime helper from `isExperimentalConfigRuntime` to
`isDeprecatedConfigRuntime` and added `deprecatedRuntimeReplacement` so
the CLI can name the replacement in its warning.
- Docs snippet updated to list the new versions and flag the deprecated
names.
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
---
|
||||
"@trigger.dev/core": patch
|
||||
"trigger.dev": patch
|
||||
---
|
||||
|
||||
Add `node-24` and `node-26` as supported `runtime` options in `trigger.config.ts`. The `experimental-node-24` and `experimental-node-26` names are now deprecated aliases and emit a deprecation warning; switch to `node-24` / `node-26` instead.
|
||||
|
||||
```ts
|
||||
import { defineConfig } from "@trigger.dev/sdk";
|
||||
|
||||
export default defineConfig({
|
||||
runtime: "node-24",
|
||||
project: "<your-project-ref>",
|
||||
});
|
||||
```
|
||||
@@ -1,13 +1,9 @@
|
||||
Trigger.dev runs your tasks on specific Node.js versions:
|
||||
|
||||
### v3
|
||||
|
||||
- Node.js `21.7.3`
|
||||
|
||||
### v4
|
||||
|
||||
- Node.js `21.7.3` (default)
|
||||
- Node.js `22.16.0` (`node-22`)
|
||||
- Node.js `24.18.0` (`node-24`)
|
||||
- Node.js `26.4.0` (`node-26`)
|
||||
- Bun `1.3.3` (`bun`)
|
||||
|
||||
You can change the runtime by setting the `runtime` field in your `trigger.config.ts` file.
|
||||
@@ -16,8 +12,8 @@ You can change the runtime by setting the `runtime` field in your `trigger.confi
|
||||
import { defineConfig } from "@trigger.dev/sdk";
|
||||
|
||||
export default defineConfig({
|
||||
// "node", "node-22" or "bun"
|
||||
runtime: "node-22",
|
||||
// "node", "node-22", "node-24", "node-26" or "bun"
|
||||
runtime: "node-24",
|
||||
project: "<your-project-ref>",
|
||||
});
|
||||
```
|
||||
|
||||
@@ -33,6 +33,10 @@ async function createProject(runtime?: string) {
|
||||
|
||||
describe("loadConfig runtime", () => {
|
||||
it.each([
|
||||
["node", "node"],
|
||||
["node-22", "node-22"],
|
||||
["node-24", "node-24"],
|
||||
["node-26", "node-26"],
|
||||
["experimental-node-24", "node-24"],
|
||||
["experimental-node-26", "node-26"],
|
||||
] as const)("normalizes %s before returning the resolved config", async (runtime, expected) => {
|
||||
@@ -47,7 +51,7 @@ describe("loadConfig runtime", () => {
|
||||
await expect(loadConfig({ cwd, warn: false })).resolves.toMatchObject({ runtime: "node" });
|
||||
});
|
||||
|
||||
it.each(["node-24", "node-26", "node-23"])(
|
||||
it.each(["node-23"])(
|
||||
"rejects unsupported public runtime %s while loading config",
|
||||
async (runtime) => {
|
||||
const cwd = await createProject(runtime);
|
||||
|
||||
@@ -8,7 +8,8 @@ import type {
|
||||
import type { ResolvedConfig } from "@trigger.dev/core/v3/build";
|
||||
import {
|
||||
DEFAULT_RUNTIME,
|
||||
isExperimentalConfigRuntime,
|
||||
deprecatedRuntimeReplacement,
|
||||
isDeprecatedConfigRuntime,
|
||||
resolveBuildRuntime,
|
||||
} from "@trigger.dev/core/v3/build";
|
||||
import * as c12 from "c12";
|
||||
@@ -184,9 +185,11 @@ async function resolveConfig(
|
||||
const configuredRuntime = overrides?.runtime ?? config.runtime ?? defaultRuntime;
|
||||
const runtime = resolveBuildRuntime(configuredRuntime);
|
||||
|
||||
if (warn && isExperimentalConfigRuntime(configuredRuntime)) {
|
||||
if (warn && isDeprecatedConfigRuntime(configuredRuntime)) {
|
||||
prettyWarning(
|
||||
`The "${configuredRuntime}" runtime is experimental and may change before general availability.`
|
||||
`The "${configuredRuntime}" runtime is deprecated. Use "${deprecatedRuntimeReplacement(
|
||||
configuredRuntime
|
||||
)}" instead.`
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,31 +1,38 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { BuildManifest, BuildRuntime, ConfigRuntime, WorkerManifest } from "../schemas/build.js";
|
||||
import { isExperimentalConfigRuntime, resolveBuildRuntime } from "./runtime.js";
|
||||
import { isDeprecatedConfigRuntime, resolveBuildRuntime } from "./runtime.js";
|
||||
|
||||
describe("runtime configuration", () => {
|
||||
it.each(["node", "node-22", "experimental-node-24", "experimental-node-26", "bun"] as const)(
|
||||
"accepts %s as a public config runtime",
|
||||
(runtime) => {
|
||||
expect(ConfigRuntime.parse(runtime)).toBe(runtime);
|
||||
}
|
||||
);
|
||||
it.each([
|
||||
"node",
|
||||
"node-22",
|
||||
"node-24",
|
||||
"node-26",
|
||||
"experimental-node-24",
|
||||
"experimental-node-26",
|
||||
"bun",
|
||||
] as const)("accepts %s as a public config runtime", (runtime) => {
|
||||
expect(ConfigRuntime.parse(runtime)).toBe(runtime);
|
||||
});
|
||||
|
||||
it.each([
|
||||
["experimental-node-24", "node-24"],
|
||||
["experimental-node-26", "node-26"],
|
||||
["node", "node"],
|
||||
["node-22", "node-22"],
|
||||
["node-24", "node-24"],
|
||||
["node-26", "node-26"],
|
||||
["bun", "bun"],
|
||||
] as const)("normalizes %s to %s", (runtime, expected) => {
|
||||
expect(resolveBuildRuntime(runtime)).toBe(expected);
|
||||
});
|
||||
|
||||
it.each(["node-24", "node-26"] as const)(
|
||||
"keeps internal runtime %s out of the public config schema",
|
||||
"accepts internal runtime %s in both public and internal schemas",
|
||||
(runtime) => {
|
||||
expect(ConfigRuntime.safeParse(runtime).success).toBe(false);
|
||||
expect(ConfigRuntime.safeParse(runtime).success).toBe(true);
|
||||
expect(BuildRuntime.safeParse(runtime).success).toBe(true);
|
||||
expect(() => resolveBuildRuntime(runtime)).toThrowError(/Unsupported runtime/);
|
||||
expect(resolveBuildRuntime(runtime)).toBe(runtime);
|
||||
}
|
||||
);
|
||||
|
||||
@@ -36,12 +43,12 @@ describe("runtime configuration", () => {
|
||||
});
|
||||
|
||||
it.each(["experimental-node-24", "experimental-node-26"] as const)(
|
||||
"keeps %s out of internal runtime schemas",
|
||||
"treats %s as a deprecated alias kept out of internal runtime schemas",
|
||||
(runtime) => {
|
||||
expect(BuildRuntime.safeParse(runtime).success).toBe(false);
|
||||
expect(BuildManifest.shape.runtime.safeParse(runtime).success).toBe(false);
|
||||
expect(WorkerManifest.shape.runtime.safeParse(runtime).success).toBe(false);
|
||||
expect(isExperimentalConfigRuntime(runtime)).toBe(true);
|
||||
expect(isDeprecatedConfigRuntime(runtime)).toBe(true);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
@@ -6,14 +6,28 @@ import { homedir } from "node:os";
|
||||
|
||||
export const DEFAULT_RUNTIME = "node" satisfies BuildRuntime;
|
||||
|
||||
export type ExperimentalConfigRuntime = "experimental-node-24" | "experimental-node-26";
|
||||
export type DeprecatedConfigRuntime = "experimental-node-24" | "experimental-node-26";
|
||||
|
||||
export function isExperimentalConfigRuntime(
|
||||
runtime: unknown
|
||||
): runtime is ExperimentalConfigRuntime {
|
||||
export function isDeprecatedConfigRuntime(runtime: unknown): runtime is DeprecatedConfigRuntime {
|
||||
return runtime === "experimental-node-24" || runtime === "experimental-node-26";
|
||||
}
|
||||
|
||||
/** Maps a deprecated runtime alias to the runtime that should be used instead. */
|
||||
export function deprecatedRuntimeReplacement(runtime: DeprecatedConfigRuntime): BuildRuntime {
|
||||
switch (runtime) {
|
||||
case "experimental-node-24":
|
||||
return "node-24";
|
||||
case "experimental-node-26":
|
||||
return "node-26";
|
||||
}
|
||||
}
|
||||
|
||||
/** @deprecated Renamed to {@link DeprecatedConfigRuntime}. */
|
||||
export type ExperimentalConfigRuntime = DeprecatedConfigRuntime;
|
||||
|
||||
/** @deprecated Renamed to {@link isDeprecatedConfigRuntime}. */
|
||||
export const isExperimentalConfigRuntime = isDeprecatedConfigRuntime;
|
||||
|
||||
export function resolveBuildRuntime(runtime: unknown): BuildRuntime {
|
||||
const parsedRuntime = ConfigRuntime.safeParse(runtime);
|
||||
|
||||
|
||||
@@ -16,6 +16,9 @@ export type BuildTarget = z.infer<typeof BuildTarget>;
|
||||
export const ConfigRuntime = z.enum([
|
||||
"node",
|
||||
"node-22",
|
||||
"node-24",
|
||||
"node-26",
|
||||
// Deprecated aliases, kept for backwards compatibility. Use "node-24"/"node-26" instead.
|
||||
"experimental-node-24",
|
||||
"experimental-node-26",
|
||||
"bun",
|
||||
|
||||
Reference in New Issue
Block a user