Skip to content
Open
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
2 changes: 1 addition & 1 deletion .github/workflows/deploy-examples.yml
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,7 @@ jobs:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
PREVIEW_NAME: pr-${{ github.event.pull_request.number }}
run: vp exec vinext-cloudflare previews deploy "$PREVIEW_NAME"
run: vp exec vinext-cloudflare previews deploy --preview-name "$PREVIEW_NAME"

- name: Deploy Named Preview Worker
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository && hashFiles(format('{0}/cloudflare.config.ts', matrix.example.working_directory)) == '' && matrix.example.worker_name
Expand Down
24 changes: 12 additions & 12 deletions docs/deploying/cloudflare.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -118,31 +118,31 @@ Use `previews deploy` with a project that has `cloudflare.config.ts` and the `cf

<PackageManagerCommand
commands={{
pnpm: "pnpm dlx @vinext/cloudflare previews deploy\npnpm dlx @vinext/cloudflare previews deploy pr-123\npnpm dlx @vinext/cloudflare previews deploy pr-123 --mode staging\npnpm dlx @vinext/cloudflare previews deploy pr-123 --skip-build",
npm: "npx @vinext/cloudflare previews deploy\nnpx @vinext/cloudflare previews deploy pr-123\nnpx @vinext/cloudflare previews deploy pr-123 --mode staging\nnpx @vinext/cloudflare previews deploy pr-123 --skip-build",
yarn: "yarn dlx @vinext/cloudflare previews deploy\nyarn dlx @vinext/cloudflare previews deploy pr-123\nyarn dlx @vinext/cloudflare previews deploy pr-123 --mode staging\nyarn dlx @vinext/cloudflare previews deploy pr-123 --skip-build",
bun: "bunx @vinext/cloudflare previews deploy\nbunx @vinext/cloudflare previews deploy pr-123\nbunx @vinext/cloudflare previews deploy pr-123 --mode staging\nbunx @vinext/cloudflare previews deploy pr-123 --skip-build",
vp: "vpx @vinext/cloudflare previews deploy\nvpx @vinext/cloudflare previews deploy pr-123\nvpx @vinext/cloudflare previews deploy pr-123 --mode staging\nvpx @vinext/cloudflare previews deploy pr-123 --skip-build",
pnpm: "pnpm dlx @vinext/cloudflare previews deploy\npnpm dlx @vinext/cloudflare previews deploy --preview-name pr-123\npnpm dlx @vinext/cloudflare previews deploy --preview-name pr-123 --mode staging\npnpm dlx @vinext/cloudflare previews deploy --preview-name pr-123 --skip-build",
npm: "npx @vinext/cloudflare previews deploy\nnpx @vinext/cloudflare previews deploy --preview-name pr-123\nnpx @vinext/cloudflare previews deploy --preview-name pr-123 --mode staging\nnpx @vinext/cloudflare previews deploy --preview-name pr-123 --skip-build",
yarn: "yarn dlx @vinext/cloudflare previews deploy\nyarn dlx @vinext/cloudflare previews deploy --preview-name pr-123\nyarn dlx @vinext/cloudflare previews deploy --preview-name pr-123 --mode staging\nyarn dlx @vinext/cloudflare previews deploy --preview-name pr-123 --skip-build",
bun: "bunx @vinext/cloudflare previews deploy\nbunx @vinext/cloudflare previews deploy --preview-name pr-123\nbunx @vinext/cloudflare previews deploy --preview-name pr-123 --mode staging\nbunx @vinext/cloudflare previews deploy --preview-name pr-123 --skip-build",
vp: "vpx @vinext/cloudflare previews deploy\nvpx @vinext/cloudflare previews deploy --preview-name pr-123\nvpx @vinext/cloudflare previews deploy --preview-name pr-123 --mode staging\nvpx @vinext/cloudflare previews deploy --preview-name pr-123 --skip-build",
}}
/>

The optional name identifies the Preview, not the Worker or the build mode. If you omit it, CF uses the current CI or Git branch. If no branch is available, provide a name.
The optional `--preview-name` identifies the Preview, not the Worker or the build mode. If you omit it, CF uses the current CI or Git branch. If no branch is available, pass `--preview-name`.

As with `cf previews deploy`, the Preview name and the Vite mode are independent. The build uses the default `production` mode unless you pass `--mode`, and loads the matching `.env*` files. Functions in `cloudflare.config.ts` receive the selected `mode` and `isPreview: true`. The command deploys the Preview Build Output with `cf previews deploy` and prints the Preview URL. Preview deployments do not use cache warming or version promotion.

`--skip-build` uploads existing Preview Build Output without rebuilding it. CF checks that the output is from a Preview build and that it was built in the selected mode. A normal build is not a substitute. To build the output separately, use:

<PackageManagerCommand
commands={{
pnpm: "CLOUDFLARE_PREVIEW_BUILD=true pnpm exec vite build\npnpm dlx @vinext/cloudflare previews deploy pr-123 --skip-build",
npm: "CLOUDFLARE_PREVIEW_BUILD=true npx vite build\nnpx @vinext/cloudflare previews deploy pr-123 --skip-build",
yarn: "CLOUDFLARE_PREVIEW_BUILD=true yarn vite build\nyarn dlx @vinext/cloudflare previews deploy pr-123 --skip-build",
bun: "CLOUDFLARE_PREVIEW_BUILD=true bunx vite build\nbunx @vinext/cloudflare previews deploy pr-123 --skip-build",
vp: "CLOUDFLARE_PREVIEW_BUILD=true vp build\nvpx @vinext/cloudflare previews deploy pr-123 --skip-build",
pnpm: "CLOUDFLARE_PREVIEW_BUILD=true pnpm exec vite build\npnpm dlx @vinext/cloudflare previews deploy --preview-name pr-123 --skip-build",
npm: "CLOUDFLARE_PREVIEW_BUILD=true npx vite build\nnpx @vinext/cloudflare previews deploy --preview-name pr-123 --skip-build",
yarn: "CLOUDFLARE_PREVIEW_BUILD=true yarn vite build\nyarn dlx @vinext/cloudflare previews deploy --preview-name pr-123 --skip-build",
bun: "CLOUDFLARE_PREVIEW_BUILD=true bunx vite build\nbunx @vinext/cloudflare previews deploy --preview-name pr-123 --skip-build",
vp: "CLOUDFLARE_PREVIEW_BUILD=true vp build\nvpx @vinext/cloudflare previews deploy --preview-name pr-123 --skip-build",
}}
/>

The subcommand accepts the optional name, `--mode`, `--skip-build`, `--vite-config`, and `--help`. Configure Preview-specific settings in `cloudflare.config.ts` using `isPreview`.
The subcommand accepts `--preview-name`, `--mode`, `--skip-build`, `--vite-config`, and `--help`. Configure Preview-specific settings in `cloudflare.config.ts` using `isPreview`.

## Use Workers bindings

Expand Down
2 changes: 1 addition & 1 deletion packages/cloudflare/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ function printHelp(commandName?: string): void {

Commands:
deploy Deploy to Cloudflare Workers
previews deploy [preview-name] Deploy a Cloudflare Worker Preview
previews deploy Deploy a Cloudflare Worker Preview

Options:
-h, --help Show this help
Expand Down
12 changes: 5 additions & 7 deletions packages/cloudflare/src/deploy-help.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,25 +132,23 @@ export function formatPreviewsDeployHelp(): string {
return `
vinext-cloudflare previews deploy - Deploy a Cloudflare Worker Preview

