feat: add node 22 and bun runtime support with version display (#2254)
* update node-22 image * update bun image * disable io_uring * fix fallback bun path * prevent duplicate warnings * add runtime and version to deployments * runtime icons * fallback to nodejs * prevent empty table cell menu * log if local build on deploy * pass io_uring env var to child * denormalize runtime and version, display on run details * add changesets * disable pr checks for changeset commits.. * add runtime data to deployed bg workers
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
---
|
||||
|
||||
Enhance deploy command output to better distinguish between local and remote builds
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
"@trigger.dev/core": patch
|
||||
---
|
||||
|
||||
Add runtime version detection for display in the dashboard
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
---
|
||||
|
||||
Update base images to latest compatible versions. The `node-22` runtime now uses v22.16.0 and `bun` uses the latest v1.2.18 release. The default `node` runtime is unchanged and points at v21.7.3.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@trigger.dev/core": patch
|
||||
---
|
||||
|
||||
Fix Bun runtime path resolution fallback
|
||||
@@ -5,6 +5,7 @@ on:
|
||||
types: [opened, synchronize, reopened]
|
||||
paths-ignore:
|
||||
- "docs/**"
|
||||
- ".changeset/**"
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
export function BunLogoIcon({ className }: { className?: string }) {
|
||||
return (
|
||||
<svg className={className} viewBox="0 0 80 70" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
id="Shadow"
|
||||
d="M71.09,20.74c-.16-.17-.33-.34-.5-.5s-.33-.34-.5-.5-.33-.34-.5-.5-.33-.34-.5-.5-.33-.34-.5-.5-.33-.34-.5-.5-.33-.34-.5-.5A26.46,26.46,0,0,1,75.5,35.7c0,16.57-16.82,30.05-37.5,30.05-11.58,0-21.94-4.23-28.83-10.86l.5.5.5.5.5.5.5.5.5.5.5.5.5.5C19.55,65.3,30.14,69.75,42,69.75c20.68,0,37.5-13.48,37.5-30C79.5,32.69,76.46,26,71.09,20.74Z"
|
||||
/>
|
||||
<g id="Body">
|
||||
<path
|
||||
id="Background"
|
||||
d="M73,35.7c0,15.21-15.67,27.54-35,27.54S3,50.91,3,35.7C3,26.27,9,17.94,18.22,13S33.18,3,38,3s8.94,4.13,19.78,10C67,17.94,73,26.27,73,35.7Z"
|
||||
style={{ fill: "#fbf0df" }}
|
||||
/>
|
||||
<path
|
||||
id="Bottom_Shadow"
|
||||
data-name="Bottom Shadow"
|
||||
d="M73,35.7a21.67,21.67,0,0,0-.8-5.78c-2.73,33.3-43.35,34.9-59.32,24.94A40,40,0,0,0,38,63.24C57.3,63.24,73,50.89,73,35.7Z"
|
||||
style={{ fill: "#f6dece" }}
|
||||
/>
|
||||
<path
|
||||
id="Light_Shine"
|
||||
data-name="Light Shine"
|
||||
d="M24.53,11.17C29,8.49,34.94,3.46,40.78,3.45A9.29,9.29,0,0,0,38,3c-2.42,0-5,1.25-8.25,3.13-1.13.66-2.3,1.39-3.54,2.15-2.33,1.44-5,3.07-8,4.7C8.69,18.13,3,26.62,3,35.7c0,.4,0,.8,0,1.19C9.06,15.48,20.07,13.85,24.53,11.17Z"
|
||||
style={{ fill: "#fffefc" }}
|
||||
/>
|
||||
<path
|
||||
id="Top"
|
||||
d="M35.12,5.53A16.41,16.41,0,0,1,29.49,18c-.28.25-.06.73.3.59,3.37-1.31,7.92-5.23,6-13.14C35.71,5,35.12,5.12,35.12,5.53Zm2.27,0A16.24,16.24,0,0,1,39,19c-.12.35.31.65.55.36C41.74,16.56,43.65,11,37.93,5,37.64,4.74,37.19,5.14,37.39,5.49Zm2.76-.17A16.42,16.42,0,0,1,47,17.12a.33.33,0,0,0,.65.11c.92-3.49.4-9.44-7.17-12.53C40.08,4.54,39.82,5.08,40.15,5.32ZM21.69,15.76a16.94,16.94,0,0,0,10.47-9c.18-.36.75-.22.66.18-1.73,8-7.52,9.67-11.12,9.45C21.32,16.4,21.33,15.87,21.69,15.76Z"
|
||||
style={{ fill: "#ccbea7", fillRule: "evenodd" }}
|
||||
/>
|
||||
<path
|
||||
id="Outline"
|
||||
d="M38,65.75C17.32,65.75.5,52.27.5,35.7c0-10,6.18-19.33,16.53-24.92,3-1.6,5.57-3.21,7.86-4.62,1.26-.78,2.45-1.51,3.6-2.19C32,1.89,35,.5,38,.5s5.62,1.2,8.9,3.14c1,.57,2,1.19,3.07,1.87,2.49,1.54,5.3,3.28,9,5.27C69.32,16.37,75.5,25.69,75.5,35.7,75.5,52.27,58.68,65.75,38,65.75ZM38,3c-2.42,0-5,1.25-8.25,3.13-1.13.66-2.3,1.39-3.54,2.15-2.33,1.44-5,3.07-8,4.7C8.69,18.13,3,26.62,3,35.7,3,50.89,18.7,63.25,38,63.25S73,50.89,73,35.7C73,26.62,67.31,18.13,57.78,13,54,11,51.05,9.12,48.66,7.64c-1.09-.67-2.09-1.29-3-1.84C42.63,4,40.42,3,38,3Z"
|
||||
/>
|
||||
</g>
|
||||
<g id="Mouth">
|
||||
<g id="Background-2" data-name="Background">
|
||||
<path
|
||||
d="M45.05,43a8.93,8.93,0,0,1-2.92,4.71,6.81,6.81,0,0,1-4,1.88A6.84,6.84,0,0,1,34,47.71,8.93,8.93,0,0,1,31.12,43a.72.72,0,0,1,.8-.81H44.26A.72.72,0,0,1,45.05,43Z"
|
||||
style={{ fill: "#b71422" }}
|
||||
/>
|
||||
</g>
|
||||
<g id="Tongue">
|
||||
<path
|
||||
id="Background-3"
|
||||
data-name="Background"
|
||||
d="M34,47.79a6.91,6.91,0,0,0,4.12,1.9,6.91,6.91,0,0,0,4.11-1.9,10.63,10.63,0,0,0,1-1.07,6.83,6.83,0,0,0-4.9-2.31,6.15,6.15,0,0,0-5,2.78C33.56,47.4,33.76,47.6,34,47.79Z"
|
||||
style={{ fill: "#ff6164" }}
|
||||
/>
|
||||
<path
|
||||
id="Outline-2"
|
||||
data-name="Outline"
|
||||
d="M34.16,47a5.36,5.36,0,0,1,4.19-2.08,6,6,0,0,1,4,1.69c.23-.25.45-.51.66-.77a7,7,0,0,0-4.71-1.93,6.36,6.36,0,0,0-4.89,2.36A9.53,9.53,0,0,0,34.16,47Z"
|
||||
/>
|
||||
</g>
|
||||
<path
|
||||
id="Outline-3"
|
||||
data-name="Outline"
|
||||
d="M38.09,50.19a7.42,7.42,0,0,1-4.45-2,9.52,9.52,0,0,1-3.11-5.05,1.2,1.2,0,0,1,.26-1,1.41,1.41,0,0,1,1.13-.51H44.26a1.44,1.44,0,0,1,1.13.51,1.19,1.19,0,0,1,.25,1h0a9.52,9.52,0,0,1-3.11,5.05A7.42,7.42,0,0,1,38.09,50.19Zm-6.17-7.4c-.16,0-.2.07-.21.09a8.29,8.29,0,0,0,2.73,4.37A6.23,6.23,0,0,0,38.09,49a6.28,6.28,0,0,0,3.65-1.73,8.3,8.3,0,0,0,2.72-4.37.21.21,0,0,0-.2-.09Z"
|
||||
/>
|
||||
</g>
|
||||
<g id="Face">
|
||||
<ellipse
|
||||
id="Right_Blush"
|
||||
data-name="Right Blush"
|
||||
cx="53.22"
|
||||
cy="40.18"
|
||||
rx="5.85"
|
||||
ry="3.44"
|
||||
style={{ fill: "#febbd0" }}
|
||||
/>
|
||||
<ellipse
|
||||
id="Left_Bluch"
|
||||
data-name="Left Bluch"
|
||||
cx="22.95"
|
||||
cy="40.18"
|
||||
rx="5.85"
|
||||
ry="3.44"
|
||||
style={{ fill: "#febbd0" }}
|
||||
/>
|
||||
<path
|
||||
id="Eyes"
|
||||
d="M25.7,38.8a5.51,5.51,0,1,0-5.5-5.51A5.51,5.51,0,0,0,25.7,38.8Zm24.77,0A5.51,5.51,0,1,0,45,33.29,5.5,5.5,0,0,0,50.47,38.8Z"
|
||||
style={{ fillRule: "evenodd" }}
|
||||
/>
|
||||
<path
|
||||
id="Iris"
|
||||
d="M24,33.64a2.07,2.07,0,1,0-2.06-2.07A2.07,2.07,0,0,0,24,33.64Zm24.77,0a2.07,2.07,0,1,0-2.06-2.07A2.07,2.07,0,0,0,48.75,33.64Z"
|
||||
style={{ fill: "#fff", fillRule: "evenodd" }}
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
export function NodejsLogoIcon({ className }: { className?: string }) {
|
||||
return (
|
||||
<svg className={className} viewBox="0 0 71 80" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clipPath="url(#clip0_337_7891)" fill="#5FA04E">
|
||||
<path d="M35.625 79.5c-1.081 0-2.09-.288-3.028-.792l-9.59-5.686c-1.442-.792-.721-1.08-.289-1.224 1.947-.648 2.308-.792 4.327-1.944.216-.144.504-.072.72.072l7.356 4.391c.288.144.649.144.865 0l28.77-16.628c.289-.144.433-.431.433-.791V23.714c0-.36-.144-.648-.432-.792L35.986 6.366c-.288-.144-.65-.144-.865 0L6.35 22.922c-.29.144-.434.504-.434.792v33.184c0 .287.145.647.433.791l7.86 4.535c4.254 2.16 6.922-.36 6.922-2.879V26.593c0-.432.36-.864.865-.864h3.678c.432 0 .865.36.865.864v32.752c0 5.687-3.1 8.998-8.509 8.998-1.658 0-2.956 0-6.633-1.8l-7.572-4.319A6.073 6.073 0 0 1 .798 56.97V23.786a6.073 6.073 0 0 1 3.028-5.255l28.77-16.628c1.804-1.008 4.255-1.008 6.058 0l28.77 16.628a6.073 6.073 0 0 1 3.029 5.255V56.97a6.073 6.073 0 0 1-3.029 5.254l-28.77 16.628c-.865.36-1.947.648-3.029.648Z" />
|
||||
<path d="M44.567 56.682c-12.62 0-15.215-5.759-15.215-10.654 0-.432.36-.864.865-.864h3.75c.433 0 .793.288.793.72.577 3.815 2.235 5.687 9.879 5.687 6.057 0 8.652-1.368 8.652-4.607 0-1.871-.72-3.24-10.167-4.175-7.86-.792-12.762-2.52-12.762-8.782 0-5.83 4.903-9.285 13.123-9.285 9.23 0 13.772 3.167 14.35 10.077 0 .216-.073.432-.217.648-.144.144-.36.288-.577.288h-3.822a.844.844 0 0 1-.793-.648c-.865-3.96-3.1-5.255-9.013-5.255-6.634 0-7.427 2.304-7.427 4.031 0 2.088.937 2.736 9.879 3.887 8.869 1.152 13.05 2.808 13.05 8.998 0 6.335-5.263 9.934-14.348 9.934Z" />
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_337_7891">
|
||||
<path fill="#fff" d="M0 .5h71v79H0z" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
import { SimpleTooltip } from "~/components/primitives/Tooltip";
|
||||
import { BunLogoIcon } from "~/assets/icons/BunLogoIcon";
|
||||
import { NodejsLogoIcon } from "~/assets/icons/NodejsLogoIcon";
|
||||
import { parseRuntime, formatRuntimeWithVersion, type NormalizedRuntime } from "~/utils/runtime";
|
||||
|
||||
interface RuntimeIconProps {
|
||||
runtime?: string | null;
|
||||
runtimeVersion?: string | null;
|
||||
className?: string;
|
||||
withLabel?: boolean;
|
||||
}
|
||||
|
||||
const getIcon = (runtime: NormalizedRuntime, className: string) => {
|
||||
switch (runtime) {
|
||||
case "bun":
|
||||
return <BunLogoIcon className={className} />;
|
||||
case "node":
|
||||
return <NodejsLogoIcon className={className} />;
|
||||
default:
|
||||
return <span className="text-text-dimmed">–</span>;
|
||||
}
|
||||
};
|
||||
|
||||
export function RuntimeIcon({
|
||||
runtime,
|
||||
runtimeVersion,
|
||||
className = "h-4 w-4",
|
||||
withLabel = false,
|
||||
}: RuntimeIconProps) {
|
||||
const parsedRuntime = parseRuntime(runtime);
|
||||
|
||||
// Default to Node.js if no runtime is specified
|
||||
const effectiveRuntime = parsedRuntime || {
|
||||
runtime: "node" as const,
|
||||
originalRuntime: "node",
|
||||
displayName: "Node.js",
|
||||
};
|
||||
|
||||
const icon = getIcon(effectiveRuntime.runtime, className);
|
||||
const formattedText = formatRuntimeWithVersion(effectiveRuntime.originalRuntime, runtimeVersion);
|
||||
|
||||
if (withLabel) {
|
||||
return (
|
||||
<span className="flex items-center gap-1">
|
||||
{icon}
|
||||
<span>{formattedText}</span>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
if (typeof icon === "object" && "type" in icon) {
|
||||
return (
|
||||
<SimpleTooltip button={icon} content={formattedText} side="top" disableHoverableContent />
|
||||
);
|
||||
}
|
||||
|
||||
return icon;
|
||||
}
|
||||
@@ -97,6 +97,8 @@ export class DeploymentListPresenter {
|
||||
id: string;
|
||||
shortCode: string;
|
||||
version: string;
|
||||
runtime: string | null;
|
||||
runtimeVersion: string | null;
|
||||
status: WorkerDeploymentStatus;
|
||||
environmentId: string;
|
||||
builtAt: Date | null;
|
||||
@@ -114,6 +116,8 @@ export class DeploymentListPresenter {
|
||||
wd."id",
|
||||
wd."shortCode",
|
||||
wd."version",
|
||||
wd."runtime",
|
||||
wd."runtimeVersion",
|
||||
(SELECT COUNT(*) FROM ${sqlDatabaseSchema}."BackgroundWorkerTask" WHERE "BackgroundWorkerTask"."workerId" = wd."workerId") AS "tasksCount",
|
||||
wd."environmentId",
|
||||
wd."status",
|
||||
@@ -148,6 +152,8 @@ LIMIT ${pageSize} OFFSET ${pageSize * (page - 1)};`;
|
||||
id: deployment.id,
|
||||
shortCode: deployment.shortCode,
|
||||
version: deployment.version,
|
||||
runtime: deployment.runtime,
|
||||
runtimeVersion: deployment.runtimeVersion,
|
||||
status: deployment.status,
|
||||
builtAt: deployment.builtAt,
|
||||
deployedAt: deployment.deployedAt,
|
||||
|
||||
@@ -72,6 +72,8 @@ export class DeploymentPresenter {
|
||||
id: true,
|
||||
shortCode: true,
|
||||
version: true,
|
||||
runtime: true,
|
||||
runtimeVersion: true,
|
||||
errorData: true,
|
||||
imageReference: true,
|
||||
imagePlatform: true,
|
||||
@@ -157,6 +159,8 @@ export class DeploymentPresenter {
|
||||
deployedBy: deployment.triggeredBy,
|
||||
sdkVersion: deployment.worker?.sdkVersion,
|
||||
cliVersion: deployment.worker?.cliVersion,
|
||||
runtime: deployment.runtime,
|
||||
runtimeVersion: deployment.runtimeVersion,
|
||||
imageReference: deployment.imageReference,
|
||||
imagePlatform: deployment.imagePlatform,
|
||||
externalBuildData:
|
||||
|
||||
@@ -142,6 +142,8 @@ export class SpanPresenter extends BasePresenter {
|
||||
select: {
|
||||
version: true,
|
||||
sdkVersion: true,
|
||||
runtime: true,
|
||||
runtimeVersion: true,
|
||||
},
|
||||
},
|
||||
engine: true,
|
||||
@@ -326,6 +328,8 @@ export class SpanPresenter extends BasePresenter {
|
||||
taskIdentifier: run.taskIdentifier,
|
||||
version: run.lockedToVersion?.version,
|
||||
sdkVersion: run.lockedToVersion?.sdkVersion,
|
||||
runtime: run.lockedToVersion?.runtime,
|
||||
runtimeVersion: run.lockedToVersion?.runtimeVersion,
|
||||
isTest: run.isTest,
|
||||
environmentId: run.runtimeEnvironment.id,
|
||||
idempotencyKey: run.idempotencyKey,
|
||||
|
||||
+11
@@ -3,6 +3,7 @@ import { type LoaderFunctionArgs } from "@remix-run/server-runtime";
|
||||
import { typedjson, useTypedLoaderData } from "remix-typedjson";
|
||||
import { ExitIcon } from "~/assets/icons/ExitIcon";
|
||||
import { GitMetadata } from "~/components/GitMetadata";
|
||||
import { RuntimeIcon } from "~/components/RuntimeIcon";
|
||||
import { UserAvatar } from "~/components/UserProfilePhoto";
|
||||
import { AdminDebugTooltip } from "~/components/admin/debugTooltip";
|
||||
import { EnvironmentCombo } from "~/components/environments/EnvironmentLabel";
|
||||
@@ -169,6 +170,16 @@ export default function Page() {
|
||||
{deployment.cliVersion ? deployment.cliVersion : "–"}
|
||||
</Property.Value>
|
||||
</Property.Item>
|
||||
<Property.Item>
|
||||
<Property.Label>Runtime</Property.Label>
|
||||
<Property.Value>
|
||||
<RuntimeIcon
|
||||
runtime={deployment.runtime}
|
||||
runtimeVersion={deployment.runtimeVersion}
|
||||
withLabel
|
||||
/>
|
||||
</Property.Value>
|
||||
</Property.Item>
|
||||
<Property.Item>
|
||||
<Property.Label>Worker type</Property.Label>
|
||||
<Property.Value>{capitalizeWord(deployment.type)}</Property.Value>
|
||||
|
||||
+10
-4
@@ -7,6 +7,7 @@ import { z } from "zod";
|
||||
import { PromoteIcon } from "~/assets/icons/PromoteIcon";
|
||||
import { DeploymentsNone, DeploymentsNoneDev } from "~/components/BlankStatePanels";
|
||||
import { GitMetadata } from "~/components/GitMetadata";
|
||||
import { RuntimeIcon } from "~/components/RuntimeIcon";
|
||||
import { UserAvatar } from "~/components/UserProfilePhoto";
|
||||
import { MainCenteredContainer, PageBody, PageContainer } from "~/components/layout/AppLayout";
|
||||
import { Badge } from "~/components/primitives/Badge";
|
||||
@@ -51,7 +52,6 @@ import { requireUserId } from "~/services/session.server";
|
||||
import { titleCase } from "~/utils";
|
||||
import { EnvironmentParamSchema, docsPath, v3DeploymentPath } from "~/utils/pathBuilder";
|
||||
import { createSearchParams } from "~/utils/searchParams";
|
||||
import { deploymentIndexingIsRetryable } from "~/v3/deploymentStatus";
|
||||
import { compareDeploymentVersions } from "~/v3/utils/deploymentVersions";
|
||||
|
||||
export const meta: MetaFunction = () => {
|
||||
@@ -190,6 +190,7 @@ export default function Page() {
|
||||
>
|
||||
Status
|
||||
</TableHeaderCell>
|
||||
<TableHeaderCell>Runtime</TableHeaderCell>
|
||||
<TableHeaderCell>Tasks</TableHeaderCell>
|
||||
<TableHeaderCell>Deployed at</TableHeaderCell>
|
||||
<TableHeaderCell>Deployed by</TableHeaderCell>
|
||||
@@ -227,6 +228,12 @@ export default function Page() {
|
||||
isBuilt={deployment.isBuilt}
|
||||
/>
|
||||
</TableCell>
|
||||
<TableCell to={path} isSelected={isSelected}>
|
||||
<RuntimeIcon
|
||||
runtime={deployment.runtime}
|
||||
runtimeVersion={deployment.runtimeVersion}
|
||||
/>
|
||||
</TableCell>
|
||||
<TableCell to={path} isSelected={isSelected}>
|
||||
{deployment.tasksCount !== null ? deployment.tasksCount : "–"}
|
||||
</TableCell>
|
||||
@@ -272,7 +279,7 @@ export default function Page() {
|
||||
);
|
||||
})
|
||||
) : (
|
||||
<TableBlankRow colSpan={7}>
|
||||
<TableBlankRow colSpan={8}>
|
||||
<Paragraph className="flex items-center justify-center">
|
||||
No deploys match your filters
|
||||
</Paragraph>
|
||||
@@ -326,14 +333,13 @@ function DeploymentActionsCell({
|
||||
const project = useProject();
|
||||
|
||||
const canBeMadeCurrent = !deployment.isCurrent && deployment.isDeployed;
|
||||
const canRetryIndexing = deployment.isLatest && deploymentIndexingIsRetryable(deployment);
|
||||
const canBeRolledBack =
|
||||
canBeMadeCurrent &&
|
||||
currentDeployment?.version &&
|
||||
compareDeploymentVersions(deployment.version, currentDeployment.version) === -1;
|
||||
const canBePromoted = canBeMadeCurrent && !canBeRolledBack;
|
||||
|
||||
if (!canBeMadeCurrent && !canRetryIndexing) {
|
||||
if (!canBeRolledBack && !canBePromoted) {
|
||||
return (
|
||||
<TableCell to={path} isSelected={isSelected}>
|
||||
{""}
|
||||
|
||||
+11
@@ -36,6 +36,7 @@ import {
|
||||
import { TabButton, TabContainer } from "~/components/primitives/Tabs";
|
||||
import { TextLink } from "~/components/primitives/TextLink";
|
||||
import { InfoIconTooltip, SimpleTooltip } from "~/components/primitives/Tooltip";
|
||||
import { RuntimeIcon } from "~/components/RuntimeIcon";
|
||||
import { RunTimeline, RunTimelineEvent, SpanTimeline } from "~/components/run/RunTimeline";
|
||||
import { PacketDisplay } from "~/components/runs/v3/PacketDisplay";
|
||||
import { RunIcon } from "~/components/runs/v3/RunIcon";
|
||||
@@ -575,6 +576,16 @@ function RunBody({
|
||||
)}
|
||||
</Property.Value>
|
||||
</Property.Item>
|
||||
<Property.Item>
|
||||
<Property.Label>Runtime</Property.Label>
|
||||
<Property.Value>
|
||||
<RuntimeIcon
|
||||
runtime={run.runtime}
|
||||
runtimeVersion={run.runtimeVersion}
|
||||
withLabel
|
||||
/>
|
||||
</Property.Value>
|
||||
</Property.Item>
|
||||
<Property.Item>
|
||||
<Property.Label>Test run</Property.Label>
|
||||
<Property.Value>
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
export type NormalizedRuntime = "node" | "bun";
|
||||
|
||||
export interface ParsedRuntime {
|
||||
/** The normalized runtime type */
|
||||
runtime: NormalizedRuntime;
|
||||
/** The original runtime string */
|
||||
originalRuntime: string;
|
||||
/** The display name for the runtime */
|
||||
displayName: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a runtime string and returns normalized runtime information
|
||||
*/
|
||||
export function parseRuntime(runtime: string | null | undefined): ParsedRuntime | null {
|
||||
if (!runtime) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Normalize runtime strings
|
||||
let normalizedRuntime: NormalizedRuntime;
|
||||
let displayName: string;
|
||||
|
||||
if (runtime.startsWith("bun")) {
|
||||
normalizedRuntime = "bun";
|
||||
displayName = "Bun";
|
||||
} else if (runtime.startsWith("node")) {
|
||||
normalizedRuntime = "node";
|
||||
displayName = "Node.js";
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
runtime: normalizedRuntime,
|
||||
originalRuntime: runtime,
|
||||
displayName,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats runtime with version for display
|
||||
*/
|
||||
export function formatRuntimeWithVersion(
|
||||
runtime: string | null | undefined,
|
||||
version: string | null | undefined
|
||||
): string {
|
||||
const parsed = parseRuntime(runtime);
|
||||
if (!parsed) {
|
||||
return "Unknown runtime";
|
||||
}
|
||||
|
||||
if (version) {
|
||||
return `${parsed.displayName} v${version}`;
|
||||
}
|
||||
|
||||
return parsed.displayName;
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
import { WorkerDeployment } from "@trigger.dev/database";
|
||||
|
||||
export const deploymentIndexingIsRetryable = ({
|
||||
builtAt,
|
||||
status,
|
||||
}: {
|
||||
builtAt: Date | null;
|
||||
status: WorkerDeployment["status"];
|
||||
}) => {
|
||||
return builtAt && (status === "FAILED" || status === "TIMED_OUT");
|
||||
};
|
||||
@@ -81,6 +81,8 @@ export class CreateBackgroundWorkerService extends BaseService {
|
||||
contentHash: body.metadata.contentHash,
|
||||
cliVersion: body.metadata.cliPackageVersion,
|
||||
sdkVersion: body.metadata.packageVersion,
|
||||
runtime: body.metadata.runtime,
|
||||
runtimeVersion: body.metadata.runtimeVersion,
|
||||
supportsLazyAttempts: body.supportsLazyAttempts,
|
||||
engine: body.engine,
|
||||
},
|
||||
|
||||
@@ -71,6 +71,8 @@ export class CreateDeploymentBackgroundWorkerServiceV4 extends BaseService {
|
||||
sdkVersion: body.metadata.packageVersion,
|
||||
supportsLazyAttempts: body.supportsLazyAttempts,
|
||||
engine: body.engine,
|
||||
runtime: body.metadata.runtime,
|
||||
runtimeVersion: body.metadata.runtimeVersion,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -160,6 +162,8 @@ export class CreateDeploymentBackgroundWorkerServiceV4 extends BaseService {
|
||||
workerId: backgroundWorker.id,
|
||||
builtAt: new Date(),
|
||||
type: backgroundWorker.engine === "V2" ? "MANAGED" : "V1",
|
||||
// runtime is already set when the deployment is created, we only need to set the version
|
||||
runtimeVersion: body.metadata.runtimeVersion,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -124,6 +124,7 @@ export class InitializeDeploymentService extends BaseService {
|
||||
imageReference: imageRef,
|
||||
imagePlatform: env.DEPLOY_IMAGE_PLATFORM,
|
||||
git: payload.gitMeta ?? undefined,
|
||||
runtime: payload.runtime ?? undefined,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE "WorkerDeployment" ADD COLUMN "runtime" TEXT;
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE "WorkerDeployment" ADD COLUMN "runtimeVersion" TEXT;
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE "BackgroundWorker" ADD COLUMN "runtime" TEXT,
|
||||
ADD COLUMN "runtimeVersion" TEXT;
|
||||
@@ -420,6 +420,9 @@ model BackgroundWorker {
|
||||
version String
|
||||
metadata Json
|
||||
|
||||
runtime String?
|
||||
runtimeVersion String?
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@ -719,24 +722,24 @@ model TaskRun {
|
||||
model TaskRunTemplate {
|
||||
id String @id @default(cuid())
|
||||
|
||||
taskSlug String
|
||||
taskSlug String
|
||||
triggerSource TaskTriggerSource
|
||||
|
||||
label String
|
||||
|
||||
payload String?
|
||||
payloadType String @default("application/json")
|
||||
metadata String?
|
||||
metadataType String @default("application/json")
|
||||
queue String?
|
||||
concurrencyKey String?
|
||||
ttlSeconds Int?
|
||||
maxAttempts Int?
|
||||
payload String?
|
||||
payloadType String @default("application/json")
|
||||
metadata String?
|
||||
metadataType String @default("application/json")
|
||||
queue String?
|
||||
concurrencyKey String?
|
||||
ttlSeconds Int?
|
||||
maxAttempts Int?
|
||||
maxDurationSeconds Int?
|
||||
tags String[]
|
||||
machinePreset String?
|
||||
tags String[]
|
||||
machinePreset String?
|
||||
|
||||
projectId String
|
||||
projectId String
|
||||
organizationId String
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
@@ -1674,6 +1677,9 @@ model WorkerDeployment {
|
||||
shortCode String
|
||||
version String
|
||||
|
||||
runtime String?
|
||||
runtimeVersion String?
|
||||
|
||||
imageReference String?
|
||||
imagePlatform String @default("linux/amd64")
|
||||
|
||||
|
||||
@@ -311,6 +311,7 @@ async function _deployCommand(dir: string, options: DeployCommandOptions) {
|
||||
userId: authorization.userId,
|
||||
gitMeta,
|
||||
type: features.run_engine_v2 ? "MANAGED" : "V1",
|
||||
runtime: buildManifest.runtime,
|
||||
});
|
||||
|
||||
if (!deploymentResponse.success) {
|
||||
@@ -389,13 +390,16 @@ async function _deployCommand(dir: string, options: DeployCommandOptions) {
|
||||
|
||||
const $spinner = spinner();
|
||||
|
||||
const buildSuffix = isLocalBuild ? " (local)" : "";
|
||||
const deploySuffix = isLocalBuild ? " (local build)" : "";
|
||||
|
||||
if (isCI) {
|
||||
log.step(`Building version ${version}\n`);
|
||||
} else {
|
||||
if (isLinksSupported) {
|
||||
$spinner.start(`Building version ${version} ${deploymentLink}`);
|
||||
$spinner.start(`Building version ${version}${buildSuffix} ${deploymentLink}`);
|
||||
} else {
|
||||
$spinner.start(`Building version ${version}`);
|
||||
$spinner.start(`Building version ${version}${buildSuffix}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -426,9 +430,11 @@ async function _deployCommand(dir: string, options: DeployCommandOptions) {
|
||||
}
|
||||
|
||||
if (isLinksSupported) {
|
||||
$spinner.message(`Building version ${version} ${deploymentLink}: ${logMessage}`);
|
||||
$spinner.message(
|
||||
`Building version ${version}${buildSuffix} ${deploymentLink}: ${logMessage}`
|
||||
);
|
||||
} else {
|
||||
$spinner.message(`Building version ${version}: ${logMessage}`);
|
||||
$spinner.message(`Building version ${version}${buildSuffix}: ${logMessage}`);
|
||||
}
|
||||
},
|
||||
// Local build options
|
||||
@@ -504,12 +510,12 @@ async function _deployCommand(dir: string, options: DeployCommandOptions) {
|
||||
}
|
||||
|
||||
if (isCI) {
|
||||
log.step(`Deploying version ${version}\n`);
|
||||
log.step(`Deploying version ${version}${deploySuffix}\n`);
|
||||
} else {
|
||||
if (isLinksSupported) {
|
||||
$spinner.message(`Deploying version ${version} ${deploymentLink}`);
|
||||
$spinner.message(`Deploying version ${version}${deploySuffix} ${deploymentLink}`);
|
||||
} else {
|
||||
$spinner.message(`Deploying version ${version}`);
|
||||
$spinner.message(`Deploying version ${version}${deploySuffix}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -526,9 +532,11 @@ async function _deployCommand(dir: string, options: DeployCommandOptions) {
|
||||
}
|
||||
|
||||
if (isLinksSupported) {
|
||||
$spinner.message(`Deploying version ${version} ${deploymentLink}: ${logMessage}`);
|
||||
$spinner.message(
|
||||
`Deploying version ${version}${deploySuffix} ${deploymentLink}: ${logMessage}`
|
||||
);
|
||||
} else {
|
||||
$spinner.message(`Deploying version ${version}: ${logMessage}`);
|
||||
$spinner.message(`Deploying version ${version}${deploySuffix}: ${logMessage}`);
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -546,9 +554,9 @@ async function _deployCommand(dir: string, options: DeployCommandOptions) {
|
||||
}
|
||||
|
||||
if (isCI) {
|
||||
log.step(`Successfully deployed version ${version}`);
|
||||
log.step(`Successfully deployed version ${version}${deploySuffix}`);
|
||||
} else {
|
||||
$spinner.stop(`Successfully deployed version ${version}`);
|
||||
$spinner.stop(`Successfully deployed version ${version}${deploySuffix}`);
|
||||
}
|
||||
|
||||
const taskCount = deploymentWithWorker.worker?.tasks.length ?? 0;
|
||||
|
||||
@@ -87,6 +87,7 @@ export async function whoAmI(
|
||||
loadConfig({
|
||||
overrides: { project: options?.projectRef ?? envVars.TRIGGER_PROJECT_REF },
|
||||
configFile: options?.config,
|
||||
warn: false,
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
@@ -27,12 +27,14 @@ export type ResolveConfigOptions = {
|
||||
cwd?: string;
|
||||
overrides?: Partial<TriggerConfig>;
|
||||
configFile?: string;
|
||||
warn?: boolean;
|
||||
};
|
||||
|
||||
export async function loadConfig({
|
||||
cwd = process.cwd(),
|
||||
overrides,
|
||||
configFile,
|
||||
warn = true,
|
||||
}: ResolveConfigOptions = {}): Promise<ResolvedConfig> {
|
||||
const result = await c12.loadConfig<TriggerConfig>({
|
||||
name: "trigger",
|
||||
@@ -41,7 +43,7 @@ export async function loadConfig({
|
||||
jitiOptions: { debug: logger.loggerLevel === "debug" },
|
||||
});
|
||||
|
||||
return await resolveConfig(cwd, result, overrides);
|
||||
return await resolveConfig(cwd, result, overrides, warn);
|
||||
}
|
||||
|
||||
type ResolveWatchConfigOptions = ResolveConfigOptions & {
|
||||
|
||||
@@ -543,10 +543,10 @@ export type GenerateContainerfileOptions = {
|
||||
};
|
||||
|
||||
const BASE_IMAGE: Record<BuildRuntime, string> = {
|
||||
bun: "imbios/bun-node:1.2.1-22-slim@sha256:6c31db8f11f0d37357ef8156c2dab684448b54a1fb50ca1c22bca82bce76c788",
|
||||
bun: "imbios/bun-node:1.2.18-20-slim@sha256:74067c73e7fe4a4da56f447f644e7090cec4eaf5500a0e384d15855107bea636",
|
||||
node: "node:21.7.3-bookworm-slim@sha256:dfc05dee209a1d7adf2ef189bd97396daad4e97c6eaa85778d6f75205ba1b0fb",
|
||||
"node-22":
|
||||
"node:22.12.0-bookworm-slim@sha256:a4b757cd491c7f0b57f57951f35f4e85b7e1ad54dbffca4cf9af0725e1650cd8",
|
||||
"node:22.16.0-bookworm-slim@sha256:048ed02c5fd52e86fda6fbd2f6a76cf0d4492fd6c6fee9e2c463ed5108da0e34",
|
||||
};
|
||||
|
||||
const DEFAULT_PACKAGES = ["busybox", "ca-certificates", "dumb-init", "git", "openssl"];
|
||||
@@ -679,6 +679,7 @@ ENV TRIGGER_PROJECT_ID=\${TRIGGER_PROJECT_ID} \
|
||||
TRIGGER_DEPLOYMENT_VERSION=\${TRIGGER_DEPLOYMENT_VERSION} \
|
||||
TRIGGER_CONTENT_HASH=\${TRIGGER_CONTENT_HASH} \
|
||||
TRIGGER_PROJECT_REF=\${TRIGGER_PROJECT_REF} \
|
||||
UV_USE_IO_URING=0 \
|
||||
NODE_EXTRA_CA_CERTS=\${NODE_EXTRA_CA_CERTS} \
|
||||
NODE_ENV=production
|
||||
|
||||
@@ -791,6 +792,7 @@ ENV TRIGGER_PROJECT_ID=\${TRIGGER_PROJECT_ID} \
|
||||
TRIGGER_DEPLOYMENT_VERSION=\${TRIGGER_DEPLOYMENT_VERSION} \
|
||||
TRIGGER_CONTENT_HASH=\${TRIGGER_CONTENT_HASH} \
|
||||
TRIGGER_PROJECT_REF=\${TRIGGER_PROJECT_REF} \
|
||||
UV_USE_IO_URING=0 \
|
||||
NODE_EXTRA_CA_CERTS=\${NODE_EXTRA_CA_CERTS} \
|
||||
NODE_ENV=production
|
||||
|
||||
|
||||
@@ -215,6 +215,8 @@ class DevSupervisor implements WorkerRuntime {
|
||||
queues: backgroundWorker.manifest.queues,
|
||||
contentHash: manifest.contentHash,
|
||||
sourceFiles,
|
||||
runtime: backgroundWorker.manifest.runtime,
|
||||
runtimeVersion: backgroundWorker.manifest.runtimeVersion,
|
||||
},
|
||||
engine: "V2",
|
||||
supportsLazyAttempts: true,
|
||||
|
||||
@@ -17,6 +17,7 @@ import sourceMapSupport from "source-map-support";
|
||||
import { registerResources } from "../indexing/registerResources.js";
|
||||
import { env } from "std-env";
|
||||
import { normalizeImportPath } from "../utilities/normalizeImportPath.js";
|
||||
import { detectRuntimeVersion } from "@trigger.dev/core/v3/build";
|
||||
|
||||
sourceMapSupport.install({
|
||||
handleUncaughtExceptions: false,
|
||||
@@ -154,6 +155,7 @@ await sendMessageInCatalog(
|
||||
queues: resourceCatalog.listQueueManifests(),
|
||||
configPath: buildManifest.configPath,
|
||||
runtime: buildManifest.runtime,
|
||||
runtimeVersion: detectRuntimeVersion(),
|
||||
workerEntryPoint: buildManifest.runWorkerEntryPoint,
|
||||
controllerEntryPoint: buildManifest.runControllerEntryPoint,
|
||||
loaderEntryPoint: buildManifest.loaderEntryPoint,
|
||||
|
||||
@@ -104,6 +104,8 @@ async function indexDeployment({
|
||||
tasks: workerManifest.tasks,
|
||||
queues: workerManifest.queues,
|
||||
sourceFiles,
|
||||
runtime: workerManifest.runtime,
|
||||
runtimeVersion: workerManifest.runtimeVersion,
|
||||
},
|
||||
engine: "V2",
|
||||
supportsLazyAttempts: true,
|
||||
|
||||
@@ -17,6 +17,7 @@ import sourceMapSupport from "source-map-support";
|
||||
import { registerResources } from "../indexing/registerResources.js";
|
||||
import { env } from "std-env";
|
||||
import { normalizeImportPath } from "../utilities/normalizeImportPath.js";
|
||||
import { detectRuntimeVersion } from "@trigger.dev/core/v3/build";
|
||||
|
||||
sourceMapSupport.install({
|
||||
handleUncaughtExceptions: false,
|
||||
@@ -154,6 +155,7 @@ await sendMessageInCatalog(
|
||||
queues: resourceCatalog.listQueueManifests(),
|
||||
configPath: buildManifest.configPath,
|
||||
runtime: buildManifest.runtime,
|
||||
runtimeVersion: detectRuntimeVersion(),
|
||||
workerEntryPoint: buildManifest.runWorkerEntryPoint,
|
||||
controllerEntryPoint: buildManifest.runControllerEntryPoint,
|
||||
loaderEntryPoint: buildManifest.loaderEntryPoint,
|
||||
|
||||
@@ -18,6 +18,7 @@ const Env = z.object({
|
||||
TRIGGER_PROJECT_REF: z.string(),
|
||||
NODE_ENV: z.string().default("production"),
|
||||
NODE_EXTRA_CA_CERTS: z.string().optional(),
|
||||
UV_USE_IO_URING: z.string().optional(),
|
||||
|
||||
// Set at runtime
|
||||
TRIGGER_WORKLOAD_CONTROLLER_ID: z.string().default(`controller_${randomUUID()}`),
|
||||
@@ -70,6 +71,9 @@ export class RunnerEnv {
|
||||
get NODE_EXTRA_CA_CERTS() {
|
||||
return this.env.NODE_EXTRA_CA_CERTS;
|
||||
}
|
||||
get UV_USE_IO_URING() {
|
||||
return this.env.UV_USE_IO_URING;
|
||||
}
|
||||
get OTEL_EXPORTER_OTLP_ENDPOINT() {
|
||||
return this.env.OTEL_EXPORTER_OTLP_ENDPOINT;
|
||||
}
|
||||
@@ -217,6 +221,7 @@ export class RunnerEnv {
|
||||
NODE_ENV: this.NODE_ENV,
|
||||
NODE_EXTRA_CA_CERTS: this.NODE_EXTRA_CA_CERTS,
|
||||
OTEL_EXPORTER_OTLP_ENDPOINT: this.OTEL_EXPORTER_OTLP_ENDPOINT,
|
||||
UV_USE_IO_URING: this.UV_USE_IO_URING,
|
||||
};
|
||||
|
||||
// Filter out undefined values
|
||||
|
||||
@@ -2,6 +2,7 @@ import { join } from "node:path";
|
||||
import { pathToFileURL } from "url";
|
||||
import { BuildRuntime } from "../schemas/build.js";
|
||||
import { dedupFlags } from "./flags.js";
|
||||
import { homedir } from "node:os";
|
||||
|
||||
export const DEFAULT_RUNTIME = "node" satisfies BuildRuntime;
|
||||
|
||||
@@ -31,7 +32,7 @@ export function execPathForRuntime(runtime: BuildRuntime): string {
|
||||
return join(process.env.BUN_INSTALL_BIN, "bun");
|
||||
}
|
||||
|
||||
return join("~", ".bin", "bin", "bun");
|
||||
return join(homedir(), ".bun", "bin", "bun");
|
||||
default:
|
||||
throw new Error(`Unsupported runtime ${runtime}`);
|
||||
}
|
||||
@@ -84,3 +85,19 @@ function nodeRuntimeNeedsGlobalWebCryptoFlag(): boolean {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function detectRuntimeVersion(): string | undefined {
|
||||
try {
|
||||
// Check if we're running under Bun
|
||||
const isBun = typeof process.versions.bun === "string";
|
||||
|
||||
if (isBun) {
|
||||
return process.versions.bun;
|
||||
}
|
||||
|
||||
// Otherwise, return Node.js version
|
||||
return process.versions.node;
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -348,6 +348,7 @@ export const InitializeDeploymentRequestBody = z.object({
|
||||
selfHosted: z.boolean().optional(),
|
||||
gitMeta: GitMeta.optional(),
|
||||
type: z.enum(["MANAGED", "UNMANAGED", "V1"]).optional(),
|
||||
runtime: z.string().optional(),
|
||||
});
|
||||
|
||||
export type InitializeDeploymentRequestBody = z.infer<typeof InitializeDeploymentRequestBody>;
|
||||
|
||||
@@ -90,6 +90,7 @@ export const WorkerManifest = z.object({
|
||||
loaderEntryPoint: z.string().optional(),
|
||||
initEntryPoint: z.string().optional(), // Optional init.ts entry point
|
||||
runtime: BuildRuntime,
|
||||
runtimeVersion: z.string().optional(),
|
||||
customConditions: z.array(z.string()).optional(),
|
||||
timings: z.record(z.number()).optional(),
|
||||
processKeepAlive: z
|
||||
|
||||
@@ -33,6 +33,8 @@ export const BackgroundWorkerMetadata = z.object({
|
||||
tasks: z.array(TaskResource),
|
||||
queues: z.array(QueueManifest).optional(),
|
||||
sourceFiles: z.array(BackgroundWorkerSourceFileMetadata).optional(),
|
||||
runtime: z.string().optional(),
|
||||
runtimeVersion: z.string().optional(),
|
||||
});
|
||||
|
||||
export type BackgroundWorkerMetadata = z.infer<typeof BackgroundWorkerMetadata>;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Database } from "bun:sqlite";
|
||||
import { task } from "@trigger.dev/sdk/v3";
|
||||
import { task } from "@trigger.dev/sdk";
|
||||
|
||||
export const bunTask = task({
|
||||
id: "bun-task",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { defineConfig } from "@trigger.dev/sdk/v3";
|
||||
import { defineConfig } from "@trigger.dev/sdk";
|
||||
|
||||
export default defineConfig({
|
||||
runtime: "bun",
|
||||
@@ -17,10 +17,4 @@ export default defineConfig({
|
||||
},
|
||||
enableConsoleLogging: false,
|
||||
logLevel: "info",
|
||||
onStart: async (payload, { ctx }) => {
|
||||
console.log(`Task ${ctx.task.id} started ${ctx.run.id}`);
|
||||
},
|
||||
onFailure: async (payload, error, { ctx }) => {
|
||||
console.log(`Task ${ctx.task.id} failed ${ctx.run.id}`);
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user