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
5 changes: 5 additions & 0 deletions .changeset/dry-spies-lay.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"wrangler": minor
---

Added `pages deployment delete <deployment>` command
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ tools/deployment-status.json

# IntelliJ
.idea/
*.iml

# VSCode Theme
*.vsix
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { http, HttpResponse } from "msw";
import { endEventLoop } from "../helpers/end-event-loop";
import { mockAccountId, mockApiToken } from "../helpers/mock-account-id";
import { mockConsoleMethods } from "../helpers/mock-console";
import { msw } from "../helpers/msw";
import { runInTempDir } from "../helpers/run-in-tmp";
import { runWrangler } from "../helpers/run-wrangler";

const PROJECT_NAME = "images";
const DEPLOYMENT = "deployment";

describe("pages deployment delete", () => {
runInTempDir();
mockAccountId();
mockApiToken();
mockConsoleMethods();

afterEach(async () => {
await endEventLoop();
msw.resetHandlers();
msw.restoreHandlers();
});

it("should make request to delete deployment", async () => {
const requests = mockDeploymentDeleteRequest(DEPLOYMENT);
await runWrangler(
`pages deployment delete ${DEPLOYMENT} --project-name=${PROJECT_NAME}`
);
expect(requests.count).toBe(1);
});

it("should throw an error if deployment ID is missing", async () => {
await expect(
runWrangler(`pages deployment delete --project-name=${PROJECT_NAME}`)
).rejects.toThrow("Must specify a project name and deployment.");
});

it("should throw an error if project name is missing in non-interactive mode", async () => {
await expect(
runWrangler(`pages deployment delete ${DEPLOYMENT}`)
).rejects.toThrow("Must specify a project name in non-interactive mode.");
});
});

/* -------------------------------------------------- */
/* Helper Functions */
/* -------------------------------------------------- */

type RequestLogger = {
count: number;
queryParams: [string, string][][];
};

function mockDeploymentDeleteRequest(deployment: string): RequestLogger {
const requests: RequestLogger = { count: 0, queryParams: [] };
msw.use(
http.delete(
"*/accounts/:accountId/pages/projects/:project/deployments/:deployment",
({ request, params }) => {
requests.count++;
const url = new URL(request.url);
requests.queryParams.push(Array.from(url.searchParams.entries()));
expect(params.project).toEqual(PROJECT_NAME);
expect(params.accountId).toEqual("some-account-id");

return HttpResponse.json(
{
success: true,
errors: [],
messages: [],
result: deployment,
},
{ status: 200 }
);
},
{ once: true }
)
);
return requests;
}
9 changes: 5 additions & 4 deletions packages/wrangler/src/__tests__/pages/pages.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,12 @@ describe("pages", () => {
Interact with the deployments of a project

COMMANDS
wrangler pages deployment list List deployments in your Cloudflare Pages project
wrangler pages deployment create [directory] Deploy a directory of static assets as a Pages deployment
wrangler pages deployment list List deployments in your Cloudflare Pages project
wrangler pages deployment create [directory] Deploy a directory of static assets as a Pages deployment

Alias for \\"wrangler pages deploy\\".
wrangler pages deployment tail [deployment] Start a tailing session for a project's deployment and livestream logs from your Functions
Alias for \\"wrangler pages deploy\\".
wrangler pages deployment delete [deployment] Delete a Pages deployment
wrangler pages deployment tail [deployment] Start a tailing session for a project's deployment and livestream logs from your Functions

GLOBAL FLAGS
--cwd Run as if Wrangler was started in the specified directory instead of the current working directory [string]
Expand Down
5 changes: 5 additions & 0 deletions packages/wrangler/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ import {
} from "./pages";
import { pagesFunctionsBuildCommand } from "./pages/build";
import { pagesFunctionsBuildEnvCommand } from "./pages/build-env";
import { pagesDeploymentDeleteCommand } from "./pages/delete-deployment";
import {
pagesDeployCommand,
pagesDeploymentCreateCommand,
Expand Down Expand Up @@ -1153,6 +1154,10 @@ export function createCLIParser(argv: string[]) {
command: "wrangler pages deployment create",
definition: pagesDeploymentCreateCommand,
},
{
command: "wrangler pages deployment delete",
definition: pagesDeploymentDeleteCommand,
},
{
command: "wrangler pages deployment tail",
definition: pagesDeploymentTailCommand,
Expand Down
81 changes: 81 additions & 0 deletions packages/wrangler/src/pages/delete-deployment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { fetchResult } from "../cfetch";
import { getConfigCache } from "../config-cache";
import { createCommand } from "../core/create-command";
import { COMPLIANCE_REGION_CONFIG_PUBLIC } from "../environment-variables/misc-variables";
import { FatalError } from "../errors";
import isInteractive from "../is-interactive";
import { logger } from "../logger";
import { requireAuth } from "../user";
import { PAGES_CONFIG_CACHE_FILENAME } from "./constants";
import { promptSelectProject } from "./prompt-select-project";
import type { PagesConfigCache } from "./types";

export const pagesDeploymentDeleteCommand = createCommand({
metadata: {
description: "Delete a Pages deployment",
status: "stable",
owner: "Workers: Authoring and Testing",
hideGlobalFlags: ["config", "env"],
},
behaviour: {
provideConfig: false,
},
args: {
deployment: {
type: "string",
description: "The ID of the deployment you wish to delete",
},
"project-name": {
type: "string",
description:
"The name of the project you would like to delete the deployment from",
},
},
positionalArgs: ["deployment"],
async handler(args) {
if (args.config) {
throw new FatalError(
"Pages does not support custom paths for the Wrangler configuration file",
1
);
}

if (args.env) {
throw new FatalError(
"Pages does not support targeting an environment with the --env flag. Use the --branch flag to target your production or preview branch",
1
);
}

const configCache = getConfigCache<PagesConfigCache>(
PAGES_CONFIG_CACHE_FILENAME
);

const accountId = await requireAuth(configCache);

let projectName = args.projectName;

if (!projectName) {
if (isInteractive()) {
projectName = await promptSelectProject({ accountId });
} else {
throw new FatalError(
"Must specify a project name in non-interactive mode.",
1
);
}
}

if (!args.deployment || !projectName) {
throw new FatalError("Must specify a project name and deployment.", 1);
}

await fetchResult(
COMPLIANCE_REGION_CONFIG_PUBLIC,
`/accounts/${accountId}/pages/projects/${projectName}/deployments/${args.deployment}`,
{ method: "DELETE" }
);

logger.log(`Deployment ${args.deployment} was successfully deleted.`);
},
});
Loading