Skip to content

Commit

Permalink
fix: wrangler pages deployment (list|tail) env filtering (#7263)
Browse files Browse the repository at this point in the history
Adds the --environment flag to `wrangler pages deployment list`, which
should allow users to list deployments of a specific type. When the flag
it's not provided it will list the latest 25 deployments regardless of
type.

Additionally, makes sure we're listing the correct type of deployments
when attempting to tail.
  • Loading branch information
danielrs authored Nov 20, 2024
1 parent 97acf07 commit 1b80dec
Show file tree
Hide file tree
Showing 5 changed files with 214 additions and 21 deletions.
5 changes: 5 additions & 0 deletions .changeset/curly-rice-travel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"wrangler": minor
---

Fix wrangler pages deployment (list|tail) environment filtering.
116 changes: 112 additions & 4 deletions packages/wrangler/src/__tests__/pages/deployment-list.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,20 +47,128 @@ describe("pages deployment list", () => {

expect(requests.count).toBe(1);
});

it("should pass no environment", async () => {
const deployments: Deployment[] = [
{
id: "87bbc8fe-16be-45cd-81e0-63d722e82cdf",
url: "https://87bbc8fe.images.pages.dev",
environment: "preview",
created_on: "2021-11-17T14:52:26.133835Z",
latest_stage: {
ended_on: "2021-11-17T14:52:26.133835Z",
status: "success",
},
deployment_trigger: {
metadata: {
branch: "main",
commit_hash: "c7649364c4cb32ad4f65b530b9424e8be5bec9d6",
},
},
project_name: "images",
},
];

const requests = mockDeploymentListRequest(deployments);
await runWrangler("pages deployment list --project-name=images");
expect(requests.count).toBe(1);
expect(
requests.queryParams[0].find(([key, _]) => {
return key === "env";
})
).toBeUndefined();
});

it("should pass production environment with flag", async () => {
const deployments: Deployment[] = [
{
id: "87bbc8fe-16be-45cd-81e0-63d722e82cdf",
url: "https://87bbc8fe.images.pages.dev",
environment: "preview",
created_on: "2021-11-17T14:52:26.133835Z",
latest_stage: {
ended_on: "2021-11-17T14:52:26.133835Z",
status: "success",
},
deployment_trigger: {
metadata: {
branch: "main",
commit_hash: "c7649364c4cb32ad4f65b530b9424e8be5bec9d6",
},
},
project_name: "images",
},
];

const requests = mockDeploymentListRequest(deployments);
await runWrangler(
"pages deployment list --project-name=images --environment=production"
);
expect(requests.count).toBe(1);
expect(
requests.queryParams[0].find(([key, _]) => {
return key === "env";
})
).toStrictEqual(["env", "production"]);
});

it("should pass preview environment with flag", async () => {
const deployments: Deployment[] = [
{
id: "87bbc8fe-16be-45cd-81e0-63d722e82cdf",
url: "https://87bbc8fe.images.pages.dev",
environment: "preview",
created_on: "2021-11-17T14:52:26.133835Z",
latest_stage: {
ended_on: "2021-11-17T14:52:26.133835Z",
status: "success",
},
deployment_trigger: {
metadata: {
branch: "main",
commit_hash: "c7649364c4cb32ad4f65b530b9424e8be5bec9d6",
},
},
project_name: "images",
},
];

const requests = mockDeploymentListRequest(deployments);
await runWrangler(
"pages deployment list --project-name=images --environment=preview"
);
expect(requests.count).toBe(1);
expect(
requests.queryParams[0].find(([key, _]) => {
return key === "env";
})
).toStrictEqual(["env", "preview"]);
});
});

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

