Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions packages/cli-kit/src/private/node/conf-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -268,11 +268,12 @@ export async function runWithRateLimit(options: RunWithRateLimitOptions, config

/**
* Get auto-upgrade preference.
* Defaults to true if the preference has never been explicitly set.
*
* @returns Whether auto-upgrade is enabled, or undefined if never set.
* @returns Whether auto-upgrade is enabled.
*/
export function getAutoUpgradeEnabled(config: LocalStorage<ConfSchema> = cliKitStore()): boolean | undefined {
return config.get('autoUpgradeEnabled')
export function getAutoUpgradeEnabled(config: LocalStorage<ConfSchema> = cliKitStore()): boolean {
return config.get('autoUpgradeEnabled') ?? true
}

/**
Expand Down
6 changes: 3 additions & 3 deletions packages/cli-kit/src/public/node/upgrade.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,11 +230,11 @@ describe('versionToAutoUpgrade', () => {
expect(versionToAutoUpgrade()).toBeUndefined()
})

test('returns undefined when auto-upgrade preference has never been set', () => {
test('returns the newer version when auto-upgrade preference has never been set (default enabled)', () => {
vi.mocked(checkForCachedNewVersion).mockReturnValue('3.91.0')
vi.mocked(isCI).mockReturnValue(false)
vi.mocked(getAutoUpgradeEnabled).mockReturnValue(undefined)
expect(versionToAutoUpgrade()).toBeUndefined()
vi.mocked(getAutoUpgradeEnabled).mockReturnValue(true)
expect(versionToAutoUpgrade()).toBe('3.91.0')
})

test('returns the newer version for a major version change when auto-upgrade is enabled', () => {
Expand Down
21 changes: 1 addition & 20 deletions packages/cli-kit/src/public/node/upgrade.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
import {outputContent, outputDebug, outputInfo, outputToken, outputWarn} from './output.js'
import {cwd, moduleDirectory, sniffForPath} from './path.js'
import {exec, isCI} from './system.js'
import {renderConfirmationPrompt} from './ui.js'
import {isPreReleaseVersion} from './version.js'
import {getAutoUpgradeEnabled, setAutoUpgradeEnabled, runAtMinimumInterval} from '../../private/node/conf-store.js'
import {CLI_KIT_VERSION} from '../common/version.js'
Expand Down Expand Up @@ -81,7 +80,7 @@ export async function runCLIUpgrade(): Promise<void> {

/**
* Returns the version to auto-upgrade to, or undefined if auto-upgrade should be skipped.
* Auto-upgrade is disabled by default and must be enabled via `shopify upgrade`.
* Auto-upgrade is enabled by default and can be disabled via `setAutoUpgradeEnabled(false)`.
* Also skips for CI, pre-release versions, or when no newer version is available.
*
* @returns The version string to upgrade to, or undefined if no upgrade should happen.
Expand Down Expand Up @@ -154,24 +153,6 @@ export function getOutputUpdateCLIReminder(version: string, isMajor = false): st
return base
}

/**
* Prompts the user to enable or disable automatic upgrades, then persists their choice.
*
* @returns Whether the user chose to enable auto-upgrade.
*/
export async function promptAutoUpgrade(): Promise<boolean> {
const current = getAutoUpgradeEnabled()
if (current !== undefined) return current

const enabled = await renderConfirmationPrompt({
message: 'Enable automatic updates for Shopify CLI?',
confirmationMessage: 'Yes, automatically update',
cancellationMessage: "No, I'll update manually",
})
setAutoUpgradeEnabled(enabled)
return enabled
}

async function upgradeLocalShopify(projectDir: string, currentVersion: string) {
const packageJson = (await findUpAndReadPackageJson(projectDir)).content
const packageJsonDependencies = packageJson.dependencies ?? {}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
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
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ describe('AutoupgradeStatus', () => {
`)
})

test('displays not configured message when never set', async () => {
test('displays auto-upgrade on message when never explicitly set (default enabled)', async () => {
// Given
vi.mocked(getAutoUpgradeEnabled).mockReturnValue(undefined)
vi.mocked(getAutoUpgradeEnabled).mockReturnValue(true)
const config = new Config({root: __dirname})
const outputMock = mockAndCaptureOutput()
outputMock.clear()
Expand All @@ -63,8 +63,7 @@ describe('AutoupgradeStatus', () => {
expect(outputMock.info()).toMatchInlineSnapshot(`
"╭─ info ───────────────────────────────────────────────────────────────────────╮
│ │
│ Auto-upgrade not configured. Run \`shopify config autoupgrade on\` to enable │
│ it. │
│ Auto-upgrade on. Shopify CLI will update automatically after each command. │
│ │
╰──────────────────────────────────────────────────────────────────────────────╯
"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@ export default class AutoupgradeStatus extends Command {

async run(): Promise<void> {
const enabled = getAutoUpgradeEnabled()
if (enabled === undefined) {
renderInfo({body: autoUpgradeStatus.notConfigured})
} else if (enabled) {
if (enabled) {
renderInfo({body: autoUpgradeStatus.on})
} else {
renderInfo({body: autoUpgradeStatus.off})
Expand Down
36 changes: 3 additions & 33 deletions packages/cli/src/cli/commands/upgrade.test.ts
Original file line number Diff line number Diff line change
@@ -1,45 +1,15 @@
import Upgrade from './upgrade.js'
import {promptAutoUpgrade, runCLIUpgrade} from '@shopify/cli-kit/node/upgrade'
import {addPublicMetadata} from '@shopify/cli-kit/node/metadata'
import {describe, test, vi, expect, afterEach} from 'vitest'
import {runCLIUpgrade} from '@shopify/cli-kit/node/upgrade'
import {describe, test, vi, expect} from 'vitest'

vi.mock('@shopify/cli-kit/node/upgrade')
vi.mock('@shopify/cli-kit/node/metadata', () => ({
addPublicMetadata: vi.fn().mockResolvedValue(undefined),
}))

afterEach(() => {
vi.mocked(addPublicMetadata).mockClear()
})

describe('upgrade command', () => {
test('calls promptAutoUpgrade and runCLIUpgrade', async () => {
vi.mocked(promptAutoUpgrade).mockResolvedValue(true)
test('calls runCLIUpgrade directly without prompting', async () => {
vi.mocked(runCLIUpgrade).mockResolvedValue(undefined)

await Upgrade.run([], import.meta.url)

expect(promptAutoUpgrade).toHaveBeenCalledOnce()
expect(runCLIUpgrade).toHaveBeenCalledOnce()
})

test('records env_auto_upgrade_accepted=true when user opts in', async () => {
vi.mocked(promptAutoUpgrade).mockResolvedValue(true)
vi.mocked(runCLIUpgrade).mockResolvedValue(undefined)

await Upgrade.run([], import.meta.url)

const calls = vi.mocked(addPublicMetadata).mock.calls.map((call) => call[0]())
expect(calls).toContainEqual(expect.objectContaining({env_auto_upgrade_accepted: true}))
})

test('records env_auto_upgrade_accepted=false when user opts out', async () => {
vi.mocked(promptAutoUpgrade).mockResolvedValue(false)
vi.mocked(runCLIUpgrade).mockResolvedValue(undefined)

await Upgrade.run([], import.meta.url)

const calls = vi.mocked(addPublicMetadata).mock.calls.map((call) => call[0]())
expect(calls).toContainEqual(expect.objectContaining({env_auto_upgrade_accepted: false}))
})
})
5 changes: 1 addition & 4 deletions packages/cli/src/cli/commands/upgrade.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import Command from '@shopify/cli-kit/node/base-command'
import {promptAutoUpgrade, runCLIUpgrade} from '@shopify/cli-kit/node/upgrade'
import {addPublicMetadata} from '@shopify/cli-kit/node/metadata'
import {runCLIUpgrade} from '@shopify/cli-kit/node/upgrade'

export default class Upgrade extends Command {
static summary = 'Upgrades Shopify CLI.'
Expand All @@ -10,8 +9,6 @@ export default class Upgrade extends Command {
static description = this.descriptionWithoutMarkdown()

async run(): Promise<void> {
const accepted = await promptAutoUpgrade()
await addPublicMetadata(() => ({env_auto_upgrade_accepted: accepted}))
await runCLIUpgrade()
}
}
Loading