From 90db70b7cf0fe45f84d2e0292861baefd7426ed2 Mon Sep 17 00:00:00 2001 From: Alfonso Noriega Date: Thu, 12 Mar 2026 17:47:40 +0100 Subject: [PATCH 1/6] [Phase 0] Deprecate --force on app deploy and app release Add a deprecation warning when --force / -f is used on app deploy and app release. The flag will be removed in Shopify CLI 4.0. Users should migrate to --allow-updates (for CI/CD) or --allow-updates --allow-deletes (when removals are also needed). The SHOPIFY_FLAG_FORCE env var is covered by the same check since oclif resolves it into flags.force. Closes shop/issues-develop#22362 Co-Authored-By: Claude Sonnet 4.6 --- .../deprecate-force-flag-deploy-release.md | 5 ++ .../app/src/cli/commands/app/deploy.test.ts | 67 +++++++++++++++++++ packages/app/src/cli/commands/app/deploy.ts | 16 ++++- .../app/src/cli/commands/app/release.test.ts | 67 +++++++++++++++++++ packages/app/src/cli/commands/app/release.ts | 16 ++++- 5 files changed, 169 insertions(+), 2 deletions(-) create mode 100644 .changeset/deprecate-force-flag-deploy-release.md create mode 100644 packages/app/src/cli/commands/app/deploy.test.ts create mode 100644 packages/app/src/cli/commands/app/release.test.ts diff --git a/.changeset/deprecate-force-flag-deploy-release.md b/.changeset/deprecate-force-flag-deploy-release.md new file mode 100644 index 00000000000..46a1ab035ea --- /dev/null +++ b/.changeset/deprecate-force-flag-deploy-release.md @@ -0,0 +1,5 @@ +--- +'@shopify/app': patch +--- + +Deprecation warning for `--force` flag on `app deploy` and `app release`. The flag will be removed in Shopify CLI 4.0. Use `--allow-updates` for CI/CD environments, or `--allow-updates --allow-deletes` if you also want to allow removals. The `SHOPIFY_FLAG_FORCE` environment variable is also deprecated. diff --git a/packages/app/src/cli/commands/app/deploy.test.ts b/packages/app/src/cli/commands/app/deploy.test.ts new file mode 100644 index 00000000000..fdd5e65b279 --- /dev/null +++ b/packages/app/src/cli/commands/app/deploy.test.ts @@ -0,0 +1,67 @@ +import Deploy from './deploy.js' +import {testAppLinked, testDeveloperPlatformClient, testOrganizationApp} from '../../models/app/app.test-data.js' +import {describe, expect, test, vi, beforeEach} from 'vitest' +import {renderWarning} from '@shopify/cli-kit/node/ui' + +vi.mock('../../services/deploy.js') +vi.mock('../../services/app-context.js') +vi.mock('../../metadata.js', () => ({default: {addPublicMetadata: vi.fn()}})) +vi.mock('@shopify/cli-kit/node/metadata', () => ({addPublicMetadata: vi.fn()})) +vi.mock('../../validations/version-name.js', () => ({validateVersion: vi.fn()})) +vi.mock('../../validations/message.js', () => ({validateMessage: vi.fn()})) +vi.mock('@shopify/cli-kit/node/ui', async (importOriginal) => { + const actual = await importOriginal() + return {...actual, renderWarning: vi.fn()} +}) + +describe('app deploy --force deprecation warning', () => { + beforeEach(async () => { + const {linkedAppContext} = await import('../../services/app-context.js') + const {deploy} = await import('../../services/deploy.js') + vi.mocked(linkedAppContext).mockResolvedValue({ + app: testAppLinked(), + remoteApp: testOrganizationApp(), + developerPlatformClient: testDeveloperPlatformClient(), + organization: {id: '1', businessName: 'test', website: '', apps: {nodes: []}, zeroPartyData: false, appsNext: false}, + }) + vi.mocked(deploy).mockResolvedValue({app: testAppLinked()}) + }) + + test('shows deprecation warning when --force is passed', async () => { + await Deploy.run(['--force']) + + expect(renderWarning).toHaveBeenCalledWith( + expect.objectContaining({ + headline: expect.arrayContaining(['The']), + body: expect.arrayContaining(['Use']), + }), + ) + const call = vi.mocked(renderWarning).mock.calls[0]![0] + expect(JSON.stringify(call)).toContain('--force') + expect(JSON.stringify(call)).toContain('4.0') + }) + + test('shows deprecation warning when SHOPIFY_FLAG_FORCE env var is set', async () => { + vi.stubEnv('SHOPIFY_FLAG_FORCE', '1') + + await Deploy.run([]) + + expect(renderWarning).toHaveBeenCalled() + const call = vi.mocked(renderWarning).mock.calls[0]![0] + expect(JSON.stringify(call)).toContain('--force') + + vi.unstubAllEnvs() + }) + + test('does not show deprecation warning when only --allow-updates is passed', async () => { + await Deploy.run(['--allow-updates']) + + expect(renderWarning).not.toHaveBeenCalled() + }) + + test('does not show deprecation warning when only --allow-deletes is passed', async () => { + await Deploy.run(['--allow-updates', '--allow-deletes']) + + expect(renderWarning).not.toHaveBeenCalled() + }) +}) diff --git a/packages/app/src/cli/commands/app/deploy.ts b/packages/app/src/cli/commands/app/deploy.ts index 1f7ec37618b..690c925d27e 100644 --- a/packages/app/src/cli/commands/app/deploy.ts +++ b/packages/app/src/cli/commands/app/deploy.ts @@ -8,6 +8,7 @@ import {linkedAppContext} from '../../services/app-context.js' import {Flags} from '@oclif/core' import {globalFlags} from '@shopify/cli-kit/node/cli' import {addPublicMetadata} from '@shopify/cli-kit/node/metadata' +import {renderWarning} from '@shopify/cli-kit/node/ui' export default class Deploy extends AppLinkedCommand { static summary = 'Deploy your Shopify app.' @@ -27,7 +28,7 @@ export default class Deploy extends AppLinkedCommand { force: Flags.boolean({ hidden: false, description: - 'Deploy without asking for confirmation. Equivalent to --allow-updates --allow-deletes. For CI/CD environments, the recommended flag is --allow-updates.', + '[Deprecated] Deploy without asking for confirmation. Equivalent to --allow-updates --allow-deletes. Use --allow-updates for CI/CD environments instead.', env: 'SHOPIFY_FLAG_FORCE', char: 'f', }), @@ -79,6 +80,19 @@ export default class Deploy extends AppLinkedCommand { async run(): Promise { const {flags} = await this.parse(Deploy) + if (flags.force) { + renderWarning({ + headline: ['The', {command: '--force'}, 'flag is deprecated and will be removed in Shopify CLI 4.0.'], + body: [ + 'Use', + {command: '--allow-updates'}, + 'for CI/CD environments, or', + {command: '--allow-updates --allow-deletes'}, + 'if you also want to allow removals.', + ], + }) + } + await metadata.addPublicMetadata(() => ({ cmd_deploy_flag_message_used: Boolean(flags.message), cmd_deploy_flag_version_used: Boolean(flags.version), diff --git a/packages/app/src/cli/commands/app/release.test.ts b/packages/app/src/cli/commands/app/release.test.ts new file mode 100644 index 00000000000..61d26180582 --- /dev/null +++ b/packages/app/src/cli/commands/app/release.test.ts @@ -0,0 +1,67 @@ +import Release from './release.js' +import {testAppLinked, testDeveloperPlatformClient, testOrganizationApp} from '../../models/app/app.test-data.js' +import {describe, expect, test, vi, beforeEach} from 'vitest' +import {renderWarning} from '@shopify/cli-kit/node/ui' + +vi.mock('../../services/release.js') +vi.mock('../../services/app-context.js') +vi.mock('@shopify/cli-kit/node/metadata', async (importOriginal) => { + const actual = await importOriginal() + return {...actual, addPublicMetadata: vi.fn()} +}) +vi.mock('@shopify/cli-kit/node/ui', async (importOriginal) => { + const actual = await importOriginal() + return {...actual, renderWarning: vi.fn()} +}) + +describe('app release --force deprecation warning', () => { + beforeEach(async () => { + const {linkedAppContext} = await import('../../services/app-context.js') + const {release} = await import('../../services/release.js') + vi.mocked(linkedAppContext).mockResolvedValue({ + app: testAppLinked(), + remoteApp: testOrganizationApp(), + developerPlatformClient: testDeveloperPlatformClient(), + organization: {id: '1', businessName: 'test', website: '', apps: {nodes: []}, zeroPartyData: false, appsNext: false}, + }) + vi.mocked(release).mockResolvedValue(undefined) + }) + + test('shows deprecation warning when --force is passed', async () => { + await Release.run(['--version', 'v1.0.0', '--force']) + + expect(renderWarning).toHaveBeenCalledWith( + expect.objectContaining({ + headline: expect.arrayContaining(['The']), + body: expect.arrayContaining(['Use']), + }), + ) + const call = vi.mocked(renderWarning).mock.calls[0]![0] + expect(JSON.stringify(call)).toContain('--force') + expect(JSON.stringify(call)).toContain('4.0') + }) + + test('shows deprecation warning when SHOPIFY_FLAG_FORCE env var is set', async () => { + vi.stubEnv('SHOPIFY_FLAG_FORCE', '1') + + await Release.run(['--version', 'v1.0.0']) + + expect(renderWarning).toHaveBeenCalled() + const call = vi.mocked(renderWarning).mock.calls[0]![0] + expect(JSON.stringify(call)).toContain('--force') + + vi.unstubAllEnvs() + }) + + test('does not show deprecation warning when only --allow-updates is passed', async () => { + await Release.run(['--version', 'v1.0.0', '--allow-updates']) + + expect(renderWarning).not.toHaveBeenCalled() + }) + + test('does not show deprecation warning when no force flags are passed', async () => { + await Release.run(['--version', 'v1.0.0', '--allow-updates']) + + expect(renderWarning).not.toHaveBeenCalled() + }) +}) diff --git a/packages/app/src/cli/commands/app/release.ts b/packages/app/src/cli/commands/app/release.ts index 502dde7e717..f39ce40f81d 100644 --- a/packages/app/src/cli/commands/app/release.ts +++ b/packages/app/src/cli/commands/app/release.ts @@ -5,6 +5,7 @@ import {linkedAppContext} from '../../services/app-context.js' import {Flags} from '@oclif/core' import {globalFlags} from '@shopify/cli-kit/node/cli' import {addPublicMetadata} from '@shopify/cli-kit/node/metadata' +import {renderWarning} from '@shopify/cli-kit/node/ui' export default class Release extends AppLinkedCommand { static summary = 'Release an app version.' @@ -21,7 +22,7 @@ export default class Release extends AppLinkedCommand { force: Flags.boolean({ hidden: false, description: - 'Release without asking for confirmation. Equivalent to --allow-updates --allow-deletes. For CI/CD environments, the recommended flag is --allow-updates.', + '[Deprecated] Release without asking for confirmation. Equivalent to --allow-updates --allow-deletes. Use --allow-updates for CI/CD environments instead.', env: 'SHOPIFY_FLAG_FORCE', char: 'f', }), @@ -49,6 +50,19 @@ export default class Release extends AppLinkedCommand { const {flags} = await this.parse(Release) const clientId = flags['client-id'] + if (flags.force) { + renderWarning({ + headline: ['The', {command: '--force'}, 'flag is deprecated and will be removed in Shopify CLI 4.0.'], + body: [ + 'Use', + {command: '--allow-updates'}, + 'for CI/CD environments, or', + {command: '--allow-updates --allow-deletes'}, + 'if you also want to allow removals.', + ], + }) + } + await addPublicMetadata(() => ({ cmd_app_reset_used: flags.reset, })) From 71e03ac83ad7aa1b2ccd56f865e4ef7e23e0eb65 Mon Sep 17 00:00:00 2001 From: Alfonso Noriega Date: Thu, 12 Mar 2026 18:16:50 +0100 Subject: [PATCH 2/6] Remove version-specific references from --force deprecation warning Replace "Shopify CLI 4.0" with "a future major release" across the deprecation warning, tests, and changeset to avoid leaking roadmap details in the public repository. Co-Authored-By: Claude Sonnet 4.6 --- .changeset/deprecate-force-flag-deploy-release.md | 2 +- packages/app/src/cli/commands/app/deploy.test.ts | 2 +- packages/app/src/cli/commands/app/deploy.ts | 2 +- packages/app/src/cli/commands/app/release.test.ts | 2 +- packages/app/src/cli/commands/app/release.ts | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.changeset/deprecate-force-flag-deploy-release.md b/.changeset/deprecate-force-flag-deploy-release.md index 46a1ab035ea..90633bfc6ab 100644 --- a/.changeset/deprecate-force-flag-deploy-release.md +++ b/.changeset/deprecate-force-flag-deploy-release.md @@ -2,4 +2,4 @@ '@shopify/app': patch --- -Deprecation warning for `--force` flag on `app deploy` and `app release`. The flag will be removed in Shopify CLI 4.0. Use `--allow-updates` for CI/CD environments, or `--allow-updates --allow-deletes` if you also want to allow removals. The `SHOPIFY_FLAG_FORCE` environment variable is also deprecated. +Deprecation warning for `--force` flag on `app deploy` and `app release`. The flag will be removed in a future major release. Use `--allow-updates` for CI/CD environments, or `--allow-updates --allow-deletes` if you also want to allow removals. The `SHOPIFY_FLAG_FORCE` environment variable is also deprecated. diff --git a/packages/app/src/cli/commands/app/deploy.test.ts b/packages/app/src/cli/commands/app/deploy.test.ts index fdd5e65b279..73499a23a52 100644 --- a/packages/app/src/cli/commands/app/deploy.test.ts +++ b/packages/app/src/cli/commands/app/deploy.test.ts @@ -38,7 +38,7 @@ describe('app deploy --force deprecation warning', () => { ) const call = vi.mocked(renderWarning).mock.calls[0]![0] expect(JSON.stringify(call)).toContain('--force') - expect(JSON.stringify(call)).toContain('4.0') + expect(JSON.stringify(call)).toContain('future major release') }) test('shows deprecation warning when SHOPIFY_FLAG_FORCE env var is set', async () => { diff --git a/packages/app/src/cli/commands/app/deploy.ts b/packages/app/src/cli/commands/app/deploy.ts index 690c925d27e..772fae512f7 100644 --- a/packages/app/src/cli/commands/app/deploy.ts +++ b/packages/app/src/cli/commands/app/deploy.ts @@ -82,7 +82,7 @@ export default class Deploy extends AppLinkedCommand { if (flags.force) { renderWarning({ - headline: ['The', {command: '--force'}, 'flag is deprecated and will be removed in Shopify CLI 4.0.'], + headline: ['The', {command: '--force'}, 'flag is deprecated and will be removed in a future major release.'], body: [ 'Use', {command: '--allow-updates'}, diff --git a/packages/app/src/cli/commands/app/release.test.ts b/packages/app/src/cli/commands/app/release.test.ts index 61d26180582..703afa76b35 100644 --- a/packages/app/src/cli/commands/app/release.test.ts +++ b/packages/app/src/cli/commands/app/release.test.ts @@ -38,7 +38,7 @@ describe('app release --force deprecation warning', () => { ) const call = vi.mocked(renderWarning).mock.calls[0]![0] expect(JSON.stringify(call)).toContain('--force') - expect(JSON.stringify(call)).toContain('4.0') + expect(JSON.stringify(call)).toContain('future major release') }) test('shows deprecation warning when SHOPIFY_FLAG_FORCE env var is set', async () => { diff --git a/packages/app/src/cli/commands/app/release.ts b/packages/app/src/cli/commands/app/release.ts index f39ce40f81d..da04f3bbde8 100644 --- a/packages/app/src/cli/commands/app/release.ts +++ b/packages/app/src/cli/commands/app/release.ts @@ -52,7 +52,7 @@ export default class Release extends AppLinkedCommand { if (flags.force) { renderWarning({ - headline: ['The', {command: '--force'}, 'flag is deprecated and will be removed in Shopify CLI 4.0.'], + headline: ['The', {command: '--force'}, 'flag is deprecated and will be removed in a future major release.'], body: [ 'Use', {command: '--allow-updates'}, From b3f577aa93fe08e282c75347546b7977453fd61f Mon Sep 17 00:00:00 2001 From: Alfonso Noriega Date: Thu, 12 Mar 2026 18:18:56 +0100 Subject: [PATCH 3/6] Use 'the next major release' in --force deprecation warning Co-Authored-By: Claude Sonnet 4.6 --- .changeset/deprecate-force-flag-deploy-release.md | 2 +- packages/app/src/cli/commands/app/deploy.test.ts | 2 +- packages/app/src/cli/commands/app/deploy.ts | 2 +- packages/app/src/cli/commands/app/release.test.ts | 2 +- packages/app/src/cli/commands/app/release.ts | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.changeset/deprecate-force-flag-deploy-release.md b/.changeset/deprecate-force-flag-deploy-release.md index 90633bfc6ab..5007db8c6ac 100644 --- a/.changeset/deprecate-force-flag-deploy-release.md +++ b/.changeset/deprecate-force-flag-deploy-release.md @@ -2,4 +2,4 @@ '@shopify/app': patch --- -Deprecation warning for `--force` flag on `app deploy` and `app release`. The flag will be removed in a future major release. Use `--allow-updates` for CI/CD environments, or `--allow-updates --allow-deletes` if you also want to allow removals. The `SHOPIFY_FLAG_FORCE` environment variable is also deprecated. +Deprecation warning for `--force` flag on `app deploy` and `app release`. The flag will be removed in the next major release. Use `--allow-updates` for CI/CD environments, or `--allow-updates --allow-deletes` if you also want to allow removals. The `SHOPIFY_FLAG_FORCE` environment variable is also deprecated. diff --git a/packages/app/src/cli/commands/app/deploy.test.ts b/packages/app/src/cli/commands/app/deploy.test.ts index 73499a23a52..44a7c6f5f8b 100644 --- a/packages/app/src/cli/commands/app/deploy.test.ts +++ b/packages/app/src/cli/commands/app/deploy.test.ts @@ -38,7 +38,7 @@ describe('app deploy --force deprecation warning', () => { ) const call = vi.mocked(renderWarning).mock.calls[0]![0] expect(JSON.stringify(call)).toContain('--force') - expect(JSON.stringify(call)).toContain('future major release') + expect(JSON.stringify(call)).toContain('next major release') }) test('shows deprecation warning when SHOPIFY_FLAG_FORCE env var is set', async () => { diff --git a/packages/app/src/cli/commands/app/deploy.ts b/packages/app/src/cli/commands/app/deploy.ts index 772fae512f7..c7780493566 100644 --- a/packages/app/src/cli/commands/app/deploy.ts +++ b/packages/app/src/cli/commands/app/deploy.ts @@ -82,7 +82,7 @@ export default class Deploy extends AppLinkedCommand { if (flags.force) { renderWarning({ - headline: ['The', {command: '--force'}, 'flag is deprecated and will be removed in a future major release.'], + headline: ['The', {command: '--force'}, 'flag is deprecated and will be removed in the next major release.'], body: [ 'Use', {command: '--allow-updates'}, diff --git a/packages/app/src/cli/commands/app/release.test.ts b/packages/app/src/cli/commands/app/release.test.ts index 703afa76b35..4b8b83f1a3f 100644 --- a/packages/app/src/cli/commands/app/release.test.ts +++ b/packages/app/src/cli/commands/app/release.test.ts @@ -38,7 +38,7 @@ describe('app release --force deprecation warning', () => { ) const call = vi.mocked(renderWarning).mock.calls[0]![0] expect(JSON.stringify(call)).toContain('--force') - expect(JSON.stringify(call)).toContain('future major release') + expect(JSON.stringify(call)).toContain('next major release') }) test('shows deprecation warning when SHOPIFY_FLAG_FORCE env var is set', async () => { diff --git a/packages/app/src/cli/commands/app/release.ts b/packages/app/src/cli/commands/app/release.ts index da04f3bbde8..c2da906e0f1 100644 --- a/packages/app/src/cli/commands/app/release.ts +++ b/packages/app/src/cli/commands/app/release.ts @@ -52,7 +52,7 @@ export default class Release extends AppLinkedCommand { if (flags.force) { renderWarning({ - headline: ['The', {command: '--force'}, 'flag is deprecated and will be removed in a future major release.'], + headline: ['The', {command: '--force'}, 'flag is deprecated and will be removed in the next major release.'], body: [ 'Use', {command: '--allow-updates'}, From 558c4ff19444a93f0d15ae080706b967b190f600 Mon Sep 17 00:00:00 2001 From: Alfonso Noriega Date: Fri, 13 Mar 2026 14:46:02 +0100 Subject: [PATCH 4/6] Fix test names, add missing --allow-deletes test, fix Organization type, refresh oclif manifests - Rename 'does not show deprecation warning when only --allow-deletes is passed' to correctly reflect its args (--allow-updates --allow-deletes) in deploy.test.ts - Add separate test for --allow-deletes alone in deploy.test.ts - Fix duplicate --allow-updates test in release.test.ts (now tests --allow-updates --allow-deletes) - Fix Organization object literal: remove non-existent fields (website, apps, zeroPartyData, appsNext) and add required 'source' field in both test files - Regenerate oclif.manifest.json and README.md via pnpm refresh-manifests Co-Authored-By: Claude Sonnet 4.6 --- packages/app/src/cli/commands/app/deploy.test.ts | 15 +++++++++++++-- packages/app/src/cli/commands/app/release.test.ts | 11 ++++++++--- packages/cli/README.md | 11 +++++------ packages/cli/oclif.manifest.json | 4 ++-- 4 files changed, 28 insertions(+), 13 deletions(-) diff --git a/packages/app/src/cli/commands/app/deploy.test.ts b/packages/app/src/cli/commands/app/deploy.test.ts index 44a7c6f5f8b..6f83b0b6041 100644 --- a/packages/app/src/cli/commands/app/deploy.test.ts +++ b/packages/app/src/cli/commands/app/deploy.test.ts @@ -1,5 +1,6 @@ import Deploy from './deploy.js' import {testAppLinked, testDeveloperPlatformClient, testOrganizationApp} from '../../models/app/app.test-data.js' +import {OrganizationSource} from '../../models/organization.js' import {describe, expect, test, vi, beforeEach} from 'vitest' import {renderWarning} from '@shopify/cli-kit/node/ui' @@ -22,7 +23,11 @@ describe('app deploy --force deprecation warning', () => { app: testAppLinked(), remoteApp: testOrganizationApp(), developerPlatformClient: testDeveloperPlatformClient(), - organization: {id: '1', businessName: 'test', website: '', apps: {nodes: []}, zeroPartyData: false, appsNext: false}, + organization: { + id: '1', + businessName: 'test', + source: OrganizationSource.Partners, + }, }) vi.mocked(deploy).mockResolvedValue({app: testAppLinked()}) }) @@ -59,9 +64,15 @@ describe('app deploy --force deprecation warning', () => { expect(renderWarning).not.toHaveBeenCalled() }) - test('does not show deprecation warning when only --allow-deletes is passed', async () => { + test('does not show deprecation warning when --allow-updates and --allow-deletes are passed', async () => { await Deploy.run(['--allow-updates', '--allow-deletes']) expect(renderWarning).not.toHaveBeenCalled() }) + + test('does not show deprecation warning when only --allow-deletes is passed', async () => { + await Deploy.run(['--allow-deletes']) + + expect(renderWarning).not.toHaveBeenCalled() + }) }) diff --git a/packages/app/src/cli/commands/app/release.test.ts b/packages/app/src/cli/commands/app/release.test.ts index 4b8b83f1a3f..63ef913ccfc 100644 --- a/packages/app/src/cli/commands/app/release.test.ts +++ b/packages/app/src/cli/commands/app/release.test.ts @@ -1,5 +1,6 @@ import Release from './release.js' import {testAppLinked, testDeveloperPlatformClient, testOrganizationApp} from '../../models/app/app.test-data.js' +import {OrganizationSource} from '../../models/organization.js' import {describe, expect, test, vi, beforeEach} from 'vitest' import {renderWarning} from '@shopify/cli-kit/node/ui' @@ -22,7 +23,11 @@ describe('app release --force deprecation warning', () => { app: testAppLinked(), remoteApp: testOrganizationApp(), developerPlatformClient: testDeveloperPlatformClient(), - organization: {id: '1', businessName: 'test', website: '', apps: {nodes: []}, zeroPartyData: false, appsNext: false}, + organization: { + id: '1', + businessName: 'test', + source: OrganizationSource.Partners, + }, }) vi.mocked(release).mockResolvedValue(undefined) }) @@ -59,8 +64,8 @@ describe('app release --force deprecation warning', () => { expect(renderWarning).not.toHaveBeenCalled() }) - test('does not show deprecation warning when no force flags are passed', async () => { - await Release.run(['--version', 'v1.0.0', '--allow-updates']) + test('does not show deprecation warning when --allow-updates and --allow-deletes are passed', async () => { + await Release.run(['--version', 'v1.0.0', '--allow-updates', '--allow-deletes']) expect(renderWarning).not.toHaveBeenCalled() }) diff --git a/packages/cli/README.md b/packages/cli/README.md index 0ef528b2e4d..de6ac31a3a5 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -316,9 +316,9 @@ USAGE FLAGS -c, --config= [env: SHOPIFY_FLAG_APP_CONFIG] The name of the app configuration. - -f, --force [env: SHOPIFY_FLAG_FORCE] Deploy without asking for confirmation. Equivalent to - --allow-updates --allow-deletes. For CI/CD environments, the recommended flag is - --allow-updates. + -f, --force [env: SHOPIFY_FLAG_FORCE] [Deprecated] Deploy without asking for confirmation. + Equivalent to --allow-updates --allow-deletes. Use --allow-updates for CI/CD + environments instead. --allow-deletes [env: SHOPIFY_FLAG_ALLOW_DELETES] Allows removing extensions and configuration without requiring user confirmation. For CI/CD environments, the recommended flag is --allow-updates. @@ -899,9 +899,8 @@ USAGE FLAGS -c, --config= [env: SHOPIFY_FLAG_APP_CONFIG] The name of the app configuration. - -f, --force [env: SHOPIFY_FLAG_FORCE] Release without asking for confirmation. Equivalent to - --allow-updates --allow-deletes. For CI/CD environments, the recommended flag is - --allow-updates. + -f, --force [env: SHOPIFY_FLAG_FORCE] [Deprecated] Release without asking for confirmation. Equivalent to + --allow-updates --allow-deletes. Use --allow-updates for CI/CD environments instead. --allow-deletes [env: SHOPIFY_FLAG_ALLOW_DELETES] Allows removing extensions and configuration without requiring user confirmation. For CI/CD environments, the recommended flag is --allow-updates. --allow-updates [env: SHOPIFY_FLAG_ALLOW_UPDATES] Allows adding and updating extensions and configuration diff --git a/packages/cli/oclif.manifest.json b/packages/cli/oclif.manifest.json index 8a053bd1ea3..5847079dab4 100644 --- a/packages/cli/oclif.manifest.json +++ b/packages/cli/oclif.manifest.json @@ -709,7 +709,7 @@ "force": { "allowNo": false, "char": "f", - "description": "Deploy without asking for confirmation. Equivalent to --allow-updates --allow-deletes. For CI/CD environments, the recommended flag is --allow-updates.", + "description": "[Deprecated] Deploy without asking for confirmation. Equivalent to --allow-updates --allow-deletes. Use --allow-updates for CI/CD environments instead.", "env": "SHOPIFY_FLAG_FORCE", "hidden": false, "name": "force", @@ -2788,7 +2788,7 @@ "force": { "allowNo": false, "char": "f", - "description": "Release without asking for confirmation. Equivalent to --allow-updates --allow-deletes. For CI/CD environments, the recommended flag is --allow-updates.", + "description": "[Deprecated] Release without asking for confirmation. Equivalent to --allow-updates --allow-deletes. Use --allow-updates for CI/CD environments instead.", "env": "SHOPIFY_FLAG_FORCE", "hidden": false, "name": "force", From 6fc82296a0886fd157f146a8da410feb2f632aea Mon Sep 17 00:00:00 2001 From: Alfonso Noriega Date: Fri, 13 Mar 2026 14:57:25 +0100 Subject: [PATCH 5/6] Add missing specifications field to linkedAppContext mock LoadedAppContextOutput requires a specifications field. Added specifications: [] to the mock in both deploy.test.ts and release.test.ts to fix the type-check CI failure. Co-Authored-By: Claude Sonnet 4.6 --- packages/app/src/cli/commands/app/deploy.test.ts | 1 + packages/app/src/cli/commands/app/release.test.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/app/src/cli/commands/app/deploy.test.ts b/packages/app/src/cli/commands/app/deploy.test.ts index 6f83b0b6041..096fb427340 100644 --- a/packages/app/src/cli/commands/app/deploy.test.ts +++ b/packages/app/src/cli/commands/app/deploy.test.ts @@ -28,6 +28,7 @@ describe('app deploy --force deprecation warning', () => { businessName: 'test', source: OrganizationSource.Partners, }, + specifications: [], }) vi.mocked(deploy).mockResolvedValue({app: testAppLinked()}) }) diff --git a/packages/app/src/cli/commands/app/release.test.ts b/packages/app/src/cli/commands/app/release.test.ts index 63ef913ccfc..e256958ead2 100644 --- a/packages/app/src/cli/commands/app/release.test.ts +++ b/packages/app/src/cli/commands/app/release.test.ts @@ -28,6 +28,7 @@ describe('app release --force deprecation warning', () => { businessName: 'test', source: OrganizationSource.Partners, }, + specifications: [], }) vi.mocked(release).mockResolvedValue(undefined) }) From 0f7035f6ef7bd334f4fa748e21863f8f2ef21aef Mon Sep 17 00:00:00 2001 From: Alfonso Noriega Date: Fri, 13 Mar 2026 14:57:25 +0100 Subject: [PATCH 6/6] Add missing specifications field to linkedAppContext mock LoadedAppContextOutput requires a specifications field. Added specifications: [] to the mock in both deploy.test.ts and release.test.ts to fix the type-check CI failure. Co-Authored-By: Claude Sonnet 4.6 --- .../commands/interfaces/app-deploy.interface.ts | 2 +- .../commands/interfaces/app-release.interface.ts | 2 +- docs-shopify.dev/generated/generated_docs_data.json | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs-shopify.dev/commands/interfaces/app-deploy.interface.ts b/docs-shopify.dev/commands/interfaces/app-deploy.interface.ts index 08078c3575c..528a6733014 100644 --- a/docs-shopify.dev/commands/interfaces/app-deploy.interface.ts +++ b/docs-shopify.dev/commands/interfaces/app-deploy.interface.ts @@ -25,7 +25,7 @@ export interface appdeploy { '-c, --config '?: string /** - * Deploy without asking for confirmation. Equivalent to --allow-updates --allow-deletes. For CI/CD environments, the recommended flag is --allow-updates. + * [Deprecated] Deploy without asking for confirmation. Equivalent to --allow-updates --allow-deletes. Use --allow-updates for CI/CD environments instead. * @environment SHOPIFY_FLAG_FORCE */ '-f, --force'?: '' diff --git a/docs-shopify.dev/commands/interfaces/app-release.interface.ts b/docs-shopify.dev/commands/interfaces/app-release.interface.ts index ad01162281e..9c381109438 100644 --- a/docs-shopify.dev/commands/interfaces/app-release.interface.ts +++ b/docs-shopify.dev/commands/interfaces/app-release.interface.ts @@ -25,7 +25,7 @@ export interface apprelease { '-c, --config '?: string /** - * Release without asking for confirmation. Equivalent to --allow-updates --allow-deletes. For CI/CD environments, the recommended flag is --allow-updates. + * [Deprecated] Release without asking for confirmation. Equivalent to --allow-updates --allow-deletes. Use --allow-updates for CI/CD environments instead. * @environment SHOPIFY_FLAG_FORCE */ '-f, --force'?: '' diff --git a/docs-shopify.dev/generated/generated_docs_data.json b/docs-shopify.dev/generated/generated_docs_data.json index 7e5a4ccc570..e2550dec6a3 100644 --- a/docs-shopify.dev/generated/generated_docs_data.json +++ b/docs-shopify.dev/generated/generated_docs_data.json @@ -901,12 +901,12 @@ "syntaxKind": "PropertySignature", "name": "-f, --force", "value": "\"\"", - "description": "Deploy without asking for confirmation. Equivalent to --allow-updates --allow-deletes. For CI/CD environments, the recommended flag is --allow-updates.", + "description": "[Deprecated] Deploy without asking for confirmation. Equivalent to --allow-updates --allow-deletes. Use --allow-updates for CI/CD environments instead.", "isOptional": true, "environmentValue": "SHOPIFY_FLAG_FORCE" } ], - "value": "export interface appdeploy {\n /**\n * Allows removing extensions and configuration without requiring user confirmation. For CI/CD environments, the recommended flag is --allow-updates.\n * @environment SHOPIFY_FLAG_ALLOW_DELETES\n */\n '--allow-deletes'?: ''\n\n /**\n * Allows adding and updating extensions and configuration without requiring user confirmation. Recommended option for CI/CD environments.\n * @environment SHOPIFY_FLAG_ALLOW_UPDATES\n */\n '--allow-updates'?: ''\n\n /**\n * The Client ID of your app.\n * @environment SHOPIFY_FLAG_CLIENT_ID\n */\n '--client-id '?: string\n\n /**\n * The name of the app configuration.\n * @environment SHOPIFY_FLAG_APP_CONFIG\n */\n '-c, --config '?: string\n\n /**\n * Deploy without asking for confirmation. Equivalent to --allow-updates --allow-deletes. For CI/CD environments, the recommended flag is --allow-updates.\n * @environment SHOPIFY_FLAG_FORCE\n */\n '-f, --force'?: ''\n\n /**\n * Optional message that will be associated with this version. This is for internal use only and won't be available externally.\n * @environment SHOPIFY_FLAG_MESSAGE\n */\n '--message '?: string\n\n /**\n * Use with caution: Skips building any elements of the app that require building. You should ensure your app has been prepared in advance, such as by running `shopify app build` or by caching build artifacts.\n * @environment SHOPIFY_FLAG_NO_BUILD\n */\n '--no-build'?: ''\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * Creates a version but doesn't release it - it's not made available to merchants. With this flag, a user confirmation is not required.\n * @environment SHOPIFY_FLAG_NO_RELEASE\n */\n '--no-release'?: ''\n\n /**\n * The path to your app directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path '?: string\n\n /**\n * Reset all your settings.\n * @environment SHOPIFY_FLAG_RESET\n */\n '--reset'?: ''\n\n /**\n * URL associated with the new app version.\n * @environment SHOPIFY_FLAG_SOURCE_CONTROL_URL\n */\n '--source-control-url '?: string\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n\n /**\n * Optional version tag that will be associated with this app version. If not provided, an auto-generated identifier will be generated for this app version.\n * @environment SHOPIFY_FLAG_VERSION\n */\n '--version '?: string\n}" + "value": "export interface appdeploy {\n /**\n * Allows removing extensions and configuration without requiring user confirmation. For CI/CD environments, the recommended flag is --allow-updates.\n * @environment SHOPIFY_FLAG_ALLOW_DELETES\n */\n '--allow-deletes'?: ''\n\n /**\n * Allows adding and updating extensions and configuration without requiring user confirmation. Recommended option for CI/CD environments.\n * @environment SHOPIFY_FLAG_ALLOW_UPDATES\n */\n '--allow-updates'?: ''\n\n /**\n * The Client ID of your app.\n * @environment SHOPIFY_FLAG_CLIENT_ID\n */\n '--client-id '?: string\n\n /**\n * The name of the app configuration.\n * @environment SHOPIFY_FLAG_APP_CONFIG\n */\n '-c, --config '?: string\n\n /**\n * [Deprecated] Deploy without asking for confirmation. Equivalent to --allow-updates --allow-deletes. Use --allow-updates for CI/CD environments instead.\n * @environment SHOPIFY_FLAG_FORCE\n */\n '-f, --force'?: ''\n\n /**\n * Optional message that will be associated with this version. This is for internal use only and won't be available externally.\n * @environment SHOPIFY_FLAG_MESSAGE\n */\n '--message '?: string\n\n /**\n * Use with caution: Skips building any elements of the app that require building. You should ensure your app has been prepared in advance, such as by running `shopify app build` or by caching build artifacts.\n * @environment SHOPIFY_FLAG_NO_BUILD\n */\n '--no-build'?: ''\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * Creates a version but doesn't release it - it's not made available to merchants. With this flag, a user confirmation is not required.\n * @environment SHOPIFY_FLAG_NO_RELEASE\n */\n '--no-release'?: ''\n\n /**\n * The path to your app directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path '?: string\n\n /**\n * Reset all your settings.\n * @environment SHOPIFY_FLAG_RESET\n */\n '--reset'?: ''\n\n /**\n * URL associated with the new app version.\n * @environment SHOPIFY_FLAG_SOURCE_CONTROL_URL\n */\n '--source-control-url '?: string\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n\n /**\n * Optional version tag that will be associated with this app version. If not provided, an auto-generated identifier will be generated for this app version.\n * @environment SHOPIFY_FLAG_VERSION\n */\n '--version '?: string\n}" } } } @@ -3071,12 +3071,12 @@ "syntaxKind": "PropertySignature", "name": "-f, --force", "value": "\"\"", - "description": "Release without asking for confirmation. Equivalent to --allow-updates --allow-deletes. For CI/CD environments, the recommended flag is --allow-updates.", + "description": "[Deprecated] Release without asking for confirmation. Equivalent to --allow-updates --allow-deletes. Use --allow-updates for CI/CD environments instead.", "isOptional": true, "environmentValue": "SHOPIFY_FLAG_FORCE" } ], - "value": "export interface apprelease {\n /**\n * Allows removing extensions and configuration without requiring user confirmation. For CI/CD environments, the recommended flag is --allow-updates.\n * @environment SHOPIFY_FLAG_ALLOW_DELETES\n */\n '--allow-deletes'?: ''\n\n /**\n * Allows adding and updating extensions and configuration without requiring user confirmation. Recommended option for CI/CD environments.\n * @environment SHOPIFY_FLAG_ALLOW_UPDATES\n */\n '--allow-updates'?: ''\n\n /**\n * The Client ID of your app.\n * @environment SHOPIFY_FLAG_CLIENT_ID\n */\n '--client-id '?: string\n\n /**\n * The name of the app configuration.\n * @environment SHOPIFY_FLAG_APP_CONFIG\n */\n '-c, --config '?: string\n\n /**\n * Release without asking for confirmation. Equivalent to --allow-updates --allow-deletes. For CI/CD environments, the recommended flag is --allow-updates.\n * @environment SHOPIFY_FLAG_FORCE\n */\n '-f, --force'?: ''\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * The path to your app directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path '?: string\n\n /**\n * Reset all your settings.\n * @environment SHOPIFY_FLAG_RESET\n */\n '--reset'?: ''\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n\n /**\n * The name of the app version to release.\n * @environment SHOPIFY_FLAG_VERSION\n */\n '--version ': string\n}" + "value": "export interface apprelease {\n /**\n * Allows removing extensions and configuration without requiring user confirmation. For CI/CD environments, the recommended flag is --allow-updates.\n * @environment SHOPIFY_FLAG_ALLOW_DELETES\n */\n '--allow-deletes'?: ''\n\n /**\n * Allows adding and updating extensions and configuration without requiring user confirmation. Recommended option for CI/CD environments.\n * @environment SHOPIFY_FLAG_ALLOW_UPDATES\n */\n '--allow-updates'?: ''\n\n /**\n * The Client ID of your app.\n * @environment SHOPIFY_FLAG_CLIENT_ID\n */\n '--client-id '?: string\n\n /**\n * The name of the app configuration.\n * @environment SHOPIFY_FLAG_APP_CONFIG\n */\n '-c, --config '?: string\n\n /**\n * [Deprecated] Release without asking for confirmation. Equivalent to --allow-updates --allow-deletes. Use --allow-updates for CI/CD environments instead.\n * @environment SHOPIFY_FLAG_FORCE\n */\n '-f, --force'?: ''\n\n /**\n * Disable color output.\n * @environment SHOPIFY_FLAG_NO_COLOR\n */\n '--no-color'?: ''\n\n /**\n * The path to your app directory.\n * @environment SHOPIFY_FLAG_PATH\n */\n '--path '?: string\n\n /**\n * Reset all your settings.\n * @environment SHOPIFY_FLAG_RESET\n */\n '--reset'?: ''\n\n /**\n * Increase the verbosity of the output.\n * @environment SHOPIFY_FLAG_VERBOSE\n */\n '--verbose'?: ''\n\n /**\n * The name of the app version to release.\n * @environment SHOPIFY_FLAG_VERSION\n */\n '--version ': string\n}" } } }