Usage: vinext-cloudflare previews deploy [preview-name] [options]
Usage: vinext-cloudflare previews deploy [options]

Builds the app with isPreview=true, then deploys its Preview Build Output
using cf previews deploy. Requires cloudflare.config.ts and the cf CLI.

Arguments:
preview-name Optional Preview name (cf uses the CI or Git branch if omitted)

Options:
--preview-name <name> Preview name (default: the current CI or Git branch)
--mode <mode> Vite mode to build and deploy in (default: production)
--skip-build Deploy existing Preview Build Output without rebuilding
--vite-config <path> Vite config file to build with (default: vite.config.*)
-h, --help Show this help

Examples:
vinext-cloudflare previews deploy
vinext-cloudflare previews deploy pr-123
vinext-cloudflare previews deploy pr-123 --mode staging
vinext-cloudflare previews deploy pr-123 --skip-build
vinext-cloudflare previews deploy --preview-name pr-123
vinext-cloudflare previews deploy --preview-name pr-123 --mode staging
vinext-cloudflare previews deploy --preview-name pr-123 --skip-build
`;
}

Expand Down
2 changes: 1 addition & 1 deletion packages/cloudflare/src/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -723,7 +723,7 @@ export function buildCfDeployArgs(
const mode = options.env || (options.preview ? "preview" : undefined);
const isPreviewDeploy = options.target?.type === "preview";
const args = isPreviewDeploy ? ["previews", "deploy"] : ["deploy"];
if (isPreviewDeploy && options.target?.name) args.push(options.target.name);
if (isPreviewDeploy && options.target?.name) args.push("--preview-name", options.target.name);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ WARNING · Code Quality

The pinned cf (1.0.0-beta.1) and the open cf: "*" peer range still allow cf versions that reject --preview-name, so named Preview deploys fail with a raw yargs error.

cf is yargs-strict, so cf versions before cloudflare/cf#519 fail on this flag with Unknown argument: preview-name. That includes the catalog pin cf: 1.0.0-beta.1 (pnpm-workspace.yaml:117). Today that breaks the Worker Preview deploy in CI. After release, it breaks previews deploy --preview-name for any user on an older cf, because the cf peer range in packages/cloudflare/package.json is "*". Before merging, bump the cloudflare-vite-v2 catalog to the cf release that includes #519, and raise the peer range minimum to that release so incompatible installs are caught at install time.

args.push("--prebuilt");
if (mode) args.push("--mode", validateWranglerEnvName(mode));
return { args, mode };
Expand Down
11 changes: 8 additions & 3 deletions packages/cloudflare/src/previews-deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,23 @@ export function parsePreviewsDeployArgs(args: string[]) {
options: {
help: { type: "boolean", short: "h", default: false },
mode: { type: "string" },
"preview-name": { type: "string" },
"skip-build": { type: "boolean", default: false },
"vite-config": { type: "string" },
},
});

if (positionals.length > 1) {
throw new Error("Expected at most one Preview name: previews deploy [preview-name].");
// Like `cf previews deploy`, the Preview name is a flag, not a positional argument.
if (positionals.length > 0) {
throw new Error(
`Unexpected argument: ${positionals[0]}. Pass the Preview name with --preview-name <name>.`,
);
}

const previewName = values["preview-name"];
return {
help: values.help,
name: positionals[0] === undefined ? undefined : validatePreviewName(positionals[0]),
name: previewName === undefined ? undefined : validatePreviewName(previewName),
mode: values.mode === undefined ? undefined : validateMode(values.mode),
skipBuild: values["skip-build"],
viteConfig: values["vite-config"]?.trim() || undefined,
Expand Down
2 changes: 2 additions & 0 deletions tests/deploy-prerender-config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,7 @@ describe("deploy prerender config wiring", () => {
expect.stringContaining(path.join("cf", "bin", "cf")),
"previews",
"deploy",
"--preview-name",
"pr-123",
"--prebuilt",
"--mode",
Expand Down Expand Up @@ -451,6 +452,7 @@ describe("deploy prerender config wiring", () => {
expect.any(String),
"previews",
"deploy",
"--preview-name",
"pr-123",
"--prebuilt",
"--mode",
Expand Down
39 changes: 31 additions & 8 deletions tests/deploy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -626,7 +626,14 @@ describe("cf Build Output deployment", () => {

it.each([undefined, "pr-123"])("builds Preview deploy args (name: %s)", (name) => {
expect(buildCfDeployArgs({ env: "preview", target: { type: "preview", name } })).toEqual({
args: ["previews", "deploy", ...(name ? [name] : []), "--prebuilt", "--mode", "preview"],
args: [
"previews",
"deploy",
...(name ? ["--preview-name", name] : []),
"--prebuilt",
"--mode",
"preview",
],
mode: "preview",
});
});
Expand Down Expand Up @@ -656,7 +663,16 @@ describe("cf Build Output deployment", () => {
expect(invocations).toEqual([
[
process.execPath,
[resolveCfBin(tmpDir), "previews", "deploy", "main", "--prebuilt", "--mode", "preview"],
[
resolveCfBin(tmpDir),
"previews",
"deploy",
"--preview-name",
"main",
"--prebuilt",
"--mode",
"preview",
],
{ cwd: tmpDir, stdio: ["inherit", "pipe", "pipe"], shell: false },
],
]);
Expand Down Expand Up @@ -816,14 +832,16 @@ describe("parseWorkerDeploymentUrl", () => {
// ─── Deploy CLI arg parsing ─────────────────────────────────────────────────

describe("parsePreviewsDeployArgs", () => {
it("accepts an optional name, mode, skip-build, and help", () => {
it("accepts an optional Preview name, mode, skip-build, and help", () => {
expect(parsePreviewsDeployArgs([])).toEqual({
name: undefined,
mode: undefined,
skipBuild: false,
help: false,
});
expect(parsePreviewsDeployArgs(["pr-123", "--mode", "staging", "--skip-build"])).toEqual({
expect(
parsePreviewsDeployArgs(["--preview-name", "pr-123", "--mode", "staging", "--skip-build"]),
).toEqual({
name: "pr-123",
mode: "staging",
skipBuild: true,
Expand All @@ -847,10 +865,15 @@ describe("parsePreviewsDeployArgs", () => {
expect(() => parsePreviewsDeployArgs([option])).toThrow();
});

it("rejects multiple or invalid Preview names", () => {
expect(() => parsePreviewsDeployArgs(["one", "two"])).toThrow("at most one");
expect(() => parsePreviewsDeployArgs([" "])).toThrow("must not be empty");
expect(() => parsePreviewsDeployArgs(["pr\0name"])).toThrow("null bytes");
it("rejects a positional Preview name", () => {
expect(() => parsePreviewsDeployArgs(["pr-123"])).toThrow(
"Unexpected argument: pr-123. Pass the Preview name with --preview-name <name>.",
);
});

it("rejects invalid Preview names", () => {
expect(() => parsePreviewsDeployArgs(["--preview-name", " "])).toThrow("must not be empty");
expect(() => parsePreviewsDeployArgs(["--preview-name", "pr\0name"])).toThrow("null bytes");
});

it.each([["--mode="], ["--mode", " "]])("rejects an empty mode: %j", (...args) => {
Expand Down
Loading