From 7a7e8eeaf9b6c015f5815fc11a5f91327073f6e7 Mon Sep 17 00:00:00 2001 From: Rahul Sethi <5822355+RamIdeas@users.noreply.github.com> Date: Mon, 11 Mar 2024 17:43:11 +0000 Subject: [PATCH 01/14] refactor renderLabelledValues to return a formatted string instead of writing it directly to stdout this will allow for nested alignment --- .../__tests__/helpers/collect-cli-output.ts | 21 +++++ .../versions/versions.deploy.test.ts | 82 ++++++++--------- .../__tests__/versions/versions.list.test.ts | 30 +++---- .../__tests__/versions/versions.view.test.ts | 90 +++---------------- .../src/utils/render-labelled-values.ts | 81 +++++++++++++---- packages/wrangler/src/versions/deploy.ts | 6 +- packages/wrangler/src/versions/list.ts | 19 ++-- packages/wrangler/src/versions/view.ts | 19 ++-- 8 files changed, 175 insertions(+), 173 deletions(-) create mode 100644 packages/wrangler/src/__tests__/helpers/collect-cli-output.ts diff --git a/packages/wrangler/src/__tests__/helpers/collect-cli-output.ts b/packages/wrangler/src/__tests__/helpers/collect-cli-output.ts new file mode 100644 index 000000000000..fe9449a1c566 --- /dev/null +++ b/packages/wrangler/src/__tests__/helpers/collect-cli-output.ts @@ -0,0 +1,21 @@ +import { stderr, stdout } from "@cloudflare/cli/streams"; + +export function collectCLIOutput() { + const std = { out: "", err: "" }; + const onStdOutData = (chunk: Buffer) => (std.out += chunk.toString()); + const onStdErrData = (chunk: Buffer) => (std.err += chunk.toString()); + + beforeEach(() => { + stdout.on("data", onStdOutData); + stderr.on("data", onStdErrData); + }); + + afterEach(() => { + stdout.off("data", onStdOutData); + stderr.off("data", onStdErrData); + std.out = ""; + std.err = ""; + }); + + return std; +} diff --git a/packages/wrangler/src/__tests__/versions/versions.deploy.test.ts b/packages/wrangler/src/__tests__/versions/versions.deploy.test.ts index 276ba0ba17b2..18a2c6918b28 100644 --- a/packages/wrangler/src/__tests__/versions/versions.deploy.test.ts +++ b/packages/wrangler/src/__tests__/versions/versions.deploy.test.ts @@ -71,12 +71,12 @@ describe("versions deploy", () => { ├ Your current deployment has 2 version(s): │ │ (10%) 00000000-0000-0000-0000-000000000000 - │ Created: 1/1/2021, TIMESTAMP AM + │ Created: TIMESTAMP │ Tag: - │ Message: - │ │ (90%) 00000000-0000-0000-0000-000000000000 - │ Created: 1/1/2021, TIMESTAMP AM + │ Created: TIMESTAMP │ Tag: - │ Message: - │ @@ -85,7 +85,7 @@ describe("versions deploy", () => { ├ 1 Worker Version(s) selected │ ├ Worker Version 1: 00000000-0000-0000-0000-000000000000 - │ Created: 1/4/2021, TIMESTAMP AM + │ Created: TIMESTAMP │ Tag: - │ Message: - │ @@ -130,12 +130,12 @@ describe("versions deploy", () => { ├ Your current deployment has 2 version(s): │ │ (10%) 00000000-0000-0000-0000-000000000000 - │ Created: 1/4/2021, TIMESTAMP AM + │ Created: TIMESTAMP │ Tag: - │ Message: - │ │ (90%) 00000000-0000-0000-0000-000000000000 - │ Created: 2/3/2021, TIMESTAMP AM + │ Created: TIMESTAMP │ Tag: - │ Message: - │ @@ -160,12 +160,12 @@ describe("versions deploy", () => { ├ Your current deployment has 2 version(s): │ │ (10%) 00000000-0000-0000-0000-000000000000 - │ Created: 1/4/2021, TIMESTAMP AM + │ Created: TIMESTAMP │ Tag: - │ Message: - │ │ (90%) 00000000-0000-0000-0000-000000000000 - │ Created: 2/3/2021, TIMESTAMP AM + │ Created: TIMESTAMP │ Tag: - │ Message: - │ @@ -174,7 +174,7 @@ describe("versions deploy", () => { ├ 1 Worker Version(s) selected │ ├ Worker Version 1: 00000000-0000-0000-0000-000000000000 - │ Created: 1/4/2021, TIMESTAMP AM + │ Created: TIMESTAMP │ Tag: - │ Message: - │ @@ -203,12 +203,12 @@ describe("versions deploy", () => { ├ Your current deployment has 2 version(s): │ │ (10%) 00000000-0000-0000-0000-000000000000 - │ Created: 1/4/2021, TIMESTAMP AM + │ Created: TIMESTAMP │ Tag: - │ Message: - │ │ (90%) 00000000-0000-0000-0000-000000000000 - │ Created: 2/3/2021, TIMESTAMP AM + │ Created: TIMESTAMP │ Tag: - │ Message: - │ @@ -217,7 +217,7 @@ describe("versions deploy", () => { ├ 1 Worker Version(s) selected │ ├ Worker Version 1: 00000000-0000-0000-0000-000000000000 - │ Created: 1/4/2021, TIMESTAMP AM + │ Created: TIMESTAMP │ Tag: - │ Message: - │ @@ -246,12 +246,12 @@ describe("versions deploy", () => { ├ Your current deployment has 2 version(s): │ │ (10%) 00000000-0000-0000-0000-000000000000 - │ Created: 1/4/2021, TIMESTAMP AM + │ Created: TIMESTAMP │ Tag: - │ Message: - │ │ (90%) 00000000-0000-0000-0000-000000000000 - │ Created: 2/3/2021, TIMESTAMP AM + │ Created: TIMESTAMP │ Tag: - │ Message: - │ @@ -260,12 +260,12 @@ describe("versions deploy", () => { ├ 2 Worker Version(s) selected │ ├ Worker Version 1: 00000000-0000-0000-0000-000000000000 - │ Created: 1/4/2021, TIMESTAMP AM + │ Created: TIMESTAMP │ Tag: - │ Message: - │ ├ Worker Version 2: 00000000-0000-0000-0000-000000000000 - │ Created: 2/3/2021, TIMESTAMP AM + │ Created: TIMESTAMP │ Tag: - │ Message: - │ @@ -297,12 +297,12 @@ describe("versions deploy", () => { ├ Your current deployment has 2 version(s): │ │ (10%) 00000000-0000-0000-0000-000000000000 - │ Created: 1/4/2021, TIMESTAMP AM + │ Created: TIMESTAMP │ Tag: - │ Message: - │ │ (90%) 00000000-0000-0000-0000-000000000000 - │ Created: 2/3/2021, TIMESTAMP AM + │ Created: TIMESTAMP │ Tag: - │ Message: - │ @@ -311,7 +311,7 @@ describe("versions deploy", () => { ├ 1 Worker Version(s) selected │ ├ Worker Version 1: 00000000-0000-0000-0000-000000000000 - │ Created: 1/4/2021, TIMESTAMP AM + │ Created: TIMESTAMP │ Tag: - │ Message: - │ @@ -340,12 +340,12 @@ describe("versions deploy", () => { ├ Your current deployment has 2 version(s): │ │ (10%) 00000000-0000-0000-0000-000000000000 - │ Created: 1/4/2021, TIMESTAMP AM + │ Created: TIMESTAMP │ Tag: - │ Message: - │ │ (90%) 00000000-0000-0000-0000-000000000000 - │ Created: 2/3/2021, TIMESTAMP AM + │ Created: TIMESTAMP │ Tag: - │ Message: - │ @@ -354,12 +354,12 @@ describe("versions deploy", () => { ├ 2 Worker Version(s) selected │ ├ Worker Version 1: 00000000-0000-0000-0000-000000000000 - │ Created: 1/4/2021, TIMESTAMP AM + │ Created: TIMESTAMP │ Tag: - │ Message: - │ ├ Worker Version 2: 00000000-0000-0000-0000-000000000000 - │ Created: 2/3/2021, TIMESTAMP AM + │ Created: TIMESTAMP │ Tag: - │ Message: - │ @@ -391,12 +391,12 @@ describe("versions deploy", () => { ├ Your current deployment has 2 version(s): │ │ (10%) 00000000-0000-0000-0000-000000000000 - │ Created: 1/4/2021, TIMESTAMP AM + │ Created: TIMESTAMP │ Tag: - │ Message: - │ │ (90%) 00000000-0000-0000-0000-000000000000 - │ Created: 2/3/2021, TIMESTAMP AM + │ Created: TIMESTAMP │ Tag: - │ Message: - │ @@ -405,12 +405,12 @@ describe("versions deploy", () => { ├ 2 Worker Version(s) selected │ ├ Worker Version 1: 00000000-0000-0000-0000-000000000000 - │ Created: 1/4/2021, TIMESTAMP AM + │ Created: TIMESTAMP │ Tag: - │ Message: - │ ├ Worker Version 2: 00000000-0000-0000-0000-000000000000 - │ Created: 2/3/2021, TIMESTAMP AM + │ Created: TIMESTAMP │ Tag: - │ Message: - │ @@ -445,12 +445,12 @@ describe("versions deploy", () => { ├ Your current deployment has 2 version(s): │ │ (10%) 00000000-0000-0000-0000-000000000000 - │ Created: 1/4/2021, TIMESTAMP AM + │ Created: TIMESTAMP │ Tag: - │ Message: - │ │ (90%) 00000000-0000-0000-0000-000000000000 - │ Created: 2/3/2021, TIMESTAMP AM + │ Created: TIMESTAMP │ Tag: - │ Message: - │ @@ -459,17 +459,17 @@ describe("versions deploy", () => { ├ 3 Worker Version(s) selected │ ├ Worker Version 1: 00000000-0000-0000-0000-000000000000 - │ Created: 1/4/2021, TIMESTAMP AM + │ Created: TIMESTAMP │ Tag: - │ Message: - │ ├ Worker Version 2: 00000000-0000-0000-0000-000000000000 - │ Created: 2/3/2021, TIMESTAMP AM + │ Created: TIMESTAMP │ Tag: - │ Message: - │ ├ Worker Version 3: 00000000-0000-0000-0000-000000000000 - │ Created: 2/2/2021, TIMESTAMP AM + │ Created: TIMESTAMP │ Tag: - │ Message: Rolled back for this version │" @@ -490,12 +490,12 @@ describe("versions deploy", () => { ├ Your current deployment has 2 version(s): │ │ (10%) 00000000-0000-0000-0000-000000000000 - │ Created: 1/4/2021, TIMESTAMP AM + │ Created: TIMESTAMP │ Tag: - │ Message: - │ │ (90%) 00000000-0000-0000-0000-000000000000 - │ Created: 2/3/2021, TIMESTAMP AM + │ Created: TIMESTAMP │ Tag: - │ Message: - │ @@ -504,17 +504,17 @@ describe("versions deploy", () => { ├ 3 Worker Version(s) selected │ ├ Worker Version 1: 00000000-0000-0000-0000-000000000000 - │ Created: 1/4/2021, TIMESTAMP AM + │ Created: TIMESTAMP │ Tag: - │ Message: - │ ├ Worker Version 2: 00000000-0000-0000-0000-000000000000 - │ Created: 2/3/2021, TIMESTAMP AM + │ Created: TIMESTAMP │ Tag: - │ Message: - │ ├ Worker Version 3: 00000000-0000-0000-0000-000000000000 - │ Created: 2/2/2021, TIMESTAMP AM + │ Created: TIMESTAMP │ Tag: - │ Message: Rolled back for this version │ @@ -552,12 +552,12 @@ describe("versions deploy", () => { ├ Your current deployment has 2 version(s): │ │ (10%) 00000000-0000-0000-0000-000000000000 - │ Created: 1/4/2021, TIMESTAMP AM + │ Created: TIMESTAMP │ Tag: - │ Message: - │ │ (90%) 00000000-0000-0000-0000-000000000000 - │ Created: 2/3/2021, TIMESTAMP AM + │ Created: TIMESTAMP │ Tag: - │ Message: - │ @@ -566,7 +566,7 @@ describe("versions deploy", () => { ├ 1 Worker Version(s) selected │ ├ Worker Version 1: 00000000-0000-0000-0000-000000000000 - │ Created: 1/4/2021, TIMESTAMP AM + │ Created: TIMESTAMP │ Tag: - │ Message: - │ @@ -599,12 +599,12 @@ describe("versions deploy", () => { ├ Your current deployment has 2 version(s): │ │ (10%) 00000000-0000-0000-0000-000000000000 - │ Created: 1/4/2021, TIMESTAMP AM + │ Created: TIMESTAMP │ Tag: - │ Message: - │ │ (90%) 00000000-0000-0000-0000-000000000000 - │ Created: 2/3/2021, TIMESTAMP AM + │ Created: TIMESTAMP │ Tag: - │ Message: - │ diff --git a/packages/wrangler/src/__tests__/versions/versions.list.test.ts b/packages/wrangler/src/__tests__/versions/versions.list.test.ts index c9dd7250637f..0d6404ae0bf2 100644 --- a/packages/wrangler/src/__tests__/versions/versions.list.test.ts +++ b/packages/wrangler/src/__tests__/versions/versions.list.test.ts @@ -1,6 +1,6 @@ import { normalizeOutput } from "../../../e2e/helpers/normalize"; +import { collectCLIOutput } from "../helpers/collect-cli-output"; import { mockAccountId, mockApiToken } from "../helpers/mock-account-id"; -import { mockConsoleMethods } from "../helpers/mock-console"; import { msw, mswListVersions } from "../helpers/msw"; import { runInTempDir } from "../helpers/run-in-tmp"; import { runWrangler } from "../helpers/run-wrangler"; @@ -10,7 +10,7 @@ describe("versions list", () => { mockAccountId(); mockApiToken(); runInTempDir(); - const std = mockConsoleMethods(); + const std = collectCLIOutput(); beforeEach(() => { msw.use(mswListVersions); @@ -28,9 +28,7 @@ describe("versions list", () => { expect(std.out).toMatchInlineSnapshot(`""`); - expect(normalizeOutput(std.err)).toMatchInlineSnapshot( - `"X [ERROR] You need to provide a name when deploying a worker. Either pass it as a cli arg with \`--name \` or in your config file as \`name = \\"\\"\`"` - ); + expect(normalizeOutput(std.err)).toMatchInlineSnapshot(`""`); }); test("prints versions to stdout", async () => { @@ -42,28 +40,25 @@ describe("versions list", () => { expect(std.out).toMatchInlineSnapshot(` "Version ID: 40000000-0000-0000-0000-000000000000 - Created: 1/1/2021, 12:00:00 AM + Created: 2021-01-01T00:00:00.000Z Author: Jean-Luc-Picard@federation.org Source: Upload Tag: - Message: - - Version ID: 30000000-0000-0000-0000-000000000000 - Created: 2/2/2021, 12:00:00 AM + Created: 2021-02-02T00:00:00.000Z Author: Kathryn-Janeway@federation.org Source: Rollback Tag: - Message: Rolled back for this version - Version ID: 20000000-0000-0000-0000-000000000000 - Created: 2/3/2021, 12:00:00 AM + Created: 2021-02-03T00:00:00.000Z Author: Kathryn-Janeway@federation.org Source: Wrangler 🤠 Tag: - Message: - - Version ID: 10000000-0000-0000-0000-000000000000 - Created: 1/4/2021, 12:00:00 AM + Created: 2021-01-04T00:00:00.000Z Author: Jean-Luc-Picard@federation.org Source: Rollback Tag: - @@ -87,28 +82,25 @@ describe("versions list", () => { expect(std.out).toMatchInlineSnapshot(` "Version ID: 40000000-0000-0000-0000-000000000000 - Created: 1/1/2021, 12:00:00 AM + Created: 2021-01-01T00:00:00.000Z Author: Jean-Luc-Picard@federation.org Source: Upload Tag: - Message: - - Version ID: 30000000-0000-0000-0000-000000000000 - Created: 2/2/2021, 12:00:00 AM + Created: 2021-02-02T00:00:00.000Z Author: Kathryn-Janeway@federation.org Source: Rollback Tag: - Message: Rolled back for this version - Version ID: 20000000-0000-0000-0000-000000000000 - Created: 2/3/2021, 12:00:00 AM + Created: 2021-02-03T00:00:00.000Z Author: Kathryn-Janeway@federation.org Source: Wrangler 🤠 Tag: - Message: - - Version ID: 10000000-0000-0000-0000-000000000000 - Created: 1/4/2021, 12:00:00 AM + Created: 2021-01-04T00:00:00.000Z Author: Jean-Luc-Picard@federation.org Source: Rollback Tag: - diff --git a/packages/wrangler/src/__tests__/versions/versions.view.test.ts b/packages/wrangler/src/__tests__/versions/versions.view.test.ts index 05bb97cf2c99..3bbf8ddac2db 100644 --- a/packages/wrangler/src/__tests__/versions/versions.view.test.ts +++ b/packages/wrangler/src/__tests__/versions/versions.view.test.ts @@ -1,6 +1,6 @@ import { normalizeOutput } from "../../../e2e/helpers/normalize"; +import { collectCLIOutput } from "../helpers/collect-cli-output"; import { mockAccountId, mockApiToken } from "../helpers/mock-account-id"; -import { mockConsoleMethods } from "../helpers/mock-console"; import { msw, mswGetVersion } from "../helpers/msw"; import { runInTempDir } from "../helpers/run-in-tmp"; import { runWrangler } from "../helpers/run-wrangler"; @@ -10,7 +10,7 @@ describe("versions view", () => { mockAccountId(); mockApiToken(); runInTempDir(); - const std = mockConsoleMethods(); + const std = collectCLIOutput(); beforeEach(() => { msw.use(mswGetVersion); @@ -26,29 +26,9 @@ describe("versions view", () => { `[Error: Not enough non-option arguments: got 0, need at least 1]` ); - expect(std.out).toMatchInlineSnapshot(` - " - wrangler versions view - - View the details of a specific version of your Worker [beta] - - Positionals: - version-id The Worker Version ID to view [string] [required] - - Flags: - -j, --experimental-json-config Experimental: Support wrangler.json [boolean] - -c, --config Path to .toml configuration file [string] - -e, --env Environment to use for operations and .env files [string] - -h, --help Show help [boolean] - -v, --version Show version number [boolean] - - Options: - --name Name of the worker [string]" - `); + expect(std.out).toMatchInlineSnapshot(`""`); - expect(normalizeOutput(std.err)).toMatchInlineSnapshot( - `"X [ERROR] Not enough non-option arguments: got 0, need at least 1"` - ); + expect(normalizeOutput(std.err)).toMatchInlineSnapshot(`""`); }); test("fails with --name arg only", async () => { @@ -60,29 +40,9 @@ describe("versions view", () => { `[Error: Not enough non-option arguments: got 0, need at least 1]` ); - expect(std.out).toMatchInlineSnapshot(` - " - wrangler versions view - - View the details of a specific version of your Worker [beta] - - Positionals: - version-id The Worker Version ID to view [string] [required] - - Flags: - -j, --experimental-json-config Experimental: Support wrangler.json [boolean] - -c, --config Path to .toml configuration file [string] - -e, --env Environment to use for operations and .env files [string] - -h, --help Show help [boolean] - -v, --version Show version number [boolean] - - Options: - --name Name of the worker [string]" - `); + expect(std.out).toMatchInlineSnapshot(`""`); - expect(normalizeOutput(std.err)).toMatchInlineSnapshot( - `"X [ERROR] Not enough non-option arguments: got 0, need at least 1"` - ); + expect(normalizeOutput(std.err)).toMatchInlineSnapshot(`""`); }); test("fails with positional version-id arg only", async () => { @@ -96,9 +56,7 @@ describe("versions view", () => { expect(std.out).toMatchInlineSnapshot(`""`); - expect(normalizeOutput(std.err)).toMatchInlineSnapshot( - `"X [ERROR] You need to provide a name when deploying a worker. Either pass it as a cli arg with \`--name \` or in your config file as \`name = \\"\\"\`"` - ); + expect(normalizeOutput(std.err)).toMatchInlineSnapshot(`""`); }); test("succeeds with positional version-id arg and --name arg", async () => { @@ -110,7 +68,7 @@ describe("versions view", () => { expect(std.out).toMatchInlineSnapshot(` "Version ID: 10000000-0000-0000-0000-000000000000 - Created: 1/1/2021, 12:00:00 AM + Created: 2021-01-01T00:00:00.000Z Author: Jean-Luc-Picard@federation.org Source: Upload Tag: - @@ -134,29 +92,9 @@ describe("versions view", () => { `[Error: Not enough non-option arguments: got 0, need at least 1]` ); - expect(std.out).toMatchInlineSnapshot(` - " - wrangler versions view - - View the details of a specific version of your Worker [beta] - - Positionals: - version-id The Worker Version ID to view [string] [required] - - Flags: - -j, --experimental-json-config Experimental: Support wrangler.json [boolean] - -c, --config Path to .toml configuration file [string] - -e, --env Environment to use for operations and .env files [string] - -h, --help Show help [boolean] - -v, --version Show version number [boolean] - - Options: - --name Name of the worker [string]" - `); + expect(std.out).toMatchInlineSnapshot(`""`); - expect(normalizeOutput(std.err)).toMatchInlineSnapshot( - `"X [ERROR] Not enough non-option arguments: got 0, need at least 1"` - ); + expect(normalizeOutput(std.err)).toMatchInlineSnapshot(`""`); }); test("succeeds with positional version-id arg only", async () => { @@ -168,7 +106,7 @@ describe("versions view", () => { expect(std.out).toMatchInlineSnapshot(` "Version ID: 10000000-0000-0000-0000-000000000000 - Created: 1/1/2021, 12:00:00 AM + Created: 2021-01-01T00:00:00.000Z Author: Jean-Luc-Picard@federation.org Source: Upload Tag: - @@ -188,11 +126,7 @@ describe("versions view", () => { `[APIError: A request to the Cloudflare API (/accounts/some-account-id/workers/scripts/test-name/versions/ffffffff-ffff-ffff-ffff-ffffffffffff) failed.]` ); - expect(normalizeOutput(std.out)).toMatchInlineSnapshot(` - "X [ERROR] A request to the Cloudflare API (/accounts/some-account-id/workers/scripts/test-name/versions/00000000-0000-0000-0000-000000000000) failed. - If you think this is a bug, please open an issue at: - https://github.com/cloudflare/workers-sdk/issues/new/choose" - `); + expect(normalizeOutput(std.out)).toMatchInlineSnapshot(`""`); expect(normalizeOutput(std.err)).toMatchInlineSnapshot(`""`); }); diff --git a/packages/wrangler/src/utils/render-labelled-values.ts b/packages/wrangler/src/utils/render-labelled-values.ts index 68900e4a0b61..558146f8c92b 100644 --- a/packages/wrangler/src/utils/render-labelled-values.ts +++ b/packages/wrangler/src/utils/render-labelled-values.ts @@ -1,22 +1,71 @@ -import { logger } from "../logger"; +import { gray, white } from "@cloudflare/cli/colors"; +import stripAnsi from "strip-ansi"; -export default function renderLabelledValues( +type Options = { + /** Hook to format each label. This is a convenience option to avoid manually formatting each label. */ + formatLabel?: (label: string) => string; + /** Hook to format each value. This is a convenience option to avoid manually formatting each value. */ + formatValue?: (value: string) => string; + /** The number of spaces to add between the label and value. */ + spacerCount?: number; + /** The number of spaces to indent each line by. Useful for when nesting outputs of formatLabelledValues. */ + indentationCount?: number; + /** Used to pad the end of each label so the values are aligned. Automatically calculated based on longest label length without ANSI -- if formatting many items any/or the items have many values, set manually for a minor perf boost. */ + valuesAlignmentColumn?: number; + /** The string to use to separate each line. */ + lineSeparator?: string; + /** Controls whether the labels are aligned with left- or right-justification */ + labelJustification?: "left" | "right"; +}; + +/** + * Render a set of labelled values into a string with the values aligned + */ +export default function formatLabelledValues( view: Record, - { print = logger.log as (line: string) => unknown, spacerCount = 2 } = {} -) { - const alignment = - Math.max(...Object.keys(view).map((key) => key.length)) + spacerCount; - for (const [label, value] of Object.entries(view)) { - const paddedLabel = label.padEnd(alignment); - const alignedValue = value - ?.split("\n") - .map((line, lineNo) => - lineNo === 0 ? line : " ".repeat(alignment) + line - ) + { + formatLabel = (label) => white(label + ":"), + formatValue = (value) => gray(value), + spacerCount = 2, + indentationCount = 0, + valuesAlignmentColumn: valuesAlignment = Math.max( + ...Object.keys(view).map((label) => stripAnsi(formatLabel(label)).length) + ), + lineSeparator = "\n", + labelJustification = "left", + }: Options = {} +): string { + const labelLengthsWithoutANSI = Object.keys(view).map( + (label) => stripAnsi(formatLabel(label)).length + ); + + const formattedLines = Object.entries(view).map(([label, value], i) => { + const indentation = indentationCount ? " ".repeat(indentationCount) : ""; + const labelAlignment = + labelJustification === "left" + ? "" + : " ".repeat(valuesAlignment - labelLengthsWithoutANSI[i]); + const formattedAndAlignedLabel = labelAlignment + formatLabel(label); + const formattedAndAlignedMultilineValue = formatValue(value) + .split("\n") + .map((line, lineNo) => { + const prefixSpacing = " ".repeat( + lineNo === 0 + ? valuesAlignment + + spacerCount - + labelLengthsWithoutANSI[i] - + labelAlignment.length + : valuesAlignment + spacerCount + ); + + return prefixSpacing + line; + }) .join("\n"); - print(paddedLabel + alignedValue); - } + return ( + indentation + formattedAndAlignedLabel + formattedAndAlignedMultilineValue + ); + }); - print(""); + return formattedLines.join(lineSeparator); } diff --git a/packages/wrangler/src/versions/deploy.ts b/packages/wrangler/src/versions/deploy.ts index 85b65f7bf0dc..f348f726ccdd 100644 --- a/packages/wrangler/src/versions/deploy.ts +++ b/packages/wrangler/src/versions/deploy.ts @@ -248,7 +248,7 @@ async function printLatestDeployment(accountId: string, workerName: string) { cli.log( gray(` ${trafficString} ${versionIdString} - Created: ${version.created.toLocaleString()} + Created: ${version.created.toISOString()} Tag: ${version.tag ?? BLANK_INPUT} Message: ${version.message ?? BLANK_INPUT}`) ); @@ -299,7 +299,7 @@ async function promptVersionsToDeploy( value: version.id, label: version.id, sublabel: gray(` -${ZERO_WIDTH_SPACE} Created: ${version.created.toLocaleString()} +${ZERO_WIDTH_SPACE} Created: ${version.created.toISOString()} ${ZERO_WIDTH_SPACE} Tag: ${version.tag ?? BLANK_INPUT} ${ZERO_WIDTH_SPACE} Message: ${version.message ?? BLANK_INPUT} `), @@ -329,7 +329,7 @@ ${ZERO_WIDTH_SPACE} Message: ${version.message ?? BLANK_INPUT} return `${grayBar} ${leftT} ${white(` Worker Version ${i + 1}: `, version.id)} -${grayBar} ${gray(" Created: ", version.created.toLocaleString())} +${grayBar} ${gray(" Created: ", version.created.toISOString())} ${grayBar} ${gray(" Tag: ", version.tag ?? BLANK_INPUT)} ${grayBar} ${gray(" Message: ", version.message ?? BLANK_INPUT)}`; }); diff --git a/packages/wrangler/src/versions/list.ts b/packages/wrangler/src/versions/list.ts index e512cb89048f..369a9a84731c 100644 --- a/packages/wrangler/src/versions/list.ts +++ b/packages/wrangler/src/versions/list.ts @@ -1,11 +1,12 @@ import path from "path"; +import { logRaw } from "@cloudflare/cli"; import { fetchResult } from "../cfetch"; import { findWranglerToml, readConfig } from "../config"; import { UserError } from "../errors"; import * as metrics from "../metrics"; import { printWranglerBanner } from "../update-check"; import { requireAuth } from "../user"; -import renderLabelledValues from "../utils/render-labelled-values"; +import formatLabelledValues from "../utils/render-labelled-values"; import type { CommonYargsArgv, StrictYargsOptionsToInterface, @@ -71,14 +72,16 @@ export async function versionsListHandler(args: VersionsListArgs) { ); for (const version of versions) { - renderLabelledValues({ - "Version ID:": version.id, - "Created:": new Date(version.metadata["created_on"]).toLocaleString(), - "Author:": version.metadata.author_email, - "Source:": getSource(version), - "Tag:": version.annotations?.["workers/tag"] ?? BLANK_INPUT, - "Message:": version.annotations?.["workers/message"] ?? BLANK_INPUT, + const formattedVersion = formatLabelledValues({ + "Version ID": version.id, + Created: new Date(version.metadata["created_on"]).toLocaleString(), + Author: version.metadata.author_email, + Source: version.metadata.source, + Tag: version.annotations?.["workers/tag"] || BLANK_INPUT, + Message: version.annotations?.["workers/message"] || BLANK_INPUT, }); + + logRaw(formattedVersion); } } diff --git a/packages/wrangler/src/versions/view.ts b/packages/wrangler/src/versions/view.ts index 19e6597294dc..dd1bba6f6577 100644 --- a/packages/wrangler/src/versions/view.ts +++ b/packages/wrangler/src/versions/view.ts @@ -1,9 +1,10 @@ +import { logRaw } from "@cloudflare/cli"; import { fetchResult } from "../cfetch"; import { UserError } from "../errors"; import * as metrics from "../metrics"; import { printWranglerBanner } from "../update-check"; import { requireAuth } from "../user"; -import renderLabelledValues from "../utils/render-labelled-values"; +import formatLabelledValues from "../utils/render-labelled-values"; import { getConfig, getSource } from "./list"; import type { CommonYargsArgv, @@ -76,12 +77,14 @@ export async function versionsViewHandler(args: VersionsViewArgs) { `/accounts/${accountId}/workers/scripts/${workerName}/versions/${args.versionId}` ); - renderLabelledValues({ - "Version ID:": version.id, - "Created:": new Date(version.metadata["created_on"]).toLocaleString(), - "Author:": version.metadata.author_email, - "Source:": getSource(version), - "Tag:": version.annotations?.["workers/tag"] ?? BLANK_INPUT, - "Message:": version.annotations?.["workers/message"] ?? BLANK_INPUT, + const formattedVersion = formatLabelledValues({ + "Version ID": version.id, + Created: new Date(version.metadata["created_on"]).toISOString(), + Author: version.metadata.author_email, + Source: version.metadata.source, + Tag: version.annotations?.["workers/tag"] || BLANK_INPUT, + Message: version.annotations?.["workers/message"] || BLANK_INPUT, }); + + logRaw(formattedVersion); } From f2e94d60a216876d97f20c75c68444e4e8800264 Mon Sep 17 00:00:00 2001 From: Rahul Sethi <5822355+RamIdeas@users.noreply.github.com> Date: Mon, 11 Mar 2024 17:47:41 +0000 Subject: [PATCH 02/14] chore: reuse types across all versions handlers --- packages/wrangler/src/versions/deploy.ts | 179 ++++------------------ packages/wrangler/src/versions/list.ts | 23 +-- packages/wrangler/src/versions/types.d.ts | 39 +++++ packages/wrangler/src/versions/view.ts | 23 +-- 4 files changed, 70 insertions(+), 194 deletions(-) create mode 100644 packages/wrangler/src/versions/types.d.ts diff --git a/packages/wrangler/src/versions/deploy.ts b/packages/wrangler/src/versions/deploy.ts index f348f726ccdd..40dd56c02350 100644 --- a/packages/wrangler/src/versions/deploy.ts +++ b/packages/wrangler/src/versions/deploy.ts @@ -14,6 +14,13 @@ import { UserError } from "../errors"; import * as metrics from "../metrics"; import { printWranglerBanner } from "../update-check"; import { requireAuth } from "../user"; +import { + ApiDeployment, + ApiVersion, + Percentage, + VersionId, + WorkerVersion, +} from "./types"; import type { CommonYargsArgv, StrictYargsOptionsToInterface, @@ -22,51 +29,13 @@ import type { const EPSILON = 0.001; // used to avoid floating-point errors. Comparions to a value +/- EPSILON will mean "roughly equals the value". const BLANK_INPUT = "-"; // To be used where optional user-input is displayed and the value is nullish const ZERO_WIDTH_SPACE = "\u200B"; // Some log lines get trimmed and so, to indent, the line is prefixed with a zero-width space -const VERSION_CACHE = new Map(); export type VersionsDeployArgs = StrictYargsOptionsToInterface< typeof versionsDeployOptions >; type OptionalPercentage = number | null; // null means automatically assign (evenly distribute remaining traffic) -type Percentage = number; -type UUID = string; -type VersionId = UUID; -type WorkerVersion = { - id: VersionId; - created: Date; - tag?: string; - message?: string; -}; -type ApiDeployment = { - id: string; - source: "api" | string; - strategy: "percentage" | string; - author_email: string; - annotations?: Record; - created_on: string; - versions: Array<{ - version_id: VersionId; - percentage: Percentage; - }>; -}; -type ApiVersion = { - id: VersionId; - number: number; - metadata: { - created_on: string; - modified_on: string; - source: "api" | string; - author_id: string; - author_email: string; - }; - annotations?: Record & { - "workers/triggered_by"?: "upload" | string; - "workers/message"?: string; - "workers/tag"?: string; - }; - // other properties not typed as not used -}; +type VersionCache = Map; export function versionsDeployOptions(yargs: CommonYargsArgv) { return yargs @@ -139,6 +108,7 @@ export async function versionsDeployHandler(args: VersionsDeployArgs) { ); } + const versionCache: VersionCache = new Map(); const optionalVersionTraffic = parseVersionSpecs(args); cli.startSection( @@ -147,13 +117,14 @@ export async function versionsDeployHandler(args: VersionsDeployArgs) { true ); - await printLatestDeployment(accountId, workerName); + await printLatestDeployment(accountId, workerName, versionCache); // prompt to confirm or change the versionIds from the args const confirmedVersionsToDeploy = await promptVersionsToDeploy( accountId, workerName, [...optionalVersionTraffic.keys()], + versionCache, args.yes ); @@ -229,11 +200,15 @@ function getConfig( return config; } -async function printLatestDeployment(accountId: string, workerName: string) { +async function printLatestDeployment( + accountId: string, + workerName: string, + versionCache: VersionCache +) { const [versions, traffic] = await spinnerWhile({ startMessage: "Fetching latest deployment", async promise() { - return fetchLatestDeploymentVersions(accountId, workerName); + return fetchLatestDeploymentVersions(accountId, workerName, versionCache); }, }); @@ -276,17 +251,23 @@ async function promptVersionsToDeploy( accountId: string, workerName: string, defaultSelectedVersionIds: VersionId[], + versionCache: VersionCache, yesFlag: boolean ): Promise { await spinnerWhile({ startMessage: "Fetching deployable versions", async promise() { - await fetchLatestUploadedVersions(accountId, workerName); - await fetchVersions(accountId, workerName, ...defaultSelectedVersionIds); + await fetchLatestUploadedVersions(accountId, workerName, versionCache); + await fetchVersions( + accountId, + workerName, + versionCache, + ...defaultSelectedVersionIds + ); }, }); - const selectableVersions = Array.from(VERSION_CACHE.values()).sort( + const selectableVersions = Array.from(versionCache.values()).sort( (a, b) => b.created.getTime() - a.created.getTime() ); @@ -322,7 +303,7 @@ ${ZERO_WIDTH_SPACE} Message: ${version.message ?? BLANK_INPUT} ); const versions = versionIds?.map((versionId, i) => { - const version = VERSION_CACHE.get(versionId); + const version = versionCache.get(versionId); // shouldn't be possible, but better a UserError than an assertion error if (version === undefined) throw new UserError("Invalid Version ID"); @@ -449,112 +430,6 @@ async function promptPercentages( // *********** // API // *********** - -async function fetchVersion( - accountId: string, - workerName: string, - versionId: VersionId -) { - const cachedVersion = VERSION_CACHE.get(versionId); - if (cachedVersion) return cachedVersion; - - const apiVersion = await fetchResult( - `/accounts/${accountId}/workers/scripts/${workerName}/versions/${versionId}` - ); - - const version = castAndCacheWorkerVersion(apiVersion); - - return version; -} -async function fetchVersions( - accountId: string, - workerName: string, - ...versionIds: VersionId[] -) { - return Promise.all( - versionIds.map((versionId) => - fetchVersion(accountId, workerName, versionId) - ) - ); -} -async function fetchLatestDeploymentVersions( - accountId: string, - workerName: string -): Promise<[WorkerVersion[], Map]> { - const { deployments } = await fetchResult<{ deployments: ApiDeployment[] }>( - `/accounts/${accountId}/workers/scripts/${workerName}/deployments` - ); - - const latestDeployment = deployments.at(0); - if (!latestDeployment) return [[], new Map()]; - - const versionTraffic = new Map( - latestDeployment.versions.map(({ version_id: versionId, percentage }) => [ - versionId, - percentage, - ]) - ); - const versions = await fetchVersions( - accountId, - workerName, - ...versionTraffic.keys() - ); - - return [versions, versionTraffic]; -} -async function fetchLatestUploadedVersions( - accountId: string, - workerName: string -): Promise { - const { items } = await fetchResult<{ items: ApiVersion[] }>( - `/accounts/${accountId}/workers/scripts/${workerName}/versions` - ); - - const versions = items.map(castAndCacheWorkerVersion); - - return versions; -} -function castAndCacheWorkerVersion(apiVersion: ApiVersion) { - const version: WorkerVersion = { - id: apiVersion.id, - created: new Date(apiVersion.metadata.created_on), - message: apiVersion.annotations?.["workers/message"], - tag: apiVersion.annotations?.["workers/tag"], - }; - - VERSION_CACHE.set(version.id, version); - - return version; -} -async function createDeployment( - accountId: string, - workerName: string, - versionTraffic: Map, - message: string | undefined -) { - const res = await fetchResult( - `/accounts/${accountId}/workers/scripts/${workerName}/deployments`, - { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ - strategy: "percentage", - versions: Array.from(versionTraffic).map( - ([version_id, percentage]) => ({ version_id, percentage }) - ), - annotations: { - "workers/triggered_by": "deployment", - "workers/message": message, - }, - }), - } - ); - - // TODO: handle specific errors - - return res; -} - // *********** // UNITS // *********** diff --git a/packages/wrangler/src/versions/list.ts b/packages/wrangler/src/versions/list.ts index 369a9a84731c..2f76b76d11a7 100644 --- a/packages/wrangler/src/versions/list.ts +++ b/packages/wrangler/src/versions/list.ts @@ -7,6 +7,7 @@ import * as metrics from "../metrics"; import { printWranglerBanner } from "../update-check"; import { requireAuth } from "../user"; import formatLabelledValues from "../utils/render-labelled-values"; +import { ApiVersion } from "./types"; import type { CommonYargsArgv, StrictYargsOptionsToInterface, @@ -18,26 +19,6 @@ export type VersionsListArgs = StrictYargsOptionsToInterface< typeof versionsListOptions >; -type UUID = string; -type VersionId = UUID; -type ApiVersion = { - id: VersionId; - number: number; - metadata: { - created_on: string; - modified_on: string; - source: "api" | string; - author_id: string; - author_email: string; - }; - annotations?: { - "workers/triggered_by"?: "upload" | string; - "workers/message"?: string; - "workers/tag"?: string; - }; - // other properties not typed as not used -}; - export function versionsListOptions(yargs: CommonYargsArgv) { return yargs.option("name", { describe: "Name of the worker", @@ -74,7 +55,7 @@ export async function versionsListHandler(args: VersionsListArgs) { for (const version of versions) { const formattedVersion = formatLabelledValues({ "Version ID": version.id, - Created: new Date(version.metadata["created_on"]).toLocaleString(), + Created: new Date(version.metadata["created_on"]).toISOString(), Author: version.metadata.author_email, Source: version.metadata.source, Tag: version.annotations?.["workers/tag"] || BLANK_INPUT, diff --git a/packages/wrangler/src/versions/types.d.ts b/packages/wrangler/src/versions/types.d.ts new file mode 100644 index 000000000000..5af6f0f09247 --- /dev/null +++ b/packages/wrangler/src/versions/types.d.ts @@ -0,0 +1,39 @@ + +export type Percentage = number; +export type UUID = string; +export type VersionId = UUID; +export type WorkerVersion = { + id: VersionId; + created: Date; + tag?: string; + message?: string; +}; +export type ApiDeployment = { + id: string; + source: "api" | string; + strategy: "percentage" | string; + author_email: string; + annotations?: Record; + created_on: string; + versions: Array<{ + version_id: VersionId; + percentage: Percentage; + }>; +}; +export type ApiVersion = { + id: VersionId; + number: number; + metadata: { + created_on: string; + modified_on: string; + source: "api" | string; + author_id: string; + author_email: string; + }; + annotations?: { + "workers/triggered_by"?: "upload" | string; + "workers/message"?: string; + "workers/tag"?: string; + }; + // other properties not typed as not used +}; \ No newline at end of file diff --git a/packages/wrangler/src/versions/view.ts b/packages/wrangler/src/versions/view.ts index dd1bba6f6577..a38b27714235 100644 --- a/packages/wrangler/src/versions/view.ts +++ b/packages/wrangler/src/versions/view.ts @@ -5,7 +5,8 @@ import * as metrics from "../metrics"; import { printWranglerBanner } from "../update-check"; import { requireAuth } from "../user"; import formatLabelledValues from "../utils/render-labelled-values"; -import { getConfig, getSource } from "./list"; +import { getConfig } from "./list"; +import { ApiVersion } from "./types"; import type { CommonYargsArgv, StrictYargsOptionsToInterface, @@ -17,26 +18,6 @@ export type VersionsViewArgs = StrictYargsOptionsToInterface< typeof versionsViewOptions >; -type UUID = string; -type VersionId = UUID; -type ApiVersion = { - id: VersionId; - number: number; - metadata: { - created_on: string; - modified_on: string; - source: "api" | string; - author_id: string; - author_email: string; - }; - annotations?: Record & { - "workers/triggered_by"?: "upload" | string; - "workers/message"?: string; - "workers/tag"?: string; - }; - // other properties not typed as not used -}; - export function versionsViewOptions(yargs: CommonYargsArgv) { return yargs .positional("version-id", { From eeddf248055342f5dbf538a56b07b9794f59afd1 Mon Sep 17 00:00:00 2001 From: Rahul Sethi <5822355+RamIdeas@users.noreply.github.com> Date: Mon, 11 Mar 2024 17:55:43 +0000 Subject: [PATCH 03/14] implement versions deployment commands --- packages/wrangler/src/index.ts | 105 ++++++++------- packages/wrangler/src/metrics/send-event.ts | 5 +- .../src/versions/deployments/index.ts | 27 ++++ .../wrangler/src/versions/deployments/list.ts | 120 +++++++++++++++++ .../src/versions/deployments/status.ts | 122 ++++++++++++++++++ 5 files changed, 332 insertions(+), 47 deletions(-) create mode 100644 packages/wrangler/src/versions/deployments/index.ts create mode 100644 packages/wrangler/src/versions/deployments/list.ts create mode 100644 packages/wrangler/src/versions/deployments/status.ts diff --git a/packages/wrangler/src/index.ts b/packages/wrangler/src/index.ts index c5925c5e517f..61b713adaa5b 100644 --- a/packages/wrangler/src/index.ts +++ b/packages/wrangler/src/index.ts @@ -67,6 +67,7 @@ import { } from "./user"; import { vectorize } from "./vectorize/index"; import registerVersionsSubcommands from "./versions"; +import registerVersionsDeploymentsSubcommands from "./versions/deployments"; import { whoami } from "./whoami"; import { asJson } from "./yargs-types"; import type { Config } from "./config"; @@ -175,6 +176,10 @@ export function demandOneOfOption(...options: string[]) { export class CommandLineArgsError extends UserError {} export function createCLIParser(argv: string[]) { + const experimentalGradualRollouts = argv.includes( + "--experimental-gradual-rollouts" + ); + // Type check result against CommonYargsOptions to make sure we've included // all common options const wrangler: CommonYargsArgv = makeCLI(argv) @@ -600,49 +605,60 @@ export function createCLIParser(argv: string[]) { //deployments const deploymentsWarning = "🚧`wrangler deployments` is a beta command. Please report any issues to https://github.com/cloudflare/workers-sdk/issues/new/choose"; - wrangler.command( - "deployments", - "🚢 List and view details for deployments", - (yargs) => - yargs - .option("name", { - describe: "The name of your worker", - type: "string", - }) - .command( - "list", - "🚢 Displays the 10 most recent deployments for a worker", - async (listYargs) => listYargs, - async (listYargs) => { - const { accountId, scriptName, config } = - await commonDeploymentCMDSetup(listYargs, deploymentsWarning); - await deployments(accountId, scriptName, config); - } - ) - .command( - "view [deployment-id]", - "🔍 View a deployment", - async (viewYargs) => - viewYargs.positional("deployment-id", { - describe: "The ID of the deployment you want to inspect", - type: "string", - demandOption: false, - }), - async (viewYargs) => { - const { accountId, scriptName, config } = - await commonDeploymentCMDSetup(viewYargs, deploymentsWarning); - - await viewDeployment( - accountId, - scriptName, - config, - viewYargs.deploymentId - ); - } - ) - .command(subHelp) - .epilogue(deploymentsWarning) - ); + if (experimentalGradualRollouts) { + wrangler + .command( + "deployments", + "List and view the current and past deployments for your Worker", + registerVersionsDeploymentsSubcommands + ) + .command(subHelp) + .epilogue(deploymentsWarning); + } else { + wrangler.command( + "deployments", + "🚢 List and view details for deployments", + (yargs) => + yargs + .option("name", { + describe: "The name of your worker", + type: "string", + }) + .command( + "list", + "🚢 Displays the 10 most recent deployments for a worker", + async (listYargs) => listYargs, + async (listYargs) => { + const { accountId, scriptName, config } = + await commonDeploymentCMDSetup(listYargs, deploymentsWarning); + await deployments(accountId, scriptName, config); + } + ) + .command( + "view [deployment-id]", + "🔍 View a deployment", + async (viewYargs) => + viewYargs.positional("deployment-id", { + describe: "The ID of the deployment you want to inspect", + type: "string", + demandOption: false, + }), + async (viewYargs) => { + const { accountId, scriptName, config } = + await commonDeploymentCMDSetup(viewYargs, deploymentsWarning); + + await viewDeployment( + accountId, + scriptName, + config, + viewYargs.deploymentId + ); + } + ) + .command(subHelp) + .epilogue(deploymentsWarning) + ); + } const rollbackWarning = "🚧`wrangler rollback` is a beta command. Please report any issues to https://github.com/cloudflare/workers-sdk/issues/new/choose"; @@ -702,9 +718,6 @@ export function createCLIParser(argv: string[]) { ); // versions - const experimentalGradualRollouts = argv.includes( - "--experimental-gradual-rollouts" - ); if (experimentalGradualRollouts) { wrangler.command("versions", false, registerVersionsSubcommands); } diff --git a/packages/wrangler/src/metrics/send-event.ts b/packages/wrangler/src/metrics/send-event.ts index 315be70d9a42..60228322c2e5 100644 --- a/packages/wrangler/src/metrics/send-event.ts +++ b/packages/wrangler/src/metrics/send-event.ts @@ -68,7 +68,10 @@ export type EventNames = | "upload worker version" | "deploy worker versions" | "view worker version" - | "list worker versions"; + | "list worker versions" + | "view versioned deployment" + | "view latest versioned deployment" + | "list versioned deployments"; /** * Send a metrics event, with no extra properties, to Cloudflare, if usage tracking is enabled. diff --git a/packages/wrangler/src/versions/deployments/index.ts b/packages/wrangler/src/versions/deployments/index.ts new file mode 100644 index 000000000000..ff31f59ca5c2 --- /dev/null +++ b/packages/wrangler/src/versions/deployments/index.ts @@ -0,0 +1,27 @@ +import { CommonYargsArgv } from "../../yargs-types"; +import { + versionsDeploymentsListHandler, + versionsDeploymentsListOptions, +} from "./list"; +import { + versionsDeploymentsStatusHandler, + versionsDeploymentsStatusOptions, +} from "./status"; + +export default function registerVersionsDeploymentsSubcommands( + versionDeploymentsYargs: CommonYargsArgv +) { + versionDeploymentsYargs + .command( + "list", + "Displays the 10 most recent deployments of your Worker [beta]", + versionsDeploymentsListOptions, + versionsDeploymentsListHandler + ) + .command( + "status", + "See the current state of your production [beta]", + versionsDeploymentsStatusOptions, + versionsDeploymentsStatusHandler + ); +} diff --git a/packages/wrangler/src/versions/deployments/list.ts b/packages/wrangler/src/versions/deployments/list.ts new file mode 100644 index 000000000000..afa9fa0ccd71 --- /dev/null +++ b/packages/wrangler/src/versions/deployments/list.ts @@ -0,0 +1,120 @@ +import assert from "assert"; +import path from "path"; +import { logRaw } from "@cloudflare/cli"; +import { brandColor, dim, gray, white } from "@cloudflare/cli/colors"; +import { fetchResult } from "../../cfetch"; +import { findWranglerToml, readConfig } from "../../config"; +import { UserError } from "../../errors"; +import * as metrics from "../../metrics"; +import { printWranglerBanner } from "../../update-check"; +import { requireAuth } from "../../user"; +import formatLabelledValues from "../../utils/render-labelled-values"; +import { ApiDeployment, ApiVersion } from "../types"; +import type { + CommonYargsArgv, + StrictYargsOptionsToInterface, +} from "../../yargs-types"; + +const BLANK_INPUT = "-"; // To be used where optional user-input is displayed and the value is nullish + +export type VersionsDeloymentsListArgs = StrictYargsOptionsToInterface< + typeof versionsDeploymentsListOptions +>; + +export function versionsDeploymentsListOptions(yargs: CommonYargsArgv) { + return yargs.option("name", { + describe: "Name of the worker", + type: "string", + requiresArg: true, + }); +} + +export async function versionsDeploymentsListHandler( + args: VersionsDeloymentsListArgs +) { + await printWranglerBanner(); + + const config = getConfig(args); + await metrics.sendMetricsEvent( + "list versioned deployments", + {}, + { + sendMetrics: config.send_metrics, + } + ); + + const accountId = await requireAuth(config); + const workerName = args.name ?? config.name; + + if (workerName === undefined) { + throw new UserError( + 'You need to provide a name when deploying a worker. Either pass it as a cli arg with `--name ` or in your config file as `name = ""`' + ); + } + + const { deployments } = await fetchResult<{ + deployments: ApiDeployment[]; + }>(`/accounts/${accountId}/workers/scripts/${workerName}/deployments`); + + const versionIds = deployments.flatMap((d) => + d.versions.map((v) => v.version_id) + ); + const versions = await Promise.all( + versionIds.map((versionId) => + fetchResult( + `/accounts/${accountId}/workers/scripts/${workerName}/versions/${versionId}` + ) + ) + ); + const versionsById = new Map( + versions.map((version) => [version.id, version]) + ); + + const formattedDeployments = deployments.map((deployment) => { + const formattedVersions = deployment.versions.map((traffic) => { + const version = versionsById.get(traffic.version_id); + assert(version); + + const percentage = brandColor(`(${traffic.percentage}%)`); + const details = formatLabelledValues( + { + Created: new Date(version.metadata["created_on"]).toISOString(), + Tag: version.annotations?.["workers/tag"] || BLANK_INPUT, + Message: version.annotations?.["workers/message"] || BLANK_INPUT, + }, + { + indentationCount: 4, + labelJustification: "right", + formatLabel: (label) => gray(label + ":"), + formatValue: (value) => gray(value), + } + ); + + return `${percentage} ${version.id}\n${details}`; + }); + + return formatLabelledValues({ + // explicitly not outputting Deployment ID + Created: new Date(deployment.created_on).toISOString(), + Author: deployment.author_email, + Source: deployment.source, + Message: deployment.annotations?.["workers/message"] || BLANK_INPUT, + "Version(s)": formattedVersions.join("\n\n"), + }); + }); + + logRaw(formattedDeployments.join("\n\n")); +} + +function getConfig( + args: Pick< + VersionsDeloymentsListArgs, + "config" | "name" | "experimentalJsonConfig" + > +) { + const configPath = + args.config || (args.name && findWranglerToml(path.dirname(args.name))); + const config = readConfig(configPath, args); + + return config; +} diff --git a/packages/wrangler/src/versions/deployments/status.ts b/packages/wrangler/src/versions/deployments/status.ts new file mode 100644 index 000000000000..141fcf5f69cf --- /dev/null +++ b/packages/wrangler/src/versions/deployments/status.ts @@ -0,0 +1,122 @@ +import assert from "assert"; +import path from "path"; +import { logRaw } from "@cloudflare/cli"; +import { brandColor, dim, gray, white } from "@cloudflare/cli/colors"; +import { fetchResult } from "../../cfetch"; +import { findWranglerToml, readConfig } from "../../config"; +import { UserError } from "../../errors"; +import * as metrics from "../../metrics"; +import { printWranglerBanner } from "../../update-check"; +import { requireAuth } from "../../user"; +import formatLabelledValues from "../../utils/render-labelled-values"; +import { ApiDeployment, ApiVersion } from "../types"; +import type { + CommonYargsArgv, + StrictYargsOptionsToInterface, +} from "../../yargs-types"; + +const BLANK_INPUT = "-"; // To be used where optional user-input is displayed and the value is nullish + +export type VersionsDeploymentsStatusArgs = StrictYargsOptionsToInterface< + typeof versionsDeploymentsStatusOptions +>; + +export function versionsDeploymentsStatusOptions(yargs: CommonYargsArgv) { + return yargs.option("name", { + describe: "Name of the worker", + type: "string", + requiresArg: true, + }); +} + +export async function versionsDeploymentsStatusHandler( + args: VersionsDeploymentsStatusArgs +) { + await printWranglerBanner(); + + const config = getConfig(args); + await metrics.sendMetricsEvent( + "view latest versioned deployment", + {}, + { + sendMetrics: config.send_metrics, + } + ); + + const accountId = await requireAuth(config); + const workerName = args.name ?? config.name; + + if (workerName === undefined) { + throw new UserError( + 'You need to provide a name when deploying a worker. Either pass it as a cli arg with `--name ` or in your config file as `name = ""`' + ); + } + + const { deployments } = await fetchResult<{ + deployments: ApiDeployment[]; + }>(`/accounts/${accountId}/workers/scripts/${workerName}/deployments`); + + const latestDeployment = deployments.at(0); + + if (!latestDeployment) { + throw new UserError(`The worker ${workerName} has no deployments.`); + } + + const versionIds = latestDeployment.versions.map((v) => v.version_id); + const versions = await Promise.all( + versionIds.map((versionId) => + fetchResult( + `/accounts/${accountId}/workers/scripts/${workerName}/versions/${versionId}` + ) + ) + ); + const versionsById = new Map( + versions.map((version) => [version.id, version]) + ); + + const formattedVersions = latestDeployment.versions.map((traffic) => { + const version = versionsById.get(traffic.version_id); + assert(version); + + const percentage = brandColor(`(${traffic.percentage}%)`); + const details = formatLabelledValues( + { + Created: new Date(version.metadata["created_on"]).toISOString(), + Tag: version.annotations?.["workers/tag"] || BLANK_INPUT, + Message: version.annotations?.["workers/message"] || BLANK_INPUT, + }, + { + indentationCount: 4, + labelJustification: "right", + formatLabel: (label) => gray(label + ":"), + formatValue: (value) => gray(value), + } + ); + + return `${percentage} ${version.id}\n${details}`; + }); + + const formattedDeployment = formatLabelledValues({ + // explicitly not outputting Deployment ID + Created: new Date(latestDeployment.created_on).toISOString(), + Author: latestDeployment.author_email, + Source: latestDeployment.source, + Message: latestDeployment.annotations?.["workers/message"] || BLANK_INPUT, + "Version(s)": formattedVersions.join("\n\n"), + }); + + logRaw(formattedDeployment); +} + +function getConfig( + args: Pick< + VersionsDeploymentsStatusArgs, + "config" | "name" | "experimentalJsonConfig" + > +) { + const configPath = + args.config || (args.name && findWranglerToml(path.dirname(args.name))); + const config = readConfig(configPath, args); + + return config; +} From 8760ebf59857195c2b3ef8c9fa88e28eca21d093 Mon Sep 17 00:00:00 2001 From: Rahul Sethi <5822355+RamIdeas@users.noreply.github.com> Date: Mon, 11 Mar 2024 18:04:13 +0000 Subject: [PATCH 04/14] add tests for versioned deployments commands --- .../deployments/deployments.list.test.ts | 181 ++++++++++++++++++ .../deployments/deployments.status.test.ts | 97 ++++++++++ packages/wrangler/src/deployments.ts | 5 + 3 files changed, 283 insertions(+) create mode 100644 packages/wrangler/src/__tests__/versions/deployments/deployments.list.test.ts create mode 100644 packages/wrangler/src/__tests__/versions/deployments/deployments.status.test.ts diff --git a/packages/wrangler/src/__tests__/versions/deployments/deployments.list.test.ts b/packages/wrangler/src/__tests__/versions/deployments/deployments.list.test.ts new file mode 100644 index 000000000000..eaef5f64ff72 --- /dev/null +++ b/packages/wrangler/src/__tests__/versions/deployments/deployments.list.test.ts @@ -0,0 +1,181 @@ +import { normalizeOutput } from "../../../../e2e/helpers/normalize"; +import { collectCLIOutput } from "../../helpers/collect-cli-output"; +import { mockAccountId, mockApiToken } from "../../helpers/mock-account-id"; +import { + msw, + mswGetVersion, + mswListNewDeployments, + mswListVersions, +} from "../../helpers/msw"; +import { runInTempDir } from "../../helpers/run-in-tmp"; +import { runWrangler } from "../../helpers/run-wrangler"; +import writeWranglerToml from "../../helpers/write-wrangler-toml"; + +describe("deployments list", () => { + mockAccountId(); + mockApiToken(); + runInTempDir(); + const std = collectCLIOutput(); + + beforeEach(() => { + msw.use(mswListNewDeployments, mswGetVersion); + }); + + describe("without wrangler.toml", () => { + test("fails with no args", async () => { + const result = runWrangler( + "deployments list --experimental-gradual-rollouts" + ); + + await expect(result).rejects.toMatchInlineSnapshot( + `[Error: You need to provide a name when deploying a worker. Either pass it as a cli arg with \`--name \` or in your config file as \`name = ""\`]` + ); + + expect(std.out).toMatchInlineSnapshot(`""`); + + expect(normalizeOutput(std.err)).toMatchInlineSnapshot(`""`); + }); + + test("prints deployments to stdout", async () => { + const result = runWrangler( + "deployments list --name test-name --experimental-gradual-rollouts" + ); + + await expect(result).resolves.toBeUndefined(); + + expect(std.out).toMatchInlineSnapshot(` + "Created: 2021-01-04T00:00:00.000Z + Author: Jean-Luc-Picard@federation.org + Source: api + Message: - + Version(s): (10%) 10000000-0000-0000-0000-000000000000 + Created: 2021-01-01T00:00:00.000Z + Tag: - + Message: - + + (90%) 20000000-0000-0000-0000-000000000000 + Created: 2021-01-01T00:00:00.000Z + Tag: - + Message: - + + Created: 2021-01-01T00:00:00.000Z + Author: Jean-Luc-Picard@federation.org + Source: wrangler + Message: - + Version(s): (20%) 10000000-0000-0000-0000-000000000000 + Created: 2021-01-01T00:00:00.000Z + Tag: - + Message: - + + (80%) 20000000-0000-0000-0000-000000000000 + Created: 2021-01-01T00:00:00.000Z + Tag: - + Message: - + + Created: 2021-02-02T00:00:00.000Z + Author: Kathryn-Janeway@federation.org + Source: wrangler + Message: Rolled back for this version + Version(s): (30%) 10000000-0000-0000-0000-000000000000 + Created: 2021-01-01T00:00:00.000Z + Tag: - + Message: - + + (70%) 20000000-0000-0000-0000-000000000000 + Created: 2021-01-01T00:00:00.000Z + Tag: - + Message: - + + Created: 2021-02-03T00:00:00.000Z + Author: Kathryn-Janeway@federation.org + Source: wrangler + Message: - + Version(s): (40%) 10000000-0000-0000-0000-000000000000 + Created: 2021-01-01T00:00:00.000Z + Tag: - + Message: - + + (60%) 20000000-0000-0000-0000-000000000000 + Created: 2021-01-01T00:00:00.000Z + Tag: - + Message: - + " + `); + + expect(std.err).toMatchInlineSnapshot(`""`); + }); + }); + + describe("with wrangler.toml", () => { + beforeEach(writeWranglerToml); + + test("prints deployments to stdout", async () => { + const result = runWrangler( + "deployments list --experimental-gradual-rollouts" + ); + + await expect(result).resolves.toBeUndefined(); + + expect(std.out).toMatchInlineSnapshot(` + "Created: 2021-01-04T00:00:00.000Z + Author: Jean-Luc-Picard@federation.org + Source: api + Message: - + Version(s): (10%) 10000000-0000-0000-0000-000000000000 + Created: 2021-01-01T00:00:00.000Z + Tag: - + Message: - + + (90%) 20000000-0000-0000-0000-000000000000 + Created: 2021-01-01T00:00:00.000Z + Tag: - + Message: - + + Created: 2021-01-01T00:00:00.000Z + Author: Jean-Luc-Picard@federation.org + Source: wrangler + Message: - + Version(s): (20%) 10000000-0000-0000-0000-000000000000 + Created: 2021-01-01T00:00:00.000Z + Tag: - + Message: - + + (80%) 20000000-0000-0000-0000-000000000000 + Created: 2021-01-01T00:00:00.000Z + Tag: - + Message: - + + Created: 2021-02-02T00:00:00.000Z + Author: Kathryn-Janeway@federation.org + Source: wrangler + Message: Rolled back for this version + Version(s): (30%) 10000000-0000-0000-0000-000000000000 + Created: 2021-01-01T00:00:00.000Z + Tag: - + Message: - + + (70%) 20000000-0000-0000-0000-000000000000 + Created: 2021-01-01T00:00:00.000Z + Tag: - + Message: - + + Created: 2021-02-03T00:00:00.000Z + Author: Kathryn-Janeway@federation.org + Source: wrangler + Message: - + Version(s): (40%) 10000000-0000-0000-0000-000000000000 + Created: 2021-01-01T00:00:00.000Z + Tag: - + Message: - + + (60%) 20000000-0000-0000-0000-000000000000 + Created: 2021-01-01T00:00:00.000Z + Tag: - + Message: - + " + `); + + expect(std.err).toMatchInlineSnapshot(`""`); + }); + }); +}); diff --git a/packages/wrangler/src/__tests__/versions/deployments/deployments.status.test.ts b/packages/wrangler/src/__tests__/versions/deployments/deployments.status.test.ts new file mode 100644 index 000000000000..20cc475c776e --- /dev/null +++ b/packages/wrangler/src/__tests__/versions/deployments/deployments.status.test.ts @@ -0,0 +1,97 @@ +import { normalizeOutput } from "../../../../e2e/helpers/normalize"; +import { collectCLIOutput } from "../../helpers/collect-cli-output"; +import { mockAccountId, mockApiToken } from "../../helpers/mock-account-id"; +import { + msw, + mswGetVersion, + mswListNewDeployments, + mswListVersions, +} from "../../helpers/msw"; +import { runInTempDir } from "../../helpers/run-in-tmp"; +import { runWrangler } from "../../helpers/run-wrangler"; +import writeWranglerToml from "../../helpers/write-wrangler-toml"; + +describe("deployments list", () => { + mockAccountId(); + mockApiToken(); + runInTempDir(); + const std = collectCLIOutput(); + + beforeEach(() => { + msw.use(mswListNewDeployments, mswGetVersion); + }); + + describe("without wrangler.toml", () => { + test("fails with no args", async () => { + const result = runWrangler( + "deployments status --experimental-gradual-rollouts" + ); + + await expect(result).rejects.toMatchInlineSnapshot( + `[Error: You need to provide a name when deploying a worker. Either pass it as a cli arg with \`--name \` or in your config file as \`name = ""\`]` + ); + + expect(std.out).toMatchInlineSnapshot(`""`); + + expect(normalizeOutput(std.err)).toMatchInlineSnapshot(`""`); + }); + + test("prints latest deployment to stdout", async () => { + const result = runWrangler( + "deployments status --name test-name --experimental-gradual-rollouts" + ); + + await expect(result).resolves.toBeUndefined(); + + expect(std.out).toMatchInlineSnapshot(` + "Created: 2021-01-04T00:00:00.000Z + Author: Jean-Luc-Picard@federation.org + Source: api + Message: - + Version(s): (10%) 10000000-0000-0000-0000-000000000000 + Created: 2021-01-01T00:00:00.000Z + Tag: - + Message: - + + (90%) 20000000-0000-0000-0000-000000000000 + Created: 2021-01-01T00:00:00.000Z + Tag: - + Message: - + " + `); + + expect(std.err).toMatchInlineSnapshot(`""`); + }); + }); + + describe("with wrangler.toml", () => { + beforeEach(writeWranglerToml); + + test("prints latest deployment to stdout", async () => { + const result = runWrangler( + "deployments status --experimental-gradual-rollouts" + ); + + await expect(result).resolves.toBeUndefined(); + + expect(std.out).toMatchInlineSnapshot(` + "Created: 2021-01-04T00:00:00.000Z + Author: Jean-Luc-Picard@federation.org + Source: api + Message: - + Version(s): (10%) 10000000-0000-0000-0000-000000000000 + Created: 2021-01-01T00:00:00.000Z + Tag: - + Message: - + + (90%) 20000000-0000-0000-0000-000000000000 + Created: 2021-01-01T00:00:00.000Z + Tag: - + Message: - + " + `); + + expect(std.err).toMatchInlineSnapshot(`""`); + }); + }); +}); diff --git a/packages/wrangler/src/deployments.ts b/packages/wrangler/src/deployments.ts index f5bc795d2819..9534cbadfcbe 100644 --- a/packages/wrangler/src/deployments.ts +++ b/packages/wrangler/src/deployments.ts @@ -55,6 +55,11 @@ export async function deployments( scriptName: string | undefined, { send_metrics: sendMetrics }: { send_metrics?: Config["send_metrics"] } = {} ) { + const versioned = await isUsingGradualRollouts({ + name: scriptName, + experimentalGradualRollouts: undefined, + }); + await metrics.sendMetricsEvent( "view deployments", { view: scriptName ? "single" : "all" }, From 00b4e1256b983e35a0bc47bc222d641162eab183 Mon Sep 17 00:00:00 2001 From: Rahul Sethi <5822355+RamIdeas@users.noreply.github.com> Date: Tue, 12 Mar 2024 20:34:49 +0000 Subject: [PATCH 05/14] translate source/triggered_by to user-friendly text in all versions/deployments commands --- packages/wrangler/src/versions/deployments/list.ts | 10 +++++++++- packages/wrangler/src/versions/deployments/status.ts | 3 ++- packages/wrangler/src/versions/list.ts | 4 ++-- packages/wrangler/src/versions/view.ts | 4 ++-- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/packages/wrangler/src/versions/deployments/list.ts b/packages/wrangler/src/versions/deployments/list.ts index afa9fa0ccd71..04e3310a92ed 100644 --- a/packages/wrangler/src/versions/deployments/list.ts +++ b/packages/wrangler/src/versions/deployments/list.ts @@ -9,6 +9,7 @@ import * as metrics from "../../metrics"; import { printWranglerBanner } from "../../update-check"; import { requireAuth } from "../../user"; import formatLabelledValues from "../../utils/render-labelled-values"; +import { getVersionSource } from "../list"; import { ApiDeployment, ApiVersion } from "../types"; import type { CommonYargsArgv, @@ -97,7 +98,7 @@ export async function versionsDeploymentsListHandler( // explicitly not outputting Deployment ID Created: new Date(deployment.created_on).toISOString(), Author: deployment.author_email, - Source: deployment.source, + Source: getDeploymentSource(deployment), Message: deployment.annotations?.["workers/message"] || BLANK_INPUT, "Version(s)": formattedVersions.join("\n\n"), }); @@ -118,3 +119,10 @@ function getConfig( return config; } + +export function getDeploymentSource(deployment: ApiDeployment) { + return getVersionSource({ + metadata: { source: deployment.source }, + annotations: deployment.annotations, + }); +} diff --git a/packages/wrangler/src/versions/deployments/status.ts b/packages/wrangler/src/versions/deployments/status.ts index 141fcf5f69cf..5be5230d8b51 100644 --- a/packages/wrangler/src/versions/deployments/status.ts +++ b/packages/wrangler/src/versions/deployments/status.ts @@ -10,6 +10,7 @@ import { printWranglerBanner } from "../../update-check"; import { requireAuth } from "../../user"; import formatLabelledValues from "../../utils/render-labelled-values"; import { ApiDeployment, ApiVersion } from "../types"; +import { getDeploymentSource } from "./list"; import type { CommonYargsArgv, StrictYargsOptionsToInterface, @@ -100,7 +101,7 @@ export async function versionsDeploymentsStatusHandler( // explicitly not outputting Deployment ID Created: new Date(latestDeployment.created_on).toISOString(), Author: latestDeployment.author_email, - Source: latestDeployment.source, + Source: getDeploymentSource(latestDeployment), Message: latestDeployment.annotations?.["workers/message"] || BLANK_INPUT, "Version(s)": formattedVersions.join("\n\n"), }); diff --git a/packages/wrangler/src/versions/list.ts b/packages/wrangler/src/versions/list.ts index 2f76b76d11a7..6e40d277730e 100644 --- a/packages/wrangler/src/versions/list.ts +++ b/packages/wrangler/src/versions/list.ts @@ -57,7 +57,7 @@ export async function versionsListHandler(args: VersionsListArgs) { "Version ID": version.id, Created: new Date(version.metadata["created_on"]).toISOString(), Author: version.metadata.author_email, - Source: version.metadata.source, + Source: getVersionSource(version), Tag: version.annotations?.["workers/tag"] || BLANK_INPUT, Message: version.annotations?.["workers/message"] || BLANK_INPUT, }); @@ -76,7 +76,7 @@ export function getConfig( return config; } -export function getSource(version: { +export function getVersionSource(version: { metadata: Pick; annotations?: Pick< NonNullable, diff --git a/packages/wrangler/src/versions/view.ts b/packages/wrangler/src/versions/view.ts index a38b27714235..18534e54c709 100644 --- a/packages/wrangler/src/versions/view.ts +++ b/packages/wrangler/src/versions/view.ts @@ -5,7 +5,7 @@ import * as metrics from "../metrics"; import { printWranglerBanner } from "../update-check"; import { requireAuth } from "../user"; import formatLabelledValues from "../utils/render-labelled-values"; -import { getConfig } from "./list"; +import { getConfig, getVersionSource } from "./list"; import { ApiVersion } from "./types"; import type { CommonYargsArgv, @@ -62,7 +62,7 @@ export async function versionsViewHandler(args: VersionsViewArgs) { "Version ID": version.id, Created: new Date(version.metadata["created_on"]).toISOString(), Author: version.metadata.author_email, - Source: version.metadata.source, + Source: getVersionSource(version), Tag: version.annotations?.["workers/tag"] || BLANK_INPUT, Message: version.annotations?.["workers/message"] || BLANK_INPUT, }); From f212644a2989b756415f192bdae2863bb1bd85e8 Mon Sep 17 00:00:00 2001 From: Rahul Sethi <5822355+RamIdeas@users.noreply.github.com> Date: Tue, 12 Mar 2024 20:46:47 +0000 Subject: [PATCH 06/14] include api data when translating an unknown source/trigger --- packages/wrangler/src/versions/list.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/wrangler/src/versions/list.ts b/packages/wrangler/src/versions/list.ts index 6e40d277730e..02f5fafcdb3b 100644 --- a/packages/wrangler/src/versions/list.ts +++ b/packages/wrangler/src/versions/list.ts @@ -99,7 +99,7 @@ export function formatSource(source: string): string { case "terraform": return "Terraform 🏗️"; default: - return "Other"; + return `Other (${source})`; } } export function formatTrigger(trigger: string): string { @@ -113,6 +113,6 @@ export function formatTrigger(trigger: string): string { case "promotion": return "Promotion"; default: - return "Unknown"; + return `Unknown (${trigger})`; } } From 5f6fe695728f2aef7cbdc7a1851b152a7b8da1d8 Mon Sep 17 00:00:00 2001 From: Rahul Sethi <5822355+RamIdeas@users.noreply.github.com> Date: Tue, 12 Mar 2024 20:51:36 +0000 Subject: [PATCH 07/14] change UserError to AssertionError --- packages/wrangler/src/versions/deploy.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/wrangler/src/versions/deploy.ts b/packages/wrangler/src/versions/deploy.ts index 40dd56c02350..d93e1b073217 100644 --- a/packages/wrangler/src/versions/deploy.ts +++ b/packages/wrangler/src/versions/deploy.ts @@ -304,9 +304,7 @@ ${ZERO_WIDTH_SPACE} Message: ${version.message ?? BLANK_INPUT} const versions = versionIds?.map((versionId, i) => { const version = versionCache.get(versionId); - - // shouldn't be possible, but better a UserError than an assertion error - if (version === undefined) throw new UserError("Invalid Version ID"); + assert(version); return `${grayBar} ${leftT} ${white(` Worker Version ${i + 1}: `, version.id)} From fb231464f625eb0e9ded03fe6bac2d2ad177faa9 Mon Sep 17 00:00:00 2001 From: Rahul Sethi <5822355+RamIdeas@users.noreply.github.com> Date: Tue, 12 Mar 2024 20:59:51 +0000 Subject: [PATCH 08/14] change error message when missing workerName --- packages/wrangler/src/versions/deploy.ts | 2 +- packages/wrangler/src/versions/deployments/list.ts | 2 +- packages/wrangler/src/versions/deployments/status.ts | 2 +- packages/wrangler/src/versions/list.ts | 2 +- packages/wrangler/src/versions/types.d.ts | 2 +- packages/wrangler/src/versions/view.ts | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/wrangler/src/versions/deploy.ts b/packages/wrangler/src/versions/deploy.ts index d93e1b073217..c3168becf9fd 100644 --- a/packages/wrangler/src/versions/deploy.ts +++ b/packages/wrangler/src/versions/deploy.ts @@ -104,7 +104,7 @@ export async function versionsDeployHandler(args: VersionsDeployArgs) { if (workerName === undefined) { throw new UserError( - 'You need to provide a name when deploying a worker. Either pass it as a cli arg with `--name ` or in your config file as `name = ""`' + 'You need to provide a name of your worker. Either pass it as a cli arg with `--name ` or in your config file as `name = ""`' ); } diff --git a/packages/wrangler/src/versions/deployments/list.ts b/packages/wrangler/src/versions/deployments/list.ts index 04e3310a92ed..5875ab65bc8f 100644 --- a/packages/wrangler/src/versions/deployments/list.ts +++ b/packages/wrangler/src/versions/deployments/list.ts @@ -49,7 +49,7 @@ export async function versionsDeploymentsListHandler( if (workerName === undefined) { throw new UserError( - 'You need to provide a name when deploying a worker. Either pass it as a cli arg with `--name ` or in your config file as `name = ""`' + 'You need to provide a name of your worker. Either pass it as a cli arg with `--name ` or in your config file as `name = ""`' ); } diff --git a/packages/wrangler/src/versions/deployments/status.ts b/packages/wrangler/src/versions/deployments/status.ts index 5be5230d8b51..430bb69c81c6 100644 --- a/packages/wrangler/src/versions/deployments/status.ts +++ b/packages/wrangler/src/versions/deployments/status.ts @@ -49,7 +49,7 @@ export async function versionsDeploymentsStatusHandler( if (workerName === undefined) { throw new UserError( - 'You need to provide a name when deploying a worker. Either pass it as a cli arg with `--name ` or in your config file as `name = ""`' + 'You need to provide a name of your worker. Either pass it as a cli arg with `--name ` or in your config file as `name = ""`' ); } diff --git a/packages/wrangler/src/versions/list.ts b/packages/wrangler/src/versions/list.ts index 02f5fafcdb3b..d44ea5a32a8a 100644 --- a/packages/wrangler/src/versions/list.ts +++ b/packages/wrangler/src/versions/list.ts @@ -44,7 +44,7 @@ export async function versionsListHandler(args: VersionsListArgs) { if (workerName === undefined) { throw new UserError( - 'You need to provide a name when deploying a worker. Either pass it as a cli arg with `--name ` or in your config file as `name = ""`' + 'You need to provide a name of your worker. Either pass it as a cli arg with `--name ` or in your config file as `name = ""`' ); } diff --git a/packages/wrangler/src/versions/types.d.ts b/packages/wrangler/src/versions/types.d.ts index 5af6f0f09247..b247d2291a0d 100644 --- a/packages/wrangler/src/versions/types.d.ts +++ b/packages/wrangler/src/versions/types.d.ts @@ -36,4 +36,4 @@ export type ApiVersion = { "workers/tag"?: string; }; // other properties not typed as not used -}; \ No newline at end of file +}; diff --git a/packages/wrangler/src/versions/view.ts b/packages/wrangler/src/versions/view.ts index 18534e54c709..db8ca5fb9ea3 100644 --- a/packages/wrangler/src/versions/view.ts +++ b/packages/wrangler/src/versions/view.ts @@ -50,7 +50,7 @@ export async function versionsViewHandler(args: VersionsViewArgs) { if (workerName === undefined) { throw new UserError( - 'You need to provide a name when deploying a worker. Either pass it as a cli arg with `--name ` or in your config file as `name = ""`' + 'You need to provide a name of your worker. Either pass it as a cli arg with `--name ` or in your config file as `name = ""`' ); } From fb3add9d760b421a5671c8d380a7144b3bdd387f Mon Sep 17 00:00:00 2001 From: Rahul Sethi <5822355+RamIdeas@users.noreply.github.com> Date: Tue, 12 Mar 2024 21:02:00 +0000 Subject: [PATCH 09/14] remove accidental commit --- packages/wrangler/src/deployments.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/packages/wrangler/src/deployments.ts b/packages/wrangler/src/deployments.ts index 9534cbadfcbe..f5bc795d2819 100644 --- a/packages/wrangler/src/deployments.ts +++ b/packages/wrangler/src/deployments.ts @@ -55,11 +55,6 @@ export async function deployments( scriptName: string | undefined, { send_metrics: sendMetrics }: { send_metrics?: Config["send_metrics"] } = {} ) { - const versioned = await isUsingGradualRollouts({ - name: scriptName, - experimentalGradualRollouts: undefined, - }); - await metrics.sendMetricsEvent( "view deployments", { view: scriptName ? "single" : "all" }, From ce45d06049a50a7e72586880e1c8375bba2a9210 Mon Sep 17 00:00:00 2001 From: Rahul Sethi <5822355+RamIdeas@users.noreply.github.com> Date: Tue, 12 Mar 2024 21:52:08 +0000 Subject: [PATCH 10/14] finish refactoring: abstract all api calls --- packages/wrangler/src/versions/api.ts | 128 ++++++++++++++++++ packages/wrangler/src/versions/deploy.ts | 46 ++++--- .../wrangler/src/versions/deployments/list.ts | 29 ++-- .../src/versions/deployments/status.ts | 26 +--- packages/wrangler/src/versions/list.ts | 11 +- packages/wrangler/src/versions/types.d.ts | 9 +- packages/wrangler/src/versions/view.ts | 7 +- 7 files changed, 184 insertions(+), 72 deletions(-) create mode 100644 packages/wrangler/src/versions/api.ts diff --git a/packages/wrangler/src/versions/api.ts b/packages/wrangler/src/versions/api.ts new file mode 100644 index 000000000000..2816d0aeb170 --- /dev/null +++ b/packages/wrangler/src/versions/api.ts @@ -0,0 +1,128 @@ +import { fetchResult } from "../cfetch"; +import { + ApiDeployment, + ApiVersion, + Percentage, + VersionCache, + VersionId, +} from "./types"; + +export async function fetchVersion( + accountId: string, + workerName: string, + versionId: VersionId, + versionCache?: VersionCache +) { + const cachedVersion = versionCache?.get(versionId); + if (cachedVersion) return cachedVersion; + + const version = await fetchResult( + `/accounts/${accountId}/workers/scripts/${workerName}/versions/${versionId}` + ); + + versionCache?.set(version.id, version); + + return version; +} + +export async function fetchVersions( + accountId: string, + workerName: string, + versionCache: VersionCache | undefined, + ...versionIds: VersionId[] +) { + return Promise.all( + versionIds.map((versionId) => + fetchVersion(accountId, workerName, versionId, versionCache) + ) + ); +} + +export async function fetchLatestDeployments( + accountId: string, + workerName: string +): Promise { + const { deployments } = await fetchResult<{ + deployments: ApiDeployment[]; + }>(`/accounts/${accountId}/workers/scripts/${workerName}/deployments`); + + return deployments; +} +export async function fetchLatestDeployment( + accountId: string, + workerName: string +): Promise { + const deployments = await fetchLatestDeployments(accountId, workerName); + + return deployments.at(0); +} + +export async function fetchLatestDeploymentVersions( + accountId: string, + workerName: string, + versionCache: VersionCache +): Promise<[ApiVersion[], Map]> { + const latestDeployment = await fetchLatestDeployment(accountId, workerName); + + if (!latestDeployment) return [[], new Map()]; + + const versionTraffic = new Map( + latestDeployment.versions.map(({ version_id: versionId, percentage }) => [ + versionId, + percentage, + ]) + ); + const versions = await fetchVersions( + accountId, + workerName, + versionCache, + ...versionTraffic.keys() + ); + + return [versions, versionTraffic]; +} + +export async function fetchLatestUploadedVersions( + accountId: string, + workerName: string, + versionCache: VersionCache +): Promise { + const { items: versions } = await fetchResult<{ items: ApiVersion[] }>( + `/accounts/${accountId}/workers/scripts/${workerName}/versions` + ); + + for (const version of versions) { + versionCache.set(version.id, version); + } + + return versions; +} + +export async function createDeployment( + accountId: string, + workerName: string, + versionTraffic: Map, + message: string | undefined +) { + const res = await fetchResult( + `/accounts/${accountId}/workers/scripts/${workerName}/deployments`, + { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + strategy: "percentage", + versions: Array.from(versionTraffic).map( + ([version_id, percentage]) => ({ version_id, percentage }) + ), + annotations: { + "workers/triggered_by": "deployment", + "workers/message": message, + }, + }), + } + ); + + // TODO: handle specific errors + + return res; +} diff --git a/packages/wrangler/src/versions/deploy.ts b/packages/wrangler/src/versions/deploy.ts index c3168becf9fd..f5a243ab9819 100644 --- a/packages/wrangler/src/versions/deploy.ts +++ b/packages/wrangler/src/versions/deploy.ts @@ -15,12 +15,12 @@ import * as metrics from "../metrics"; import { printWranglerBanner } from "../update-check"; import { requireAuth } from "../user"; import { - ApiDeployment, - ApiVersion, - Percentage, - VersionId, - WorkerVersion, -} from "./types"; + createDeployment, + fetchLatestDeploymentVersions, + fetchLatestUploadedVersions, + fetchVersions, +} from "./api"; +import { Percentage, VersionCache, VersionId } from "./types"; import type { CommonYargsArgv, StrictYargsOptionsToInterface, @@ -35,7 +35,6 @@ export type VersionsDeployArgs = StrictYargsOptionsToInterface< >; type OptionalPercentage = number | null; // null means automatically assign (evenly distribute remaining traffic) -type VersionCache = Map; export function versionsDeployOptions(yargs: CommonYargsArgv) { return yargs @@ -223,9 +222,9 @@ async function printLatestDeployment( cli.log( gray(` ${trafficString} ${versionIdString} - Created: ${version.created.toISOString()} - Tag: ${version.tag ?? BLANK_INPUT} - Message: ${version.message ?? BLANK_INPUT}`) + Created: ${version.metadata.created_on} + Tag: ${version.annotations?.["workers/tag"] ?? BLANK_INPUT} + Message: ${version.annotations?.["workers/message"] ?? BLANK_INPUT}`) ); } @@ -268,7 +267,7 @@ async function promptVersionsToDeploy( }); const selectableVersions = Array.from(versionCache.values()).sort( - (a, b) => b.created.getTime() - a.created.getTime() + (a, b) => b.metadata.created_on.localeCompare(a.metadata.created_on) // String#localeCompare should work because they are ISO strings ); const question = "Which version(s) do you want to deploy?"; @@ -280,9 +279,13 @@ async function promptVersionsToDeploy( value: version.id, label: version.id, sublabel: gray(` -${ZERO_WIDTH_SPACE} Created: ${version.created.toISOString()} -${ZERO_WIDTH_SPACE} Tag: ${version.tag ?? BLANK_INPUT} -${ZERO_WIDTH_SPACE} Message: ${version.message ?? BLANK_INPUT} +${ZERO_WIDTH_SPACE} Created: ${version.metadata.created_on} +${ZERO_WIDTH_SPACE} Tag: ${ + version.annotations?.["workers/tag"] ?? BLANK_INPUT + } +${ZERO_WIDTH_SPACE} Message: ${ + version.annotations?.["workers/message"] ?? BLANK_INPUT + } `), })), label: "", @@ -308,9 +311,15 @@ ${ZERO_WIDTH_SPACE} Message: ${version.message ?? BLANK_INPUT} return `${grayBar} ${leftT} ${white(` Worker Version ${i + 1}: `, version.id)} -${grayBar} ${gray(" Created: ", version.created.toISOString())} -${grayBar} ${gray(" Tag: ", version.tag ?? BLANK_INPUT)} -${grayBar} ${gray(" Message: ", version.message ?? BLANK_INPUT)}`; +${grayBar} ${gray(" Created: ", version.metadata.created_on)} +${grayBar} ${gray( + " Tag: ", + version.annotations?.["workers/tag"] ?? BLANK_INPUT + )} +${grayBar} ${gray( + " Message: ", + version.annotations?.["workers/message"] ?? BLANK_INPUT + )}`; }); return [ @@ -425,9 +434,6 @@ async function promptPercentages( return confirmedVersionTraffic; } -// *********** -// API -// *********** // *********** // UNITS // *********** diff --git a/packages/wrangler/src/versions/deployments/list.ts b/packages/wrangler/src/versions/deployments/list.ts index 5875ab65bc8f..da048edb5e25 100644 --- a/packages/wrangler/src/versions/deployments/list.ts +++ b/packages/wrangler/src/versions/deployments/list.ts @@ -1,16 +1,20 @@ import assert from "assert"; import path from "path"; import { logRaw } from "@cloudflare/cli"; -import { brandColor, dim, gray, white } from "@cloudflare/cli/colors"; -import { fetchResult } from "../../cfetch"; +import { brandColor, gray } from "@cloudflare/cli/colors"; import { findWranglerToml, readConfig } from "../../config"; import { UserError } from "../../errors"; import * as metrics from "../../metrics"; import { printWranglerBanner } from "../../update-check"; import { requireAuth } from "../../user"; import formatLabelledValues from "../../utils/render-labelled-values"; +import { + fetchLatestDeployment, + fetchLatestDeployments, + fetchVersions, +} from "../api"; import { getVersionSource } from "../list"; -import { ApiDeployment, ApiVersion } from "../types"; +import { ApiDeployment, VersionCache } from "../types"; import type { CommonYargsArgv, StrictYargsOptionsToInterface, @@ -53,27 +57,16 @@ export async function versionsDeploymentsListHandler( ); } - const { deployments } = await fetchResult<{ - deployments: ApiDeployment[]; - }>(`/accounts/${accountId}/workers/scripts/${workerName}/deployments`); - + const deployments = await fetchLatestDeployments(accountId, workerName); + const versionCache: VersionCache = new Map(); const versionIds = deployments.flatMap((d) => d.versions.map((v) => v.version_id) ); - const versions = await Promise.all( - versionIds.map((versionId) => - fetchResult( - `/accounts/${accountId}/workers/scripts/${workerName}/versions/${versionId}` - ) - ) - ); - const versionsById = new Map( - versions.map((version) => [version.id, version]) - ); + await fetchVersions(accountId, workerName, versionCache, ...versionIds); const formattedDeployments = deployments.map((deployment) => { const formattedVersions = deployment.versions.map((traffic) => { - const version = versionsById.get(traffic.version_id); + const version = versionCache.get(traffic.version_id); assert(version); const percentage = brandColor(`(${traffic.percentage}%)`); diff --git a/packages/wrangler/src/versions/deployments/status.ts b/packages/wrangler/src/versions/deployments/status.ts index 430bb69c81c6..0b0a1a0fd2e9 100644 --- a/packages/wrangler/src/versions/deployments/status.ts +++ b/packages/wrangler/src/versions/deployments/status.ts @@ -1,15 +1,15 @@ import assert from "assert"; import path from "path"; import { logRaw } from "@cloudflare/cli"; -import { brandColor, dim, gray, white } from "@cloudflare/cli/colors"; -import { fetchResult } from "../../cfetch"; +import { brandColor, gray } from "@cloudflare/cli/colors"; import { findWranglerToml, readConfig } from "../../config"; import { UserError } from "../../errors"; import * as metrics from "../../metrics"; import { printWranglerBanner } from "../../update-check"; import { requireAuth } from "../../user"; import formatLabelledValues from "../../utils/render-labelled-values"; -import { ApiDeployment, ApiVersion } from "../types"; +import { fetchLatestDeployment, fetchVersions } from "../api"; +import { VersionCache } from "../types"; import { getDeploymentSource } from "./list"; import type { CommonYargsArgv, @@ -53,30 +53,18 @@ export async function versionsDeploymentsStatusHandler( ); } - const { deployments } = await fetchResult<{ - deployments: ApiDeployment[]; - }>(`/accounts/${accountId}/workers/scripts/${workerName}/deployments`); - - const latestDeployment = deployments.at(0); + const latestDeployment = await fetchLatestDeployment(accountId, workerName); if (!latestDeployment) { throw new UserError(`The worker ${workerName} has no deployments.`); } + const versionCache: VersionCache = new Map(); const versionIds = latestDeployment.versions.map((v) => v.version_id); - const versions = await Promise.all( - versionIds.map((versionId) => - fetchResult( - `/accounts/${accountId}/workers/scripts/${workerName}/versions/${versionId}` - ) - ) - ); - const versionsById = new Map( - versions.map((version) => [version.id, version]) - ); + await fetchVersions(accountId, workerName, versionCache, ...versionIds); const formattedVersions = latestDeployment.versions.map((traffic) => { - const version = versionsById.get(traffic.version_id); + const version = versionCache.get(traffic.version_id); assert(version); const percentage = brandColor(`(${traffic.percentage}%)`); diff --git a/packages/wrangler/src/versions/list.ts b/packages/wrangler/src/versions/list.ts index d44ea5a32a8a..93f5126facfb 100644 --- a/packages/wrangler/src/versions/list.ts +++ b/packages/wrangler/src/versions/list.ts @@ -1,13 +1,13 @@ import path from "path"; import { logRaw } from "@cloudflare/cli"; -import { fetchResult } from "../cfetch"; import { findWranglerToml, readConfig } from "../config"; import { UserError } from "../errors"; import * as metrics from "../metrics"; import { printWranglerBanner } from "../update-check"; import { requireAuth } from "../user"; import formatLabelledValues from "../utils/render-labelled-values"; -import { ApiVersion } from "./types"; +import { fetchLatestUploadedVersions } from "./api"; +import { ApiVersion, VersionCache } from "./types"; import type { CommonYargsArgv, StrictYargsOptionsToInterface, @@ -48,8 +48,11 @@ export async function versionsListHandler(args: VersionsListArgs) { ); } - const { items: versions } = await fetchResult<{ items: ApiVersion[] }>( - `/accounts/${accountId}/workers/scripts/${workerName}/versions` + const versionCache: VersionCache = new Map(); + const versions = await fetchLatestUploadedVersions( + accountId, + workerName, + versionCache ); for (const version of versions) { diff --git a/packages/wrangler/src/versions/types.d.ts b/packages/wrangler/src/versions/types.d.ts index b247d2291a0d..ea2aa122dc63 100644 --- a/packages/wrangler/src/versions/types.d.ts +++ b/packages/wrangler/src/versions/types.d.ts @@ -2,12 +2,7 @@ export type Percentage = number; export type UUID = string; export type VersionId = UUID; -export type WorkerVersion = { - id: VersionId; - created: Date; - tag?: string; - message?: string; -}; + export type ApiDeployment = { id: string; source: "api" | string; @@ -37,3 +32,5 @@ export type ApiVersion = { }; // other properties not typed as not used }; + +type VersionCache = Map; diff --git a/packages/wrangler/src/versions/view.ts b/packages/wrangler/src/versions/view.ts index db8ca5fb9ea3..de4c85598f8c 100644 --- a/packages/wrangler/src/versions/view.ts +++ b/packages/wrangler/src/versions/view.ts @@ -1,12 +1,11 @@ import { logRaw } from "@cloudflare/cli"; -import { fetchResult } from "../cfetch"; import { UserError } from "../errors"; import * as metrics from "../metrics"; import { printWranglerBanner } from "../update-check"; import { requireAuth } from "../user"; import formatLabelledValues from "../utils/render-labelled-values"; +import { fetchVersion } from "./api"; import { getConfig, getVersionSource } from "./list"; -import { ApiVersion } from "./types"; import type { CommonYargsArgv, StrictYargsOptionsToInterface, @@ -54,9 +53,7 @@ export async function versionsViewHandler(args: VersionsViewArgs) { ); } - const version = await fetchResult( - `/accounts/${accountId}/workers/scripts/${workerName}/versions/${args.versionId}` - ); + const version = await fetchVersion(accountId, workerName, args.versionId); const formattedVersion = formatLabelledValues({ "Version ID": version.id, From c61f372a9c5949d0f62d582d6218c605fb2d8324 Mon Sep 17 00:00:00 2001 From: Rahul Sethi <5822355+RamIdeas@users.noreply.github.com> Date: Tue, 12 Mar 2024 21:56:17 +0000 Subject: [PATCH 11/14] update snapshots --- .../deployments/deployments.list.test.ts | 18 +++++++++--------- .../deployments/deployments.status.test.ts | 6 +++--- .../__tests__/versions/versions.deploy.test.ts | 2 +- .../__tests__/versions/versions.list.test.ts | 2 +- .../__tests__/versions/versions.view.test.ts | 2 +- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/packages/wrangler/src/__tests__/versions/deployments/deployments.list.test.ts b/packages/wrangler/src/__tests__/versions/deployments/deployments.list.test.ts index eaef5f64ff72..1bab7ab4b5df 100644 --- a/packages/wrangler/src/__tests__/versions/deployments/deployments.list.test.ts +++ b/packages/wrangler/src/__tests__/versions/deployments/deployments.list.test.ts @@ -28,7 +28,7 @@ describe("deployments list", () => { ); await expect(result).rejects.toMatchInlineSnapshot( - `[Error: You need to provide a name when deploying a worker. Either pass it as a cli arg with \`--name \` or in your config file as \`name = ""\`]` + `[Error: You need to provide a name of your worker. Either pass it as a cli arg with \`--name \` or in your config file as \`name = ""\`]` ); expect(std.out).toMatchInlineSnapshot(`""`); @@ -46,7 +46,7 @@ describe("deployments list", () => { expect(std.out).toMatchInlineSnapshot(` "Created: 2021-01-04T00:00:00.000Z Author: Jean-Luc-Picard@federation.org - Source: api + Source: Rollback Message: - Version(s): (10%) 10000000-0000-0000-0000-000000000000 Created: 2021-01-01T00:00:00.000Z @@ -60,7 +60,7 @@ describe("deployments list", () => { Created: 2021-01-01T00:00:00.000Z Author: Jean-Luc-Picard@federation.org - Source: wrangler + Source: Upload Message: - Version(s): (20%) 10000000-0000-0000-0000-000000000000 Created: 2021-01-01T00:00:00.000Z @@ -74,7 +74,7 @@ describe("deployments list", () => { Created: 2021-02-02T00:00:00.000Z Author: Kathryn-Janeway@federation.org - Source: wrangler + Source: Rollback Message: Rolled back for this version Version(s): (30%) 10000000-0000-0000-0000-000000000000 Created: 2021-01-01T00:00:00.000Z @@ -88,7 +88,7 @@ describe("deployments list", () => { Created: 2021-02-03T00:00:00.000Z Author: Kathryn-Janeway@federation.org - Source: wrangler + Source: Wrangler 🤠 Message: - Version(s): (40%) 10000000-0000-0000-0000-000000000000 Created: 2021-01-01T00:00:00.000Z @@ -119,7 +119,7 @@ describe("deployments list", () => { expect(std.out).toMatchInlineSnapshot(` "Created: 2021-01-04T00:00:00.000Z Author: Jean-Luc-Picard@federation.org - Source: api + Source: Rollback Message: - Version(s): (10%) 10000000-0000-0000-0000-000000000000 Created: 2021-01-01T00:00:00.000Z @@ -133,7 +133,7 @@ describe("deployments list", () => { Created: 2021-01-01T00:00:00.000Z Author: Jean-Luc-Picard@federation.org - Source: wrangler + Source: Upload Message: - Version(s): (20%) 10000000-0000-0000-0000-000000000000 Created: 2021-01-01T00:00:00.000Z @@ -147,7 +147,7 @@ describe("deployments list", () => { Created: 2021-02-02T00:00:00.000Z Author: Kathryn-Janeway@federation.org - Source: wrangler + Source: Rollback Message: Rolled back for this version Version(s): (30%) 10000000-0000-0000-0000-000000000000 Created: 2021-01-01T00:00:00.000Z @@ -161,7 +161,7 @@ describe("deployments list", () => { Created: 2021-02-03T00:00:00.000Z Author: Kathryn-Janeway@federation.org - Source: wrangler + Source: Wrangler 🤠 Message: - Version(s): (40%) 10000000-0000-0000-0000-000000000000 Created: 2021-01-01T00:00:00.000Z diff --git a/packages/wrangler/src/__tests__/versions/deployments/deployments.status.test.ts b/packages/wrangler/src/__tests__/versions/deployments/deployments.status.test.ts index 20cc475c776e..81e1d2145eef 100644 --- a/packages/wrangler/src/__tests__/versions/deployments/deployments.status.test.ts +++ b/packages/wrangler/src/__tests__/versions/deployments/deployments.status.test.ts @@ -28,7 +28,7 @@ describe("deployments list", () => { ); await expect(result).rejects.toMatchInlineSnapshot( - `[Error: You need to provide a name when deploying a worker. Either pass it as a cli arg with \`--name \` or in your config file as \`name = ""\`]` + `[Error: You need to provide a name of your worker. Either pass it as a cli arg with \`--name \` or in your config file as \`name = ""\`]` ); expect(std.out).toMatchInlineSnapshot(`""`); @@ -46,7 +46,7 @@ describe("deployments list", () => { expect(std.out).toMatchInlineSnapshot(` "Created: 2021-01-04T00:00:00.000Z Author: Jean-Luc-Picard@federation.org - Source: api + Source: Rollback Message: - Version(s): (10%) 10000000-0000-0000-0000-000000000000 Created: 2021-01-01T00:00:00.000Z @@ -77,7 +77,7 @@ describe("deployments list", () => { expect(std.out).toMatchInlineSnapshot(` "Created: 2021-01-04T00:00:00.000Z Author: Jean-Luc-Picard@federation.org - Source: api + Source: Rollback Message: - Version(s): (10%) 10000000-0000-0000-0000-000000000000 Created: 2021-01-01T00:00:00.000Z diff --git a/packages/wrangler/src/__tests__/versions/versions.deploy.test.ts b/packages/wrangler/src/__tests__/versions/versions.deploy.test.ts index 18a2c6918b28..702156e08d52 100644 --- a/packages/wrangler/src/__tests__/versions/versions.deploy.test.ts +++ b/packages/wrangler/src/__tests__/versions/versions.deploy.test.ts @@ -106,7 +106,7 @@ describe("versions deploy", () => { ); await expect(result).rejects.toMatchInlineSnapshot( - `[Error: You need to provide a name when deploying a worker. Either pass it as a cli arg with \`--name \` or in your config file as \`name = ""\`]` + `[Error: You need to provide a name of your worker. Either pass it as a cli arg with \`--name \` or in your config file as \`name = ""\`]` ); }); }); diff --git a/packages/wrangler/src/__tests__/versions/versions.list.test.ts b/packages/wrangler/src/__tests__/versions/versions.list.test.ts index 0d6404ae0bf2..a8a85b76df99 100644 --- a/packages/wrangler/src/__tests__/versions/versions.list.test.ts +++ b/packages/wrangler/src/__tests__/versions/versions.list.test.ts @@ -23,7 +23,7 @@ describe("versions list", () => { ); await expect(result).rejects.toMatchInlineSnapshot( - `[Error: You need to provide a name when deploying a worker. Either pass it as a cli arg with \`--name \` or in your config file as \`name = ""\`]` + `[Error: You need to provide a name of your worker. Either pass it as a cli arg with \`--name \` or in your config file as \`name = ""\`]` ); expect(std.out).toMatchInlineSnapshot(`""`); diff --git a/packages/wrangler/src/__tests__/versions/versions.view.test.ts b/packages/wrangler/src/__tests__/versions/versions.view.test.ts index 3bbf8ddac2db..7023e0cc6200 100644 --- a/packages/wrangler/src/__tests__/versions/versions.view.test.ts +++ b/packages/wrangler/src/__tests__/versions/versions.view.test.ts @@ -51,7 +51,7 @@ describe("versions view", () => { ); await expect(result).rejects.toMatchInlineSnapshot( - `[Error: You need to provide a name when deploying a worker. Either pass it as a cli arg with \`--name \` or in your config file as \`name = ""\`]` + `[Error: You need to provide a name of your worker. Either pass it as a cli arg with \`--name \` or in your config file as \`name = ""\`]` ); expect(std.out).toMatchInlineSnapshot(`""`); From b5b2d068f9f63108219151ecf039eef1b6f77e5e Mon Sep 17 00:00:00 2001 From: Rahul Sethi <5822355+RamIdeas@users.noreply.github.com> Date: Tue, 12 Mar 2024 23:01:15 +0000 Subject: [PATCH 12/14] fix linting --- .../deployments/deployments.list.test.ts | 23 ++++++++----------- .../deployments/deployments.status.test.ts | 11 +++------ packages/wrangler/src/versions/api.ts | 2 +- packages/wrangler/src/versions/deploy.ts | 3 +-- .../src/versions/deployments/index.ts | 2 +- .../wrangler/src/versions/deployments/list.ts | 8 ++----- .../src/versions/deployments/status.ts | 2 +- packages/wrangler/src/versions/list.ts | 2 +- 8 files changed, 19 insertions(+), 34 deletions(-) diff --git a/packages/wrangler/src/__tests__/versions/deployments/deployments.list.test.ts b/packages/wrangler/src/__tests__/versions/deployments/deployments.list.test.ts index 1bab7ab4b5df..fecc9ed49f7c 100644 --- a/packages/wrangler/src/__tests__/versions/deployments/deployments.list.test.ts +++ b/packages/wrangler/src/__tests__/versions/deployments/deployments.list.test.ts @@ -1,12 +1,7 @@ import { normalizeOutput } from "../../../../e2e/helpers/normalize"; import { collectCLIOutput } from "../../helpers/collect-cli-output"; import { mockAccountId, mockApiToken } from "../../helpers/mock-account-id"; -import { - msw, - mswGetVersion, - mswListNewDeployments, - mswListVersions, -} from "../../helpers/msw"; +import { msw, mswGetVersion, mswListNewDeployments } from "../../helpers/msw"; import { runInTempDir } from "../../helpers/run-in-tmp"; import { runWrangler } from "../../helpers/run-wrangler"; import writeWranglerToml from "../../helpers/write-wrangler-toml"; @@ -52,7 +47,7 @@ describe("deployments list", () => { Created: 2021-01-01T00:00:00.000Z Tag: - Message: - - + (90%) 20000000-0000-0000-0000-000000000000 Created: 2021-01-01T00:00:00.000Z Tag: - @@ -66,7 +61,7 @@ describe("deployments list", () => { Created: 2021-01-01T00:00:00.000Z Tag: - Message: - - + (80%) 20000000-0000-0000-0000-000000000000 Created: 2021-01-01T00:00:00.000Z Tag: - @@ -80,7 +75,7 @@ describe("deployments list", () => { Created: 2021-01-01T00:00:00.000Z Tag: - Message: - - + (70%) 20000000-0000-0000-0000-000000000000 Created: 2021-01-01T00:00:00.000Z Tag: - @@ -94,7 +89,7 @@ describe("deployments list", () => { Created: 2021-01-01T00:00:00.000Z Tag: - Message: - - + (60%) 20000000-0000-0000-0000-000000000000 Created: 2021-01-01T00:00:00.000Z Tag: - @@ -125,7 +120,7 @@ describe("deployments list", () => { Created: 2021-01-01T00:00:00.000Z Tag: - Message: - - + (90%) 20000000-0000-0000-0000-000000000000 Created: 2021-01-01T00:00:00.000Z Tag: - @@ -139,7 +134,7 @@ describe("deployments list", () => { Created: 2021-01-01T00:00:00.000Z Tag: - Message: - - + (80%) 20000000-0000-0000-0000-000000000000 Created: 2021-01-01T00:00:00.000Z Tag: - @@ -153,7 +148,7 @@ describe("deployments list", () => { Created: 2021-01-01T00:00:00.000Z Tag: - Message: - - + (70%) 20000000-0000-0000-0000-000000000000 Created: 2021-01-01T00:00:00.000Z Tag: - @@ -167,7 +162,7 @@ describe("deployments list", () => { Created: 2021-01-01T00:00:00.000Z Tag: - Message: - - + (60%) 20000000-0000-0000-0000-000000000000 Created: 2021-01-01T00:00:00.000Z Tag: - diff --git a/packages/wrangler/src/__tests__/versions/deployments/deployments.status.test.ts b/packages/wrangler/src/__tests__/versions/deployments/deployments.status.test.ts index 81e1d2145eef..cbe9a7de93c8 100644 --- a/packages/wrangler/src/__tests__/versions/deployments/deployments.status.test.ts +++ b/packages/wrangler/src/__tests__/versions/deployments/deployments.status.test.ts @@ -1,12 +1,7 @@ import { normalizeOutput } from "../../../../e2e/helpers/normalize"; import { collectCLIOutput } from "../../helpers/collect-cli-output"; import { mockAccountId, mockApiToken } from "../../helpers/mock-account-id"; -import { - msw, - mswGetVersion, - mswListNewDeployments, - mswListVersions, -} from "../../helpers/msw"; +import { msw, mswGetVersion, mswListNewDeployments } from "../../helpers/msw"; import { runInTempDir } from "../../helpers/run-in-tmp"; import { runWrangler } from "../../helpers/run-wrangler"; import writeWranglerToml from "../../helpers/write-wrangler-toml"; @@ -52,7 +47,7 @@ describe("deployments list", () => { Created: 2021-01-01T00:00:00.000Z Tag: - Message: - - + (90%) 20000000-0000-0000-0000-000000000000 Created: 2021-01-01T00:00:00.000Z Tag: - @@ -83,7 +78,7 @@ describe("deployments list", () => { Created: 2021-01-01T00:00:00.000Z Tag: - Message: - - + (90%) 20000000-0000-0000-0000-000000000000 Created: 2021-01-01T00:00:00.000Z Tag: - diff --git a/packages/wrangler/src/versions/api.ts b/packages/wrangler/src/versions/api.ts index 2816d0aeb170..7969cb8c0603 100644 --- a/packages/wrangler/src/versions/api.ts +++ b/packages/wrangler/src/versions/api.ts @@ -1,5 +1,5 @@ import { fetchResult } from "../cfetch"; -import { +import type { ApiDeployment, ApiVersion, Percentage, diff --git a/packages/wrangler/src/versions/deploy.ts b/packages/wrangler/src/versions/deploy.ts index f5a243ab9819..1c00460ba31b 100644 --- a/packages/wrangler/src/versions/deploy.ts +++ b/packages/wrangler/src/versions/deploy.ts @@ -8,7 +8,6 @@ import { leftT, spinnerWhile, } from "@cloudflare/cli/interactive"; -import { fetchResult } from "../cfetch"; import { findWranglerToml, readConfig } from "../config"; import { UserError } from "../errors"; import * as metrics from "../metrics"; @@ -20,11 +19,11 @@ import { fetchLatestUploadedVersions, fetchVersions, } from "./api"; -import { Percentage, VersionCache, VersionId } from "./types"; import type { CommonYargsArgv, StrictYargsOptionsToInterface, } from "../yargs-types"; +import type { Percentage, VersionCache, VersionId } from "./types"; const EPSILON = 0.001; // used to avoid floating-point errors. Comparions to a value +/- EPSILON will mean "roughly equals the value". const BLANK_INPUT = "-"; // To be used where optional user-input is displayed and the value is nullish diff --git a/packages/wrangler/src/versions/deployments/index.ts b/packages/wrangler/src/versions/deployments/index.ts index ff31f59ca5c2..8c65b2083f42 100644 --- a/packages/wrangler/src/versions/deployments/index.ts +++ b/packages/wrangler/src/versions/deployments/index.ts @@ -1,4 +1,3 @@ -import { CommonYargsArgv } from "../../yargs-types"; import { versionsDeploymentsListHandler, versionsDeploymentsListOptions, @@ -7,6 +6,7 @@ import { versionsDeploymentsStatusHandler, versionsDeploymentsStatusOptions, } from "./status"; +import type { CommonYargsArgv } from "../../yargs-types"; export default function registerVersionsDeploymentsSubcommands( versionDeploymentsYargs: CommonYargsArgv diff --git a/packages/wrangler/src/versions/deployments/list.ts b/packages/wrangler/src/versions/deployments/list.ts index da048edb5e25..4c2161d2e0d2 100644 --- a/packages/wrangler/src/versions/deployments/list.ts +++ b/packages/wrangler/src/versions/deployments/list.ts @@ -8,17 +8,13 @@ import * as metrics from "../../metrics"; import { printWranglerBanner } from "../../update-check"; import { requireAuth } from "../../user"; import formatLabelledValues from "../../utils/render-labelled-values"; -import { - fetchLatestDeployment, - fetchLatestDeployments, - fetchVersions, -} from "../api"; +import { fetchLatestDeployments, fetchVersions } from "../api"; import { getVersionSource } from "../list"; -import { ApiDeployment, VersionCache } from "../types"; import type { CommonYargsArgv, StrictYargsOptionsToInterface, } from "../../yargs-types"; +import type { ApiDeployment, VersionCache } from "../types"; const BLANK_INPUT = "-"; // To be used where optional user-input is displayed and the value is nullish diff --git a/packages/wrangler/src/versions/deployments/status.ts b/packages/wrangler/src/versions/deployments/status.ts index 0b0a1a0fd2e9..e73bced8d651 100644 --- a/packages/wrangler/src/versions/deployments/status.ts +++ b/packages/wrangler/src/versions/deployments/status.ts @@ -9,12 +9,12 @@ import { printWranglerBanner } from "../../update-check"; import { requireAuth } from "../../user"; import formatLabelledValues from "../../utils/render-labelled-values"; import { fetchLatestDeployment, fetchVersions } from "../api"; -import { VersionCache } from "../types"; import { getDeploymentSource } from "./list"; import type { CommonYargsArgv, StrictYargsOptionsToInterface, } from "../../yargs-types"; +import type { VersionCache } from "../types"; const BLANK_INPUT = "-"; // To be used where optional user-input is displayed and the value is nullish diff --git a/packages/wrangler/src/versions/list.ts b/packages/wrangler/src/versions/list.ts index 93f5126facfb..478a77523b1b 100644 --- a/packages/wrangler/src/versions/list.ts +++ b/packages/wrangler/src/versions/list.ts @@ -7,11 +7,11 @@ import { printWranglerBanner } from "../update-check"; import { requireAuth } from "../user"; import formatLabelledValues from "../utils/render-labelled-values"; import { fetchLatestUploadedVersions } from "./api"; -import { ApiVersion, VersionCache } from "./types"; import type { CommonYargsArgv, StrictYargsOptionsToInterface, } from "../yargs-types"; +import type { ApiVersion, VersionCache } from "./types"; const BLANK_INPUT = "-"; // To be used where optional user-input is displayed and the value is nullish From ee50f03333980bf29583a4c8883e5b4e3684a892 Mon Sep 17 00:00:00 2001 From: Rahul Sethi <5822355+RamIdeas@users.noreply.github.com> Date: Tue, 12 Mar 2024 23:02:56 +0000 Subject: [PATCH 13/14] add changeset --- .changeset/grumpy-ghosts-tan.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/grumpy-ghosts-tan.md diff --git a/.changeset/grumpy-ghosts-tan.md b/.changeset/grumpy-ghosts-tan.md new file mode 100644 index 000000000000..fcca31e8b9e9 --- /dev/null +++ b/.changeset/grumpy-ghosts-tan.md @@ -0,0 +1,5 @@ +--- +"wrangler": minor +--- + +feature: Implement `wrangler deployments list` and `wrangler deployments status` behind `--experimental-gradual-rollouts` flag. From 2b3b8d648d0b59c6f288db12561bfca25ccea6f7 Mon Sep 17 00:00:00 2001 From: Rahul Sethi <5822355+RamIdeas@users.noreply.github.com> Date: Tue, 12 Mar 2024 23:21:59 +0000 Subject: [PATCH 14/14] update snapshots --- .../deployments/deployments.list.test.ts | 16 ++++++++-------- .../deployments/deployments.status.test.ts | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/wrangler/src/__tests__/versions/deployments/deployments.list.test.ts b/packages/wrangler/src/__tests__/versions/deployments/deployments.list.test.ts index fecc9ed49f7c..303e3c4c238d 100644 --- a/packages/wrangler/src/__tests__/versions/deployments/deployments.list.test.ts +++ b/packages/wrangler/src/__tests__/versions/deployments/deployments.list.test.ts @@ -47,7 +47,7 @@ describe("deployments list", () => { Created: 2021-01-01T00:00:00.000Z Tag: - Message: - - + (90%) 20000000-0000-0000-0000-000000000000 Created: 2021-01-01T00:00:00.000Z Tag: - @@ -61,7 +61,7 @@ describe("deployments list", () => { Created: 2021-01-01T00:00:00.000Z Tag: - Message: - - + (80%) 20000000-0000-0000-0000-000000000000 Created: 2021-01-01T00:00:00.000Z Tag: - @@ -75,7 +75,7 @@ describe("deployments list", () => { Created: 2021-01-01T00:00:00.000Z Tag: - Message: - - + (70%) 20000000-0000-0000-0000-000000000000 Created: 2021-01-01T00:00:00.000Z Tag: - @@ -89,7 +89,7 @@ describe("deployments list", () => { Created: 2021-01-01T00:00:00.000Z Tag: - Message: - - + (60%) 20000000-0000-0000-0000-000000000000 Created: 2021-01-01T00:00:00.000Z Tag: - @@ -120,7 +120,7 @@ describe("deployments list", () => { Created: 2021-01-01T00:00:00.000Z Tag: - Message: - - + (90%) 20000000-0000-0000-0000-000000000000 Created: 2021-01-01T00:00:00.000Z Tag: - @@ -134,7 +134,7 @@ describe("deployments list", () => { Created: 2021-01-01T00:00:00.000Z Tag: - Message: - - + (80%) 20000000-0000-0000-0000-000000000000 Created: 2021-01-01T00:00:00.000Z Tag: - @@ -148,7 +148,7 @@ describe("deployments list", () => { Created: 2021-01-01T00:00:00.000Z Tag: - Message: - - + (70%) 20000000-0000-0000-0000-000000000000 Created: 2021-01-01T00:00:00.000Z Tag: - @@ -162,7 +162,7 @@ describe("deployments list", () => { Created: 2021-01-01T00:00:00.000Z Tag: - Message: - - + (60%) 20000000-0000-0000-0000-000000000000 Created: 2021-01-01T00:00:00.000Z Tag: - diff --git a/packages/wrangler/src/__tests__/versions/deployments/deployments.status.test.ts b/packages/wrangler/src/__tests__/versions/deployments/deployments.status.test.ts index cbe9a7de93c8..0cd1cd81332a 100644 --- a/packages/wrangler/src/__tests__/versions/deployments/deployments.status.test.ts +++ b/packages/wrangler/src/__tests__/versions/deployments/deployments.status.test.ts @@ -47,7 +47,7 @@ describe("deployments list", () => { Created: 2021-01-01T00:00:00.000Z Tag: - Message: - - + (90%) 20000000-0000-0000-0000-000000000000 Created: 2021-01-01T00:00:00.000Z Tag: - @@ -78,7 +78,7 @@ describe("deployments list", () => { Created: 2021-01-01T00:00:00.000Z Tag: - Message: - - + (90%) 20000000-0000-0000-0000-000000000000 Created: 2021-01-01T00:00:00.000Z Tag: -