Skip to content
Draft
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
1 change: 1 addition & 0 deletions packages/deploy-helpers/src/triggers/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ export async function triggersDeploy(
config,
workerUrl,
accountId,
scriptName,
customDomainsOnly
).then(
(result) => ({ ...result, category: "Custom domains" }),
Expand Down
24 changes: 15 additions & 9 deletions packages/deploy-helpers/src/triggers/publish-routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ export async function publishCustomDomains(
complianceConfig: ComplianceConfig,
workerUrl: string,
accountId: string,
scriptName: string,
domains: Array<RouteObject>
): Promise<TriggerDeployment> {
const options = {
Expand Down Expand Up @@ -314,17 +315,22 @@ export async function publishCustomDomains(
)
)
);
const existingRendered = existing
.map(
(domain) =>
`\t• ${domain.hostname} (used as a domain for "${domain.service}")`
)
.join("\n");
const message = `Custom Domains already exist for these domains:
const existingForOtherWorkers = existing.filter(
(domain) => domain.service !== scriptName
);
if (existingForOtherWorkers.length > 0) {
const existingRendered = existingForOtherWorkers
.map(
(domain) =>
`\t• ${domain.hostname} (used as a domain for "${domain.service}")`
)
.join("\n");
const message = `Custom Domains already exist for these domains:
${existingRendered}
Update them to point to this script instead?`;
if (!(await confirm(message))) {
return fail();
if (!(await confirm(message))) {
return fail();
}
}
options.override_existing_origin = true;
}
Expand Down
135 changes: 135 additions & 0 deletions packages/deploy-helpers/tests/publish-custom-domains.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import { afterEach, beforeEach, describe, it } from "vitest";
import { initDeployHelpersContext } from "../src/shared/context";
import { publishCustomDomains } from "../src/triggers/publish-routes";
import type { CustomDomainChangeset } from "../src/triggers/publish-routes";
import type { ComplianceConfig } from "@cloudflare/workers-utils";

const ACCOUNT_ID = "some-account-id";
const SCRIPT_NAME = "test-name";
const WORKER_URL = `/accounts/${ACCOUNT_ID}/workers/scripts/${SCRIPT_NAME}`;

describe("publishCustomDomains", () => {
const originalStdoutIsTTY = process.stdout.isTTY;
let confirmRequests: number;
let publishedBody: unknown;

beforeEach(() => {
confirmRequests = 0;
publishedBody = undefined;
Object.defineProperty(process.stdout, "isTTY", {
value: true,
configurable: true,
});

initDeployHelpersContext({
logger: {
debug() {},
error() {},
info() {},
log() {},
warn() {},
},
fetchResult: fetchResult as never,
fetchListResult: (() => {}) as never,
fetchPagedListResult: (() => {}) as never,
fetchKVGetValue: (() => {}) as never,
confirm: async () => {
confirmRequests++;
return true;
},
prompt: (() => {}) as never,
select: (() => {}) as never,
});
});

afterEach(() => {
Object.defineProperty(process.stdout, "isTTY", {
value: originalStdoutIsTTY,
configurable: true,
});
});

async function fetchResult(
_config: ComplianceConfig,
path: string,
init?: RequestInit
): Promise<unknown> {
const body =
typeof init?.body === "string" ? JSON.parse(init.body) : undefined;

if (path === `${WORKER_URL}/domains/changeset?replace_state=true`) {
return {
added: [],
removed: [],
updated: [
{
id: "101",
zone_id: "",
zone_name: "",
hostname: "api.example.com",
service: SCRIPT_NAME,
environment: "",
enabled: true,
previews_enabled: false,
modified: true,
},
],
conflicting: [],
} satisfies CustomDomainChangeset;
}

if (path === `/accounts/${ACCOUNT_ID}/workers/domains/records/101`) {
return {
id: "101",
zone_id: "",
zone_name: "",
hostname: "api.example.com",
service: SCRIPT_NAME,
environment: "",
enabled: true,
previews_enabled: false,
};
}

if (path === `${WORKER_URL}/domains/records`) {
publishedBody = body;
return null;
}

throw new Error(`Unexpected request: ${init?.method ?? "GET"} ${path}`);
}

it("updates a domain already attached to this Worker without prompting", async ({
expect,
}) => {
const result = await publishCustomDomains(
{} as ComplianceConfig,
WORKER_URL,
ACCOUNT_ID,
SCRIPT_NAME,
[
{
pattern: "api.example.com",
custom_domain: true,
previews_enabled: true,
},
]
);

expect(confirmRequests).toBe(0);
expect(publishedBody).toEqual({
override_scope: true,
override_existing_origin: true,
override_existing_dns_record: false,
origins: [
{
hostname: "api.example.com",
previews_enabled: true,
},
],
});
expect(result.targets).toEqual([
"api.example.com (custom domain) [previews: enabled]",
]);
});
});
63 changes: 63 additions & 0 deletions packages/wrangler/src/__tests__/deploy/routes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,69 @@ Update them to point to this script instead?`,
expect(std.out).toContain("api.example.com (custom domain)");
});

it("should not confirm override if custom domain already belongs to this Worker", async ({
expect,
}) => {
writeWranglerConfig({
routes: [
{
pattern: "api.example.com",
custom_domain: true,
previews_enabled: true,
},
],
});
writeWorkerSource();
mockUpdateWorkerSubdomain({ enabled: false });
mockUploadWorkerRequest({ expectedType: "esm" });
mockGetZones(expect, "api.example.com", [{ id: "api-example-com-id" }]);
mockGetZoneWorkerRoutes(expect, "api-example-com-id", []);
mockCustomDomainsChangesetRequest({
originConflicts: [
{
id: "101",
zone_id: "",
zone_name: "",
hostname: "api.example.com",
service: "test-name",
environment: "",
enabled: true,
previews_enabled: false,
},
],
});
mockCustomDomainLookup({
id: "101",
zone_id: "",
zone_name: "",
hostname: "api.example.com",
service: "test-name",
environment: "",
enabled: true,
previews_enabled: false,
});
mockPublishCustomDomainsRequest({
publishFlags: {
override_scope: true,
override_existing_origin: true,
override_existing_dns_record: false,
},
domains: [
{
hostname: "api.example.com",
previews_enabled: true,
},
],
});

await runWrangler("deploy ./index");

expect(std.out).toContain(
"api.example.com (custom domain) [previews: enabled]"
);
expect(std.out).not.toContain("Custom Domains already exist");
});

it("should confirm override if custom domain deploy contains a conflicting DNS record", async ({
expect,
}) => {
Expand Down
Loading