Visitar URL original
fix(cli): carry extraCACerts through bundle deploys and fix Windows p… · developerfred/trigger.dev@4fa5363 · GitHub
Skip to content

Commit 4fa5363

Browse files
developerfredclaude
andcommitted
fix(cli): carry extraCACerts through bundle deploys and fix Windows paths
Address review feedback on the extraCACerts fix: - Store the in-image CA path in the build manifest config so the regular deploy, --from-bundle and --local-bundle all pass NODE_EXTRA_CA_CERTS to the image build. - Split relative paths on the platform separator in findFilesByMatchers so files outside the project dir land inside the build output on Windows, matching resolveExtraCACertsImagePath. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
1 parent 1119e9c commit 4fa5363

7 files changed

Lines changed: 49 additions & 19 deletions

File tree

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
---
22
"trigger.dev": patch
3+
"@trigger.dev/core": patch
4+
"@trigger.dev/build": patch
35
---
46

5-
Fix `extraCACerts` in `trigger.config.ts` having no effect on deployed tasks. The CA file is now included in the deployed image and `NODE_EXTRA_CA_CERTS` points at it, so self-signed or corporate certificates are trusted at runtime.
7+
Fix `extraCACerts` in `trigger.config.ts` having no effect on deployed tasks. The CA file is now included in the deployed image and `NODE_EXTRA_CA_CERTS` points at it, so self-signed or corporate certificates are trusted at runtime, including with `--local-bundle` and `--from-bundle`. Also fixes files outside the project directory (such as `../shared/ca.crt`) being copied to the wrong place on Windows.

‎packages/build/src/internal/copyFiles.ts‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { cp, copyFile, mkdir } from "node:fs/promises";
2-
import { dirname, join, posix, relative } from "node:path";
2+
import { dirname, join, relative, sep } from "node:path";
33
import { glob } from "tinyglobby";
44

