diff --git a/packages/cli-kit/src/public/node/upgrade.ts b/packages/cli-kit/src/public/node/upgrade.ts index 482d62ceff8..c121498584d 100644 --- a/packages/cli-kit/src/public/node/upgrade.ts +++ b/packages/cli-kit/src/public/node/upgrade.ts @@ -18,6 +18,8 @@ import {isPreReleaseVersion} from './version.js' import {getAutoUpgradeEnabled, setAutoUpgradeEnabled, runAtMinimumInterval} from '../../private/node/conf-store.js' import {CLI_KIT_VERSION} from '../common/version.js' +export {getAutoUpgradeEnabled, setAutoUpgradeEnabled} + /** * Utility function for generating an install command for the user to run * to install an updated version of Shopify CLI. @@ -158,6 +160,9 @@ export function getOutputUpdateCLIReminder(version: string, isMajor = false): st * @returns Whether the user chose to enable auto-upgrade. */ export async function promptAutoUpgrade(): Promise { + const current = getAutoUpgradeEnabled() + if (current !== undefined) return current + const enabled = await renderConfirmationPrompt({ message: 'Enable automatic updates for Shopify CLI?', confirmationMessage: 'Yes, automatically update', diff --git a/packages/cli/README.md b/packages/cli/README.md index 9a25dfeb007..54f76ab3515 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -36,6 +36,9 @@ * [`shopify config autocorrect off`](#shopify-config-autocorrect-off) * [`shopify config autocorrect on`](#shopify-config-autocorrect-on) * [`shopify config autocorrect status`](#shopify-config-autocorrect-status) +* [`shopify config autoupgrade off`](#shopify-config-autoupgrade-off) +* [`shopify config autoupgrade on`](#shopify-config-autoupgrade-on) +* [`shopify config autoupgrade status`](#shopify-config-autoupgrade-status) * [`shopify help [command] [flags]`](#shopify-help-command-flags) * [`shopify hydrogen build`](#shopify-hydrogen-build) * [`shopify hydrogen check RESOURCE`](#shopify-hydrogen-check-resource) @@ -1162,6 +1165,61 @@ DESCRIPTION When autocorrection is disabled, you need to confirm that you want to run corrections for mistyped commands. ``` +## `shopify config autoupgrade off` + +Disable automatic upgrades for Shopify CLI. + +``` +USAGE + $ shopify config autoupgrade off + +DESCRIPTION + Disable automatic upgrades for Shopify CLI. + + Disable automatic upgrades for Shopify CLI. + + When auto-upgrade is disabled, Shopify CLI won't automatically update. Run `shopify upgrade` to update manually. + + To enable auto-upgrade, run `shopify config autoupgrade on`. +``` + +## `shopify config autoupgrade on` + +Enable automatic upgrades for Shopify CLI. + +``` +USAGE + $ shopify config autoupgrade on + +DESCRIPTION + Enable automatic upgrades for Shopify CLI. + + Enable automatic upgrades for Shopify CLI. + + When auto-upgrade is enabled, Shopify CLI automatically updates to the latest version once per day. Major version + upgrades are skipped and must be done manually. + + To disable auto-upgrade, run `shopify config autoupgrade off`. +``` + +## `shopify config autoupgrade status` + +Check whether auto-upgrade is enabled, disabled, or not yet configured. + +``` +USAGE + $ shopify config autoupgrade status + +DESCRIPTION + Check whether auto-upgrade is enabled, disabled, or not yet configured. + + Check whether auto-upgrade is enabled, disabled, or not yet configured. + + When auto-upgrade is enabled, Shopify CLI automatically updates to the latest version after each command. + + Run `shopify config autoupgrade on` or `shopify config autoupgrade off` to configure it. +``` + ## `shopify help [command] [flags]` Display help for Shopify CLI diff --git a/packages/cli/oclif.manifest.json b/packages/cli/oclif.manifest.json index 82dbca3b896..2c6392432ce 100644 --- a/packages/cli/oclif.manifest.json +++ b/packages/cli/oclif.manifest.json @@ -3386,6 +3386,66 @@ "strict": true, "summary": "Check whether autocorrect is enabled or disabled. On by default." }, + "config:autoupgrade:off": { + "aliases": [ + ], + "args": { + }, + "description": "Disable automatic upgrades for Shopify CLI.\n\n When auto-upgrade is disabled, Shopify CLI won't automatically update. Run `shopify upgrade` to update manually.\n\n To enable auto-upgrade, run `shopify config autoupgrade on`.\n", + "descriptionWithMarkdown": "Disable automatic upgrades for Shopify CLI.\n\n When auto-upgrade is disabled, Shopify CLI won't automatically update. Run `shopify upgrade` to update manually.\n\n To enable auto-upgrade, run `shopify config autoupgrade on`.\n", + "enableJsonFlag": false, + "flags": { + }, + "hasDynamicHelp": false, + "hiddenAliases": [ + ], + "id": "config:autoupgrade:off", + "pluginAlias": "@shopify/cli", + "pluginName": "@shopify/cli", + "pluginType": "core", + "strict": true, + "summary": "Disable automatic upgrades for Shopify CLI." + }, + "config:autoupgrade:on": { + "aliases": [ + ], + "args": { + }, + "description": "Enable automatic upgrades for Shopify CLI.\n\n When auto-upgrade is enabled, Shopify CLI automatically updates to the latest version once per day. Major version upgrades are skipped and must be done manually.\n\n To disable auto-upgrade, run `shopify config autoupgrade off`.\n", + "descriptionWithMarkdown": "Enable automatic upgrades for Shopify CLI.\n\n When auto-upgrade is enabled, Shopify CLI automatically updates to the latest version once per day. Major version upgrades are skipped and must be done manually.\n\n To disable auto-upgrade, run `shopify config autoupgrade off`.\n", + "enableJsonFlag": false, + "flags": { + }, + "hasDynamicHelp": false, + "hiddenAliases": [ + ], + "id": "config:autoupgrade:on", + "pluginAlias": "@shopify/cli", + "pluginName": "@shopify/cli", + "pluginType": "core", + "strict": true, + "summary": "Enable automatic upgrades for Shopify CLI." + }, + "config:autoupgrade:status": { + "aliases": [ + ], + "args": { + }, + "description": "Check whether auto-upgrade is enabled, disabled, or not yet configured.\n\n When auto-upgrade is enabled, Shopify CLI automatically updates to the latest version after each command.\n\n Run `shopify config autoupgrade on` or `shopify config autoupgrade off` to configure it.\n", + "descriptionWithMarkdown": "Check whether auto-upgrade is enabled, disabled, or not yet configured.\n\n When auto-upgrade is enabled, Shopify CLI automatically updates to the latest version after each command.\n\n Run `shopify config autoupgrade on` or `shopify config autoupgrade off` to configure it.\n", + "enableJsonFlag": false, + "flags": { + }, + "hasDynamicHelp": false, + "hiddenAliases": [ + ], + "id": "config:autoupgrade:status", + "pluginAlias": "@shopify/cli", + "pluginName": "@shopify/cli", + "pluginType": "core", + "strict": true, + "summary": "Check whether auto-upgrade is enabled, disabled, or not yet configured." + }, "debug:command-flags": { "aliases": [ ], diff --git a/packages/cli/src/cli/commands/config/autoupgrade/constants.ts b/packages/cli/src/cli/commands/config/autoupgrade/constants.ts new file mode 100644 index 00000000000..3c217d9c477 --- /dev/null +++ b/packages/cli/src/cli/commands/config/autoupgrade/constants.ts @@ -0,0 +1,5 @@ +export const autoUpgradeStatus = { + on: 'Auto-upgrade on. Shopify CLI will update automatically after each command.', + off: "Auto-upgrade off. You'll need to run `shopify upgrade` to update manually.", + notConfigured: 'Auto-upgrade not configured. Run `shopify config autoupgrade on` to enable it.', +} as const diff --git a/packages/cli/src/cli/commands/config/autoupgrade/off.test.ts b/packages/cli/src/cli/commands/config/autoupgrade/off.test.ts new file mode 100644 index 00000000000..4817cb3b9c2 --- /dev/null +++ b/packages/cli/src/cli/commands/config/autoupgrade/off.test.ts @@ -0,0 +1,29 @@ +import AutoupgradeOff from './off.js' +import {setAutoUpgradeEnabled} from '@shopify/cli-kit/node/upgrade' +import {Config} from '@oclif/core' +import {describe, expect, vi, test} from 'vitest' +import {mockAndCaptureOutput} from '@shopify/cli-kit/node/testing/output' + +vi.mock('@shopify/cli-kit/node/upgrade') + +describe('AutoupgradeOff', () => { + test('disables auto-upgrade', async () => { + // Given + const config = new Config({root: __dirname}) + const outputMock = mockAndCaptureOutput() + + // When + await new AutoupgradeOff([], config).run() + + // Then + expect(setAutoUpgradeEnabled).toBeCalledWith(false) + expect(outputMock.info()).toMatchInlineSnapshot(` + "╭─ info ───────────────────────────────────────────────────────────────────────╮ + │ │ + │ Auto-upgrade off. You'll need to run \`shopify upgrade\` to update manually. │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────╯ + " + `) + }) +}) diff --git a/packages/cli/src/cli/commands/config/autoupgrade/off.ts b/packages/cli/src/cli/commands/config/autoupgrade/off.ts new file mode 100644 index 00000000000..533ad6dbe39 --- /dev/null +++ b/packages/cli/src/cli/commands/config/autoupgrade/off.ts @@ -0,0 +1,22 @@ +import {autoUpgradeStatus} from './constants.js' +import {setAutoUpgradeEnabled} from '@shopify/cli-kit/node/upgrade' +import Command from '@shopify/cli-kit/node/base-command' +import {renderInfo} from '@shopify/cli-kit/node/ui' + +export default class AutoupgradeOff extends Command { + static summary = 'Disable automatic upgrades for Shopify CLI.' + + static descriptionWithMarkdown = `Disable automatic upgrades for Shopify CLI. + + When auto-upgrade is disabled, Shopify CLI won't automatically update. Run \`shopify upgrade\` to update manually. + + To enable auto-upgrade, run \`shopify config autoupgrade on\`. +` + + static description = this.descriptionWithoutMarkdown() + + async run(): Promise { + setAutoUpgradeEnabled(false) + renderInfo({body: autoUpgradeStatus.off}) + } +} diff --git a/packages/cli/src/cli/commands/config/autoupgrade/on.test.ts b/packages/cli/src/cli/commands/config/autoupgrade/on.test.ts new file mode 100644 index 00000000000..76c4a83bd8d --- /dev/null +++ b/packages/cli/src/cli/commands/config/autoupgrade/on.test.ts @@ -0,0 +1,29 @@ +import AutoupgradeOn from './on.js' +import {setAutoUpgradeEnabled} from '@shopify/cli-kit/node/upgrade' +import {Config} from '@oclif/core' +import {describe, expect, vi, test} from 'vitest' +import {mockAndCaptureOutput} from '@shopify/cli-kit/node/testing/output' + +vi.mock('@shopify/cli-kit/node/upgrade') + +describe('AutoupgradeOn', () => { + test('enables auto-upgrade', async () => { + // Given + const config = new Config({root: __dirname}) + const outputMock = mockAndCaptureOutput() + + // When + await new AutoupgradeOn([], config).run() + + // Then + expect(setAutoUpgradeEnabled).toBeCalledWith(true) + expect(outputMock.info()).toMatchInlineSnapshot(` + "╭─ info ───────────────────────────────────────────────────────────────────────╮ + │ │ + │ Auto-upgrade on. Shopify CLI will update automatically after each command. │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────╯ + " + `) + }) +}) diff --git a/packages/cli/src/cli/commands/config/autoupgrade/on.ts b/packages/cli/src/cli/commands/config/autoupgrade/on.ts new file mode 100644 index 00000000000..aeac1a3d8b4 --- /dev/null +++ b/packages/cli/src/cli/commands/config/autoupgrade/on.ts @@ -0,0 +1,22 @@ +import {autoUpgradeStatus} from './constants.js' +import {setAutoUpgradeEnabled} from '@shopify/cli-kit/node/upgrade' +import Command from '@shopify/cli-kit/node/base-command' +import {renderInfo} from '@shopify/cli-kit/node/ui' + +export default class AutoupgradeOn extends Command { + static summary = 'Enable automatic upgrades for Shopify CLI.' + + static descriptionWithMarkdown = `Enable automatic upgrades for Shopify CLI. + + When auto-upgrade is enabled, Shopify CLI automatically updates to the latest version once per day. Major version upgrades are skipped and must be done manually. + + To disable auto-upgrade, run \`shopify config autoupgrade off\`. +` + + static description = this.descriptionWithoutMarkdown() + + async run(): Promise { + setAutoUpgradeEnabled(true) + renderInfo({body: autoUpgradeStatus.on}) + } +} diff --git a/packages/cli/src/cli/commands/config/autoupgrade/status.test.ts b/packages/cli/src/cli/commands/config/autoupgrade/status.test.ts new file mode 100644 index 00000000000..f869a935f7c --- /dev/null +++ b/packages/cli/src/cli/commands/config/autoupgrade/status.test.ts @@ -0,0 +1,73 @@ +import AutoupgradeStatus from './status.js' +import {getAutoUpgradeEnabled} from '@shopify/cli-kit/node/upgrade' +import {Config} from '@oclif/core' +import {describe, expect, vi, test} from 'vitest' +import {mockAndCaptureOutput} from '@shopify/cli-kit/node/testing/output' + +vi.mock('@shopify/cli-kit/node/upgrade') + +describe('AutoupgradeStatus', () => { + test('displays auto-upgrade on message when enabled', async () => { + // Given + vi.mocked(getAutoUpgradeEnabled).mockReturnValue(true) + const config = new Config({root: __dirname}) + const outputMock = mockAndCaptureOutput() + outputMock.clear() + + // When + await new AutoupgradeStatus([], config).run() + + // Then + expect(outputMock.info()).toMatchInlineSnapshot(` + "╭─ info ───────────────────────────────────────────────────────────────────────╮ + │ │ + │ Auto-upgrade on. Shopify CLI will update automatically after each command. │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────╯ + " + `) + }) + + test('displays auto-upgrade off message when disabled', async () => { + // Given + vi.mocked(getAutoUpgradeEnabled).mockReturnValue(false) + const config = new Config({root: __dirname}) + const outputMock = mockAndCaptureOutput() + outputMock.clear() + + // When + await new AutoupgradeStatus([], config).run() + + // Then + expect(outputMock.info()).toMatchInlineSnapshot(` + "╭─ info ───────────────────────────────────────────────────────────────────────╮ + │ │ + │ Auto-upgrade off. You'll need to run \`shopify upgrade\` to update manually. │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────╯ + " + `) + }) + + test('displays not configured message when never set', async () => { + // Given + vi.mocked(getAutoUpgradeEnabled).mockReturnValue(undefined) + const config = new Config({root: __dirname}) + const outputMock = mockAndCaptureOutput() + outputMock.clear() + + // When + await new AutoupgradeStatus([], config).run() + + // Then + expect(outputMock.info()).toMatchInlineSnapshot(` + "╭─ info ───────────────────────────────────────────────────────────────────────╮ + │ │ + │ Auto-upgrade not configured. Run \`shopify config autoupgrade on\` to enable │ + │ it. │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────╯ + " + `) + }) +}) diff --git a/packages/cli/src/cli/commands/config/autoupgrade/status.ts b/packages/cli/src/cli/commands/config/autoupgrade/status.ts new file mode 100644 index 00000000000..c87ddc10dee --- /dev/null +++ b/packages/cli/src/cli/commands/config/autoupgrade/status.ts @@ -0,0 +1,28 @@ +import {autoUpgradeStatus} from './constants.js' +import {getAutoUpgradeEnabled} from '@shopify/cli-kit/node/upgrade' +import Command from '@shopify/cli-kit/node/base-command' +import {renderInfo} from '@shopify/cli-kit/node/ui' + +export default class AutoupgradeStatus extends Command { + static summary = 'Check whether auto-upgrade is enabled, disabled, or not yet configured.' + + static descriptionWithMarkdown = `Check whether auto-upgrade is enabled, disabled, or not yet configured. + + When auto-upgrade is enabled, Shopify CLI automatically updates to the latest version after each command. + + Run \`shopify config autoupgrade on\` or \`shopify config autoupgrade off\` to configure it. +` + + static description = this.descriptionWithoutMarkdown() + + async run(): Promise { + const enabled = getAutoUpgradeEnabled() + if (enabled === undefined) { + renderInfo({body: autoUpgradeStatus.notConfigured}) + } else if (enabled) { + renderInfo({body: autoUpgradeStatus.on}) + } else { + renderInfo({body: autoUpgradeStatus.off}) + } + } +} diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index 429836541d0..04de2fd4933 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -17,6 +17,9 @@ import Generate from './cli/commands/notifications/generate.js' import ClearCache from './cli/commands/cache/clear.js' import StoreAuth from './cli/commands/store/auth.js' import StoreExecute from './cli/commands/store/execute.js' +import AutoupgradeOff from './cli/commands/config/autoupgrade/off.js' +import AutoupgradeOn from './cli/commands/config/autoupgrade/on.js' +import AutoupgradeStatus from './cli/commands/config/autoupgrade/status.js' import {createGlobalProxyAgent} from 'global-agent' import ThemeCommands from '@shopify/theme' import {COMMANDS as HydrogenCommands, HOOKS as HydrogenHooks} from '@shopify/cli-hydrogen' @@ -154,6 +157,9 @@ export const COMMANDS: any = { 'cache:clear': ClearCache, 'store:auth': StoreAuth, 'store:execute': StoreExecute, + 'config:autoupgrade:off': AutoupgradeOff, + 'config:autoupgrade:on': AutoupgradeOn, + 'config:autoupgrade:status': AutoupgradeStatus, } export default runShopifyCLI