Skip to content

Commit a2277d5

Browse files
committed
Merge branch 'main' into fix/tri-6732-hover-vertical-timeline-does-not-update-on-task-runs
2 parents b4d6d78 + 6d6ed47 commit a2277d5

File tree

15 files changed

+104
-46
lines changed

15 files changed

+104
-46
lines changed

.changeset/five-pens-fly.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"trigger.dev": minor
3+
"@trigger.dev/core": minor
4+
---
5+
6+
feat(cli): deterministic image builds for deployments

apps/supervisor/src/index.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,12 @@ class ManagedSupervisor {
244244
}
245245

246246
try {
247+
if (!message.deployment.friendlyId) {
248+
// mostly a type guard, deployments always exists for deployed environments
249+
// a proper fix would be to use a discriminated union schema to differentiate between dequeued runs in dev and in deployed environments.
250+
throw new Error("Deployment is missing");
251+
}
252+
247253
await this.workloadManager.create({
248254
dequeuedAt: message.dequeuedAt,
249255
envId: message.environment.id,
@@ -252,6 +258,8 @@ class ManagedSupervisor {
252258
machine: message.run.machine,
253259
orgId: message.organization.id,
254260
projectId: message.project.id,
261+
deploymentFriendlyId: message.deployment.friendlyId,
262+
deploymentVersion: message.backgroundWorker.version,
255263
runId: message.run.id,
256264
runFriendlyId: message.run.friendlyId,
257265
version: message.version,

apps/supervisor/src/workloadManager/docker.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ export class DockerWorkloadManager implements WorkloadManager {
7272
`TRIGGER_DEQUEUED_AT_MS=${opts.dequeuedAt.getTime()}`,
7373
`TRIGGER_POD_SCHEDULED_AT_MS=${Date.now()}`,
7474
`TRIGGER_ENV_ID=${opts.envId}`,
75+
`TRIGGER_DEPLOYMENT_ID=${opts.deploymentFriendlyId}`,
76+
`TRIGGER_DEPLOYMENT_VERSION=${opts.deploymentVersion}`,
7577
`TRIGGER_RUN_ID=${opts.runFriendlyId}`,
7678
`TRIGGER_SNAPSHOT_ID=${opts.snapshotFriendlyId}`,
7779
`TRIGGER_SUPERVISOR_API_PROTOCOL=${this.opts.workloadApiProtocol}`,

apps/supervisor/src/workloadManager/kubernetes.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,14 @@ export class KubernetesWorkloadManager implements WorkloadManager {
123123
name: "TRIGGER_ENV_ID",
124124
value: opts.envId,
125125
},
126+
{
127+
name: "TRIGGER_DEPLOYMENT_ID",
128+
value: opts.deploymentFriendlyId,
129+
},
130+
{
131+
name: "TRIGGER_DEPLOYMENT_VERSION",
132+
value: opts.deploymentVersion,
133+
},
126134
{
127135
name: "TRIGGER_SNAPSHOT_ID",
128136
value: opts.snapshotFriendlyId,

apps/supervisor/src/workloadManager/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ export interface WorkloadManagerCreateOptions {
2929
envType: EnvironmentType;
3030
orgId: string;
3131
projectId: string;
32+
deploymentFriendlyId: string;
33+
deploymentVersion: string;
3234
runId: string;
3335
runFriendlyId: string;
3436
snapshotId: string;

internal-packages/run-engine/src/engine/systems/dequeueSystem.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,8 @@ export class DequeueSystem {
559559
friendlyId: result.worker.friendlyId,
560560
version: result.worker.version,
561561
},
562+
// TODO: use a discriminated union schema to differentiate between dequeued runs in dev and in deployed environments.
563+
// Would help make the typechecking stricter
562564
deployment: {
563565
id: result.deployment?.id,
564566
friendlyId: result.deployment?.friendlyId,

packages/cli-v3/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,10 +92,10 @@
9292
"@opentelemetry/resources": "2.0.1",
9393
"@opentelemetry/sdk-trace-node": "2.0.1",
9494
"@opentelemetry/semantic-conventions": "1.36.0",
95+
"@s2-dev/streamstore": "^0.17.6",
9596
"@trigger.dev/build": "workspace:4.2.0",
9697
"@trigger.dev/core": "workspace:4.2.0",
9798
"@trigger.dev/schema-to-json": "workspace:4.2.0",
98-
"@s2-dev/streamstore": "^0.17.6",
9999
"ansi-escapes": "^7.0.0",
100100
"braces": "^3.0.3",
101101
"c12": "^1.11.1",
@@ -117,6 +117,7 @@
117117
"import-in-the-middle": "1.11.0",
118118
"import-meta-resolve": "^4.1.0",
119119
"ini": "^5.0.0",
120+
"json-stable-stringify": "^1.3.0",
120121
"jsonc-parser": "3.2.1",
121122
"magicast": "^0.3.4",
122123
"minimatch": "^10.0.1",

packages/cli-v3/src/build/buildWorker.ts

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { join, relative, sep } from "node:path";
1212
import { generateContainerfile } from "../deploy/buildImage.js";
1313
import { writeFile } from "node:fs/promises";
1414
import { buildManifestToJSON } from "../utilities/buildManifest.js";
15-
import { readPackageJSON, writePackageJSON } from "pkg-types";
15+
import { readPackageJSON } from "pkg-types";
1616
import { writeJSONFile } from "../utilities/fileSystem.js";
1717
import { isWindows } from "std-env";
1818
import { pathToFileURL } from "node:url";
@@ -192,20 +192,23 @@ async function writeDeployFiles({
192192
) ?? {};
193193

194194
// Step 3: Write the resolved dependencies to the package.json file
195-
await writePackageJSON(join(outputPath, "package.json"), {
196-
...packageJson,
197-
name: packageJson.name ?? "trigger-project",
198-
dependencies: {
199-
...dependencies,
195+
await writeJSONFile(
196+
join(outputPath, "package.json"),
197+
{
198+
...packageJson,
199+
name: packageJson.name ?? "trigger-project",
200+
dependencies: {
201+
...dependencies,
202+
},
203+
trustedDependencies: Object.keys(dependencies).sort(),
204+
devDependencies: {},
205+
peerDependencies: {},
206+
scripts: {},
200207
},
201-
trustedDependencies: Object.keys(dependencies),
202-
devDependencies: {},
203-
peerDependencies: {},
204-
scripts: {},
205-
});
208+
true
209+
);
206210

207211
await writeJSONFile(join(outputPath, "build.json"), buildManifestToJSON(buildManifest));
208-
await writeJSONFile(join(outputPath, "metafile.json"), bundleResult.metafile);
209212
await writeContainerfile(outputPath, buildManifest);
210213
}
211214

packages/cli-v3/src/build/bundle.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,9 @@ export async function createBuildManifestFromBundle({
414414
otelImportHook: {
415415
include: resolvedConfig.instrumentedPackageNames ?? [],
416416
},
417-
outputHashes: bundle.outputHashes,
417+
// `outputHashes` is only needed for dev builds for the deduplication mechanism during rebuilds.
418+
// For deploys builds, we omit it to ensure deterministic builds
419+
outputHashes: target === "dev" ? bundle.outputHashes : {},
418420
};
419421

420422
if (!workerDir) {

packages/cli-v3/src/deploy/buildImage.ts

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ async function remoteBuildImage(options: DepotBuildImageOptions): Promise<BuildI
201201
const outputOptions = getOutputOptions({
202202
imageTag: undefined, // This is already handled via the --save flag
203203
push: true, // We always push the image to the registry
204+
load: options.load,
204205
compression: options.compression,
205206
compressionLevel: options.compressionLevel,
206207
forceCompression: options.forceCompression,
@@ -213,18 +214,17 @@ async function remoteBuildImage(options: DepotBuildImageOptions): Promise<BuildI
213214
options.noCache ? "--no-cache" : undefined,
214215
"--platform",
215216
options.imagePlatform,
216-
options.load ? "--load" : undefined,
217217
"--provenance",
218218
"false",
219219
"--metadata-file",
220220
"metadata.json",
221221
"--build-arg",
222+
`SOURCE_DATE_EPOCH=0`,
223+
"--build-arg",
222224
`TRIGGER_PROJECT_ID=${options.projectId}`,
223225
"--build-arg",
224226
`TRIGGER_DEPLOYMENT_ID=${options.deploymentId}`,
225227
"--build-arg",
226-
`TRIGGER_DEPLOYMENT_VERSION=${options.deploymentVersion}`,
227-
"--build-arg",
228228
`TRIGGER_CONTENT_HASH=${options.contentHash}`,
229229
"--build-arg",
230230
`TRIGGER_PROJECT_REF=${options.projectRef}`,
@@ -534,6 +534,7 @@ async function localBuildImage(options: SelfHostedBuildImageOptions): Promise<Bu
534534
const outputOptions = getOutputOptions({
535535
imageTag,
536536
push,
537+
load,
537538
compression,
538539
compressionLevel,
539540
forceCompression,
@@ -563,18 +564,17 @@ async function localBuildImage(options: SelfHostedBuildImageOptions): Promise<Bu
563564
options.imagePlatform,
564565
options.network ? `--network=${options.network}` : undefined,
565566
addHost ? `--add-host=${addHost}` : undefined,
566-
load ? "--load" : undefined,
567567
"--provenance",
568568
"false",
569569
"--metadata-file",
570570
"metadata.json",
571571
"--build-arg",
572+
`SOURCE_DATE_EPOCH=0`,
573+
"--build-arg",
572574
`TRIGGER_PROJECT_ID=${options.projectId}`,
573575
"--build-arg",
574576
`TRIGGER_DEPLOYMENT_ID=${options.deploymentId}`,
575577
"--build-arg",
576-
`TRIGGER_DEPLOYMENT_VERSION=${options.deploymentVersion}`,
577-
"--build-arg",
578578
`TRIGGER_CONTENT_HASH=${options.contentHash}`,
579579
"--build-arg",
580580
`TRIGGER_PROJECT_REF=${options.projectRef}`,
@@ -588,8 +588,6 @@ async function localBuildImage(options: SelfHostedBuildImageOptions): Promise<Bu
588588
...(options.extraCACerts ? ["--build-arg", `NODE_EXTRA_CA_CERTS=${options.extraCACerts}`] : []),
589589
"--progress",
590590
"plain",
591-
"-t",
592-
imageTag,
593591
".", // The build context
594592
].filter(Boolean) as string[];
595593

@@ -814,15 +812,11 @@ USER bun
814812
WORKDIR /app
815813
816814
ARG TRIGGER_PROJECT_ID
817-
ARG TRIGGER_DEPLOYMENT_ID
818-
ARG TRIGGER_DEPLOYMENT_VERSION
819815
ARG TRIGGER_CONTENT_HASH
820816
ARG TRIGGER_PROJECT_REF
821817
ARG NODE_EXTRA_CA_CERTS
822818
823819
ENV TRIGGER_PROJECT_ID=\${TRIGGER_PROJECT_ID} \
824-
TRIGGER_DEPLOYMENT_ID=\${TRIGGER_DEPLOYMENT_ID} \
825-
TRIGGER_DEPLOYMENT_VERSION=\${TRIGGER_DEPLOYMENT_VERSION} \
826820
TRIGGER_CONTENT_HASH=\${TRIGGER_CONTENT_HASH} \
827821
TRIGGER_PROJECT_REF=\${TRIGGER_PROJECT_REF} \
828822
UV_USE_IO_URING=0 \
@@ -928,15 +922,11 @@ USER node
928922
WORKDIR /app
929923
930924
ARG TRIGGER_PROJECT_ID
931-
ARG TRIGGER_DEPLOYMENT_ID
932-
ARG TRIGGER_DEPLOYMENT_VERSION
933925
ARG TRIGGER_CONTENT_HASH
934926
ARG TRIGGER_PROJECT_REF
935927
ARG NODE_EXTRA_CA_CERTS
936928
937929
ENV TRIGGER_PROJECT_ID=\${TRIGGER_PROJECT_ID} \
938-
TRIGGER_DEPLOYMENT_ID=\${TRIGGER_DEPLOYMENT_ID} \
939-
TRIGGER_DEPLOYMENT_VERSION=\${TRIGGER_DEPLOYMENT_VERSION} \
940930
TRIGGER_CONTENT_HASH=\${TRIGGER_CONTENT_HASH} \
941931
TRIGGER_PROJECT_REF=\${TRIGGER_PROJECT_REF} \
942932
UV_USE_IO_URING=0 \
@@ -1129,18 +1119,20 @@ function shouldLoad(load?: boolean, push?: boolean) {
11291119
function getOutputOptions({
11301120
imageTag,
11311121
push,
1122+
load,
11321123
compression,
11331124
compressionLevel,
11341125
forceCompression,
11351126
}: {
11361127
imageTag?: string;
11371128
push?: boolean;
1129+
load?: boolean;
11381130
compression?: "zstd" | "gzip";
11391131
compressionLevel?: number;
11401132
forceCompression?: boolean;
11411133
}): string[] {
11421134
// Always use OCI media types for compatibility
1143-
const outputOptions: string[] = ["type=image", "oci-mediatypes=true"];
1135+
const outputOptions: string[] = ["type=image", "oci-mediatypes=true", "rewrite-timestamp=true"];
11441136

11451137
if (imageTag) {
11461138
outputOptions.push(`name=${imageTag}`);
@@ -1150,6 +1142,10 @@ function getOutputOptions({
11501142
outputOptions.push("push=true");
11511143
}
11521144

1145+
if (load) {
1146+
outputOptions.push("load=true");
1147+
}
1148+
11531149
// Only add compression args when using zstd (gzip is the default, no args needed)
11541150
if (compression === "zstd") {
11551151
outputOptions.push("compression=zstd");

0 commit comments

Comments
 (0)