Skip to content

Commit 8f7916c

Browse files
[deploy-helpers] Containers support for Worker Preview deployments in the Build Output (#15822)
Co-authored-by: Pete Bacon Darwin <pbacondarwin@cloudflare.com>
1 parent c59dae6 commit 8f7916c

16 files changed

Lines changed: 895 additions & 69 deletions

File tree

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@cloudflare/workers-utils": minor
3+
---
4+
5+
Expose a helper for identifying live Durable Object exports
6+
7+
Use `isLiveDurableObjectExport()` to distinguish created and incoming-transfer exports from deleted, renamed, and transferred tombstones.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@cloudflare/deploy-helpers": minor
3+
"wrangler": minor
4+
---
5+
6+
Support Containers in Worker Preview deployments with the Build Output.

‎packages/containers-shared/src/build.ts‎

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ export async function pushImageIfChanged({
282282
pathToDocker: string;
283283
sourceTag: string;
284284
targetTag: string;
285-
containerConfig?: DockerfileContainerConfig;
285+
containerConfig?: ContainerNormalizedConfig;
286286
accountId?: string;
287287
complianceConfig?: ComplianceConfig;
288288
cleanupSourceTag?: boolean;
@@ -353,11 +353,12 @@ export async function pushImageIfChanged({
353353

354354
if (parsedRemoteManifest.Descriptor.digest === hash) {
355355
logger.log("Image already exists remotely, skipping push");
356-
logger.debug(
357-
`Untagging built image: ${sourceTag} since there was no change.`
358-
);
359-
360-
await runDockerCmd(pathToDocker, ["image", "rm", sourceTag]);
356+
if (cleanupSourceTag !== false) {
357+
logger.debug(
358+
`Untagging built image: ${sourceTag} since there was no change.`
359+
);
360+
await runDockerCmd(pathToDocker, ["image", "rm", sourceTag]);
361+
}
361362

362363
return { remoteDigest };
363364
}

‎packages/containers-shared/tests/build-and-push.test.ts‎

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
InstanceType,
2020
pushBuiltContainerImage,
2121
pushCommand,
22+
pushImageIfChanged,
2223
SchedulingPolicy,
2324
} from "../index";
2425
import type { BuiltContainerImage, BuiltImage } from "../src/build";
@@ -314,6 +315,64 @@ describe("buildCommand", () => {
314315
]);
315316
});
316317

318+
it("preserves a reusable Build Output image tag across uploads", async ({
319+
expect,
320+
}) => {
321+
const digest =
322+
"registry.cloudflare.com/some-account-id/test-app@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
323+
inspectOutputs = [
324+
"[]",
325+
"53387881 2",
326+
`["${digest}"]`,
327+
`["${digest}"]`,
328+
"53387881 2",
329+
];
330+
vi.mocked(execFileSync).mockReturnValue(
331+
'{"Descriptor":{"digest":"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}}'
332+
);
333+
334+
for (let attempt = 0; attempt < 2; attempt++) {
335+
await expect(
336+
pushImageIfChanged({
337+
pathToDocker: "docker",
338+
sourceTag: "test-app:tag",
339+
targetTag: "test-app:tag",
340+
accountId: "some-account-id",
341+
containerConfig: dockerfileContainer,
342+
cleanupSourceTag: false,
343+
})
344+
).resolves.toEqual({
345+
remoteDigest: `${getCloudflareContainerRegistry()}/some-account-id/test-app@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`,
346+
});
347+
}
348+
349+
expectNoSpawnWith(["image", "rm", "test-app:tag"]);
350+
expect(
351+
vi.mocked(spawn).mock.calls.filter(([, args]) => args?.[0] === "push")
352+
).toHaveLength(1);
353+
});
354+
355+
it("validates a local image against its container disk limit", async ({
356+
expect,
357+
}) => {
358+
inspectOutputs = ["[]", "2200000000 2"];
359+
360+
await expect(
361+
pushImageIfChanged({
362+
pathToDocker: "docker",
363+
sourceTag: "test-app:tag",
364+
targetTag: "test-app:tag",
365+
accountId: "some-account-id",
366+
containerConfig: dockerfileContainer,
367+
cleanupSourceTag: false,
368+
})
369+
).rejects.toThrow(/Image too large/);
370+
expectNoSpawnWith([
371+
"push",
372+
`${getCloudflareContainerRegistry()}/some-account-id/test-app:tag`,
373+
]);
374+
});
375+
317376
it("uses docker manifest inspect when pushed image inspect has no digest", async ({
318377
expect,
319378
}) => {

‎packages/deploy-helpers/src/deploy/deploy.ts‎

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -791,12 +791,16 @@ async function deployWorker(
791791
});
792792
}
793793
}
794-
await deployContainers(config, containerDeployments, {
795-
versionId,
796-
accountId,
797-
scriptName,
798-
dispatchNamespace: props.dispatchNamespace,
799-
});
794+
await deployContainers(
795+
{ ...config, containers: props.containers.source },
796+
containerDeployments,
797+
{
798+
versionId,
799+
accountId,
800+
scriptName,
801+
dispatchNamespace: props.dispatchNamespace,
802+
}
803+
);
800804
}
801805
if (!skipContainerChanges && durableObjectContainerConfig.length > 0) {
802806
assert(versionId && accountId);

0 commit comments

Comments
 (0)