Skip to content

Commit

Permalink
Feature: dispatch-namespace option in wrangler deploy (#5093)
Browse files Browse the repository at this point in the history
* Add dispatch-namespace option to wrangler deploy

* Add config validation for Worker name and move isDispatchNamespace

---------

Co-authored-by: Daniel Walsh <walshy@cloudflare.com>
  • Loading branch information
benycodes and WalshyDev committed Mar 14, 2024
1 parent 7a0da67 commit a676f55
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 7 deletions.
5 changes: 5 additions & 0 deletions .changeset/seven-spies-drive.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"wrangler": minor
---

feature: add --dispatch-namespace to wrangler deploy to support uploading Workers directly to a Workers for Platforms dispatch namespace.
13 changes: 13 additions & 0 deletions packages/wrangler/src/__tests__/configuration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1190,6 +1190,19 @@ describe("normalizeAndValidateConfig()", () => {
- Expected \\"name\\" to be of type string, alphanumeric and lowercase with dashes only but got \\"!@#$%^&*(()\\"."
`);
});

it("should accept any Worker name if the dispatch-namespace flag is used", () => {
const { diagnostics } = normalizeAndValidateConfig(
{
name: "example.com",
main: "index.js",
},
undefined,
{ env: undefined, "dispatch-namespace": "test-namespace" }
);
expect(diagnostics.hasWarnings()).toBe(false);
expect(diagnostics.hasErrors()).toBe(false);
});
});

describe("[build]", () => {
Expand Down
28 changes: 28 additions & 0 deletions packages/wrangler/src/__tests__/deploy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9015,6 +9015,34 @@ export default{
expect(std.err).toMatchInlineSnapshot(`""`);
});
});

describe("--dispatch-namespace", () => {
it("should upload to dispatch namespace", async () => {
writeWranglerToml();
const scriptContent = `
export default {
fetch() {
return new Response("Hello, World!");
}
}
`;
fs.writeFileSync("index.js", scriptContent);
mockUploadWorkerRequest({
expectedMainModule: "index.js",
expectedDispatchNamespace: "test-dispatch-namespace",
});

await runWrangler(
"deploy --dispatch-namespace test-dispatch-namespace index.js"
);
expect(std.out).toMatchInlineSnapshot(`
"Total Upload: xx KiB / gzip: xx KiB
Uploaded test-name (TIMINGS)
Dispatch Namespace: test-dispatch-namespace
Current Deployment ID: Galaxy-Class"
`);
});
});
});

/** Write mock assets to the file system so they can be uploaded. */
Expand Down
12 changes: 12 additions & 0 deletions packages/wrangler/src/__tests__/helpers/mock-upload-worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export function mockUploadWorkerRequest(
legacyEnv?: boolean;
keepVars?: boolean;
tag?: string;
expectedDispatchNamespace?: string;
} = {}
) {
const {
Expand All @@ -46,6 +47,7 @@ export function mockUploadWorkerRequest(
expectedCapnpSchema,
expectedLimits,
keepVars,
expectedDispatchNamespace,
} = options;
if (env && !legacyEnv) {
msw.use(
Expand All @@ -54,6 +56,13 @@ export function mockUploadWorkerRequest(
handleUpload
)
);
} else if (expectedDispatchNamespace) {
msw.use(
rest.put(
"*/accounts/:accountId/workers/dispatch/namespaces/:dispatchNamespace/scripts/:scriptName",
handleUpload
)
);
} else {
msw.use(
rest.put(
Expand All @@ -79,6 +88,9 @@ export function mockUploadWorkerRequest(
"true"
);
expect(req.url.searchParams.get("excludeScript")).toEqual("true");
if (expectedDispatchNamespace) {
expect(req.params.dispatchNamespace).toEqual(expectedDispatchNamespace);
}

const formBody = await (
req as MockedRequest as RestRequestWithFormData
Expand Down
29 changes: 26 additions & 3 deletions packages/wrangler/src/config/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,15 @@ export function normalizeAndValidateConfig(
);
}

const isDispatchNamespace =
typeof args["dispatch-namespace"] === "string" &&
args["dispatch-namespace"].trim() !== "";

const topLevelEnv = normalizeAndValidateEnvironment(
diagnostics,
configPath,
rawConfig
rawConfig,
isDispatchNamespace
);

//TODO: find a better way to define the type of Args that can be passed to the normalizeAndValidateConfig()
Expand All @@ -149,6 +154,7 @@ export function normalizeAndValidateConfig(
envDiagnostics,
configPath,
rawEnv,
isDispatchNamespace,
envName,
topLevelEnv,
isLegacyEnv,
Expand All @@ -163,6 +169,7 @@ export function normalizeAndValidateConfig(
envDiagnostics,
configPath,
{},
isDispatchNamespace,
envName,
topLevelEnv,
isLegacyEnv,
Expand Down Expand Up @@ -995,7 +1002,8 @@ const validateTailConsumers: ValidatorFn = (diagnostics, field, value) => {
function normalizeAndValidateEnvironment(
diagnostics: Diagnostics,
configPath: string | undefined,
topLevelEnv: RawEnvironment
topLevelEnv: RawEnvironment,
isDispatchNamespace: boolean
): Environment;
/**
* Validate the named environment configuration and return the normalized values.
Expand All @@ -1004,15 +1012,30 @@ function normalizeAndValidateEnvironment(
diagnostics: Diagnostics,
configPath: string | undefined,
rawEnv: RawEnvironment,
isDispatchNamespace: boolean,
envName: string,
topLevelEnv: Environment,
isLegacyEnv: boolean,
rawConfig: RawConfig
): Environment;
/**
* Validate the named environment configuration and return the normalized values.
*/
function normalizeAndValidateEnvironment(
diagnostics: Diagnostics,
configPath: string | undefined,
rawEnv: RawEnvironment,
isDispatchNamespace: boolean,
envName?: string,
topLevelEnv?: Environment,
isLegacyEnv?: boolean,
rawConfig?: RawConfig
): Environment;
function normalizeAndValidateEnvironment(
diagnostics: Diagnostics,
configPath: string | undefined,
rawEnv: RawEnvironment,
isDispatchNamespace: boolean,
envName = "top level",
topLevelEnv?: Environment | undefined,
isLegacyEnv?: boolean,
Expand Down Expand Up @@ -1130,7 +1153,7 @@ function normalizeAndValidateEnvironment(
topLevelEnv,
rawEnv,
"name",
isValidName,
isDispatchNamespace ? isString : isValidName,
appendEnvName(envName),
undefined
),
Expand Down
26 changes: 22 additions & 4 deletions packages/wrangler/src/deploy/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ type Props = {
logpush: boolean | undefined;
oldAssetTtl: number | undefined;
projectRoot: string | undefined;
dispatchNamespace: string | undefined;
};

type RouteObject = ZoneIdRoute | ZoneNameRoute | CustomDomainRoute;
Expand Down Expand Up @@ -282,7 +283,7 @@ Update them to point to this script instead?`;
export default async function deploy(props: Props): Promise<void> {
// TODO: warn if git/hg has uncommitted changes
const { config, accountId, name } = props;
if (accountId && name) {
if (!props.dispatchNamespace && accountId && name) {
try {
const serviceMetaData = await fetchResult(
`/accounts/${accountId}/workers/services/${name}`
Expand Down Expand Up @@ -422,7 +423,9 @@ See https://developers.cloudflare.com/workers/platform/compatibility-dates for m
const start = Date.now();
const notProd = Boolean(!props.legacyEnv && props.env);
const workerName = notProd ? `${scriptName} (${envName})` : scriptName;
const workerUrl = notProd
const workerUrl = props.dispatchNamespace
? `/accounts/${accountId}/workers/dispatch/namespaces/${props.dispatchNamespace}/scripts/${scriptName}`
: notProd
? `/accounts/${accountId}/workers/services/${scriptName}/environments/${envName}`
: `/accounts/${accountId}/workers/scripts/${scriptName}`;

Expand Down Expand Up @@ -787,6 +790,14 @@ See https://developers.cloudflare.com/workers/platform/compatibility-dates for m
const uploadMs = Date.now() - start;
const deployments: Promise<string[]>[] = [];

logger.log("Uploaded", workerName, formatTime(uploadMs));

// Early exit for WfP since it doesn't need the below code
if (props.dispatchNamespace !== undefined) {
deployWfpUserWorker(props.dispatchNamespace, deploymentId);
return;
}

if (deployToWorkersDev) {
// Deploy to a subdomain of `workers.dev`
const userSubdomain = await getWorkersDevSubdomain(accountId);
Expand Down Expand Up @@ -885,8 +896,6 @@ See https://developers.cloudflare.com/workers/platform/compatibility-dates for m
}
}

logger.log("Uploaded", workerName, formatTime(uploadMs));

// Update routing table for the script.
if (routesOnly.length > 0) {
deployments.push(
Expand Down Expand Up @@ -947,6 +956,15 @@ See https://developers.cloudflare.com/workers/platform/compatibility-dates for m
logger.log("Current Deployment ID:", deploymentId);
}

function deployWfpUserWorker(
dispatchNamespace: string,
deploymentId: string | null
) {
// Will go under the "Uploaded" text
logger.log(" Dispatch Namespace:", dispatchNamespace);
logger.log("Current Deployment ID:", deploymentId);
}

export function helpIfErrorIsSizeOrScriptStartup(
err: unknown,
dependencies: { [path: string]: { bytesInOutput: number } }
Expand Down
6 changes: 6 additions & 0 deletions packages/wrangler/src/deploy/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,11 @@ export function deployOptions(yargs: CommonYargsArgv) {
"Expire old assets in given seconds rather than immediate deletion.",
type: "number",
})
.option("dispatch-namespace", {
describe:
"Name of a dispatch namespace to deploy the Worker to (Workers for Platforms)",
type: "string",
})
);
}

Expand Down Expand Up @@ -299,5 +304,6 @@ export async function deployHandler(
logpush: args.logpush,
oldAssetTtl: args.oldAssetTtl,
projectRoot,
dispatchNamespace: args.dispatchNamespace,
});
}

0 comments on commit a676f55

Please sign in to comment.