Skip to content

Commit f5c081f

Browse files
WillTaylorDevCarmenPopoviciu
authored andcommitted
Provide validation around experimental_serve_directly usage in dev and deploy
1 parent 4fe93de commit f5c081f

File tree

24 files changed

+1464
-160
lines changed

24 files changed

+1464
-160
lines changed

.changeset/clean-peas-exist.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+
Add file prefix option to wrangler pipelines commands
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"wrangler": patch
3+
---
4+
5+
The `x-provision` experimental flag now identifies draft and inherit bindings by looking up the current binding settings.
6+
7+
Draft bindings can then be provisioned (connected to new or existing KV, D1, or R2 resources) during `wrangler deploy`.

.changeset/swift-zebras-guess.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"wrangler": minor
3+
---
4+
5+
Provide validation around assets.experimental_serve_directly

packages/wrangler/e2e/helpers/normalize.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export function normalizeOutput(
1212
removeWorkerPreviewUrl,
1313
removeUUID,
1414
removeBinding,
15+
removeKVId,
1516
normalizeErrorMarkers,
1617
replaceByte,
1718
stripTrailingWhitespace,
@@ -77,6 +78,10 @@ function removeBinding(str: string) {
7778
);
7879
}
7980

81+
function removeKVId(str: string) {
82+
return str.replace(/([0-9a-f]{32})/g, "00000000000000000000000000000000");
83+
}
84+
8085
/**
8186
* Remove the Wrangler version/update check header
8287
*/
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
import assert from "node:assert";
2+
import dedent from "ts-dedent";
3+
import { fetch } from "undici";
4+
import { afterAll, beforeAll, describe, expect, it } from "vitest";
5+
import { CLOUDFLARE_ACCOUNT_ID } from "./helpers/account-id";
6+
import { WranglerE2ETestHelper } from "./helpers/e2e-wrangler-test";
7+
import { fetchText } from "./helpers/fetch-text";
8+
import { generateResourceName } from "./helpers/generate-resource-name";
9+
import { normalizeOutput } from "./helpers/normalize";
10+
import { retry } from "./helpers/retry";
11+
12+
const TIMEOUT = 500_000;
13+
const normalize = (str: string) => {
14+
return normalizeOutput(str, {
15+
[CLOUDFLARE_ACCOUNT_ID]: "CLOUDFLARE_ACCOUNT_ID",
16+
});
17+
};
18+
const workerName = generateResourceName();
19+
20+
describe("provisioning", { timeout: TIMEOUT }, () => {
21+
let deployedUrl: string;
22+
let kvId: string;
23+
let d1Id: string;
24+
const helper = new WranglerE2ETestHelper();
25+
26+
it("can run dev without resource ids", async () => {
27+
const worker = helper.runLongLived("wrangler dev --x-provision");
28+
29+
const { url } = await worker.waitForReady();
30+
await fetch(url);
31+
32+
const text = await fetchText(url);
33+
34+
expect(text).toMatchInlineSnapshot(`"Hello World!"`);
35+
});
36+
37+
beforeAll(async () => {
38+
await helper.seed({
39+
"wrangler.toml": dedent`
40+
name = "${workerName}"
41+
main = "src/index.ts"
42+
compatibility_date = "2023-01-01"
43+
44+
[[kv_namespaces]]
45+
binding = "KV"
46+
47+
[[r2_buckets]]
48+
binding = "R2"
49+
50+
[[d1_databases]]
51+
binding = "D1"
52+
`,
53+
"src/index.ts": dedent`
54+
export default {
55+
fetch(request) {
56+
return new Response("Hello World!")
57+
}
58+
}`,
59+
"package.json": dedent`
60+
{
61+
"name": "${workerName}",
62+
"version": "0.0.0",
63+
"private": true
64+
}
65+
`,
66+
});
67+
});
68+
69+
it("can provision resources and deploy worker", async () => {
70+
const worker = helper.runLongLived(
71+
`wrangler deploy --x-provision --x-auto-create`
72+
);
73+
await worker.exitCode;
74+
const output = await worker.output;
75+
expect(normalize(output)).toMatchInlineSnapshot(`
76+
"Total Upload: xx KiB / gzip: xx KiB
77+
The following bindings need to be provisioned:
78+
- KV Namespaces:
79+
- KV
80+
- D1 Databases:
81+
- D1
82+
- R2 Buckets:
83+
- R2
84+
Provisioning KV (KV Namespace)...
85+
🌀 Creating new KV Namespace "tmp-e2e-worker-00000000-0000-0000-0000-000000000000-kv"...
86+
✨ KV provisioned with tmp-e2e-worker-00000000-0000-0000-0000-000000000000-kv
87+
--------------------------------------
88+
Provisioning D1 (D1 Database)...
89+
🌀 Creating new D1 Database "tmp-e2e-worker-00000000-0000-0000-0000-000000000000-d1"...
90+
✨ D1 provisioned with tmp-e2e-worker-00000000-0000-0000-0000-000000000000-d1
91+
--------------------------------------
92+
Provisioning R2 (R2 Bucket)...
93+
🌀 Creating new R2 Bucket "tmp-e2e-worker-00000000-0000-0000-0000-000000000000-r2"...
94+
✨ R2 provisioned with tmp-e2e-worker-00000000-0000-0000-0000-000000000000-r2
95+
--------------------------------------
96+
🎉 All resources provisioned, continuing with deployment...
97+
Your worker has access to the following bindings:
98+
- KV Namespaces:
99+
- KV: 00000000000000000000000000000000
100+
- D1 Databases:
101+
- D1: 00000000-0000-0000-0000-000000000000
102+
- R2 Buckets:
103+
- R2: tmp-e2e-worker-00000000-0000-0000-0000-000000000000-r2
104+
Uploaded tmp-e2e-worker-00000000-0000-0000-0000-000000000000 (TIMINGS)
105+
Deployed tmp-e2e-worker-00000000-0000-0000-0000-000000000000 triggers (TIMINGS)
106+
https://tmp-e2e-worker-00000000-0000-0000-0000-000000000000.SUBDOMAIN.workers.dev
107+
Current Version ID: 00000000-0000-0000-0000-000000000000"
108+
`);
109+
const urlMatch = output.match(
110+
/(?<url>https:\/\/tmp-e2e-.+?\..+?\.workers\.dev)/
111+
);
112+
assert(urlMatch?.groups);
113+
deployedUrl = urlMatch.groups.url;
114+
115+
const kvMatch = output.match(/- KV: (?<kv>[0-9a-f]{32})/);
116+
assert(kvMatch?.groups);
117+
kvId = kvMatch.groups.kv;
118+
119+
const d1Match = output.match(/- D1: (?<d1>\w{8}-\w{4}-\w{4}-\w{4}-\w{12})/);
120+
assert(d1Match?.groups);
121+
d1Id = d1Match.groups.d1;
122+
123+
const { text } = await retry(
124+
(s) => s.status !== 200,
125+
async () => {
126+
const r = await fetch(deployedUrl);
127+
return { text: await r.text(), status: r.status };
128+
}
129+
);
130+
expect(text).toMatchInlineSnapshot('"Hello World!"');
131+
});
132+
133+
it("can inherit bindings on re-deploy and won't re-provision", async () => {
134+
const worker = helper.runLongLived(`wrangler deploy --x-provision`);
135+
await worker.exitCode;
136+
const output = await worker.output;
137+
expect(normalize(output)).toMatchInlineSnapshot(`
138+
"Total Upload: xx KiB / gzip: xx KiB
139+
Your worker has access to the following bindings:
140+
- KV Namespaces:
141+
- KV
142+
- D1 Databases:
143+
- D1
144+
- R2 Buckets:
145+
- R2
146+
Uploaded tmp-e2e-worker-00000000-0000-0000-0000-000000000000 (TIMINGS)
147+
Deployed tmp-e2e-worker-00000000-0000-0000-0000-000000000000 triggers (TIMINGS)
148+
https://tmp-e2e-worker-00000000-0000-0000-0000-000000000000.SUBDOMAIN.workers.dev
149+
Current Version ID: 00000000-0000-0000-0000-000000000000"
150+
`);
151+
152+
const { text } = await retry(
153+
(s) => s.status !== 200,
154+
async () => {
155+
const r = await fetch(deployedUrl);
156+
return { text: await r.text(), status: r.status };
157+
}
158+
);
159+
expect(text).toMatchInlineSnapshot('"Hello World!"');
160+
});
161+
162+
afterAll(async () => {
163+
// we need to add d1 back into the config because otherwise wrangler will
164+
// call the api for all 5000 or so db's the e2e test account has
165+
// :(
166+
await helper.seed({
167+
"wrangler.toml": dedent`
168+
name = "${workerName}"
169+
main = "src/index.ts"
170+
compatibility_date = "2023-01-01"
171+
172+
[[d1_databases]]
173+
binding = "D1"
174+
database_name = "${workerName}-d1"
175+
database_id = "${d1Id}"
176+
`,
177+
});
178+
let output = await helper.run(`wrangler r2 bucket delete ${workerName}-r2`);
179+
expect(output.stdout).toContain(`Deleted bucket`);
180+
output = await helper.run(`wrangler d1 delete ${workerName}-d1 -y`);
181+
expect(output.stdout).toContain(`Deleted '${workerName}-d1' successfully.`);
182+
output = await helper.run(`wrangler delete`);
183+
expect(output.stdout).toContain("Successfully deleted");
184+
const status = await retry(
185+
(s) => s === 200 || s === 500,
186+
() => fetch(deployedUrl).then((r) => r.status)
187+
);
188+
expect(status).toBe(404);
189+
190+
output = await helper.run(
191+
`wrangler kv namespace delete --namespace-id ${kvId}`
192+
);
193+
expect(output.stdout).toContain(`Deleted KV namespace`);
194+
}, TIMEOUT);
195+
});

0 commit comments

Comments
 (0)