55
/**
@@ -44,9 +44,9 @@ export async function findFilesByMatchers(
4444

4545
const assets: CopyPair[] = files.map((file) => {
4646
const pathInsideDestinationDir = relative(cwd, file)
47-
.split(posix.sep)
47+
.split(sep)
4848
.filter((p) => p !== "..")
49-
.join(posix.sep);
49+
.join(sep);
5050
return {
5151
source: file,
5252
destination: join(destinationDir, pathInsideDestinationDir),

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { BuildManifest, BuildTarget, TaskFile } from "@trigger.dev/core/v3/schem
44
import * as esbuild from "esbuild";
55
import { createHash } from "node:crypto";
66
import { basename, join, relative, resolve } from "node:path";
7+
import { resolveExtraCACertsImagePath } from "../deploy/buildImage.js";
78
import { createFile, createFileWithStore } from "../utilities/fileSystem.js";
89
import { logger } from "../utilities/logger.js";
910
import { resolveFileSources } from "../utilities/sourceFiles.js";
@@ -404,6 +405,10 @@ export async function createBuildManifestFromBundle({
404405
config: {
405406
project: resolvedConfig.project,
406407
dirs: resolvedConfig.dirs,
408+
extraCACerts: resolveExtraCACertsImagePath(
409+
resolvedConfig.extraCACerts,
410+
resolvedConfig.workingDir
411+
),
407412
},
408413
outputPath: destination,
409414
indexControllerEntryPoint:

‎packages/cli-v3/src/commands/deploy.ts‎

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ import {
5050
} from "../cli/common.js";
5151
import { loadConfig } from "../config.js";
5252
import { authenticateForDeploy, userIdForDeploy } from "../deploy/auth.js";
53-
import { buildImage, resolveExtraCACertsImagePath } from "../deploy/buildImage.js";
53+
import { buildImage } from "../deploy/buildImage.js";
5454
import {
5555
checkLogsForErrors,
5656
checkLogsForWarnings,
@@ -765,10 +765,7 @@ async function _deployCommand(dir: string, options: DeployCommandOptions) {
765765
externalBuildProjectId: deployment.externalBuildData?.projectId,
766766
projectId: projectClient.id,
767767
projectRef: resolvedConfig.project,
768-
extraCACerts: resolveExtraCACertsImagePath(
769-
resolvedConfig.extraCACerts,
770-
resolvedConfig.workingDir
771-
),
768+
extraCACerts: buildManifest.config.extraCACerts,
772769
apiUrl: projectClient.client.apiURL,
773770
apiKey: projectClient.client.accessToken!,
774771
apiClient: projectClient.client,
@@ -1670,11 +1667,17 @@ async function handleLocalBundleDeploy({
16701667
const bundleOutputPath = destination.path;
16711668

16721669
// Extensions can set undefined values at runtime despite the manifest type
1673-
const bundleBuildEnvVars = Object.fromEntries(
1674-
Object.entries(buildManifest.build.env ?? {}).filter(
1675-
(entry): entry is [string, string] => typeof entry[1] === "string"
1676-
)
1677-
);
1670+
const bundleBuildEnvVars: Record<string, string> = {
1671+
...Object.fromEntries(
1672+
Object.entries(buildManifest.build.env ?? {}).filter(
1673+
(entry): entry is [string, string] => typeof entry[1] === "string"
1674+
)
1675+
),
1676+
// The Containerfile reads NODE_EXTRA_CA_CERTS as a build arg, which the build server passes through
1677+
...(buildManifest.config.extraCACerts
1678+
? { NODE_EXTRA_CA_CERTS: buildManifest.config.extraCACerts }
1679+
: {}),
1680+
};
16781681

16791682
if (options.dryRun) {
16801683
logger.info(`Dry run complete. View the built bundle at ${destination.path}`);
@@ -1911,6 +1914,7 @@ async function buildAndFinalizeFromBundle({
19111914
authAccessToken,
19121915
compilationPath,
19131916
buildEnvVars,
1917+
extraCACerts,
19141918
branch,
19151919
isLocalBuild,
19161920
}: {
@@ -1923,6 +1927,7 @@ async function buildAndFinalizeFromBundle({
19231927
authAccessToken: string;
19241928
compilationPath: string;
19251929
buildEnvVars: Record<string, string | undefined> | undefined;
1930+
extraCACerts: string | undefined;
19261931
branch: string | undefined;
19271932
isLocalBuild: boolean;
19281933
}) {
@@ -1975,6 +1980,7 @@ async function buildAndFinalizeFromBundle({
19751980
externalBuildProjectId: deployment.externalBuildData?.projectId,
19761981
projectId,
19771982
projectRef,
1983+
extraCACerts,
19781984
apiUrl: apiClient.apiURL,
19791985
apiKey: apiClient.accessToken!,
19801986
apiClient,
@@ -2343,6 +2349,7 @@ async function handleFromBundleDeploy({
23432349
authAccessToken: auth.accessToken,
23442350
compilationPath: bundlePath,
23452351
buildEnvVars,
2352+
extraCACerts: bundleManifest.config.extraCACerts,
23462353
branch,
23472354
isLocalBuild: true,
23482355
});

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { readFileSync } from "node:fs";
2-
import { join } from "node:path";
2+
import path, { join } from "node:path";
33
import { fileURLToPath } from "node:url";
44
import type { BuildRuntime } from "@trigger.dev/core/v3/schemas";
55
import { describe, expect, it } from "vitest";
@@ -66,6 +66,15 @@ describe("resolveExtraCACertsImagePath", () => {
6666
it("strips leading parent segments the same way additionalFiles does", () => {
6767
expect(resolveExtraCACertsImagePath("../shared/ca.crt", "/project")).toBe("/app/shared/ca.crt");
6868
});
69+
70+
it("handles Windows separators", () => {
71+
expect(resolveExtraCACertsImagePath("../shared/ca.crt", "C:\\project", path.win32)).toBe(
72+
"/app/shared/ca.crt"
73+
);
74+
expect(resolveExtraCACertsImagePath("./certs/ca.crt", "C:\\project", path.win32)).toBe(
75+
"/app/certs/ca.crt"
76+
);
77+
});
6978
});
7079

7180
describe("generateContainerfile", () => {

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

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { depot } from "@depot/cli";
33
import { x } from "tinyexec";
44
import type { BuildManifest, BuildRuntime } from "@trigger.dev/core/v3/schemas";
55
import { networkInterfaces } from "os";
6-
import { join, relative, resolve, sep } from "path";
6+
import path, { join } from "path";
77
import { safeReadJSONFile } from "../utilities/fileSystem.js";
88
import { readFileSync } from "fs";
99

@@ -59,13 +59,18 @@ export interface BuildImageOptions {
5959
* Where the CA file ends up inside the image. The build copies it into /app using the same layout
6060
* as additionalFiles (path relative to the project root, with leading `..` segments stripped).
6161
*/
62-
export function resolveExtraCACertsImagePath(extraCACerts: string | undefined, workingDir: string) {
62+
export function resolveExtraCACertsImagePath(
63+
extraCACerts: string | undefined,
64+
workingDir: string,
65+
pathApi: Pick<typeof path, "relative" | "resolve" | "sep"> = path
66+
) {
6367
if (!extraCACerts) {
6468
return undefined;
6569
}
6670

67-
const relativePath = relative(workingDir, resolve(workingDir, extraCACerts))
68-
.split(sep)
71+
const relativePath = pathApi
72+
.relative(workingDir, pathApi.resolve(workingDir, extraCACerts))
73+
.split(pathApi.sep)
6974
.filter((segment) => segment !== "..")
7075
.join("/");
7176

‎packages/core/src/v3/schemas/config.ts‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { z } from "zod/v4";
33
export const ConfigManifest = z.object({
44
project: z.string(),
55
dirs: z.string().array(),
6+
/** Path of the extra CA file inside the image, used for NODE_EXTRA_CA_CERTS */
7+
extraCACerts: z.string().optional(),
68
});
79

810
export type ConfigManifest = z.infer<typeof ConfigManifest>;

0 commit comments

Comments
 (0)