From 4ef30a0ae1210c541953d85090fe2e47f67d48aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Isaac=20Rold=C3=A1n?= Date: Tue, 6 Oct 2026 10:22:20 +0200 Subject: [PATCH] Add typed JSON output to config autoupgrade status --- .changeset/auto-upgrade-status-json.md | 5 + .../generated/generated_docs_data_v2.json | 38 ++++- packages/cli/README.md | 40 ++++- packages/cli/oclif.manifest.json | 34 ++++- .../config/autoupgrade/autoupgrade.test.ts | 142 ++++++++++++++++++ .../config/autoupgrade/status.test.ts | 10 +- .../cli/commands/config/autoupgrade/status.ts | 25 +-- .../commands/config/autoupgrade/index.test.ts | 40 +++++ .../commands/config/autoupgrade/index.ts | 6 + .../config/autoupgrade/result.test.ts | 50 ++++++ .../commands/config/autoupgrade/result.ts | 16 ++ .../commands/config/autoupgrade/types.ts | 9 ++ .../rules/json-output-command-exceptions.js | 1 - 13 files changed, 396 insertions(+), 20 deletions(-) create mode 100644 .changeset/auto-upgrade-status-json.md create mode 100644 packages/cli/src/cli/commands/config/autoupgrade/autoupgrade.test.ts create mode 100644 packages/cli/src/cli/services/commands/config/autoupgrade/index.test.ts create mode 100644 packages/cli/src/cli/services/commands/config/autoupgrade/index.ts create mode 100644 packages/cli/src/cli/services/commands/config/autoupgrade/result.test.ts create mode 100644 packages/cli/src/cli/services/commands/config/autoupgrade/result.ts create mode 100644 packages/cli/src/cli/services/commands/config/autoupgrade/types.ts diff --git a/.changeset/auto-upgrade-status-json.md b/.changeset/auto-upgrade-status-json.md new file mode 100644 index 00000000000..322f944b1e6 --- /dev/null +++ b/.changeset/auto-upgrade-status-json.md @@ -0,0 +1,5 @@ +--- +'@shopify/cli': minor +--- + +Add typed JSON output to `config autoupgrade status`. diff --git a/docs-shopify.dev/generated/generated_docs_data_v2.json b/docs-shopify.dev/generated/generated_docs_data_v2.json index 9b687d4a245..cb35de0a99a 100644 --- a/docs-shopify.dev/generated/generated_docs_data_v2.json +++ b/docs-shopify.dev/generated/generated_docs_data_v2.json @@ -4401,9 +4401,45 @@ "description": "Print the command's JSON schemas.", "isOptional": true, "environmentValue": "SHOPIFY_FLAG_JSON_SCHEMA" + }, + { + "filePath": "docs-shopify.dev/commands/interfaces/config-autoupgrade-status.interface.ts", + "syntaxKind": "PropertySignature", + "name": "--no-color", + "value": "''", + "description": "Disable color output.", + "isOptional": true, + "environmentValue": "SHOPIFY_FLAG_NO_COLOR" + }, + { + "filePath": "docs-shopify.dev/commands/interfaces/config-autoupgrade-status.interface.ts", + "syntaxKind": "PropertySignature", + "name": "--no-input", + "value": "''", + "description": "Disable interactive prompts and browser authentication.", + "isOptional": true, + "environmentValue": "SHOPIFY_FLAG_NO_INPUT" + }, + { + "filePath": "docs-shopify.dev/commands/interfaces/config-autoupgrade-status.interface.ts", + "syntaxKind": "PropertySignature", + "name": "--verbose", + "value": "''", + "description": "Increase the verbosity of the output. May include sensitive data.", + "isOptional": true, + "environmentValue": "SHOPIFY_FLAG_VERBOSE" + }, + { + "filePath": "docs-shopify.dev/commands/interfaces/config-autoupgrade-status.interface.ts", + "syntaxKind": "PropertySignature", + "name": "-j, --json", + "value": "''", + "description": "Output the result as JSON. Automatically disables color output.", + "isOptional": true, + "environmentValue": "SHOPIFY_FLAG_JSON" } ], - "value": "export interface configautoupgradestatus {\n /**\n * Print the command's JSON schemas.\n * @environment SHOPIFY_FLAG_JSON_SCHEMA\n */\n '--json-schema'?: ''\n}" + "value": "export interface configautoupgradestatus {\n /**\n * Output the result as JSON. Automatically disables color output.\n * @environment SHOPIFY_FLAG_JSON\n */\n '-j, --json'?: ''\n\n /**\n * Print the command's JSON schemas.\n * @environment SHOPIFY_FLAG_JSON_SCHEMA\n */\n '--json-schema'?: ''\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * Disable interactive prompts and browser authentication.\n * @environment SHOPIFY_FLAG_NO_INPUT\n */\n '--no-input'?: ''\n\n /**\n * Increase the verbosity of the output. May include sensitive data.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n}" } }, "docfetch": { diff --git a/packages/cli/README.md b/packages/cli/README.md index 2512c38bcd4..4a506d0561d 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -3902,13 +3902,29 @@ Check whether auto-upgrade is enabled, disabled, or not yet configured. ``` USAGE - $ shopify config autoupgrade status [--json-schema] + $ shopify config autoupgrade status [-j] [--json-schema] [--no-color] [--no-input] [--verbose] FLAGS + -j, --json + Output the result as JSON. Automatically disables color output. + [env: SHOPIFY_FLAG_JSON] + --json-schema Print the command's JSON schemas. [env: SHOPIFY_FLAG_JSON_SCHEMA] + --no-color + Disable color output. + [env: SHOPIFY_FLAG_NO_COLOR] + + --no-input + Disable interactive prompts and browser authentication. + [env: SHOPIFY_FLAG_NO_INPUT] + + --verbose + Increase the verbosity of the output. May include sensitive data. + [env: SHOPIFY_FLAG_VERBOSE] + DESCRIPTION Check whether auto-upgrade is enabled, disabled, or not yet configured. @@ -3917,6 +3933,28 @@ DESCRIPTION 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. + + + Use `--json-schema` to print the result, error, and event schemas. + + Output from `--json` conforms to the `AutoUpgradeResult` schema. + + ```json + { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + } + }, + "required": [ + "enabled" + ], + "additionalProperties": false, + "title": "AutoUpgradeResult", + "$schema": "http://json-schema.org/draft-07/schema#" + } + ``` ``` ## `shopify doc fetch` diff --git a/packages/cli/oclif.manifest.json b/packages/cli/oclif.manifest.json index 23379d0440f..2afa43d8a84 100644 --- a/packages/cli/oclif.manifest.json +++ b/packages/cli/oclif.manifest.json @@ -5858,16 +5858,48 @@ ], "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", + "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\n\nUse `--json-schema` to print the result, error, and event schemas.\n\nOutput from `--json` conforms to the `AutoUpgradeResult` schema.\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"enabled\": {\n \"type\": \"boolean\"\n }\n },\n \"required\": [\n \"enabled\"\n ],\n \"additionalProperties\": false,\n \"title\": \"AutoUpgradeResult\",\n \"$schema\": \"http://json-schema.org/draft-07/schema#\"\n}\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": { + "json": { + "allowNo": false, + "char": "j", + "description": "Output the result as JSON. Automatically disables color output.", + "env": "SHOPIFY_FLAG_JSON", + "hidden": false, + "name": "json", + "type": "boolean" + }, "json-schema": { "allowNo": false, "description": "Print the command's JSON schemas.", "env": "SHOPIFY_FLAG_JSON_SCHEMA", "name": "json-schema", "type": "boolean" + }, + "no-color": { + "allowNo": false, + "description": "Disable color output.", + "env": "SHOPIFY_FLAG_NO_COLOR", + "hidden": false, + "name": "no-color", + "type": "boolean" + }, + "no-input": { + "allowNo": false, + "description": "Disable interactive prompts and browser authentication.", + "env": "SHOPIFY_FLAG_NO_INPUT", + "name": "no-input", + "type": "boolean" + }, + "verbose": { + "allowNo": false, + "description": "Increase the verbosity of the output. May include sensitive data.", + "env": "SHOPIFY_FLAG_VERBOSE", + "hidden": false, + "name": "verbose", + "type": "boolean" } }, "hasDynamicHelp": false, diff --git a/packages/cli/src/cli/commands/config/autoupgrade/autoupgrade.test.ts b/packages/cli/src/cli/commands/config/autoupgrade/autoupgrade.test.ts new file mode 100644 index 00000000000..42f7ef95bcc --- /dev/null +++ b/packages/cli/src/cli/commands/config/autoupgrade/autoupgrade.test.ts @@ -0,0 +1,142 @@ +import AutoupgradeStatus from './status.js' +import {autoUpgradeJsonOutputSchema} from '../../../services/commands/config/autoupgrade/types.js' +import {getAutoUpgradeEnabled, setAutoUpgradeEnabled} from '@shopify/cli-kit/node/upgrade' +import {launchCLI} from '@shopify/cli-kit/node/cli-launcher' +import {ShopifyConfig} from '@shopify/cli-kit/node/custom-oclif-loader' +import {AbortError} from '@shopify/cli-kit/node/error' +import {outputWarn} from '@shopify/cli-kit/node/output' +import {mockAndCaptureOutput, withCapturedStandardStreams} from '@shopify/cli-kit/node/testing/output' +import {beforeEach, afterEach, expect, test, vi} from 'vitest' + +vi.mock('@shopify/cli-kit/node/upgrade') + +beforeEach(() => { + vi.stubEnv('CI', '1') + vi.stubEnv('SHOPIFY_CLI_NO_ANALYTICS', '1') + vi.spyOn(ShopifyConfig.prototype, 'runHook').mockResolvedValue({successes: [], failures: []}) +}) + +afterEach(() => { + vi.unstubAllEnvs() + mockAndCaptureOutput().clear() +}) + +const commands = [{name: 'status', command: AutoupgradeStatus, enabled: false}] + +test.each(commands)('$name exposes the result schema and JSON flags in help', ({command}) => { + expect(command.jsonOutputSchema).toBe(autoUpgradeJsonOutputSchema) + expect(command.flags.json.char).toBe('j') + expect(command.description).toContain('Output from `--json` conforms to the `AutoUpgradeResult` schema.') + expect(command.description).toContain('"enabled"') +}) + +test.each(commands)('$name writes one JSON document through the real launcher', async ({name, command, enabled}) => { + vi.mocked(getAutoUpgradeEnabled).mockReturnValue(enabled) + + await withCapturedStandardStreams(async ({stdout, stderr}) => { + await launchCLI({ + moduleURL: import.meta.url, + argv: ['config', 'autoupgrade', name, '--json'], + lazyCommandLoader: async () => command, + }) + + expect(stdout()).toBe(`${JSON.stringify({enabled}, null, 2)}\n`) + expect(JSON.parse(stdout())).toEqual({enabled}) + expect(stderr()).toBe('') + if (name === 'status') { + expect(setAutoUpgradeEnabled).not.toHaveBeenCalled() + } else { + expect(setAutoUpgradeEnabled).toHaveBeenCalledExactlyOnceWith(enabled) + } + }) +}) + +test.each(commands)('$name discovers the schema without changing configuration', async ({name, command}) => { + await withCapturedStandardStreams(async ({stdout, stderr}) => { + await launchCLI({ + moduleURL: import.meta.url, + argv: ['config', 'autoupgrade', name, '--json-schema'], + lazyCommandLoader: async () => command, + }) + + expect(JSON.parse(stdout()).definitions.Result).toMatchObject({ + type: 'object', + properties: {enabled: {type: 'boolean'}}, + required: ['enabled'], + additionalProperties: false, + }) + expect(stderr()).toBe('') + expect(setAutoUpgradeEnabled).not.toHaveBeenCalled() + expect(getAutoUpgradeEnabled).not.toHaveBeenCalled() + }) +}) + +test.each([ + {args: ['-j'], json: true}, + {args: ['--json', '--no-input'], json: true}, + {args: ['--no-input'], json: false}, +])('selects JSON independently from input policy for $args', async ({args, json}) => { + vi.mocked(getAutoUpgradeEnabled).mockReturnValue(true) + + await withCapturedStandardStreams(async ({stdout, stderr}) => { + await AutoupgradeStatus.run(args, import.meta.url) + + if (json) { + expect(JSON.parse(stdout())).toEqual({enabled: true}) + expect(stderr()).toBe('') + } else { + expect(stdout()).toBe('') + expect(stderr()).toContain('Auto-upgrade on.') + } + }) +}) + +test('selects JSON from SHOPIFY_FLAG_JSON', async () => { + vi.stubEnv('SHOPIFY_FLAG_JSON', '1') + vi.mocked(getAutoUpgradeEnabled).mockReturnValue(true) + + await withCapturedStandardStreams(async ({stdout, stderr}) => { + await AutoupgradeStatus.run([], import.meta.url) + + expect(JSON.parse(stdout())).toEqual({enabled: true}) + expect(stderr()).toBe('') + }) +}) + +test('keeps diagnostic events on stderr and out of the final result', async () => { + vi.mocked(getAutoUpgradeEnabled).mockImplementation(() => { + outputWarn('Configuration diagnostic') + return false + }) + + await withCapturedStandardStreams(async ({stdout, stderr}) => { + await AutoupgradeStatus.run(['--json'], import.meta.url) + + expect(JSON.parse(stdout())).toEqual({enabled: false}) + expect(JSON.parse(stderr())).toMatchObject({ + type: 'diagnostic', + level: 'warning', + message: 'Configuration diagnostic', + }) + }) +}) + +test.each(commands)('$name uses the standard fatal error output without a success result', async ({command, name}) => { + vi.stubEnv('SHOPIFY_FLAG_JSON', '1') + const error = new AbortError('Cannot access auto-upgrade preference.') + const exit = vi.spyOn(process, 'exit').mockReturnValue(undefined as never) + const operation = name === 'status' ? getAutoUpgradeEnabled : setAutoUpgradeEnabled + vi.mocked(operation).mockImplementation(() => { + throw error + }) + + await withCapturedStandardStreams(async ({stdout, stderr}) => { + await command.run(['--json'], import.meta.url) + + expect(JSON.parse(stdout())).toEqual({ + error: {type: 'abort', message: 'Cannot access auto-upgrade preference.'}, + }) + expect(stderr()).toBe('') + expect(exit).toHaveBeenCalledExactlyOnceWith(1) + }) +}) diff --git a/packages/cli/src/cli/commands/config/autoupgrade/status.test.ts b/packages/cli/src/cli/commands/config/autoupgrade/status.test.ts index 64eb4bf456d..4c6e810bbc6 100644 --- a/packages/cli/src/cli/commands/config/autoupgrade/status.test.ts +++ b/packages/cli/src/cli/commands/config/autoupgrade/status.test.ts @@ -1,6 +1,5 @@ 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' @@ -10,12 +9,11 @@ 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() + await AutoupgradeStatus.run([], import.meta.url) // Then expect(outputMock.info()).toMatchInlineSnapshot(` @@ -31,12 +29,11 @@ describe('AutoupgradeStatus', () => { 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() + await AutoupgradeStatus.run([], import.meta.url) // Then expect(outputMock.info()).toMatchInlineSnapshot(` @@ -52,12 +49,11 @@ describe('AutoupgradeStatus', () => { test('displays auto-upgrade on message when never explicitly set (default 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() + await AutoupgradeStatus.run([], import.meta.url) // Then expect(outputMock.info()).toMatchInlineSnapshot(` diff --git a/packages/cli/src/cli/commands/config/autoupgrade/status.ts b/packages/cli/src/cli/commands/config/autoupgrade/status.ts index 4db65534bef..29a65e3b51d 100644 --- a/packages/cli/src/cli/commands/config/autoupgrade/status.ts +++ b/packages/cli/src/cli/commands/config/autoupgrade/status.ts @@ -1,7 +1,8 @@ -import {autoUpgradeStatus} from './constants.js' -import {getAutoUpgradeEnabled} from '@shopify/cli-kit/node/upgrade' +import {getAutoUpgradeStatus} from '../../../services/commands/config/autoupgrade/index.js' +import {presentAutoUpgradeResult} from '../../../services/commands/config/autoupgrade/result.js' +import {autoUpgradeJsonOutputSchema} from '../../../services/commands/config/autoupgrade/types.js' import Command from '@shopify/cli-kit/node/base-command' -import {renderInfo} from '@shopify/cli-kit/node/ui' +import {globalFlags, jsonFlag} from '@shopify/cli-kit/node/cli' export default class AutoupgradeStatus extends Command { static summary = 'Check whether auto-upgrade is enabled, disabled, or not yet configured.' @@ -15,12 +16,18 @@ export default class AutoupgradeStatus extends Command { static description = this.descriptionForHelp() + static flags = { + ...globalFlags, + ...jsonFlag, + } + + static get jsonOutputSchema() { + return autoUpgradeJsonOutputSchema + } + async run(): Promise { - const enabled = getAutoUpgradeEnabled() - if (enabled) { - renderInfo({body: autoUpgradeStatus.on}) - } else { - renderInfo({body: autoUpgradeStatus.off}) - } + const {flags} = await this.parse(AutoupgradeStatus) + const result = getAutoUpgradeStatus() + presentAutoUpgradeResult(result, flags.json ? 'json' : 'text') } } diff --git a/packages/cli/src/cli/services/commands/config/autoupgrade/index.test.ts b/packages/cli/src/cli/services/commands/config/autoupgrade/index.test.ts new file mode 100644 index 00000000000..3412c9784de --- /dev/null +++ b/packages/cli/src/cli/services/commands/config/autoupgrade/index.test.ts @@ -0,0 +1,40 @@ +import {getAutoUpgradeStatus} from './index.js' +import * as upgrade from '@shopify/cli-kit/node/upgrade' +import {LocalStorage} from '@shopify/cli-kit/node/local-storage' +import {inTemporaryDirectory} from '@shopify/cli-kit/node/fs' +import {mockAndCaptureOutput} from '@shopify/cli-kit/node/testing/output' +import {afterEach, expect, test, vi} from 'vitest' + +afterEach(() => { + mockAndCaptureOutput().clear() +}) + +test('returns the default and persisted preferences without presenting output', async () => { + await inTemporaryDirectory(async (directory) => { + const storage = new LocalStorage<{sessionStore: string; autoUpgradeEnabled?: boolean}>({cwd: directory}) + const {getAutoUpgradeEnabled, setAutoUpgradeEnabled} = upgrade + vi.spyOn(upgrade, 'getAutoUpgradeEnabled').mockImplementation(() => getAutoUpgradeEnabled(storage)) + const output = mockAndCaptureOutput() + + expect(getAutoUpgradeStatus()).toEqual({enabled: true}) + + for (const enabled of [false, true]) { + setAutoUpgradeEnabled(enabled, storage) + expect(getAutoUpgradeStatus()).toEqual({enabled}) + const reloadedStorage = new LocalStorage<{sessionStore: string; autoUpgradeEnabled?: boolean}>({cwd: directory}) + expect(reloadedStorage.get('autoUpgradeEnabled')).toBe(enabled) + } + + expect(output.output()).toBe('') + expect(output.info()).toBe('') + }) +}) + +test('propagates a configuration read failure', () => { + const error = new Error('Cannot read auto-upgrade preference.') + vi.spyOn(upgrade, 'getAutoUpgradeEnabled').mockImplementation(() => { + throw error + }) + + expect(() => getAutoUpgradeStatus()).toThrow(error) +}) diff --git a/packages/cli/src/cli/services/commands/config/autoupgrade/index.ts b/packages/cli/src/cli/services/commands/config/autoupgrade/index.ts new file mode 100644 index 00000000000..72e50603fcd --- /dev/null +++ b/packages/cli/src/cli/services/commands/config/autoupgrade/index.ts @@ -0,0 +1,6 @@ +import {getAutoUpgradeEnabled} from '@shopify/cli-kit/node/upgrade' +import type {AutoUpgradeResult} from './types.js' + +export function getAutoUpgradeStatus(): AutoUpgradeResult { + return {enabled: getAutoUpgradeEnabled()} +} diff --git a/packages/cli/src/cli/services/commands/config/autoupgrade/result.test.ts b/packages/cli/src/cli/services/commands/config/autoupgrade/result.test.ts new file mode 100644 index 00000000000..d02d90249eb --- /dev/null +++ b/packages/cli/src/cli/services/commands/config/autoupgrade/result.test.ts @@ -0,0 +1,50 @@ +import {presentAutoUpgradeResult} from './result.js' +import {autoUpgradeJsonOutputSchema} from './types.js' +import {mockAndCaptureOutput, withCapturedStandardStreams} from '@shopify/cli-kit/node/testing/output' +import {afterEach, expect, test} from 'vitest' + +afterEach(() => { + mockAndCaptureOutput().clear() +}) + +test.each([true, false])('encodes the enabled preference %s', (enabled) => { + expect(autoUpgradeJsonOutputSchema.encode({enabled})).toBe(JSON.stringify({enabled}, null, 2)) +}) + +test.each([{}, {enabled: 'false'}, {enabled: null}, {enabled: false, message: 'disabled'}])( + 'rejects an invalid result %j', + (value) => { + expect(() => autoUpgradeJsonOutputSchema.validate(value)).toThrow() + }, +) + +test('declares a closed result with a required boolean', () => { + expect(autoUpgradeJsonOutputSchema.jsonSchema).toMatchObject({ + type: 'object', + properties: {enabled: {type: 'boolean'}}, + required: ['enabled'], + additionalProperties: false, + }) +}) + +test.each([true, false])('writes one JSON result for preference %s without a terminal banner', async (enabled) => { + await withCapturedStandardStreams(({stdout, stderr}) => { + presentAutoUpgradeResult({enabled}, 'json') + + expect(stdout()).toBe(`${JSON.stringify({enabled}, null, 2)}\n`) + expect(JSON.parse(stdout())).toEqual({enabled}) + expect(stderr()).toBe('') + }) +}) + +test.each([ + [true, 'Auto-upgrade on. Shopify CLI will update automatically after each command.'], + [false, "Auto-upgrade off. You'll need to run `shopify upgrade` to update manually."], +] as const)('keeps text presentation on stderr for preference %s', async (enabled, message) => { + await withCapturedStandardStreams(({stdout, stderr}) => { + presentAutoUpgradeResult({enabled}, 'text') + + expect(stdout()).toBe('') + expect(stderr()).toContain(message) + }) +}) diff --git a/packages/cli/src/cli/services/commands/config/autoupgrade/result.ts b/packages/cli/src/cli/services/commands/config/autoupgrade/result.ts new file mode 100644 index 00000000000..eda65ec1140 --- /dev/null +++ b/packages/cli/src/cli/services/commands/config/autoupgrade/result.ts @@ -0,0 +1,16 @@ +import {autoUpgradeJsonOutputSchema, type AutoUpgradeResult} from './types.js' +import {outputResult} from '@shopify/cli-kit/node/output' +import {renderInfo} from '@shopify/cli-kit/node/ui' + +export function presentAutoUpgradeResult(result: AutoUpgradeResult, format: 'json' | 'text'): void { + if (format === 'json') { + outputResult(autoUpgradeJsonOutputSchema.encode({enabled: result.enabled})) + return + } + + renderInfo({ + body: result.enabled + ? 'Auto-upgrade on. Shopify CLI will update automatically after each command.' + : "Auto-upgrade off. You'll need to run `shopify upgrade` to update manually.", + }) +} diff --git a/packages/cli/src/cli/services/commands/config/autoupgrade/types.ts b/packages/cli/src/cli/services/commands/config/autoupgrade/types.ts new file mode 100644 index 00000000000..174c867a8ce --- /dev/null +++ b/packages/cli/src/cli/services/commands/config/autoupgrade/types.ts @@ -0,0 +1,9 @@ +import {defineJsonOutputSchema, type InferJsonOutputSchema} from '@shopify/cli-kit/node/json-output-schema' +import {zod} from '@shopify/cli-kit/node/schema' + +export const autoUpgradeJsonOutputSchema = defineJsonOutputSchema({ + name: 'AutoUpgradeResult', + schema: zod.object({enabled: zod.boolean()}).strict(), +}) + +export type AutoUpgradeResult = InferJsonOutputSchema diff --git a/packages/eslint-plugin-cli/rules/json-output-command-exceptions.js b/packages/eslint-plugin-cli/rules/json-output-command-exceptions.js index a74387bce8f..7a84b47bd83 100644 --- a/packages/eslint-plugin-cli/rules/json-output-command-exceptions.js +++ b/packages/eslint-plugin-cli/rules/json-output-command-exceptions.js @@ -36,7 +36,6 @@ const commandExceptions = [ 'packages/cli/src/cli/commands/auth/logout.ts', 'packages/cli/src/cli/commands/config/autoupgrade/off.ts', 'packages/cli/src/cli/commands/config/autoupgrade/on.ts', - 'packages/cli/src/cli/commands/config/autoupgrade/status.ts', 'packages/cli/src/cli/commands/doc/fetch.ts', 'packages/cli/src/cli/commands/doc/search.ts', 'packages/cli/src/cli/commands/upgrade.ts',