Skip to content

Commit

Permalink
Have deployment view output in table (#2844)
Browse files Browse the repository at this point in the history
* Add suggested changes and update wrangler docs

* Separate content into option on view command

---------

Co-authored-by: jjohnson <jjohnson@cloudflare.com>
  • Loading branch information
jspspike and jspspike committed Mar 15, 2023
1 parent 64a1341 commit cbc8881
Show file tree
Hide file tree
Showing 7 changed files with 305 additions and 214 deletions.
42 changes: 18 additions & 24 deletions .changeset/brown-wasps-fail.md
Expand Up @@ -4,7 +4,7 @@

feature: add `deployment view` and `deployment rollbak` subcommands

`deployment view <deployment-id>` will get the details of a deployment, including versioned script, bindings, and usage model information.
`deployment view <deployment-id>` will get the details of a deployment, including bindings and usage model information. When using the `--content` option, the command will return the script content for that deployment.
This information can be used to help debug bad deployments or get insights on changes between deployments.

`deployment rollback [deployment-id]` will rollback to a specific deployment in the runtime. This will be useful in situations like recovering from a bad
Expand All @@ -14,27 +14,21 @@ in a developer's local setup.
example of `view <deployment-id>` output:

```ts
{
Tag: '',
Number: 0,
'Metadata.author_id': 'Picard-Gamma-6-0-7-3',
'Metadata.author_email': 'picard@vinyard.com',
'Metadata.source': 'wrangler',
'Metadata.created_on': '2021-01-01T00:00:00.000000Z',
'Metadata.modified_on': '2021-01-01T00:00:00.000000Z',
'resources.script': {
etag: 'mock-e-tag',
handlers: [ 'fetch' ],
last_deployed_from: 'wrangler'
},
'resources.bindings': []
}



export default {
async fetch(request) {
return new Response('Hello World from Deployment 1701-E');
},
};
Deployment ID: 07d7143d-0284-427e-ba22-2d5e6e91b479
Created on: 2023-03-02T21:05:15.622446Z
Author: jspspike@gmail.com
Source: Upload from Wrangler 🤠
------------------------------------------------------------
Author ID: e5a3ca86e08fb0940d3a05691310bb42
Usage Model: bundled
Handlers: fetch
Compatibility Date: 2022-10-03
--------------------------bindings--------------------------
[[r2_buckets]]
binding = "MY_BUCKET"
bucket_name = "testr2"

[[kv_namespaces]]
id = "79300c6d17eb4180a07270f450efe53f"
binding = "yeee"
```
79 changes: 56 additions & 23 deletions packages/wrangler/src/__tests__/deployments.test.ts
Expand Up @@ -69,23 +69,23 @@ describe("deployments", () => {
Deployment ID: Constitution-Class
Created on: 2021-01-01T00:00:00.000000Z
Author: Jean-Luc-Picard@federation.org
Source: Upload from Wrangler 🤠
Source: Upload from Wrangler 🤠
Deployment ID: Intrepid-Class
Created on: 2021-02-02T00:00:00.000000Z
Author: Kathryn-Janeway@federation.org
Source: Rollback from Wrangler 🤠
Source: Rollback from Wrangler 🤠
Rollback from: MOCK-DEPLOYMENT-ID-1111
Deployment ID: 3mEgaU1T-Intrepid-someThing
Created on: 2021-02-03T00:00:00.000000Z
Author: Kathryn-Janeway@federation.org
Source: Wrangler 🤠
Source: Wrangler 🤠
Deployment ID: Galaxy-Class
Created on: 2021-01-04T00:00:00.000000Z
Author: Jean-Luc-Picard@federation.org
Source: Rollback from Wrangler 🤠
Source: Rollback from Wrangler 🤠
Rollback from: MOCK-DEPLOYMENT-ID-2222
🟩 Active"
`);
Expand All @@ -100,23 +100,23 @@ describe("deployments", () => {
Deployment ID: Constitution-Class
Created on: 2021-01-01T00:00:00.000000Z
Author: Jean-Luc-Picard@federation.org
Source: Upload from Wrangler 🤠
Source: Upload from Wrangler 🤠
Deployment ID: Intrepid-Class
Created on: 2021-02-02T00:00:00.000000Z
Author: Kathryn-Janeway@federation.org
Source: Rollback from Wrangler 🤠
Source: Rollback from Wrangler 🤠
Rollback from: MOCK-DEPLOYMENT-ID-1111
Deployment ID: 3mEgaU1T-Intrepid-someThing
Created on: 2021-02-03T00:00:00.000000Z
Author: Kathryn-Janeway@federation.org
Source: Wrangler 🤠
Source: Wrangler 🤠
Deployment ID: Galaxy-Class
Created on: 2021-01-04T00:00:00.000000Z
Author: Jean-Luc-Picard@federation.org
Source: Rollback from Wrangler 🤠
Source: Rollback from Wrangler 🤠
Rollback from: MOCK-DEPLOYMENT-ID-2222
🟩 Active"
`);
Expand All @@ -138,27 +138,60 @@ describe("deployments", () => {
expect(std.out).toMatchInlineSnapshot(`
"🚧\`wrangler deployments\` is a beta command. Please report any issues to https://github.com/cloudflare/workers-sdk/issues/new/choose
{
Tag: '',
Number: 0,
'Metadata.author_id': 'Picard-Gamma-6-0-7-3',
'Metadata.author_email': 'Jean-Luc-Picard@federation.org',
'Metadata.source': 'wrangler',
'Metadata.created_on': '2021-01-01T00:00:00.000000Z',
'Metadata.modified_on': '2021-01-01T00:00:00.000000Z',
'resources.script': {
etag: 'mock-e-tag',
handlers: [ 'fetch' ],
last_deployed_from: 'wrangler'
},
'resources.bindings': []
}
Deployment ID: undefined
Created on: 2021-01-01T00:00:00.000000Z
Author: Jean-Luc-Picard@federation.org
Source: Wrangler 🤠
------------------------------------------------------------
Author ID: Picard-Gamma-6-0-7-3
Usage Model: bundled
Handlers: fetch
--------------------------bindings--------------------------
None
"
`);
});
it("should log deployment script", async () => {
writeWranglerToml();

await runWrangler("deployments view 1701-E --content");

expect(std.out).toMatchInlineSnapshot(`
"🚧\`wrangler deployments\` is a beta command. Please report any issues to https://github.com/cloudflare/workers-sdk/issues/new/choose
export default {
async fetch(request) {
return new Response('Hello World from Deployment 1701-E');
},
};"
`);
});

it("should log deployment details with bindings", async () => {
writeWranglerToml();

await runWrangler("deployments view bindings-tag");

expect(std.out).toMatchInlineSnapshot(`
"🚧\`wrangler deployments\` is a beta command. Please report any issues to https://github.com/cloudflare/workers-sdk/issues/new/choose
Deployment ID: undefined
Created on: 2021-01-01T00:00:00.000000Z
Author: Jean-Luc-Picard@federation.org
Source: Wrangler 🤠
------------------------------------------------------------
Author ID: Picard-Gamma-6-0-7-3
Usage Model: bundled
Handlers: fetch
--------------------------bindings--------------------------
[[r2_buckets]]
binding = \\"MY_BUCKET\\"
bucket_name = \\"testr2\\"
"
`);
});
});
Expand Down
Expand Up @@ -97,13 +97,23 @@ export const mswSuccessDeploymentScriptMetadata = [
export const mswSuccessDeploymentDetails = [
rest.get(
"*/accounts/:accountId/workers/deployments/by-script/:scriptTag/detail/:deploymentId",
(_, res, ctx) => {
(req, res, ctx) => {
let bindings: object[] = [];
if (req.url.toString().includes("bindings-tag")) {
bindings = [
{
bucket_name: "testr2",
name: "MY_BUCKET",
type: "r2_bucket",
},
];
}
return res.once(
ctx.json(
createFetchResult({
Tag: "",
Number: 0,
Metadata: {
metadata: {
author_id: "Picard-Gamma-6-0-7-3",
author_email: "Jean-Luc-Picard@federation.org",
source: "wrangler",
Expand All @@ -116,7 +126,10 @@ export const mswSuccessDeploymentDetails = [
handlers: ["fetch"],
last_deployed_from: "wrangler",
},
bindings: [],
script_runtime: {
usage_model: "bundled",
},
bindings: bindings,
},
})
)
Expand Down
2 changes: 1 addition & 1 deletion packages/wrangler/src/create-worker-upload-form.ts
Expand Up @@ -23,7 +23,7 @@ export function toMimeType(type: CfModuleType): string {
}
}

type WorkerMetadataBinding =
export type WorkerMetadataBinding =
// If you add any new binding types here, also add it to safeBindings
// under validateUnsafeBinding in config/validation.ts
| { type: "plain_text"; name: string; text: string }
Expand Down
90 changes: 63 additions & 27 deletions packages/wrangler/src/deployments.ts
@@ -1,14 +1,17 @@
import { URLSearchParams } from "url";
import TOML from "@iarna/toml";
import chalk from "chalk";
import { fetchResult, fetchScriptContent } from "./cfetch";
import { readConfig } from "./config";
import { confirm } from "./dialogs";
import { mapBindings } from "./init";
import { logger } from "./logger";
import * as metrics from "./metrics";
import { requireAuth } from "./user";
import { getScriptName, printWranglerBanner } from ".";

import type { Config } from "./config";
import type { WorkerMetadataBinding } from "./create-worker-upload-form";
import type { ServiceMetadataRes } from "./init";
import type { CommonYargsOptions } from "./yargs-types";
import type { ArgumentsCamelCase } from "yargs";
Expand All @@ -28,8 +31,15 @@ type DeploymentDetails = {
modified_on: string;
};
resources: {
script: string;
bindings: unknown[];
script: {
handlers: string[];
};
bindings: WorkerMetadataBinding[];
script_runtime: {
compatibility_date: string | undefined;
compatibility_flags: string[] | undefined;
usage_model: string | undefined;
};
};
};

Expand Down Expand Up @@ -81,7 +91,7 @@ export async function deployments(
Deployment ID: ${versions.id}
Created on: ${versions.metadata.created_on}
Author: ${versions.metadata.author_email}
Source: ${triggerStr}`;
Source: ${triggerStr}`;

if (versions.annotations?.["workers/rollback_from"]) {
version += `\nRollback from: ${versions.annotations["workers/rollback_from"]}`;
Expand Down Expand Up @@ -198,7 +208,8 @@ export async function viewDeployment(
accountId: string,
scriptName: string | undefined,
{ send_metrics: sendMetrics }: { send_metrics?: Config["send_metrics"] } = {},
deploymentId: string
deploymentId: string,
content: boolean
) {
await metrics.sendMetricsEvent(
"view deployments",
Expand All @@ -214,34 +225,59 @@ export async function viewDeployment(
)
).default_environment.script.tag;

const scriptContent = await fetchScriptContent(
`/accounts/${accountId}/workers/scripts/${scriptName}?deployment=${deploymentId}`
);
if (content) {
const scriptContent = await fetchScriptContent(
`/accounts/${accountId}/workers/scripts/${scriptName}?deployment=${deploymentId}`
);
logger.log(scriptContent);
return;
}

const deploymentDetails = await fetchResult<DeploymentListResult["latest"]>(
`/accounts/${accountId}/workers/deployments/by-script/${scriptTag}/detail/${deploymentId}`
);

const flatObj: Record<string, unknown> = {};
for (const deployDetailsKey in deploymentDetails) {
if (
Object.prototype.hasOwnProperty.call(deploymentDetails, deployDetailsKey)
) {
//@ts-expect-error flattening objects causes the index signature to error
const value = deploymentDetails[deployDetailsKey];
if (typeof value === "object" && value !== null) {
for (const subKey in value) {
if (Object.prototype.hasOwnProperty.call(value, subKey)) {
flatObj[`${deployDetailsKey}.${subKey}`] = value[subKey];
}
}
} else {
flatObj[deployDetailsKey] = value;
}
}
}
const triggerStr = deploymentDetails.annotations?.["workers/triggered_by"]
? `${formatTrigger(
deploymentDetails.annotations["workers/triggered_by"]
)} from ${formatSource(deploymentDetails.metadata.source)}`
: `${formatSource(deploymentDetails.metadata.source)}`;

const rollbackStr = deploymentDetails.annotations?.["workers/rollback_from"]
? `\nRollback from: ${deploymentDetails.annotations["workers/rollback_from"]}`
: ``;

const compatDateStr = deploymentDetails.resources.script_runtime
?.compatibility_date
? `\nCompatibility Date: ${deploymentDetails.resources.script_runtime?.compatibility_date}`
: ``;
const compatFlagsStr = deploymentDetails.resources.script_runtime
?.compatibility_flags
? `\nCompatibility Flags: ${deploymentDetails.resources.script_runtime?.compatibility_flags}`
: ``;

const bindings = deploymentDetails.resources.bindings;

const version = `
Deployment ID: ${deploymentDetails.id}
Created on: ${deploymentDetails.metadata.created_on}
Author: ${deploymentDetails.metadata.author_email}
Source: ${triggerStr}${rollbackStr}
------------------------------------------------------------
Author ID: ${deploymentDetails.metadata.author_id}
Usage Model: ${deploymentDetails.resources.script_runtime.usage_model}
Handlers: ${
deploymentDetails.resources.script.handlers
}${compatDateStr}${compatFlagsStr}
--------------------------bindings--------------------------
${
bindings.length > 0
? TOML.stringify(mapBindings(bindings) as TOML.JsonMap)
: `None`
}
`;

logger.log(flatObj);
logger.log(scriptContent);
logger.log(version);

// early return to skip the deployments listings
return;
Expand Down
8 changes: 7 additions & 1 deletion packages/wrangler/src/index.ts
Expand Up @@ -625,6 +625,11 @@ export function createCLIParser(argv: string[]) {
type: "string",
demandOption: true,
})
.option("content", {
describe: "Show script content for given deployment ID",
type: "boolean",
default: false,
})
.option("yes", {
alias: "y",
describe: "Skip confirmation prompt",
Expand All @@ -639,7 +644,8 @@ export function createCLIParser(argv: string[]) {
accountId,
scriptName,
config,
viewYargs.deploymentId
viewYargs.deploymentId,
viewYargs.content
);
}
)
Expand Down

0 comments on commit cbc8881

Please sign in to comment.