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
5 changes: 5 additions & 0 deletions .changeset/deprecate-force-flag-deploy-release.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@shopify/app': patch
---

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.
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export interface appdeploy {
'-c, --config <value>'?: 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'?: ''
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export interface apprelease {
'-c, --config <value>'?: 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'?: ''
Expand Down
8 changes: 4 additions & 4 deletions docs-shopify.dev/generated/generated_docs_data.json
Original file line number Diff line number Diff line change
Expand Up @@ -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 <value>'?: string\n\n /**\n * The name of the app configuration.\n * @environment SHOPIFY_FLAG_APP_CONFIG\n */\n '-c, --config <value>'?: 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 <value>'?: 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 <value>'?: 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 <value>'?: 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 <value>'?: 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 <value>'?: string\n\n /**\n * The name of the app configuration.\n * @environment SHOPIFY_FLAG_APP_CONFIG\n */\n '-c, --config <value>'?: 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 <value>'?: 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 <value>'?: 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 <value>'?: 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 <value>'?: string\n}"
}
}
}
Expand Down Expand Up @@ -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 <value>'?: string\n\n /**\n * The name of the app configuration.\n * @environment SHOPIFY_FLAG_APP_CONFIG\n */\n '-c, --config <value>'?: 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 <value>'?: 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 <value>': 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 <value>'?: string\n\n /**\n * The name of the app configuration.\n * @environment SHOPIFY_FLAG_APP_CONFIG\n */\n '-c, --config <value>'?: 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 <value>'?: 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 <value>': string\n}"
}
}
}
Expand Down
79 changes: 79 additions & 0 deletions packages/app/src/cli/commands/app/deploy.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
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<typeof import('@shopify/cli-kit/node/ui')>()
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: [],
})
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()
})
})
16 changes: 15 additions & 1 deletion packages/app/src/cli/commands/app/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.'
Expand All @@ -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',
}),
Expand Down Expand Up @@ -79,6 +80,19 @@ export default class Deploy extends AppLinkedCommand {
async run(): Promise<AppLinkedCommandOutput> {
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),
Expand Down
73 changes: 73 additions & 0 deletions packages/app/src/cli/commands/app/release.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
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'

vi.mock('../../services/release.js')
vi.mock('../../services/app-context.js')
vi.mock('@shopify/cli-kit/node/metadata', async (importOriginal) => {
const actual = await importOriginal<typeof import('@shopify/cli-kit/node/metadata')>()
return {...actual, addPublicMetadata: vi.fn()}
})
vi.mock('@shopify/cli-kit/node/ui', async (importOriginal) => {
const actual = await importOriginal<typeof import('@shopify/cli-kit/node/ui')>()
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',
source: OrganizationSource.Partners,
},
specifications: [],
})
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('next major release')
})

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 --allow-updates and --allow-deletes are passed', async () => {
await Release.run(['--version', 'v1.0.0', '--allow-updates', '--allow-deletes'])

expect(renderWarning).not.toHaveBeenCalled()
})
})
16 changes: 15 additions & 1 deletion packages/app/src/cli/commands/app/release.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.'
Expand All @@ -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',
}),
Expand Down Expand Up @@ -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 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 addPublicMetadata(() => ({
cmd_app_reset_used: flags.reset,
}))
Expand Down
Loading
Loading