function mockDeploymentListRequest(deployments: unknown[]) {
const requests = { count: 0 };
/**
* A logger used to check how many times a mock API has been hit.
* Useful as a helper in our testing to check if wrangler is making
* the correct API calls without actually sending any web traffic.
*/
type RequestLogger = {
count: number;
queryParams: [string, string][][];
};

function mockDeploymentListRequest(deployments: unknown[]): RequestLogger {
const requests: RequestLogger = { count: 0, queryParams: [] };
msw.use(
http.get(
"*/accounts/:accountId/pages/projects/:project/deployments",
({ params }) => {
({ request, params }) => {
requests.count++;

const url = new URL(request.url);
requests.queryParams.push(Array.from(url.searchParams.entries()));
expect(params.project).toEqual("images");
expect(params.accountId).toEqual("some-account-id");

Expand Down
97 changes: 83 additions & 14 deletions packages/wrangler/src/__tests__/pages/pages-deployment-tail.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,63 @@ describe("pages deployment tail", () => {
);
await api.closeHelper();
});

it("passes default environment to deployments list", async () => {
api = mockTailAPIs();
expect(api.requests.creation.length).toStrictEqual(0);

await runWrangler(
"pages deployment tail --project-name mock-project mock-deployment-id"
);

await expect(api.ws.connected).resolves.toBeTruthy();
console.log(api.requests.deployments.queryParams[0]);
expect(api.requests.deployments.count).toStrictEqual(1);
expect(
api.requests.deployments.queryParams[0].find(([key, _]) => {
return key === "env";
})
).toStrictEqual(["env", "production"]);
await api.closeHelper();
});

it("passes production environment to deployments list", async () => {
api = mockTailAPIs();
expect(api.requests.creation.length).toStrictEqual(0);

await runWrangler(
"pages deployment tail --project-name mock-project mock-deployment-id --environment production"
);

await expect(api.ws.connected).resolves.toBeTruthy();
console.log(api.requests.deployments.queryParams[0]);
expect(api.requests.deployments.count).toStrictEqual(1);
expect(
api.requests.deployments.queryParams[0].find(([key, _]) => {
return key === "env";
})
).toStrictEqual(["env", "production"]);
await api.closeHelper();
});

it("passes preview environment to deployments list", async () => {
api = mockTailAPIs();
expect(api.requests.creation.length).toStrictEqual(0);

await runWrangler(
"pages deployment tail --project-name mock-project mock-deployment-id --environment preview"
);

await expect(api.ws.connected).resolves.toBeTruthy();
console.log(api.requests.deployments.queryParams[0]);
expect(api.requests.deployments.count).toStrictEqual(1);
expect(
api.requests.deployments.queryParams[0].find(([key, _]) => {
return key === "env";
})
).toStrictEqual(["env", "preview"]);
await api.closeHelper();
});
});

describe("filtering", () => {
Expand Down Expand Up @@ -783,7 +840,7 @@ function deserializeToJson(message: WebSocket.RawData): string {
*/
type MockAPI = {
requests: {
deployments: RequestCounter;
deployments: RequestLogger;
creation: RequestInit[];
deletion: RequestCounter;
};
Expand All @@ -792,17 +849,29 @@ type MockAPI = {
closeHelper: () => Promise<void>;
};

/**
* A logger used to check how many times a mock API has been hit.
* Useful as a helper in our testing to check if wrangler is making
* the correct API calls without actually sending any web traffic.
*/
type RequestLogger = {
count: number;
queryParams: [string, string][][];
};

/**
* Mock out the API hit during Tail creation
*
* @returns a `RequestCounter` for counting how many times the API is hit
*/
function mockListDeployments(): RequestCounter {
const requests: RequestCounter = { count: 0 };
function mockListDeployments(): RequestLogger {
const requests: RequestLogger = { count: 0, queryParams: [] };
msw.use(
http.get(
`*/accounts/:accountId/pages/projects/:projectName/deployments`,
() => {
({ request }) => {
const url = new URL(request.url);
requests.queryParams.push(Array.from(url.searchParams.entries()));
requests.count++;
return HttpResponse.json(
{
Expand Down Expand Up @@ -839,15 +908,6 @@ function mockListDeployments(): RequestCounter {
return requests;
}

/**
* A counter used to check how many times a mock API has been hit.
* Useful as a helper in our testing to check if wrangler is making
* the correct API calls without actually sending any web traffic
*/
type RequestCounter = {
count: number;
};

/**
* Mock out the API hit during Tail creation
*
Expand Down Expand Up @@ -911,6 +971,15 @@ const mockEmailEventTo = "[email protected]";
*/
const mockEmailEventSize = 45416;

/**
* A counter used to check how many times a mock API has been hit.
* Useful as a helper in our testing to check if wrangler is making
* the correct API calls without actually sending any web traffic
*/
type RequestCounter = {
count: number;
};

/**
* Mock out the API hit during Tail deletion
*
Expand Down Expand Up @@ -950,7 +1019,7 @@ function mockTailAPIs(): MockAPI {
requests: {
deletion: { count: 0 },
creation: [],
deployments: { count: 0 },
deployments: { count: 0, queryParams: [] },
},
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
ws: null!, // will be set in the `beforeEach()`.
Expand Down
4 changes: 3 additions & 1 deletion packages/wrangler/src/pages/deployment-tails.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,9 @@ export async function Handler({
}

const deployments: Array<Deployment> = await fetchResult(
`/accounts/${accountId}/pages/projects/${projectName}/deployments`
`/accounts/${accountId}/pages/projects/${projectName}/deployments`,
{},
new URLSearchParams({ env: environment })
);

const envDeployments = deployments.filter(
Expand Down
13 changes: 11 additions & 2 deletions packages/wrangler/src/pages/deployments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,15 @@ export function ListOptions(yargs: CommonYargsArgv) {
description:
"The name of the project you would like to list deployments for",
},
environment: {
type: "string",
choices: ["production", "preview"],
description: "Environment type to list deployments for",
},
});
}

export async function ListHandler({ projectName }: ListArgs) {
export async function ListHandler({ projectName, environment }: ListArgs) {
const config = getConfigCache<PagesConfigCache>(PAGES_CONFIG_CACHE_FILENAME);
const accountId = await requireAuth(config);

Expand All @@ -42,7 +47,11 @@ export async function ListHandler({ projectName }: ListArgs) {
}

const deployments: Array<Deployment> = await fetchResult(
`/accounts/${accountId}/pages/projects/${projectName}/deployments`
`/accounts/${accountId}/pages/projects/${projectName}/deployments`,
{},
environment
? new URLSearchParams({ env: environment })
: new URLSearchParams({})
);

const titleCase = (word: string) =>
Expand Down

0 comments on commit 1b80dec

Please sign in to comment.