diff --git a/.changeset/five-suits-rest.md b/.changeset/five-suits-rest.md new file mode 100644 index 000000000000..cae677642a42 --- /dev/null +++ b/.changeset/five-suits-rest.md @@ -0,0 +1,17 @@ +--- +"wrangler": minor +--- + +fix: suppress compatibility date fallback warnings if no `wrangler` update is available + +If a compatibility date greater than the installed version of `workerd` was +configured, a warning would be logged. This warning was only actionable if a new +version of `wrangler` was available. The intent here was to warn if a user set +a new compatibility date, but forgot to update `wrangler` meaning changes +enabled by the new date wouldn't take effect. This change hides the warning if +no update is available. + +It also changes the default compatibility date for `wrangler dev` sessions +without a configured compatibility date to the installed version of `workerd`. +This previously defaulted to the current date, which may have been unsupported +by the installed runtime. diff --git a/packages/wrangler/src/__tests__/dev.test.tsx b/packages/wrangler/src/__tests__/dev.test.tsx index 587c1c892e95..ffab0fd92546 100644 --- a/packages/wrangler/src/__tests__/dev.test.tsx +++ b/packages/wrangler/src/__tests__/dev.test.tsx @@ -1,4 +1,5 @@ import * as fs from "node:fs"; +import module from "node:module"; import getPort from "get-port"; import { rest } from "msw"; import patchConsole from "patch-console"; @@ -68,11 +69,18 @@ describe("wrangler dev", () => { }); fs.writeFileSync("index.js", `export default {};`); await runWrangler("dev"); - const currentDate = new Date().toISOString().substring(0, 10); + + const miniflareEntry = require.resolve("miniflare"); + const miniflareRequire = module.createRequire(miniflareEntry); + const miniflareWorkerd = miniflareRequire("workerd") as { + compatibilityDate: string; + }; + const currentDate = miniflareWorkerd.compatibilityDate; + expect(std.out).toMatchInlineSnapshot(`""`); expect(std.warn.replaceAll(currentDate, "")) .toMatchInlineSnapshot(` - "▲ [WARNING] No compatibility_date was specified. Using today's date: . + "▲ [WARNING] No compatibility_date was specified. Using the installed Workers runtime's latest supported date: . Add one to your wrangler.toml file: \`\`\` diff --git a/packages/wrangler/src/dev/miniflare.ts b/packages/wrangler/src/dev/miniflare.ts index c862965e8945..5808a735d116 100644 --- a/packages/wrangler/src/dev/miniflare.ts +++ b/packages/wrangler/src/dev/miniflare.ts @@ -13,6 +13,7 @@ import { ModuleTypeToRuleType } from "../deployment-bundle/module-collection"; import { withSourceURLs } from "../deployment-bundle/source-url"; import { getHttpsOptions } from "../https-options"; import { logger } from "../logger"; +import { updateCheck } from "../update-check"; import type { Config } from "../config"; import type { CfD1Database, @@ -122,10 +123,19 @@ class WranglerLog extends Log { warn(message: string) { // Only log warning about requesting a compatibility date after the workerd - // binary's version once + // binary's version once, and only if there's an update available. if (message.startsWith("The latest compatibility date supported by")) { if (this.#warnedCompatibilityDateFallback) return; this.#warnedCompatibilityDateFallback = true; + return void updateCheck().then((maybeNewVersion) => { + if (maybeNewVersion === undefined) return; + message += [ + "", + "Features enabled by your requested compatibility date may not be available.", + `Upgrade to \`wrangler@${maybeNewVersion}\` to remove this warning.`, + ].join("\n"); + super.warn(message); + }); } super.warn(message); } diff --git a/packages/wrangler/src/index.ts b/packages/wrangler/src/index.ts index 5ef5f9e22760..c1cbc9237db1 100644 --- a/packages/wrangler/src/index.ts +++ b/packages/wrangler/src/index.ts @@ -1,3 +1,4 @@ +import module from "node:module"; import os from "node:os"; import TOML from "@iarna/toml"; import chalk from "chalk"; @@ -806,11 +807,18 @@ export async function main(argv: string[]): Promise { export function getDevCompatibilityDate( config: Config, compatibilityDate = config.compatibility_date -) { - const currentDate = new Date().toISOString().substring(0, 10); +): string { + // Get the maximum compatibility date supported by the installed Miniflare + const miniflareEntry = require.resolve("miniflare"); + const miniflareRequire = module.createRequire(miniflareEntry); + const miniflareWorkerd = miniflareRequire("workerd") as { + compatibilityDate: string; + }; + const currentDate = miniflareWorkerd.compatibilityDate; + if (config.configPath !== undefined && compatibilityDate === undefined) { logger.warn( - `No compatibility_date was specified. Using today's date: ${currentDate}.\n` + + `No compatibility_date was specified. Using the installed Workers runtime's latest supported date: ${currentDate}.\n` + "Add one to your wrangler.toml file:\n" + "```\n" + `compatibility_date = "${currentDate}"\n` + diff --git a/packages/wrangler/src/update-check.ts b/packages/wrangler/src/update-check.ts index 1592e9f81f12..5c316e5687ee 100644 --- a/packages/wrangler/src/update-check.ts +++ b/packages/wrangler/src/update-check.ts @@ -2,7 +2,7 @@ import checkForUpdate from "update-check"; import pkg from "../package.json"; import type { Result } from "update-check"; -export async function updateCheck(): Promise { +async function doUpdateCheck(): Promise { let update: Result | null = null; try { // default cache for update check is 1 day @@ -14,3 +14,11 @@ export async function updateCheck(): Promise { } return update?.latest; } + +// Memoise update check promise, so we can call this multiple times as required +// without having to prop drill the result. It's unlikely to change through the +// process lifetime. +let updateCheckPromise: Promise; +export function updateCheck(): Promise { + return (updateCheckPromise ??= doUpdateCheck()); +}