diff --git a/.changeset/ready-banks-repair.md b/.changeset/ready-banks-repair.md new file mode 100644 index 000000000000..36bb912cde04 --- /dev/null +++ b/.changeset/ready-banks-repair.md @@ -0,0 +1,8 @@ +--- +"wrangler": minor +--- + +Beta feature preview_urls is now disabled by default. + +This change makes preview_urls disabled by default when it's not provided, making +the feature opt-in instead of opt-out. diff --git a/packages/wrangler/src/__tests__/config/configuration.test.ts b/packages/wrangler/src/__tests__/config/configuration.test.ts index 5ff8c5ee0471..3e1dfa4b9e63 100644 --- a/packages/wrangler/src/__tests__/config/configuration.test.ts +++ b/packages/wrangler/src/__tests__/config/configuration.test.ts @@ -130,7 +130,7 @@ describe("normalizeAndValidateConfig()", () => { wasm_modules: undefined, data_blobs: undefined, workers_dev: undefined, - preview_urls: true, + preview_urls: undefined, zone_id: undefined, no_bundle: undefined, minify: undefined, diff --git a/packages/wrangler/src/__tests__/deploy.test.ts b/packages/wrangler/src/__tests__/deploy.test.ts index 6cc09122858c..087508ef8d6b 100644 --- a/packages/wrangler/src/__tests__/deploy.test.ts +++ b/packages/wrangler/src/__tests__/deploy.test.ts @@ -21,9 +21,11 @@ import { mockAccountId, mockApiToken } from "./helpers/mock-account-id"; import { mockAuthDomain } from "./helpers/mock-auth-domain"; import { mockConsoleMethods } from "./helpers/mock-console"; import { clearDialogs, mockConfirm, mockPrompt } from "./helpers/mock-dialogs"; -import { mockGetZoneFromHostRequest } from "./helpers/mock-get-zone-from-host"; +import { + mockGetZones, + mockGetZonesMulti, +} from "./helpers/mock-get-zone-from-host"; import { useMockIsTTY } from "./helpers/mock-istty"; -import { mockCollectKnownRoutesRequest } from "./helpers/mock-known-routes"; import { mockKeyListRequest, mockListKVNamespacesRequest, @@ -40,6 +42,10 @@ import { mockSubDomainRequest, mockUpdateWorkerSubdomain, } from "./helpers/mock-workers-subdomain"; +import { + mockGetZoneWorkerRoutes, + mockGetZoneWorkerRoutesMulti, +} from "./helpers/mock-zone-routes"; import { createFetchResult, msw, @@ -1098,6 +1104,11 @@ describe("deploy", () => { writeWorkerSource(); mockUpdateWorkerSubdomain({ enabled: false }); mockUploadWorkerRequest({ expectedType: "esm" }); + // These run during route conflict resolution. + // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + mockGetZones("example.com", [{ id: "example-com-id" }]); + mockGetZoneWorkerRoutes("example-com-id"); + // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mockPublishRoutesRequest({ routes: ["example.com/some-route/*"] }); await runWrangler("deploy ./index"); }); @@ -1136,27 +1147,64 @@ describe("deploy", () => { writeWranglerConfig({ routes: [ "some-example.com/some-route/*", - { pattern: "*a-boring-website.com", zone_id: "54sdf7fsda" }, + { pattern: "*a-boring-website.com", zone_id: "a-boring-website-id" }, { pattern: "*another-boring-website.com", zone_name: "some-zone.com", }, - { pattern: "example.com/some-route/*", zone_id: "JGHFHG654gjcj" }, + { pattern: "example.com/some-route/*", zone_id: "example-com-id" }, "more-examples.com/*", ], }); writeWorkerSource(); mockUpdateWorkerSubdomain({ enabled: false }); mockUploadWorkerRequest({ expectedType: "esm" }); + // These run during route conflict resolution. + // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + mockGetZonesMulti({ + "some-example.com": { + accountId: "some-account-id", + zones: [{ id: "some-example-com-id" }], + }, + "a-boring-website.com": { + accountId: "some-account-id", + zones: [{ id: "a-boring-website-id" }], + }, + "another-boring-website.com": { + accountId: "some-account-id", + zones: [{ id: "another-boring-website-id" }], + }, + "some-zone.com": { + accountId: "some-account-id", + zones: [{ id: "some-zone-id" }], + }, + "example.com": { + accountId: "some-account-id", + zones: [{ id: "example-com-id" }], + }, + "more-examples.com": { + accountId: "some-account-id", + zones: [{ id: "more-examples-id" }], + }, + }); + mockGetZoneWorkerRoutesMulti({ + "some-example-com-id": [], + "a-boring-website-id": [], + "another-boring-website-id": [], + "some-zone-id": [], + "example-com-id": [], + "more-examples-id": [], + }); + // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mockPublishRoutesRequest({ routes: [ "some-example.com/some-route/*", - { pattern: "*a-boring-website.com", zone_id: "54sdf7fsda" }, + { pattern: "*a-boring-website.com", zone_id: "a-boring-website-id" }, { pattern: "*another-boring-website.com", zone_name: "some-zone.com", }, - { pattern: "example.com/some-route/*", zone_id: "JGHFHG654gjcj" }, + { pattern: "example.com/some-route/*", zone_id: "example-com-id" }, "more-examples.com/*", ], }); @@ -1171,9 +1219,9 @@ describe("deploy", () => { Uploaded test-name (TIMINGS) Deployed test-name triggers (TIMINGS) some-example.com/some-route/* - *a-boring-website.com (zone id: 54sdf7fsda) + *a-boring-website.com (zone id: a-boring-website-id) *another-boring-website.com (zone name: some-zone.com) - example.com/some-route/* (zone id: JGHFHG654gjcj) + example.com/some-route/* (zone id: example-com-id) more-examples.com/* Current Version ID: Galaxy-Class", "warn": "", @@ -1195,7 +1243,7 @@ describe("deploy", () => { mockUploadWorkerRequest(); mockGetWorkerSubdomain({ enabled: false }); mockGetZones("owned-zone.com", [{ id: "owned-zone-id-1" }]); - mockGetWorkerRoutes("owned-zone-id-1"); + mockGetZoneWorkerRoutes("owned-zone-id-1"); mockPublishRoutesRequest({ routes: [ { @@ -1235,7 +1283,7 @@ describe("deploy", () => { mockUploadWorkerRequest(); mockGetWorkerSubdomain({ enabled: false }); mockGetZones("owned-zone.com", [{ id: "owned-zone-id-1" }]); - mockGetWorkerRoutes("owned-zone-id-1"); + mockGetZoneWorkerRoutes("owned-zone-id-1"); mockPublishRoutesRequest({ routes: [ { @@ -1267,12 +1315,18 @@ describe("deploy", () => { staging: { routes: [ "some-example.com/some-route/*", - { pattern: "*a-boring-website.com", zone_id: "54sdf7fsda" }, + { + pattern: "*a-boring-website.com", + zone_id: "a-boring-website-id", + }, { pattern: "*another-boring-website.com", zone_name: "some-zone.com", }, - { pattern: "example.com/some-route/*", zone_id: "JGHFHG654gjcj" }, + { + pattern: "example.com/some-route/*", + zone_id: "example-com-id", + }, "more-examples.com/*", ], }, @@ -1291,15 +1345,52 @@ describe("deploy", () => { legacyEnv: false, useOldUploadApi: true, }); + // These run during route conflict resolution. + // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + mockGetZonesMulti({ + "some-example.com": { + accountId: "some-account-id", + zones: [{ id: "some-example-com-id" }], + }, + "a-boring-website.com": { + accountId: "some-account-id", + zones: [{ id: "a-boring-website-id" }], + }, + "another-boring-website.com": { + accountId: "some-account-id", + zones: [{ id: "another-boring-website-id" }], + }, + "some-zone.com": { + accountId: "some-account-id", + zones: [{ id: "some-zone-id" }], + }, + "example.com": { + accountId: "some-account-id", + zones: [{ id: "example-com-id" }], + }, + "more-examples.com": { + accountId: "some-account-id", + zones: [{ id: "more-examples-id" }], + }, + }); + mockGetZoneWorkerRoutesMulti({ + "some-example-com-id": [], + "a-boring-website-id": [], + "another-boring-website-id": [], + "some-zone-id": [], + "example-com-id": [], + "more-examples-id": [], + }); + // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mockPublishRoutesRequest({ routes: [ "some-example.com/some-route/*", - { pattern: "*a-boring-website.com", zone_id: "54sdf7fsda" }, + { pattern: "*a-boring-website.com", zone_id: "a-boring-website-id" }, { pattern: "*another-boring-website.com", zone_name: "some-zone.com", }, - { pattern: "example.com/some-route/*", zone_id: "JGHFHG654gjcj" }, + { pattern: "example.com/some-route/*", zone_id: "example-com-id" }, "more-examples.com/*", ], env: "staging", @@ -1316,9 +1407,9 @@ describe("deploy", () => { Uploaded test-name (staging) (TIMINGS) Deployed test-name (staging) triggers (TIMINGS) some-example.com/some-route/* - *a-boring-website.com (zone id: 54sdf7fsda) + *a-boring-website.com (zone id: a-boring-website-id) *another-boring-website.com (zone name: some-zone.com) - example.com/some-route/* (zone id: JGHFHG654gjcj) + example.com/some-route/* (zone id: example-com-id) more-examples.com/* Current Version ID: Galaxy-Class", "warn": "▲ [WARNING] Processing wrangler.toml configuration: @@ -1351,6 +1442,23 @@ describe("deploy", () => { legacyEnv: true, env: "dev", }); + // These run during route conflict resolution. + // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + mockGetZonesMulti({ + "example.com": { + accountId: "some-account-id", + zones: [{ id: "example-com-id" }], + }, + "dev-example.com": { + accountId: "some-account-id", + zones: [{ id: "dev-example-com-id" }], + }, + }); + mockGetZoneWorkerRoutesMulti({ + "example-com-id": [], + "dev-example-com-id": [], + }); + // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mockPublishRoutesRequest({ routes: ["dev-example.com/some-route/*"], legacyEnv: true, @@ -1374,6 +1482,23 @@ describe("deploy", () => { expectedType: "esm", env: "dev", }); + // These run during route conflict resolution. + // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + mockGetZonesMulti({ + "example.com": { + accountId: "some-account-id", + zones: [{ id: "example-com-id" }], + }, + "dev-example.com": { + accountId: "some-account-id", + zones: [{ id: "dev-example-com-id" }], + }, + }); + mockGetZoneWorkerRoutesMulti({ + "example-com-id": [], + "dev-example-com-id": [], + }); + // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mockPublishRoutesRequest({ routes: ["dev-example.com/some-route/*"], env: "dev", @@ -1388,16 +1513,19 @@ describe("deploy", () => { writeWorkerSource(); mockUpdateWorkerSubdomain({ enabled: false }); mockUploadWorkerRequest({ expectedType: "esm" }); - // Simulate the bulk-routes API failing with a not authorized error. - mockUnauthorizedPublishRoutesRequest(); - // Simulate that the worker has already been deployed to another route in this zone. - mockCollectKnownRoutesRequest([ + // These run during route conflict resolution. + // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + mockGetZones("example.com", [{ id: "example-com-id" }]); + mockGetZoneWorkerRoutes("example-com-id", [ + // Simulate that the worker has already been deployed to another route. { pattern: "foo.example.com/other-route", script: "test-name", }, ]); - mockGetZoneFromHostRequest("example.com", "some-zone-id"); + // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + // Simulate the bulk-routes API failing with a not authorized error. + mockUnauthorizedPublishRoutesRequest(); mockPublishRoutesFallbackRequest({ pattern: "example.com/some-route/*", script: "test-name", @@ -1406,22 +1534,22 @@ describe("deploy", () => { expect(std.err).toMatchInlineSnapshot(`""`); expect(std.warn).toMatchInlineSnapshot(` - "▲ [WARNING] The current authentication token does not have 'All Zones' permissions. + "▲ [WARNING] The current authentication token does not have 'All Zones' permissions. - Falling back to using the zone-based API endpoint to update each route individually. - Note that there is no access to routes associated with zones that the API token does not have - permission for. - Existing routes for this Worker in such zones will not be deleted. + Falling back to using the zone-based API endpoint to update each route individually. + Note that there is no access to routes associated with zones that the API token does not have + permission for. + Existing routes for this Worker in such zones will not be deleted. - ▲ [WARNING] Previously deployed routes: + ▲ [WARNING] Previously deployed routes: - The following routes were already associated with this worker, and have not been deleted: - - \\"foo.example.com/other-route\\" - If these routes are not wanted then you can remove them in the dashboard. + The following routes were already associated with this worker, and have not been deleted: + - \\"foo.example.com/other-route\\" + If these routes are not wanted then you can remove them in the dashboard. - " - `); + " + `); expect(std.out).toMatchInlineSnapshot(` "Total Upload: xx KiB / gzip: xx KiB Worker Startup Time: 100 ms @@ -1440,16 +1568,19 @@ describe("deploy", () => { writeWorkerSource(); mockUpdateWorkerSubdomain({ env: "staging", enabled: false }); mockUploadWorkerRequest({ env: "staging", expectedType: "esm" }); - // Simulate the bulk-routes API failing with a not authorized error. - mockUnauthorizedPublishRoutesRequest({ env: "staging" }); - // Simulate that the worker has already been deployed to another route in this zone. - mockCollectKnownRoutesRequest([ + // These run during route conflict resolution. + // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + mockGetZones("example.com", [{ id: "example-com-id" }]); + mockGetZoneWorkerRoutes("example-com-id", [ + // Simulate that the worker has already been deployed to another route. { pattern: "foo.example.com/other-route", script: "test-name", }, ]); - mockGetZoneFromHostRequest("example.com", "some-zone-id"); + // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + // Simulate the bulk-routes API failing with a not authorized error. + mockUnauthorizedPublishRoutesRequest({ env: "staging" }); mockPublishRoutesFallbackRequest({ pattern: "example.com/some-route/*", script: "test-name", @@ -1469,6 +1600,11 @@ describe("deploy", () => { writeWorkerSource(); mockUpdateWorkerSubdomain({ enabled: false }); mockUploadWorkerRequest({ expectedType: "esm" }); + // These run during route conflict resolution. + // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + mockGetZones("api.example.com", [{ id: "api-example-com-id" }]); + mockGetZoneWorkerRoutes("api-example-com-id", []); + // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mockCustomDomainsChangesetRequest({}); mockPublishCustomDomainsRequest({ publishFlags: { @@ -1489,6 +1625,11 @@ describe("deploy", () => { writeWorkerSource(); mockUpdateWorkerSubdomain({ enabled: false }); mockUploadWorkerRequest({ expectedType: "esm" }); + // These run during route conflict resolution. + // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + mockGetZones("api.example.com", [{ id: "api-example-com-id" }]); + mockGetZoneWorkerRoutes("api-example-com-id", []); + // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mockCustomDomainsChangesetRequest({ originConflicts: [ { @@ -1534,6 +1675,11 @@ Update them to point to this script instead?`, writeWorkerSource(); mockUpdateWorkerSubdomain({ enabled: false }); mockUploadWorkerRequest({ expectedType: "esm" }); + // These run during route conflict resolution. + // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + mockGetZones("api.example.com", [{ id: "api-example-com-id" }]); + mockGetZoneWorkerRoutes("api-example-com-id", []); + // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mockCustomDomainsChangesetRequest({ dnsRecordConflicts: [ { @@ -1571,6 +1717,11 @@ Update them to point to this script instead?`, writeWorkerSource(); mockUpdateWorkerSubdomain({ enabled: false }); mockUploadWorkerRequest({ expectedType: "esm" }); + // These run during route conflict resolution. + // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + mockGetZones("api.example.com", [{ id: "api-example-com-id" }]); + mockGetZoneWorkerRoutes("api-example-com-id", []); + // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mockCustomDomainsChangesetRequest({ originConflicts: [ { @@ -1663,6 +1814,11 @@ Update them to point to this script instead?`, writeWorkerSource(); mockUpdateWorkerSubdomain({ enabled: false }); mockUploadWorkerRequest({ expectedType: "esm" }); + // These run during route conflict resolution. + // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + mockGetZones("api.example.com", [{ id: "api-example-com-id" }]); + mockGetZoneWorkerRoutes("api-example-com-id", []); + // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mockCustomDomainsChangesetRequest({ originConflicts: [ { @@ -1748,6 +1904,23 @@ Update them to point to this script instead?`, mockSubDomainRequest(); mockUpdateWorkerSubdomain({ enabled: false }); mockUploadWorkerRequest({ expectedType: "esm" }); + // These run during route conflict resolution. + // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + mockGetZonesMulti({ + "example.com": { + accountId: "some-account-id", + zones: [{ id: "example-com-id" }], + }, + "api.example.com": { + accountId: "some-account-id", + zones: [{ id: "api-example-com-id" }], + }, + }); + mockGetZoneWorkerRoutesMulti({ + "example-com-id": [], + "api-example-com-id": [], + }); + // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mockCustomDomainsChangesetRequest({}); mockPublishCustomDomainsRequest({ publishFlags: { @@ -1814,6 +1987,28 @@ Update them to point to this script instead?`, mockSubDomainRequest(); mockUpdateWorkerSubdomain({ enabled: false }); mockUploadWorkerRequest({ expectedType: "esm" }); + // These run during route conflict resolution. + // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + mockGetZonesMulti({ + "config.com": { + accountId: "some-account-id", + zones: [{ id: "config-com-id" }], + }, + "api.example.com": { + accountId: "some-account-id", + zones: [{ id: "api-example-com-id" }], + }, + "cli.com": { + accountId: "some-account-id", + zones: [{ id: "cli-com-id" }], + }, + }); + mockGetZoneWorkerRoutesMulti({ + "config-com-id": [], + "api-example-com-id": [], + "cli-com-id": [], + }); + // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mockCustomDomainsChangesetRequest({}); mockPublishCustomDomainsRequest({ publishFlags: { @@ -1891,14 +2086,14 @@ Update them to point to this script instead?`, "simple.co.uk/*", "*/*", "*/blog/*", - { pattern: "example.com/blog/*", zone_id: "asdfadsf" }, - { pattern: "example.com/*", zone_id: "asdfadsf" }, - { pattern: "example.com/abc/def/*", zone_id: "asdfadsf" }, + { pattern: "example.com/blog/*", zone_id: "example-com-id" }, + { pattern: "example.com/*", zone_id: "example-com-id" }, + { pattern: "example.com/abc/def/*", zone_id: "example-com-id" }, ], }); await mockAUSRequest([]); mockSubDomainRequest(); - mockUpdateWorkerSubdomain({ enabled: false, previews_enabled: true }); + mockUpdateWorkerSubdomain({ enabled: false, previews_enabled: false }); mockUploadWorkerRequest({ expectedAssets: { jwt: "<>", @@ -1906,6 +2101,23 @@ Update them to point to this script instead?`, }, expectedType: "none", }); + // These run during route conflict resolution. + // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + mockGetZonesMulti({ + "simple.co.uk": { + accountId: "some-account-id", + zones: [{ id: "simple-co-uk-id" }], + }, + "example.com": { + accountId: "some-account-id", + zones: [{ id: "example-com-id" }], + }, + }); + mockGetZoneWorkerRoutesMulti({ + "simple-co-uk-id": [], + "example-com-id": [], + }); + // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mockPublishRoutesRequest({ routes: [ // @ts-expect-error - this is what is expected @@ -1926,15 +2138,15 @@ Update them to point to this script instead?`, }, { pattern: "example.com/blog/*", - zone_id: "asdfadsf", + zone_id: "example-com-id", }, { pattern: "example.com/*", - zone_id: "asdfadsf", + zone_id: "example-com-id", }, { pattern: "example.com/abc/def/*", - zone_id: "asdfadsf", + zone_id: "example-com-id", }, ], }); @@ -1963,9 +2175,9 @@ Update them to point to this script instead?`, simple.co.uk/* */* */blog/* - example.com/blog/* (zone id: asdfadsf) - example.com/* (zone id: asdfadsf) - example.com/abc/def/* (zone id: asdfadsf) + example.com/blog/* (zone id: example-com-id) + example.com/* (zone id: example-com-id) + example.com/abc/def/* (zone id: example-com-id) Current Version ID: Galaxy-Class" `); }); @@ -1973,9 +2185,9 @@ Update them to point to this script instead?`, it("does not mention 404s hit a Worker if it's assets only", async () => { writeWranglerConfig({ routes: [ - { pattern: "example.com/blog/*", zone_id: "asdfadsf" }, - { pattern: "example.com/*", zone_id: "asdfadsf" }, - { pattern: "example.com/abc/def/*", zone_id: "asdfadsf" }, + { pattern: "example.com/blog/*", zone_id: "example-com-id" }, + { pattern: "example.com/*", zone_id: "example-com-id" }, + { pattern: "example.com/abc/def/*", zone_id: "example-com-id" }, ], assets: { directory: "assets", @@ -1983,7 +2195,7 @@ Update them to point to this script instead?`, }); await mockAUSRequest([]); mockSubDomainRequest(); - mockUpdateWorkerSubdomain({ enabled: false, previews_enabled: true }); + mockUpdateWorkerSubdomain({ enabled: false, previews_enabled: false }); mockUploadWorkerRequest({ expectedAssets: { jwt: "<>", @@ -1991,19 +2203,24 @@ Update them to point to this script instead?`, }, expectedType: "none", }); + // These run during route conflict resolution. + // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + mockGetZones("example.com", [{ id: "example-com-id" }]); + mockGetZoneWorkerRoutes("example-com-id", []); + // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mockPublishRoutesRequest({ routes: [ { pattern: "example.com/blog/*", - zone_id: "asdfadsf", + zone_id: "example-com-id", }, { pattern: "example.com/*", - zone_id: "asdfadsf", + zone_id: "example-com-id", }, { pattern: "example.com/abc/def/*", - zone_id: "asdfadsf", + zone_id: "example-com-id", }, ], }); @@ -2025,9 +2242,9 @@ Update them to point to this script instead?`, Worker Startup Time: 100 ms Uploaded test-name (TIMINGS) Deployed test-name triggers (TIMINGS) - example.com/blog/* (zone id: asdfadsf) - example.com/* (zone id: asdfadsf) - example.com/abc/def/* (zone id: asdfadsf) + example.com/blog/* (zone id: example-com-id) + example.com/* (zone id: example-com-id) + example.com/abc/def/* (zone id: example-com-id) Current Version ID: Galaxy-Class" `); }); @@ -2035,9 +2252,9 @@ Update them to point to this script instead?`, it("does mention hitting the Worker on 404 if there is one", async () => { writeWranglerConfig({ routes: [ - { pattern: "example.com/blog/*", zone_id: "asdfadsf" }, - { pattern: "example.com/*", zone_id: "asdfadsf" }, - { pattern: "example.com/abc/def/*", zone_id: "asdfadsf" }, + { pattern: "example.com/blog/*", zone_id: "example-com-id" }, + { pattern: "example.com/*", zone_id: "example-com-id" }, + { pattern: "example.com/abc/def/*", zone_id: "example-com-id" }, ], assets: { directory: "assets", @@ -2046,7 +2263,7 @@ Update them to point to this script instead?`, writeWorkerSource(); await mockAUSRequest([]); mockSubDomainRequest(); - mockUpdateWorkerSubdomain({ enabled: false, previews_enabled: true }); + mockUpdateWorkerSubdomain({ enabled: false, previews_enabled: false }); mockUploadWorkerRequest({ expectedAssets: { jwt: "<>", @@ -2055,19 +2272,24 @@ Update them to point to this script instead?`, expectedType: "esm", expectedMainModule: "index.js", }); + // These run during route conflict resolution. + // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + mockGetZones("example.com", [{ id: "example-com-id" }]); + mockGetZoneWorkerRoutes("example-com-id", []); + // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mockPublishRoutesRequest({ routes: [ { pattern: "example.com/blog/*", - zone_id: "asdfadsf", + zone_id: "example-com-id", }, { pattern: "example.com/*", - zone_id: "asdfadsf", + zone_id: "example-com-id", }, { pattern: "example.com/abc/def/*", - zone_id: "asdfadsf", + zone_id: "example-com-id", }, ], }); @@ -2091,9 +2313,9 @@ Update them to point to this script instead?`, Worker Startup Time: 100 ms Uploaded test-name (TIMINGS) Deployed test-name triggers (TIMINGS) - example.com/blog/* (zone id: asdfadsf) - example.com/* (zone id: asdfadsf) - example.com/abc/def/* (zone id: asdfadsf) + example.com/blog/* (zone id: example-com-id) + example.com/* (zone id: example-com-id) + example.com/abc/def/* (zone id: example-com-id) Current Version ID: Galaxy-Class" `); }); @@ -2105,9 +2327,9 @@ Update them to point to this script instead?`, "simple.co.uk/*", "*/*", "*/blog/*", - { pattern: "example.com/blog/*", zone_id: "asdfadsf" }, - { pattern: "example.com/*", zone_id: "asdfadsf" }, - { pattern: "example.com/abc/def/*", zone_id: "asdfadsf" }, + { pattern: "example.com/blog/*", zone_id: "example-com-id" }, + { pattern: "example.com/*", zone_id: "example-com-id" }, + { pattern: "example.com/abc/def/*", zone_id: "example-com-id" }, ], assets: { directory: "assets", @@ -2116,7 +2338,7 @@ Update them to point to this script instead?`, }); await mockAUSRequest([]); mockSubDomainRequest(); - mockUpdateWorkerSubdomain({ enabled: false, previews_enabled: true }); + mockUpdateWorkerSubdomain({ enabled: false, previews_enabled: false }); mockUploadWorkerRequest({ expectedAssets: { jwt: "<>", @@ -2126,6 +2348,23 @@ Update them to point to this script instead?`, }, expectedType: "none", }); + // These run during route conflict resolution. + // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + mockGetZonesMulti({ + "simple.co.uk": { + accountId: "some-account-id", + zones: [{ id: "simple-co-uk-id" }], + }, + "example.com": { + accountId: "some-account-id", + zones: [{ id: "example-com-id" }], + }, + }); + mockGetZoneWorkerRoutesMulti({ + "simple-co-uk-id": [], + "example-com-id": [], + }); + // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mockPublishRoutesRequest({ routes: [ // @ts-expect-error - this is what is expected @@ -2146,15 +2385,15 @@ Update them to point to this script instead?`, }, { pattern: "example.com/blog/*", - zone_id: "asdfadsf", + zone_id: "example-com-id", }, { pattern: "example.com/*", - zone_id: "asdfadsf", + zone_id: "example-com-id", }, { pattern: "example.com/abc/def/*", - zone_id: "asdfadsf", + zone_id: "example-com-id", }, ], }); @@ -2174,9 +2413,9 @@ Update them to point to this script instead?`, simple.co.uk/* */* */blog/* - example.com/blog/* (zone id: asdfadsf) - example.com/* (zone id: asdfadsf) - example.com/abc/def/* (zone id: asdfadsf) + example.com/blog/* (zone id: example-com-id) + example.com/* (zone id: example-com-id) + example.com/abc/def/* (zone id: example-com-id) Current Version ID: Galaxy-Class" `); }); @@ -5775,6 +6014,42 @@ addEventListener('fetch', event => {});` vi.useRealTimers(); }); + it("should include Cloudflare-Workers-Script-Api-Date header", async () => { + writeWranglerConfig(); + writeWorkerSource(); + mockUploadWorkerRequest(); + mockGetWorkerSubdomain({ enabled: false }); + mockSubDomainRequest(); + msw.use( + http.post( + `*/accounts/:accountId/workers/scripts/:scriptName/subdomain`, + async ({ request, params }) => { + expect(params.accountId).toEqual("some-account-id"); + expect(params.scriptName).toEqual("test-name"); + expect( + request.headers.get("Cloudflare-Workers-Script-Api-Date") + ).toEqual("2025-08-01"); + return HttpResponse.json( + createFetchResult({ enabled: true, previews_enabled: false }) + ); + }, + { once: true } + ) + ); + + await runWrangler("deploy ./index"); + + expect(std.out).toMatchInlineSnapshot(` + "Total Upload: xx KiB / gzip: xx KiB + Worker Startup Time: 100 ms + Uploaded test-name (TIMINGS) + Deployed test-name triggers (TIMINGS) + https://test-name.test-sub-domain.workers.dev + Current Version ID: Galaxy-Class" + `); + expect(std.err).toMatchInlineSnapshot(`""`); + }); + it("should deploy to a workers.dev domain if workers_dev is undefined", async () => { writeWranglerConfig(); writeWorkerSource(); @@ -6333,7 +6608,7 @@ addEventListener('fetch', event => {});` mockGetWorkerSubdomain({ enabled: false }); // no set-subdomain call mockGetZones("example.com", [{ id: "example-id" }]); - mockGetWorkerRoutes("example-id"); + mockGetZoneWorkerRoutes("example-id"); mockPublishRoutesRequest({ routes: ["http://example.com/*"] }); await runWrangler("deploy index.js"); @@ -6366,7 +6641,7 @@ addEventListener('fetch', event => {});` legacyEnv: true, }); mockGetZones("production.example.com", [{ id: "example-id" }]); - mockGetWorkerRoutes("example-id"); + mockGetZoneWorkerRoutes("example-id"); mockPublishRoutesRequest({ routes: ["http://production.example.com/*"], env: "production", @@ -6403,7 +6678,7 @@ addEventListener('fetch', event => {});` legacyEnv: true, }); mockGetZones("production.example.com", [{ id: "example-id" }]); - mockGetWorkerRoutes("example-id"); + mockGetZoneWorkerRoutes("example-id"); mockPublishRoutesRequest({ routes: ["http://production.example.com/*"], env: "production", @@ -6557,7 +6832,7 @@ addEventListener('fetch', event => {});` legacyEnv: true, }); mockGetZones("production.example.com", [{ id: "example-id" }]); - mockGetWorkerRoutes("example-id"); + mockGetZoneWorkerRoutes("example-id"); mockPublishRoutesRequest({ routes: ["http://production.example.com/*"], env: "production", @@ -6595,7 +6870,7 @@ addEventListener('fetch', event => {});` legacyEnv: true, }); mockGetZones("production.example.com", [{ id: "example-id" }]); - mockGetWorkerRoutes("example-id"); + mockGetZoneWorkerRoutes("example-id"); mockPublishRoutesRequest({ routes: ["http://production.example.com/*"], env: "production", @@ -6614,6 +6889,60 @@ addEventListener('fetch', event => {});` expect(std.err).toMatchInlineSnapshot(`""`); expect(std.warn).toMatchInlineSnapshot(`""`); }); + + it("should warn the user if workers_dev default is different from remote", async () => { + writeWranglerConfig({}); // Default workers_dev should be true, since there's no routes. + writeWorkerSource(); + mockSubDomainRequest(); + mockUploadWorkerRequest(); + mockGetWorkerSubdomain({ enabled: false }); + mockUpdateWorkerSubdomain({ enabled: true }); + await runWrangler("deploy ./index"); + + expect(std.out).toMatchInlineSnapshot(` + "Total Upload: xx KiB / gzip: xx KiB + Worker Startup Time: 100 ms + Uploaded test-name (TIMINGS) + Deployed test-name triggers (TIMINGS) + https://test-name.test-sub-domain.workers.dev + Current Version ID: Galaxy-Class" + `); + expect(std.err).toMatchInlineSnapshot(`""`); + expect(std.warn).toMatchInlineSnapshot(` + "▲ [WARNING] Worker has workers.dev disabled, but 'workers_dev' is not in the config. + + Using fallback value 'workers_dev = true'. + + " + `); + }); + + it("should warn the user if preview_urls default is different from remote", async () => { + writeWranglerConfig({}); // Default preview_urls should be false. + writeWorkerSource(); + mockSubDomainRequest(); + mockUploadWorkerRequest(); + mockGetWorkerSubdomain({ enabled: true, previews_enabled: true }); + mockUpdateWorkerSubdomain({ enabled: true, previews_enabled: false }); + await runWrangler("deploy ./index"); + + expect(std.out).toMatchInlineSnapshot(` + "Total Upload: xx KiB / gzip: xx KiB + Worker Startup Time: 100 ms + Uploaded test-name (TIMINGS) + Deployed test-name triggers (TIMINGS) + https://test-name.test-sub-domain.workers.dev + Current Version ID: Galaxy-Class" + `); + expect(std.err).toMatchInlineSnapshot(`""`); + expect(std.warn).toMatchInlineSnapshot(` + "▲ [WARNING] Worker has preview URLs enabled, but 'preview_urls' is not in the config. + + Using fallback value 'preview_urls = false'. + + " + `); + }); }); describe("[define]", () => { @@ -12987,7 +13316,10 @@ export default{ ]); mockGetServiceRoutes("test-name", []); mockGetServiceCustomDomainRecords([]); - mockGetServiceSubDomainData("test-name", { enabled: true }); + mockGetServiceSubDomainData("test-name", { + enabled: true, + previews_enabled: false, + }); mockGetServiceSchedules("test-name", { schedules: [] }); mockGetServiceMetadata("test-name", { created_on: "2025-08-07T09:34:47.846308Z", @@ -13012,7 +13344,7 @@ export default{ "▲ [WARNING] The local configuration being used (generated from your local configuration file) differs from the remote configuration of your Worker set via the Cloudflare Dashboard: \\"workers_dev\\": true, - \\"preview_urls\\": true, + \\"preview_urls\\": false, \\"vars\\": { - \\"MY_VAR\\": \\"abc\\" + \\"MY_VAR\\": 123 @@ -13049,7 +13381,10 @@ export default{ ]); mockGetServiceRoutes("test-name", []); mockGetServiceCustomDomainRecords([]); - mockGetServiceSubDomainData("test-name", { enabled: true }); + mockGetServiceSubDomainData("test-name", { + enabled: true, + previews_enabled: false, + }); mockGetServiceSchedules("test-name", { schedules: [] }); mockGetServiceMetadata("test-name", { created_on: "2025-08-07T09:34:47.846308Z", @@ -13077,7 +13412,7 @@ export default{ "▲ [WARNING] The local configuration being used (generated from your local configuration file) differs from the remote configuration of your Worker set via the Cloudflare Dashboard: \\"workers_dev\\": true, - \\"preview_urls\\": true, + \\"preview_urls\\": false, \\"vars\\": { - \\"MY_VAR\\": \\"abc\\" + \\"MY_VAR\\": \\"this is a toml file\\" @@ -13228,51 +13563,6 @@ function mockUnauthorizedPublishRoutesRequest({ ); } -function mockGetZones( - domain: string, - zones: { id: string }[] = [], - accountId = "some-account-id" -) { - msw.use( - http.get("*/zones", ({ request }) => { - const url = new URL(request.url); - - expect([...url.searchParams.entries()]).toEqual([ - ["name", domain], - ["account.id", accountId], - ]); - - return HttpResponse.json( - { - success: true, - errors: [], - messages: [], - result: zones, - }, - { status: 200 } - ); - }) - ); -} - -function mockGetWorkerRoutes(zoneId: string) { - msw.use( - http.get("*/zones/:zoneId/workers/routes", ({ params }) => { - expect(params.zoneId).toEqual(zoneId); - - return HttpResponse.json( - { - success: true, - errors: [], - messages: [], - result: [], - }, - { status: 200 } - ); - }) - ); -} - function mockPublishRoutesFallbackRequest(route: { pattern: string; script: string; @@ -13925,6 +14215,7 @@ function mockGetServiceSubDomainData( serviceName: string, data: { enabled: boolean; + previews_enabled: boolean; } ) { msw.use( diff --git a/packages/wrangler/src/__tests__/deploy/config-diffs.test.ts b/packages/wrangler/src/__tests__/deploy/config-diffs.test.ts index 2926b8af2566..9a97a009ddc1 100644 --- a/packages/wrangler/src/__tests__/deploy/config-diffs.test.ts +++ b/packages/wrangler/src/__tests__/deploy/config-diffs.test.ts @@ -8,6 +8,7 @@ describe("getRemoteConfigsDiff", () => { name: "silent-firefly-dbe3", main: "/tmp/src/index.js", workers_dev: true, + preview_urls: false, compatibility_date: "2025-07-08", compatibility_flags: undefined, placement: undefined, @@ -38,6 +39,7 @@ describe("getRemoteConfigsDiff", () => { name: "silent-firefly-dbe3", main: "/tmp/src/index.js", workers_dev: true, + preview_urls: false, compatibility_date: "2025-07-08", compatibility_flags: undefined, placement: undefined, @@ -75,6 +77,7 @@ describe("getRemoteConfigsDiff", () => { name: "silent-firefly-dbe3", main: "/tmp/src/index.js", workers_dev: true, + preview_urls: false, compatibility_date: "2025-07-08", compatibility_flags: undefined, placement: undefined, @@ -104,20 +107,7 @@ describe("getRemoteConfigsDiff", () => { + \\"id\\": \\"my-kv-456\\" } ], - - \\"workers_dev\\": true, - \\"observability\\": { - \\"enabled\\": false, - \\"head_sampling_rate\\": 1, - - ... - - \\"head_sampling_rate\\": 1, - \\"invocation_logs\\": true - } - - } - + }, - + \\"workers_dev\\": true - }" + \\"workers_dev\\": true," `); expect(nonDestructive).toBe(true); }); @@ -128,6 +118,7 @@ describe("getRemoteConfigsDiff", () => { name: "silent-firefly-dbe3", main: "/tmp/src/index.js", workers_dev: true, + preview_urls: false, compatibility_date: "2025-07-08", compatibility_flags: undefined, placement: undefined, @@ -161,11 +152,11 @@ describe("getRemoteConfigsDiff", () => { ... - } }, \\"account_id\\": \\"account-id-123\\", - + \\"workers_dev\\": true - - \\"workers_dev\\": true, + \\"workers_dev\\": true, + + \\"preview_urls\\": false + - \\"preview_urls\\": false, - \\"kv_namespaces\\": [ - { - \\"binding\\": \\"MY_KV\\", @@ -191,6 +182,7 @@ describe("getRemoteConfigsDiff", () => { { observability: remoteObservability, workers_dev: true, + preview_urls: false, }, { observability: localObservability, diff --git a/packages/wrangler/src/__tests__/helpers/mock-get-zone-from-host.ts b/packages/wrangler/src/__tests__/helpers/mock-get-zone-from-host.ts index 0087337389fa..3039e38fc455 100644 --- a/packages/wrangler/src/__tests__/helpers/mock-get-zone-from-host.ts +++ b/packages/wrangler/src/__tests__/helpers/mock-get-zone-from-host.ts @@ -1,13 +1,53 @@ import { http, HttpResponse } from "msw"; -import { createFetchResult, msw } from "./msw"; +import { msw } from "./msw"; +import type { RequestHandlerOptions } from "msw"; -export function mockGetZoneFromHostRequest(host: string, zone?: string) { +export function mockGetZonesMulti( + domains: { + [domain: string]: { accountId: string; zones: { id: string }[] }; + } = {}, + options: RequestHandlerOptions = {} +) { msw.use( - http.get("*/zones", ({ request }) => { - const url = new URL(request.url); + http.get( + "*/zones", + ({ request }) => { + const url = new URL(request.url); + const reqName = url.searchParams.get("name") || ""; + const reqAccountId = url.searchParams.get("account.id") || ""; + expect(reqName).not.toEqual(""); + expect(reqAccountId).not.toEqual(""); - expect(url.searchParams.get("name")).toEqual(host); - return HttpResponse.json(createFetchResult(zone ? [{ id: zone }] : [])); - }) + expect(Object.keys(domains)).toContain(reqName); + const domain = domains[reqName]; + expect(domain.accountId).toEqual(reqAccountId); + const zones = domain.zones; + + return HttpResponse.json( + { + success: true, + errors: [], + messages: [], + result: zones, + }, + { status: 200 } + ); + }, + options + ) + ); +} + +export function mockGetZones( + domain: string, + zones: { id: string }[] = [], + accountId = "some-account-id", + options: RequestHandlerOptions = {} +) { + return mockGetZonesMulti( + { + [domain]: { accountId, zones }, + }, + options ); } diff --git a/packages/wrangler/src/__tests__/helpers/mock-known-routes.ts b/packages/wrangler/src/__tests__/helpers/mock-known-routes.ts deleted file mode 100644 index 76c5bf3fdc78..000000000000 --- a/packages/wrangler/src/__tests__/helpers/mock-known-routes.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { http, HttpResponse } from "msw"; -import { createFetchResult, msw } from "./msw"; - -export function mockCollectKnownRoutesRequest( - routes: { pattern: string; script: string }[] -) { - msw.use( - http.get( - `*/zones/:zoneId/workers/routes`, - () => HttpResponse.json(createFetchResult(routes)), - { once: true } - ) - ); -} diff --git a/packages/wrangler/src/__tests__/helpers/mock-upload-worker.ts b/packages/wrangler/src/__tests__/helpers/mock-upload-worker.ts index ba77de712a0a..f9ef5d266f21 100644 --- a/packages/wrangler/src/__tests__/helpers/mock-upload-worker.ts +++ b/packages/wrangler/src/__tests__/helpers/mock-upload-worker.ts @@ -1,7 +1,11 @@ import { http, HttpResponse } from "msw"; +import { ParseError } from "../../parse"; +import { getSubdomainValues } from "../../triggers/deploy"; import { mockGetWorkerSubdomain } from "./mock-workers-subdomain"; import { createFetchResult, msw } from "./msw"; import { serialize, toString } from "./serialize-form-data-entry"; +import { readWranglerConfig } from "./write-wrangler-config"; +import type { RawConfig, RawEnvironment } from "../../config"; import type { AssetConfigMetadata, WorkerMetadata, @@ -236,9 +240,30 @@ export function mockUploadWorkerRequest( ) ); } - // TODO make explicit by callers? + // Every upload is followed by a GET subdomain request, to check if the worker is enabled. + // TODO: make this explicit by callers? + let config: RawConfig = {}; + try { + config = readWranglerConfig(); + } catch (e) { + if (e instanceof ParseError) { + // Ignore, config is either bad or doesn't exist. + } else { + throw e; + } + } + let envConfig: RawEnvironment = config; + if (env) { + envConfig = config.env?.[env] ?? {}; + } + const { workers_dev, preview_urls } = getSubdomainValues( + envConfig.workers_dev, + envConfig.preview_urls, + envConfig.routes ?? [] + ); mockGetWorkerSubdomain({ - enabled: true, + enabled: workers_dev, + previews_enabled: preview_urls, env, legacyEnv, expectedScriptName, diff --git a/packages/wrangler/src/__tests__/helpers/mock-workers-subdomain.ts b/packages/wrangler/src/__tests__/helpers/mock-workers-subdomain.ts index df2895697102..9e99eac7ba4f 100644 --- a/packages/wrangler/src/__tests__/helpers/mock-workers-subdomain.ts +++ b/packages/wrangler/src/__tests__/helpers/mock-workers-subdomain.ts @@ -36,7 +36,7 @@ export function mockSubDomainRequest( /** Create a mock handler to fetch the