diff --git a/.changeset/remove-app-deploy-force-flag.md b/.changeset/remove-app-deploy-force-flag.md new file mode 100644 index 00000000000..06028dbf16a --- /dev/null +++ b/.changeset/remove-app-deploy-force-flag.md @@ -0,0 +1,5 @@ +--- +'@shopify/app': major +--- + +Remove the deprecated `--force` (`-f`) flag and `SHOPIFY_FLAG_FORCE` environment variable from `shopify app deploy`. Use `--allow-updates` for CI/CD environments, or `--allow-updates --allow-deletes` if you also want to allow removals. The `--no-release` flag continues to work and implicitly allows updates and deletes. diff --git a/docs-shopify.dev/commands/interfaces/app-deploy.interface.ts b/docs-shopify.dev/commands/interfaces/app-deploy.interface.ts index 6fd04ce3911..e7d9472cfaf 100644 --- a/docs-shopify.dev/commands/interfaces/app-deploy.interface.ts +++ b/docs-shopify.dev/commands/interfaces/app-deploy.interface.ts @@ -28,12 +28,6 @@ export interface appdeploy { */ '-c, --config '?: string - /** - * [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'?: '' - /** * Optional message that will be associated with this version. This is for internal use only and won't be available externally. * @environment SHOPIFY_FLAG_MESSAGE diff --git a/packages/app/src/cli/commands/app/deploy.test.ts b/packages/app/src/cli/commands/app/deploy.test.ts deleted file mode 100644 index 3232008e273..00000000000 --- a/packages/app/src/cli/commands/app/deploy.test.ts +++ /dev/null @@ -1,81 +0,0 @@ -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' - -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', - source: OrganizationSource.Partners, - }, - specifications: [], - project: {} as any, - activeConfig: {} as any, - }) - 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('next major release') - }) - - 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 --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/deploy.ts b/packages/app/src/cli/commands/app/deploy.ts index a7c3bc3b1b6..b5b5a437db3 100644 --- a/packages/app/src/cli/commands/app/deploy.ts +++ b/packages/app/src/cli/commands/app/deploy.ts @@ -8,7 +8,6 @@ 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.' @@ -25,13 +24,6 @@ export default class Deploy extends AppLinkedCommand { static flags = { ...globalFlags, ...appFlags, - force: Flags.boolean({ - hidden: false, - 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', - char: 'f', - }), 'allow-updates': Flags.boolean({ hidden: false, description: @@ -80,19 +72,6 @@ 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 the next major release.'], - 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), @@ -108,9 +87,9 @@ export default class Deploy extends AppLinkedCommand { cmd_app_reset_used: flags.reset, })) - const force = flags.force || flags['no-release'] + const force = flags['no-release'] - // When releasing, we require --force or --allow-updates or --allow-deletes for non-TTY. + // When releasing, we require --no-release or --allow-updates or --allow-deletes for non-TTY. const requiredNonTTYFlags: string[] = [] const hasAnyForceFlags = force || flags['allow-updates'] || flags['allow-deletes'] if (!hasAnyForceFlags) { diff --git a/packages/app/src/cli/prompts/deploy-release.ts b/packages/app/src/cli/prompts/deploy-release.ts index 40b91d5b57a..7d779fdde7b 100644 --- a/packages/app/src/cli/prompts/deploy-release.ts +++ b/packages/app/src/cli/prompts/deploy-release.ts @@ -58,7 +58,7 @@ function shouldSkipConfirmationPrompt({ extensionIdentifiersBreakdown: ExtensionIdentifiersBreakdown configExtensionIdentifiersBreakdown?: ConfigExtensionIdentifiersBreakdown }): boolean { - // --force is equivalent to --allow-updates --allow-deletes + // --no-release (which sets force=true internally) is equivalent to --allow-updates --allow-deletes if (force || (allowUpdates && allowDeletes)) return true const hasDeletedExtensions = extensionIdentifiersBreakdown.onlyRemote.length > 0 diff --git a/packages/app/src/cli/prompts/uid-mapping-error.ts b/packages/app/src/cli/prompts/uid-mapping-error.ts index 71a073c98f7..a26873b3b0e 100644 --- a/packages/app/src/cli/prompts/uid-mapping-error.ts +++ b/packages/app/src/cli/prompts/uid-mapping-error.ts @@ -6,7 +6,9 @@ export function throwUidMappingError() { 'You must first map IDs to your existing extensions by running', {command: 'shopify app deploy'}, 'interactively, without', - {command: '--force'}, + {command: '--allow-updates'}, + 'or', + {command: '--allow-deletes'}, ', to finish the migration.', ] const customSection = { diff --git a/packages/app/src/cli/services/context.ts b/packages/app/src/cli/services/context.ts index dce2c07c7ec..2381683d7c4 100644 --- a/packages/app/src/cli/services/context.ts +++ b/packages/app/src/cli/services/context.ts @@ -220,7 +220,15 @@ async function checkIncludeConfigOnDeploy({ {command: 'include_config_on_deploy'}, 'in your TOML file. Including configuration will be required very soon.', ] - const nextSteps = ['Run', {command: 'shopify app deploy'}, 'interactively, without', {command: '--force'}, '.'] + const nextSteps = [ + 'Run', + {command: 'shopify app deploy'}, + 'interactively, without', + {command: '--allow-updates'}, + 'or', + {command: '--allow-deletes'}, + '.', + ] throw new AbortError(message, nextSteps) } diff --git a/packages/cli/README.md b/packages/cli/README.md index 24866f3a032..8bfb0312129 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -342,15 +342,12 @@ Deploy your Shopify app. ``` USAGE - $ shopify app deploy [--client-id | -c ] [-f] [--message ] [--no-build] [--no-color] + $ shopify app deploy [--client-id | -c ] [--message ] [--no-build] [--no-color] [--no-release | --allow-updates | --allow-deletes] [--path ] [--reset | ] [--source-control-url ] [--verbose] [--version ] FLAGS -c, --config= [env: SHOPIFY_FLAG_APP_CONFIG] The name of the app configuration. - -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. diff --git a/packages/cli/oclif.manifest.json b/packages/cli/oclif.manifest.json index b44ecc21b27..a1b7db2dccd 100644 --- a/packages/cli/oclif.manifest.json +++ b/packages/cli/oclif.manifest.json @@ -793,15 +793,6 @@ "name": "config", "type": "option" }, - "force": { - "allowNo": false, - "char": "f", - "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", - "type": "boolean" - }, "message": { "description": "Optional message that will be associated with this version. This is for internal use only and won't be available externally.", "env": "SHOPIFY_FLAG_MESSAGE",