From 45cdb01d5a3a5e89c21d693d9342f1eab787a892 Mon Sep 17 00:00:00 2001 From: Samuel Macleod Date: Wed, 20 Mar 2024 11:06:40 +0000 Subject: [PATCH 1/8] Support watching multiple modules + requirements.txt --- packages/wrangler/e2e/dev.test.ts | 42 +++++++++++++++++++++--- packages/wrangler/src/dev/use-esbuild.ts | 18 ++++++++-- 2 files changed, 52 insertions(+), 8 deletions(-) diff --git a/packages/wrangler/e2e/dev.test.ts b/packages/wrangler/e2e/dev.test.ts index 1bc0a1540b34..651cdfe8cddb 100644 --- a/packages/wrangler/e2e/dev.test.ts +++ b/packages/wrangler/e2e/dev.test.ts @@ -285,10 +285,15 @@ describe("basic dev python tests", () => { compatibility_date = "2023-01-01" compatibility_flags = ["python_workers"] `, + "arith.py": dedent` + def mul(a,b): + return a*b`, "index.py": dedent` - from js import Response - def on_fetch(request): - return Response.new('py hello world')`, + from arith import mul + + from js import Response + def on_fetch(request): + return Response.new(f"py hello world {mul(2,3)}")`, "package.json": dedent` { "name": "${workerName}", @@ -299,7 +304,7 @@ describe("basic dev python tests", () => { })); }); - it("can run and modify python worker during dev session (local)", async () => { + it("can run and modify python worker entrypoint during dev session (local)", async () => { await worker.runDevSession("", async (session) => { const { text } = await retry( (s) => s.status !== 200, @@ -308,7 +313,7 @@ describe("basic dev python tests", () => { return { text: await r.text(), status: r.status }; } ); - expect(text).toMatchInlineSnapshot('"py hello world"'); + expect(text).toMatchInlineSnapshot('"py hello world 6"'); await worker.seed({ "index.py": dedent` @@ -327,6 +332,33 @@ describe("basic dev python tests", () => { expect(text2).toMatchInlineSnapshot('"Updated Python Worker value"'); }); }); + it("can run and modify python worker imports during dev session (local)", async () => { + await worker.runDevSession("", async (session) => { + const { text } = await retry( + (s) => s.status !== 200, + async () => { + const r = await fetch(`http://127.0.0.1:${session.port}`); + return { text: await r.text(), status: r.status }; + } + ); + expect(text).toMatchInlineSnapshot('"py hello world 6"'); + + await worker.seed({ + "arith.py": dedent` + def mul(a,b): + return a+b`, + }); + + const { text: text2 } = await retry( + (s) => s.status !== 200 || s.text === "py hello world 6", + async () => { + const r = await fetch(`http://127.0.0.1:${session.port}`); + return { text: await r.text(), status: r.status }; + } + ); + expect(text2).toMatchInlineSnapshot('"py hello world 5"'); + }); + }); }); describe("dev registry", () => { diff --git a/packages/wrangler/src/dev/use-esbuild.ts b/packages/wrangler/src/dev/use-esbuild.ts index 8eb4b6f3a848..1dae6d2d878f 100644 --- a/packages/wrangler/src/dev/use-esbuild.ts +++ b/packages/wrangler/src/dev/use-esbuild.ts @@ -199,11 +199,23 @@ export function useEsbuild({ // Capture the `stop()` method to use as the `useEffect()` destructor. stopWatching = bundleResult?.stop; - // if "noBundle" is true, then we need to manually watch the entry point and - // trigger "builds" when it changes + // if "noBundle" is true, then we need to manually watch all modules and + // trigger "builds" when any change if (noBundle) { - const watcher = watch(entry.file, { + const watching = [path.resolve(entry.moduleRoot)]; + // Should we try and watch a Python reqyurements.txt file? + const pythonRequirements = + getBundleType(entry.format, entry.file) === "python" + ? path.resolve(entry.directory, "requirements.txt") + : undefined; + + if (pythonRequirements) { + watching.push(pythonRequirements); + } + + const watcher = watch(watching, { persistent: true, + ignored: [".git", "node_modules"], }).on("change", async (_event) => { await updateBundle(); }); From ece0ba569f373659b2d117bc8610eec0132bd4bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Somhairle=20MacLe=C3=B2id?= Date: Wed, 20 Mar 2024 11:14:33 +0000 Subject: [PATCH 2/8] Create green-jokes-decide.md --- .changeset/green-jokes-decide.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/green-jokes-decide.md diff --git a/.changeset/green-jokes-decide.md b/.changeset/green-jokes-decide.md new file mode 100644 index 000000000000..a50021cdd25e --- /dev/null +++ b/.changeset/green-jokes-decide.md @@ -0,0 +1,5 @@ +--- +"wrangler": minor +--- + +feat: Watch the entire module root for changes in `--no-bundle` mode, rather than just the entrypoint file. From 79bec923beb0c8027de156d8c6ba68d0731195f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Somhairle=20MacLe=C3=B2id?= Date: Wed, 20 Mar 2024 11:15:15 +0000 Subject: [PATCH 3/8] Create thin-penguins-drum.md --- .changeset/thin-penguins-drum.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/thin-penguins-drum.md diff --git a/.changeset/thin-penguins-drum.md b/.changeset/thin-penguins-drum.md new file mode 100644 index 000000000000..c7d76220463c --- /dev/null +++ b/.changeset/thin-penguins-drum.md @@ -0,0 +1,5 @@ +--- +"wrangler": patch +--- + +fix: Reload Python workers when the `requirements.txt` file changes From d4a3c5ec3ae8788d6dca2cad1b2682fd41de82e2 Mon Sep 17 00:00:00 2001 From: Samuel Macleod Date: Wed, 20 Mar 2024 12:23:49 +0000 Subject: [PATCH 4/8] Fix e2e tests --- packages/wrangler/e2e/deployments.test.ts | 3 +- packages/wrangler/e2e/dev.test.ts | 7 +++-- packages/wrangler/e2e/helpers/setup.ts | 38 ----------------------- packages/wrangler/e2e/pages-dev.test.ts | 3 +- 4 files changed, 8 insertions(+), 43 deletions(-) diff --git a/packages/wrangler/e2e/deployments.test.ts b/packages/wrangler/e2e/deployments.test.ts index e205dab01b9a..689840e3f57e 100644 --- a/packages/wrangler/e2e/deployments.test.ts +++ b/packages/wrangler/e2e/deployments.test.ts @@ -1,12 +1,13 @@ import crypto from "node:crypto"; import path from "node:path"; import shellac from "shellac"; +import dedent from "ts-dedent"; import { fetch } from "undici"; import { beforeAll, describe, expect, it } from "vitest"; import { CLOUDFLARE_ACCOUNT_ID } from "./helpers/account-id"; import { normalizeOutput } from "./helpers/normalize"; import { retry } from "./helpers/retry"; -import { dedent, makeRoot, seed } from "./helpers/setup"; +import { makeRoot, seed } from "./helpers/setup"; import { WRANGLER } from "./helpers/wrangler-command"; function matchWorkersDev(stdout: string): string { diff --git a/packages/wrangler/e2e/dev.test.ts b/packages/wrangler/e2e/dev.test.ts index 651cdfe8cddb..319129bcf3f0 100644 --- a/packages/wrangler/e2e/dev.test.ts +++ b/packages/wrangler/e2e/dev.test.ts @@ -5,11 +5,12 @@ import * as nodeNet from "node:net"; import path from "node:path"; import { setTimeout } from "node:timers/promises"; import shellac from "shellac"; +import dedent from "ts-dedent"; import { Agent, fetch, setGlobalDispatcher } from "undici"; import { afterEach, beforeEach, describe, expect, it } from "vitest"; import { normalizeOutput } from "./helpers/normalize"; import { retry } from "./helpers/retry"; -import { dedent, makeRoot, seed } from "./helpers/setup"; +import { makeRoot, seed } from "./helpers/setup"; import { WRANGLER } from "./helpers/wrangler-command"; // Use `Agent` with lower timeouts so `fetch()`s inside `retry()`s don't block for a long time @@ -90,7 +91,7 @@ async function runDevSession( in ${workerPath} { exits { - $ ${WRANGLER} dev ${flags} + $$ ${WRANGLER} dev ${flags} } } `; @@ -323,7 +324,7 @@ describe("basic dev python tests", () => { }); const { text: text2 } = await retry( - (s) => s.status !== 200 || s.text === "py hello world", + (s) => s.status !== 200 || s.text === "py hello world 6", async () => { const r = await fetch(`http://127.0.0.1:${session.port}`); return { text: await r.text(), status: r.status }; diff --git a/packages/wrangler/e2e/helpers/setup.ts b/packages/wrangler/e2e/helpers/setup.ts index 5d15e17c9a81..b55bb5b6d286 100644 --- a/packages/wrangler/e2e/helpers/setup.ts +++ b/packages/wrangler/e2e/helpers/setup.ts @@ -1,4 +1,3 @@ -import assert from "node:assert"; import { mkdir, mkdtemp, writeFile } from "node:fs/promises"; import os from "node:os"; import path from "node:path"; @@ -7,43 +6,6 @@ export async function makeRoot() { return await mkdtemp(path.join(os.tmpdir(), "wrangler-smoke-")); } -// Tagged template literal for removing indentation from a block of text. -// If the first line is empty, it will be ignored. -export function dedent(strings: TemplateStringsArray, ...values: unknown[]) { - // Convert template literal arguments back to a regular string - const raw = String.raw({ raw: strings }, ...values); - // Split the string by lines - let lines = raw.split("\n"); - assert(lines.length > 0); - - // If the last line is just whitespace, remove it - if (lines[lines.length - 1].trim() === "") { - lines = lines.slice(0, lines.length - 1); - } - - // Find the minimum-length indent, excluding the first line - let minIndent = ""; - // (Could use `minIndent.length` for this, but then would need to start with - // infinitely long string) - let minIndentLength = Infinity; - for (const line of lines.slice(1)) { - const indent = line.match(/^[ \t]*/)?.[0]; - if (indent != null && indent.length < minIndentLength) { - minIndent = indent; - minIndentLength = indent.length; - } - } - - // If the first line is just whitespace, remove it - if (lines.length > 0 && lines[0].trim() === "") lines = lines.slice(1); - - // Remove indent from all lines, and return them all joined together - lines = lines.map((line) => - line.startsWith(minIndent) ? line.substring(minIndent.length) : line - ); - return lines.join("\n"); -} - // Seeds the `root` directory on the file system with some data. Use in // combination with `dedent` for petty formatting of seeded contents. export async function seed(root: string, files: Record) { diff --git a/packages/wrangler/e2e/pages-dev.test.ts b/packages/wrangler/e2e/pages-dev.test.ts index 9777c8d6f6d7..89737ac90347 100644 --- a/packages/wrangler/e2e/pages-dev.test.ts +++ b/packages/wrangler/e2e/pages-dev.test.ts @@ -3,11 +3,12 @@ import path from "node:path"; import { setTimeout } from "node:timers/promises"; import getPort from "get-port"; import shellac from "shellac"; +import dedent from "ts-dedent"; import { fetch } from "undici"; import { beforeEach, describe, expect, it } from "vitest"; import { normalizeOutput } from "./helpers/normalize"; import { retry } from "./helpers/retry"; -import { dedent, makeRoot, seed } from "./helpers/setup"; +import { makeRoot, seed } from "./helpers/setup"; import { WRANGLER } from "./helpers/wrangler-command"; type MaybePromise = T | Promise; From 4fe25195517d42f31b7c6b0ea334b58eaa4aa8a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Somhairle=20MacLe=C3=B2id?= Date: Fri, 22 Mar 2024 14:45:43 +0000 Subject: [PATCH 5/8] Update packages/wrangler/src/dev/use-esbuild.ts Co-authored-by: Pete Bacon Darwin --- packages/wrangler/src/dev/use-esbuild.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/wrangler/src/dev/use-esbuild.ts b/packages/wrangler/src/dev/use-esbuild.ts index 1dae6d2d878f..a4d57c50aeb3 100644 --- a/packages/wrangler/src/dev/use-esbuild.ts +++ b/packages/wrangler/src/dev/use-esbuild.ts @@ -203,7 +203,7 @@ export function useEsbuild({ // trigger "builds" when any change if (noBundle) { const watching = [path.resolve(entry.moduleRoot)]; - // Should we try and watch a Python reqyurements.txt file? + // Check whether we need to watch a Python requirements.txt file. const pythonRequirements = getBundleType(entry.format, entry.file) === "python" ? path.resolve(entry.directory, "requirements.txt") From 24c1febfbe6e15e3c57d43715d4dfe4dc4943fd8 Mon Sep 17 00:00:00 2001 From: Samuel Macleod Date: Fri, 22 Mar 2024 14:48:30 +0000 Subject: [PATCH 6/8] Address review comments --- packages/wrangler/e2e/dev.test.ts | 6 +++--- packages/wrangler/src/dev/use-esbuild.ts | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/wrangler/e2e/dev.test.ts b/packages/wrangler/e2e/dev.test.ts index 319129bcf3f0..f504e0e1f49f 100644 --- a/packages/wrangler/e2e/dev.test.ts +++ b/packages/wrangler/e2e/dev.test.ts @@ -286,11 +286,11 @@ describe("basic dev python tests", () => { compatibility_date = "2023-01-01" compatibility_flags = ["python_workers"] `, - "arith.py": dedent` + "arithmetic.py": dedent` def mul(a,b): return a*b`, "index.py": dedent` - from arith import mul + from arithmetic import mul from js import Response def on_fetch(request): @@ -345,7 +345,7 @@ describe("basic dev python tests", () => { expect(text).toMatchInlineSnapshot('"py hello world 6"'); await worker.seed({ - "arith.py": dedent` + "arithmetic.py": dedent` def mul(a,b): return a+b`, }); diff --git a/packages/wrangler/src/dev/use-esbuild.ts b/packages/wrangler/src/dev/use-esbuild.ts index a4d57c50aeb3..75dfad47f8c0 100644 --- a/packages/wrangler/src/dev/use-esbuild.ts +++ b/packages/wrangler/src/dev/use-esbuild.ts @@ -204,13 +204,13 @@ export function useEsbuild({ if (noBundle) { const watching = [path.resolve(entry.moduleRoot)]; // Check whether we need to watch a Python requirements.txt file. - const pythonRequirements = + const watchPythonRequirements = getBundleType(entry.format, entry.file) === "python" ? path.resolve(entry.directory, "requirements.txt") : undefined; - if (pythonRequirements) { - watching.push(pythonRequirements); + if (watchPythonRequirements) { + watching.push(watchPythonRequirements); } const watcher = watch(watching, { From 79c9cc2d0be4f59fd411f68f38dce37764e334a6 Mon Sep 17 00:00:00 2001 From: Samuel Macleod Date: Fri, 22 Mar 2024 15:27:22 +0000 Subject: [PATCH 7/8] fix versions e2e --- packages/wrangler/e2e/versions.test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/wrangler/e2e/versions.test.ts b/packages/wrangler/e2e/versions.test.ts index 7d864b174c77..757420061a5a 100644 --- a/packages/wrangler/e2e/versions.test.ts +++ b/packages/wrangler/e2e/versions.test.ts @@ -1,10 +1,11 @@ import crypto from "node:crypto"; import path from "node:path"; import shellac from "shellac"; +import dedent from "ts-dedent"; import { beforeAll, chai, describe, expect, it } from "vitest"; import { CLOUDFLARE_ACCOUNT_ID } from "./helpers/account-id"; import { normalizeOutput } from "./helpers/normalize"; -import { dedent, makeRoot, seed } from "./helpers/setup"; +import { makeRoot, seed } from "./helpers/setup"; import { WRANGLER } from "./helpers/wrangler-command"; chai.config.truncateThreshold = 1e6; From 93f592b79c87fdef59ea63d5745831c07b445530 Mon Sep 17 00:00:00 2001 From: Samuel Macleod Date: Fri, 22 Mar 2024 15:32:27 +0000 Subject: [PATCH 8/8] Remove logs --- packages/wrangler/e2e/dev.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/wrangler/e2e/dev.test.ts b/packages/wrangler/e2e/dev.test.ts index f504e0e1f49f..460f603a816a 100644 --- a/packages/wrangler/e2e/dev.test.ts +++ b/packages/wrangler/e2e/dev.test.ts @@ -91,7 +91,7 @@ async function runDevSession( in ${workerPath} { exits { - $$ ${WRANGLER} dev ${flags} + $ ${WRANGLER} dev ${flags} } } `;