diff --git a/README.md b/README.md index 3ebec33e..05688f2a 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,9 @@ > [!NOTE] -> This tool is only used for managing [Deno Deploy Classic](https://docs.deno.com/deploy/classic/) organizations and their projects. New Deno Deploy organizations use the `deno deploy` command built into the Deno Runtime. Learn more about the new `deno deploy` command in the [reference docs](https://docs.deno.com/runtime/reference/cli/deploy/) +> This tool is only used for managing +> [Deno Deploy Classic](https://docs.deno.com/deploy/classic/) organizations and +> their projects. New Deno Deploy organizations use the `deno deploy` command +> built into the Deno Runtime. Learn more about the new `deno deploy` command in +> the [reference docs](https://docs.deno.com/runtime/reference/cli/deploy/) # deployctl diff --git a/deployctl.ts b/deployctl.ts index 58df3363..d438355d 100755 --- a/deployctl.ts +++ b/deployctl.ts @@ -6,7 +6,7 @@ import { greaterOrEqual as semverGreaterThanOrEquals, parse as semverParse, } from "@std/semver"; -import { setColorEnabled } from "@std/fmt/colors"; +import { bold, setColorEnabled, yellow } from "@std/fmt/colors"; import { type Args, parseArgs } from "./src/args.ts"; import { error } from "./src/error.ts"; import deploySubcommand from "./src/subcommands/deploy.ts"; @@ -23,7 +23,7 @@ import inferConfig from "./src/config_inference.ts"; import { wait } from "./src/utils/spinner.ts"; const help = `deployctl ${VERSION} -Command line tool for Deno Deploy. +Command line tool for Deno Deploy Classic. SUBCOMMANDS: deploy Deploy a script with static files to Deno Deploy @@ -99,6 +99,57 @@ if (Deno.stdin.isTerminal()) { } } +// Show a deprecation notice directing users to the new "deno deploy" command. +// - Interactive terminals: always show +// - Non-interactive (CI): show once per day, cached to disk +// - Set DEPLOYCTL_NO_DEPRECATION_NOTICE=1 to suppress entirely +if (!Deno.env.get("DEPLOYCTL_NO_DEPRECATION_NOTICE")) { + let showNotice = false; + + if (Deno.stdin.isTerminal()) { + showNotice = true; + } else { + // In non-interactive environments, only show once per day + const { deprecationNoticePath, configDir } = getConfigPaths(); + try { + const json = await Deno.readTextFile(deprecationNoticePath); + const { lastShown } = JSON.parse(json) as { lastShown: number }; + const moreThanADay = + Math.abs(Date.now() - lastShown) > 24 * 60 * 60 * 1000; + if (moreThanADay) { + showNotice = true; + } + } catch { + // File doesn't exist yet or is unreadable — show the notice + showNotice = true; + } + + if (showNotice) { + // Update the cache so we don't show again for 24 hours + try { + await Deno.mkdir(configDir, { recursive: true }); + await Deno.writeTextFile( + deprecationNoticePath, + JSON.stringify({ lastShown: Date.now() }, null, 2), + ); + } catch { + // Not critical — if we can't write the cache, the notice will + // just show again next time. + } + } + } + + if (showNotice) { + console.error( + yellow(bold("warning")) + + `: deployctl is for Deno Deploy Classic only.\n` + + ` For the new Deno Deploy, use the "deno deploy" command built into the Deno runtime.\n` + + ` Learn more: https://docs.deno.com/runtime/reference/cli/deploy/\n` + + ` To suppress this warning, set DEPLOYCTL_NO_DEPRECATION_NOTICE=1\n`, + ); + } +} + const subcommand = args._.shift(); switch (subcommand) { case "deploy": diff --git a/examples/fresh/static/logo.svg b/examples/fresh/static/logo.svg index ef2fbe4c..5b99e0b1 100644 --- a/examples/fresh/static/logo.svg +++ b/examples/fresh/static/logo.svg @@ -1,6 +1,19 @@ - - - - - \ No newline at end of file + + + + + diff --git a/src/utils/info.ts b/src/utils/info.ts index 37c4c707..181f9f73 100644 --- a/src/utils/info.ts +++ b/src/utils/info.ts @@ -11,6 +11,7 @@ export function getConfigPaths() { configDir, updatePath: join(configDir, "update.json"), credentialsPath: join(configDir, "credentials.json"), + deprecationNoticePath: join(configDir, "deprecation_notice.json"), }; }