Skip to content

Commit 2429533

Browse files
authored
Fix manifest inspect failing due to wrong image ref (#10923)
* update manifest inspect command * changeset * e2e test * fixups and pr feedback * remove retries * only run e2e tests on linux now that we build the image * linting
1 parent 88b5b7f commit 2429533

File tree

5 files changed

+283
-107
lines changed

5 files changed

+283
-107
lines changed

.changeset/rich-wasps-sell.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"wrangler": patch
3+
---
4+
5+
fix: update `docker manifest inspect` to use full image registry uri when checking if the image exists remotely

packages/wrangler/e2e/deployments.test.ts

Lines changed: 83 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import assert from "node:assert";
2+
import isCI from "is-ci";
23
import dedent from "ts-dedent";
34
import { fetch } from "undici";
45
import {
56
afterAll,
67
afterEach,
8+
beforeAll,
79
beforeEach,
810
describe,
911
expect,
@@ -842,11 +844,21 @@ Current Version ID: 00000000-0000-0000-0000-000000000000`);
842844
await checkAssets(testCases, deployedUrl);
843845
});
844846
});
847+
});
845848

846-
describe("durable objects [containers]", () => {
847-
beforeEach(async () => {
848-
await helper.seed({
849-
"wrangler.toml": dedent`
849+
const skipContainersTest =
850+
!CLOUDFLARE_ACCOUNT_ID || (isCI && process.platform !== "linux");
851+
describe.skipIf(skipContainersTest)("containers", () => {
852+
let helper: WranglerE2ETestHelper;
853+
let workerName: string;
854+
let applicationId: string | undefined;
855+
let deployedUrl: string;
856+
857+
beforeAll(async () => {
858+
helper = new WranglerE2ETestHelper();
859+
workerName = generateResourceName();
860+
await helper.seed({
861+
"wrangler.toml": dedent`
850862
name = "${workerName}"
851863
main = "src/index.ts"
852864
compatibility_date = "2023-01-01"
@@ -859,14 +871,36 @@ Current Version ID: 00000000-0000-0000-0000-000000000000`);
859871
[[containers]]
860872
name = "e2e-test-${workerName}"
861873
class_name = "MyDurableObject"
862-
image = "registry.cloudchamber.cfdata.org/e2e-test:1.0"
874+
image = "./Dockerfile"
863875
max_instances = 1
864876
865877
[[migrations]]
866878
tag = "v1"
867879
new_sqlite_classes = ["MyDurableObject"]
880+
881+
[observability]
882+
enabled = true
868883
`,
869-
"src/index.ts": dedent`
884+
"container/index.js": dedent`
885+
const { createServer } = require("http");
886+
887+
const server = createServer((req, res) => {
888+
res.writeHead(200, { 'Content-Type': 'text/plain' });
889+
res.end('hello from container');
890+
});
891+
892+
server.listen(80, () => {
893+
console.log('Server running on port 80');
894+
});
895+
`,
896+
Dockerfile: dedent`
897+
FROM node:18-slim
898+
WORKDIR /app
899+
COPY container/index.js .
900+
CMD ["node", "index.js"]
901+
EXPOSE 80
902+
`,
903+
"src/index.ts": dedent`
870904
export default {
871905
async fetch(req, env) {
872906
const url = new URL(req.url)
@@ -902,45 +936,55 @@ Current Version ID: 00000000-0000-0000-0000-000000000000`);
902936
return this.ctx.container.getTcpPort(80).fetch(new Request("http://foo"));
903937
}
904938
}`,
905-
});
906939
});
940+
});
907941

908-
it.skip(
909-
"can fetch DO container",
910-
{ timeout: 60 * 3 * 1000, retry: 3 },
911-
async () => {
912-
const output = await helper.run(`wrangler deploy`);
913-
914-
const deployedUrl = getDeployedUrl(output);
915-
916-
const matchApplicationId = output.stdout.match(
917-
/([(]Application ID: (?<applicationId>.+?)[)])/
918-
);
919-
assert(matchApplicationId?.groups);
920-
921-
try {
922-
await vi.waitFor(
923-
async () => {
924-
const response = await fetch(`${deployedUrl}/do`);
925-
if (!response.ok) {
926-
throw new Error(
927-
"Durable object transient error: " + (await response.text())
928-
);
929-
}
942+
afterAll(async () => {
943+
// clean up user Worker after each test
944+
const deleteWorker = helper.run(`wrangler delete`);
945+
const deleteContainer = helper.run(
946+
`wrangler containers delete ${applicationId}`
947+
);
948+
await Promise.allSettled([deleteWorker, deleteContainer]);
949+
});
930950

931-
expect(await response.text()).toEqual("hello from container");
932-
},
951+
it(
952+
"won't rebuild unchanged containers",
953+
{ timeout: 60 * 2 * 1000 },
954+
async () => {
955+
const outputOne = await helper.run(`wrangler deploy`);
933956

934-
// big timeout for containers
935-
// (3m)
936-
{ timeout: 60 * 3 * 1000, interval: 1000 }
937-
);
938-
} finally {
939-
await helper.run(
940-
`wrangler containers delete ${matchApplicationId.groups.applicationId}`
957+
deployedUrl = getDeployedUrl(outputOne);
958+
959+
const matchApplicationId = outputOne.stdout.match(
960+
/([(]Application ID: (?<applicationId>.+?)[)])/
961+
);
962+
applicationId = matchApplicationId?.groups?.applicationId;
963+
assert(matchApplicationId?.groups);
964+
965+
const outputTwo = await helper.run(`wrangler deploy`);
966+
expect(outputTwo.stdout).toContain(`No changes to be made`);
967+
}
968+
);
969+
970+
it("can fetch DO container", { timeout: 60 * 2 * 1000 }, async () => {
971+
await vi.waitFor(
972+
async () => {
973+
const response = await fetch(`${deployedUrl}/do`, {
974+
signal: AbortSignal.timeout(5_000),
975+
});
976+
if (!response.ok) {
977+
throw new Error(
978+
"Durable object transient error: " + (await response.text())
941979
);
942980
}
943-
}
981+
982+
expect(await response.text()).toEqual("hello from container");
983+
},
984+
985+
// big timeout for containers
986+
// (3m)
987+
{ timeout: 60 * 2 * 1000, interval: 1000 }
944988
);
945989
});
946990
});

packages/wrangler/src/__tests__/cloudchamber/build.test.ts

Lines changed: 17 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,8 @@ describe("buildAndMaybePush", () => {
7373
dockerfile,
7474
});
7575

76-
// 3 calls: docker tag + docker push + docker rm
77-
expect(runDockerCmd).toHaveBeenCalledTimes(3);
76+
// 3 calls: docker tag + docker push
77+
expect(runDockerCmd).toHaveBeenCalledTimes(2);
7878
expect(runDockerCmd).toHaveBeenNthCalledWith(1, "docker", [
7979
"tag",
8080
`test-app:tag`,
@@ -84,15 +84,11 @@ describe("buildAndMaybePush", () => {
8484
"push",
8585
`${getCloudflareContainerRegistry()}/some-account-id/test-app:tag`,
8686
]);
87-
expect(runDockerCmd).toHaveBeenNthCalledWith(3, "docker", [
88-
"image",
89-
"rm",
90-
`${getCloudflareContainerRegistry()}/some-account-id/test-app:tag`,
91-
]);
87+
9288
expect(dockerImageInspect).toHaveBeenCalledTimes(2);
9389
expect(dockerImageInspect).toHaveBeenNthCalledWith(1, "docker", {
9490
imageTag: `test-app:tag`,
95-
formatString: "{{ json .RepoDigests }} {{ .Id }}",
91+
formatString: "{{ json .RepoDigests }}",
9692
});
9793
expect(dockerImageInspect).toHaveBeenNthCalledWith(2, "docker", {
9894
imageTag: `test-app:tag`,
@@ -121,8 +117,8 @@ describe("buildAndMaybePush", () => {
121117
dockerfile,
122118
});
123119

124-
// 3 calls: docker tag + docker push + docker rm
125-
expect(runDockerCmd).toHaveBeenCalledTimes(3);
120+
// 3 calls: docker tag + docker push
121+
expect(runDockerCmd).toHaveBeenCalledTimes(2);
126122
expect(runDockerCmd).toHaveBeenNthCalledWith(1, "docker", [
127123
"tag",
128124
`registry.cloudflare.com/test-app:tag`,
@@ -132,15 +128,10 @@ describe("buildAndMaybePush", () => {
132128
"push",
133129
`${getCloudflareContainerRegistry()}/some-account-id/test-app:tag`,
134130
]);
135-
expect(runDockerCmd).toHaveBeenNthCalledWith(3, "docker", [
136-
"image",
137-
"rm",
138-
`${getCloudflareContainerRegistry()}/some-account-id/test-app:tag`,
139-
]);
140131
expect(dockerImageInspect).toHaveBeenCalledTimes(2);
141132
expect(dockerImageInspect).toHaveBeenNthCalledWith(1, "docker", {
142133
imageTag: `${getCloudflareContainerRegistry()}/test-app:tag`,
143-
formatString: "{{ json .RepoDigests }} {{ .Id }}",
134+
formatString: "{{ json .RepoDigests }}",
144135
});
145136
expect(dockerImageInspect).toHaveBeenNthCalledWith(2, "docker", {
146137
imageTag: `${getCloudflareContainerRegistry()}/test-app:tag`,
@@ -169,8 +160,8 @@ describe("buildAndMaybePush", () => {
169160
dockerfile,
170161
});
171162

172-
// 3 calls: docker tag + docker push + docker rm
173-
expect(runDockerCmd).toHaveBeenCalledTimes(3);
163+
// 3 calls: docker tag + docker push
164+
expect(runDockerCmd).toHaveBeenCalledTimes(2);
174165
expect(runDockerCmd).toHaveBeenNthCalledWith(1, "docker", [
175166
"tag",
176167
`registry.cloudflare.com/some-account-id/test-app:tag`,
@@ -180,15 +171,10 @@ describe("buildAndMaybePush", () => {
180171
"push",
181172
`${getCloudflareContainerRegistry()}/some-account-id/test-app:tag`,
182173
]);
183-
expect(runDockerCmd).toHaveBeenNthCalledWith(3, "docker", [
184-
"image",
185-
"rm",
186-
`${getCloudflareContainerRegistry()}/some-account-id/test-app:tag`,
187-
]);
188174
expect(dockerImageInspect).toHaveBeenCalledTimes(2);
189175
expect(dockerImageInspect).toHaveBeenNthCalledWith(1, "docker", {
190176
imageTag: `registry.cloudflare.com/some-account-id/test-app:tag`,
191-
formatString: "{{ json .RepoDigests }} {{ .Id }}",
177+
formatString: "{{ json .RepoDigests }}",
192178
});
193179
expect(dockerImageInspect).toHaveBeenNthCalledWith(2, "docker", {
194180
imageTag: `registry.cloudflare.com/some-account-id/test-app:tag`,
@@ -222,7 +208,7 @@ describe("buildAndMaybePush", () => {
222208
"/custom/docker/path",
223209
{
224210
imageTag: `test-app:tag`,
225-
formatString: "{{ json .RepoDigests }} {{ .Id }}",
211+
formatString: "{{ json .RepoDigests }}",
226212
}
227213
);
228214
expect(dockerImageInspect).toHaveBeenNthCalledWith(
@@ -262,8 +248,8 @@ describe("buildAndMaybePush", () => {
262248
dockerfile,
263249
});
264250

265-
// 3 calls: docker tag + docker push + docker rm
266-
expect(runDockerCmd).toHaveBeenCalledTimes(3);
251+
// 3 calls: docker tag + docker push
252+
expect(runDockerCmd).toHaveBeenCalledTimes(2);
267253
expect(runDockerCmd).toHaveBeenNthCalledWith(1, "docker", [
268254
"tag",
269255
`test-app:tag`,
@@ -273,15 +259,10 @@ describe("buildAndMaybePush", () => {
273259
"push",
274260
`${getCloudflareContainerRegistry()}/some-account-id/test-app:tag`,
275261
]);
276-
expect(runDockerCmd).toHaveBeenNthCalledWith(3, "docker", [
277-
"image",
278-
"rm",
279-
`${getCloudflareContainerRegistry()}/some-account-id/test-app:tag`,
280-
]);
281262
expect(dockerImageInspect).toHaveBeenCalledTimes(2);
282263
expect(dockerImageInspect).toHaveBeenNthCalledWith(1, "docker", {
283264
imageTag: `test-app:tag`,
284-
formatString: "{{ json .RepoDigests }} {{ .Id }}",
265+
formatString: "{{ json .RepoDigests }}",
285266
});
286267
expect(dockerImageInspect).toHaveBeenNthCalledWith(2, "docker", {
287268
imageTag: `test-app:tag`,
@@ -298,12 +279,12 @@ describe("buildAndMaybePush", () => {
298279
vi.mocked(dockerImageInspect).mockReset();
299280
vi.mocked(dockerImageInspect)
300281
.mockResolvedValueOnce(
301-
'["registry.cloudflare.com/test-app@sha256:three"] matching-config-sha'
282+
'["registry.cloudflare.com/test-app@sha256:three"]'
302283
)
303284
.mockResolvedValueOnce("53387881 2");
304285
vi.mocked(runDockerCmdWithOutput).mockReset();
305286
vi.mocked(runDockerCmdWithOutput).mockImplementationOnce(() => {
306-
return '{"Descriptor":{"digest":"matching-config-sha"}}';
287+
return '{"Descriptor":{"digest":"three}}';
307288
});
308289

309290
await runWrangler(
@@ -330,16 +311,10 @@ describe("buildAndMaybePush", () => {
330311
"-v",
331312
`${getCloudflareContainerRegistry()}/some-account-id/test-app@sha256:three`,
332313
]);
333-
expect(runDockerCmd).toHaveBeenCalledOnce();
334-
expect(runDockerCmd).toHaveBeenCalledWith("docker", [
335-
"image",
336-
"rm",
337-
`test-app:tag`,
338-
]);
339314
expect(dockerImageInspect).toHaveBeenCalledTimes(2);
340315
expect(dockerImageInspect).toHaveBeenNthCalledWith(1, "docker", {
341316
imageTag: `test-app:tag`,
342-
formatString: "{{ json .RepoDigests }} {{ .Id }}",
317+
formatString: "{{ json .RepoDigests }}",
343318
});
344319
expect(dockerImageInspect).toHaveBeenNthCalledWith(2, "docker", {
345320
imageTag: `test-app:tag`,

0 commit comments

Comments
 (0)