From 1b80decfaf56c8782e49dad685c344288629b668 Mon Sep 17 00:00:00 2001 From: Daniel Rivas <1887507+danielrs@users.noreply.github.com> Date: Wed, 20 Nov 2024 04:54:34 -0600 Subject: [PATCH] fix: wrangler pages deployment (list|tail) env filtering (#7263) 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. --- .changeset/curly-rice-travel.md | 5 + .../__tests__/pages/deployment-list.test.ts | 116 +++++++++++++++++- .../pages/pages-deployment-tail.test.ts | 97 ++++++++++++--- .../wrangler/src/pages/deployment-tails.ts | 4 +- packages/wrangler/src/pages/deployments.ts | 13 +- 5 files changed, 214 insertions(+), 21 deletions(-) create mode 100644 .changeset/curly-rice-travel.md diff --git a/.changeset/curly-rice-travel.md b/.changeset/curly-rice-travel.md new file mode 100644 index 000000000000..05a806c0117f --- /dev/null +++ b/.changeset/curly-rice-travel.md @@ -0,0 +1,5 @@ +--- +"wrangler": minor +--- + +Fix wrangler pages deployment (list|tail) environment filtering. diff --git a/packages/wrangler/src/__tests__/pages/deployment-list.test.ts b/packages/wrangler/src/__tests__/pages/deployment-list.test.ts index 828e2ad00ca2..8d86f743288a 100644 --- a/packages/wrangler/src/__tests__/pages/deployment-list.test.ts +++ b/packages/wrangler/src/__tests__/pages/deployment-list.test.ts @@ -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"); diff --git a/packages/wrangler/src/__tests__/pages/pages-deployment-tail.test.ts b/packages/wrangler/src/__tests__/pages/pages-deployment-tail.test.ts index f293c051ac33..344792b252f7 100644 --- a/packages/wrangler/src/__tests__/pages/pages-deployment-tail.test.ts +++ b/packages/wrangler/src/__tests__/pages/pages-deployment-tail.test.ts @@ -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", () => { @@ -783,7 +840,7 @@ function deserializeToJson(message: WebSocket.RawData): string { */ type MockAPI = { requests: { - deployments: RequestCounter; + deployments: RequestLogger; creation: RequestInit[]; deletion: RequestCounter; }; @@ -792,17 +849,29 @@ type MockAPI = { closeHelper: () => Promise; }; +/** + * 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( { @@ -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 * @@ -911,6 +971,15 @@ const mockEmailEventTo = "to@example.com"; */ 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 * @@ -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()`. diff --git a/packages/wrangler/src/pages/deployment-tails.ts b/packages/wrangler/src/pages/deployment-tails.ts index 96e2a9646302..9e0e9c0cdc57 100644 --- a/packages/wrangler/src/pages/deployment-tails.ts +++ b/packages/wrangler/src/pages/deployment-tails.ts @@ -163,7 +163,9 @@ export async function Handler({ } const deployments: Array = await fetchResult( - `/accounts/${accountId}/pages/projects/${projectName}/deployments` + `/accounts/${accountId}/pages/projects/${projectName}/deployments`, + {}, + new URLSearchParams({ env: environment }) ); const envDeployments = deployments.filter( diff --git a/packages/wrangler/src/pages/deployments.ts b/packages/wrangler/src/pages/deployments.ts index 2de7612ab9f2..6547d8ae1970 100644 --- a/packages/wrangler/src/pages/deployments.ts +++ b/packages/wrangler/src/pages/deployments.ts @@ -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(PAGES_CONFIG_CACHE_FILENAME); const accountId = await requireAuth(config); @@ -42,7 +47,11 @@ export async function ListHandler({ projectName }: ListArgs) { } const deployments: Array = 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) =>