Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/green-jokes-decide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"wrangler": minor
---

feat: Watch the entire module root for changes in `--no-bundle` mode, rather than just the entrypoint file.
5 changes: 5 additions & 0 deletions .changeset/thin-penguins-drum.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"wrangler": patch
---

fix: Reload Python workers when the `requirements.txt` file changes
3 changes: 2 additions & 1 deletion packages/wrangler/e2e/deployments.test.ts
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down
47 changes: 40 additions & 7 deletions packages/wrangler/e2e/dev.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -285,10 +286,15 @@ describe("basic dev python tests", () => {
compatibility_date = "2023-01-01"
compatibility_flags = ["python_workers"]
`,
"arithmetic.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 arithmetic 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}",
Expand All @@ -299,7 +305,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,
Expand All @@ -308,7 +314,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`
Expand All @@ -318,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 };
Expand All @@ -327,6 +333,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({
"arithmetic.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", () => {
Expand Down
38 changes: 0 additions & 38 deletions packages/wrangler/e2e/helpers/setup.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -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<string, string>) {
Expand Down
3 changes: 2 additions & 1 deletion packages/wrangler/e2e/pages-dev.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 = void> = T | Promise<T>;
Expand Down
3 changes: 2 additions & 1 deletion packages/wrangler/e2e/versions.test.ts
Original file line number Diff line number Diff line change
@@ -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;
Expand Down
18 changes: 15 additions & 3 deletions packages/wrangler/src/dev/use-esbuild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)];
// Check whether we need to watch a Python requirements.txt file.
const watchPythonRequirements =
getBundleType(entry.format, entry.file) === "python"
? path.resolve(entry.directory, "requirements.txt")
: undefined;

if (watchPythonRequirements) {
watching.push(watchPythonRequirements);
}

const watcher = watch(watching, {
persistent: true,
ignored: [".git", "node_modules"],
}).on("change", async (_event) => {
await updateBundle();
});
Expand Down