Skip to content

Commit

Permalink
feat: wrangler deploy prompts warning with deployment (#5992)
Browse files Browse the repository at this point in the history
* feat: wrangler deploy prompts warning with deployment

* fix: wrangler deploy prompts warning with deployment styling

Styling of the warning about multiple deployments during
`wrangler deploy` should be consistent with `wrangler versions`
styling.

* Fix typo in packages/wrangler/src/versions/deploy.ts

Co-authored-by: Rahul Sethi <5822355+RamIdeas@users.noreply.github.com>

* Fix typo in packages/wrangler/src/versions/deploy.ts

Co-authored-by: Rahul Sethi <5822355+RamIdeas@users.noreply.github.com>

---------

Co-authored-by: Daniel Rivas <drivas@cloudflare.com>
Co-authored-by: Rahul Sethi <5822355+RamIdeas@users.noreply.github.com>
  • Loading branch information
3 people authored Jun 13, 2024
1 parent 88ca59b commit c13fb91
Show file tree
Hide file tree
Showing 8 changed files with 265 additions and 29 deletions.
3 changes: 2 additions & 1 deletion packages/cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,15 +163,16 @@ export const warn = (
shape = shapes.corners.bl,
// current default for backcompat -- TODO: change default to true once all callees have been updated
multiline = false,
newlineBefore = true,
} = {}
) => {
logRaw(
format(msg, {
firstLinePrefix: gray(shape) + space() + status.warning,
linePrefix: gray(shapes.bar),
newlineBefore: true,
formatLine: (line) => dim(line), // for backcompat but it's not ideal for this to be "dim"
multiline,
newlineBefore,
})
);
};
Expand Down
2 changes: 2 additions & 0 deletions packages/wrangler/src/__tests__/deploy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import {
mswSuccessOauthHandlers,
mswSuccessUserHandlers,
} from "./helpers/msw";
import { mswListNewDeploymentsLatestFull } from "./helpers/msw/handlers/versions";
import { runInTempDir } from "./helpers/run-in-tmp";
import { runWrangler } from "./helpers/run-wrangler";
import { writeWorkerSource } from "./helpers/write-worker-source";
Expand Down Expand Up @@ -78,6 +79,7 @@ describe("deploy", () => {
setIsTTY(true);
mockLastDeploymentRequest();
mockDeploymentsListRequest();
msw.use(...mswListNewDeploymentsLatestFull);
logger.loggerLevel = "log";
});

Expand Down
11 changes: 9 additions & 2 deletions packages/wrangler/src/__tests__/deprecated-usage-model.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { mockConsoleMethods } from "./helpers/mock-console";
import { mockUploadWorkerRequest } from "./helpers/mock-upload-worker";
import { mockSubDomainRequest } from "./helpers/mock-workers-subdomain";
import { msw, mswSuccessDeploymentScriptMetadata } from "./helpers/msw";
import { mswListNewDeploymentsLatestFull } from "./helpers/msw/handlers/versions";
import { runInTempDir } from "./helpers/run-in-tmp";
import { runWrangler } from "./helpers/run-wrangler";
import { writeWorkerSource } from "./helpers/write-worker-source";
Expand All @@ -26,7 +27,10 @@ describe("deprecated-usage-model", () => {
});

it("should warn user about ignored usage model if usage_model specified", async () => {
msw.use(...mswSuccessDeploymentScriptMetadata);
msw.use(
...mswSuccessDeploymentScriptMetadata,
...mswListNewDeploymentsLatestFull
);
writeWranglerToml({ usage_model: "bundled" });
writeWorkerSource();
mockSubDomainRequest();
Expand All @@ -41,7 +45,10 @@ describe("deprecated-usage-model", () => {
`);
});
it("should not warn user about ignored usage model if usage_model not specified", async () => {
msw.use(...mswSuccessDeploymentScriptMetadata);
msw.use(
...mswSuccessDeploymentScriptMetadata,
...mswListNewDeploymentsLatestFull
);
writeWranglerToml();
writeWorkerSource();
mockSubDomainRequest();
Expand Down
97 changes: 97 additions & 0 deletions packages/wrangler/src/__tests__/helpers/msw/handlers/versions.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,102 @@
import { http, HttpResponse } from "msw";
import { createFetchResult } from "../index";
import type { ApiDeployment, ApiVersion } from "../../../../versions/types";

export const mswListNewDeploymentsLatestFull = [
http.get(
"*/accounts/:accountId/workers/scripts/:scriptName/deployments",
({ params }) => {
return HttpResponse.json(
createFetchResult({
deployments: [
{
id: `deployment:${params["scriptName"]}`,
source: "api",
strategy: "percentage",
author_email: "author@example.com",
created_on: "2021-01-01T00:00:00.000000Z",
versions: [
{
version_id: `${params["scriptName"]}:version:0`,
percentage: 100.0,
},
],
},
] as Array<ApiDeployment>,
})
);
},
{ once: true }
),
http.get(
"*/accounts/:accountId/workers/scripts/:scriptName/versions/:version",
({ params }) => {
return HttpResponse.json(
createFetchResult({
id: params["version"],
number: 1,
metadata: {
created_on: "2021-01-01T00:00:00.000000Z",
modified_on: "2021-01-01T00:00:00.000000Z",
source: "api",
author_email: "author@example.com",
},
} as ApiVersion)
);
},
{ once: false }
),
];

export const mswListNewDeploymentsLatestFiftyFifty = [
http.get(
"*/accounts/:accountId/workers/scripts/:scriptName/deployments",
({ params }) => {
return HttpResponse.json(
createFetchResult({
deployments: [
{
id: `deployment:${params["scriptName"]}`,
source: "api",
strategy: "percentage",
author_email: "author@example.com",
created_on: "2021-01-01T00:00:00.000000Z",
versions: [
{
version_id: `${params["scriptName"]}:version:0`,
percentage: 50.0,
},
{
version_id: `${params["scriptName"]}:version:1`,
percentage: 50.0,
},
],
},
] as Array<ApiDeployment>,
})
);
},
{ once: true }
),
http.get(
"*/accounts/:accountId/workers/scripts/:scriptName/versions/:version",
({ params }) => {
return HttpResponse.json(
createFetchResult({
id: params["version"],
number: 1,
metadata: {
created_on: "2021-01-01T00:00:00.000000Z",
modified_on: "2021-01-01T00:00:00.000000Z",
source: "api",
author_email: "author@example.com",
},
} as ApiVersion)
);
},
{ once: false }
),
];

export const mswListNewDeployments = http.get(
"*/accounts/:accountId/workers/scripts/:workerName/deployments",
Expand Down
41 changes: 41 additions & 0 deletions packages/wrangler/src/__tests__/versions/versions.deploy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,21 @@ import { collectCLIOutput } from "../helpers/collect-cli-output";
import { mockAccountId, mockApiToken } from "../helpers/mock-account-id";
import { mockConsoleMethods } from "../helpers/mock-console";
import { useMockIsTTY } from "../helpers/mock-istty";
import { mockUploadWorkerRequest } from "../helpers/mock-upload-worker";
import { mockSubDomainRequest } from "../helpers/mock-workers-subdomain";
import {
msw,
mswGetVersion,
mswListNewDeployments,
mswListVersions,
mswPatchNonVersionedScriptSettings,
mswPostNewDeployment,
mswSuccessDeploymentScriptMetadata,
} from "../helpers/msw";
import { mswListNewDeploymentsLatestFiftyFifty } from "../helpers/msw/handlers/versions";
import { runInTempDir } from "../helpers/run-in-tmp";
import { runWrangler } from "../helpers/run-wrangler";
import { writeWorkerSource } from "../helpers/write-worker-source";
import writeWranglerToml from "../helpers/write-wrangler-toml";
import type { VersionsDeployArgs } from "../../versions/deploy";

Expand All @@ -43,6 +48,42 @@ describe("versions deploy", () => {
);
});

describe("legacy deploy", () => {
test("should warn user when worker has deployment with multiple versions", async () => {
msw.use(
...mswSuccessDeploymentScriptMetadata,
...mswListNewDeploymentsLatestFiftyFifty
);
writeWranglerToml();
writeWorkerSource();
mockSubDomainRequest();
mockUploadWorkerRequest();

await runWrangler("deploy ./index");

expect(normalizeOutput(std.out)).toMatchInlineSnapshot(`
"╭ WARNING Your last deployment has multiple versions. To progress that deployment use \\"wrangler versions deploy\\" instead.
├ Your last deployment has 2 version(s):
│ (50%) test-name:version:0
│ Created: TIMESTAMP
│ Tag: -
│ Message: -
│ (50%) test-name:version:1
│ Created: TIMESTAMP
│ Tag: -
│ Message: -
├ \\"wrangler deploy\\" will upload a new version and deploy it globally immediately.
Are you sure you want to continue?
│ yes
│"
`);
});
});

describe("without wrangler.toml", () => {
test("succeeds with --name arg", async () => {
const result = runWrangler(
Expand Down
14 changes: 13 additions & 1 deletion packages/wrangler/src/deploy/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import assert from "node:assert";
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
import path from "node:path";
import { URLSearchParams } from "node:url";
import { cancel } from "@cloudflare/cli";
import { fetchListResult, fetchResult } from "../cfetch";
import { printBindings } from "../config";
import { bundleWorker } from "../deployment-bundle/bundle";
Expand Down Expand Up @@ -45,6 +46,7 @@ import {
} from "../sourcemap";
import triggersDeploy from "../triggers/deploy";
import { logVersionIdChange } from "../utils/deployment-id-version-id-change";
import { confirmLatestDeploymentOverwrite } from "../versions/deploy";
import { getZoneForRoute } from "../zones";
import type { Config } from "../config";
import type {
Expand Down Expand Up @@ -421,7 +423,8 @@ See https://developers.cloudflare.com/workers/platform/compatibility-dates for m
const envName = props.env ?? "production";

const start = Date.now();
const notProd = Boolean(!props.legacyEnv && props.env);
const prod = Boolean(props.legacyEnv || !props.env);
const notProd = !prod;
const workerName = notProd ? `${scriptName} (${envName})` : scriptName;
const workerUrl = props.dispatchNamespace
? `/accounts/${accountId}/workers/dispatch/namespaces/${props.dispatchNamespace}/scripts/${scriptName}`
Expand All @@ -433,6 +436,14 @@ See https://developers.cloudflare.com/workers/platform/compatibility-dates for m

const { format } = props.entry;

if (!props.dispatchNamespace && prod && accountId && scriptName) {
const yes = await confirmLatestDeploymentOverwrite(accountId, scriptName);
if (!yes) {
cancel("Aborting deploy...");
return;
}
}

if (
!props.isWorkersSite &&
Boolean(props.assetPaths) &&
Expand Down Expand Up @@ -460,6 +471,7 @@ See https://developers.cloudflare.com/workers/platform/compatibility-dates for m
"You cannot configure [data_blobs] with an ES module worker. Instead, import the file directly in your code, and optionally configure `[rules]` in your wrangler.toml"
);
}

try {
if (props.noBundle) {
// if we're not building, let's just copy the entry to the destination directory
Expand Down
13 changes: 5 additions & 8 deletions packages/wrangler/src/versions/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,23 +60,20 @@ export async function fetchLatestDeployment(
return deployments.at(0);
}

export async function fetchLatestDeploymentVersions(
export async function fetchDeploymentVersions(
accountId: string,
workerName: string,
deployment: ApiDeployment | undefined,
versionCache: VersionCache
): Promise<[ApiVersion[], Map<VersionId, Percentage>]> {
const latestDeployment = await fetchLatestDeployment(accountId, workerName);

if (!latestDeployment) {
if (!deployment) {
return [[], new Map()];
}

const versionTraffic = new Map(
latestDeployment.versions.map(({ version_id: versionId, percentage }) => [
versionId,
percentage,
])
deployment.versions.map((v) => [v.version_id, v.percentage])
);

const versions = await fetchVersions(
accountId,
workerName,
Expand Down
Loading

0 comments on commit c13fb91

Please sign in to comment.