From c414faedefb177676c66f96afaf5442c05c84f9d Mon Sep 17 00:00:00 2001 From: Dawson David Date: Fri, 27 Jun 2025 13:39:06 -0600 Subject: [PATCH 1/4] feat: bare bones package bundle delete --- messages/package_bundle_delete.md | 51 +++++++++++++++++++++++ src/commands/package/bundle/delete.ts | 59 +++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 messages/package_bundle_delete.md create mode 100644 src/commands/package/bundle/delete.ts diff --git a/messages/package_bundle_delete.md b/messages/package_bundle_delete.md new file mode 100644 index 00000000..d49fdd98 --- /dev/null +++ b/messages/package_bundle_delete.md @@ -0,0 +1,51 @@ +# summary + +Delete a package bundle. + +# description + +Specify the ID or alias of the package bundle you want to delete. + +Delete package bundles. Before you delete a package bundle, first delete all associated package bundle versions. + +# examples + +- Delete a package bundle using its alias from your default Dev Hub org: + + <%= config.bin %> <%= command.id %> --bundle "Your Bundle Alias" + +- Delete a package bundle using its ID from the specified Dev Hub org: + + <%= config.bin %> <%= command.id %> --bundle 1Fl... --target-dev-hub devhub@example.com + +# flags.bundle.summary + +ID (starts with 1Fl) or alias of the package bundle to delete. + +# flags.undelete.summary + +Undelete a deleted package bundle. + +# flags.no-prompt.summary + +Don't prompt before deleting the package bundle. + +# prompt-delete + +Deleted package bundles can't be recovered. + +Do you want to continue? (y/n) + +# prompt-undelete + +This will undelete the package bundle, which may result in unintended consequences for customers. Proceed with caution. + +Do you want to continue? (y/n) + +# prompt-delete-deny + +The request to delete this package bundle was canceled + +# humanSuccess + +Successfully deleted the package bundle. diff --git a/src/commands/package/bundle/delete.ts b/src/commands/package/bundle/delete.ts new file mode 100644 index 00000000..c4d7a285 --- /dev/null +++ b/src/commands/package/bundle/delete.ts @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2022, salesforce.com, inc. + * All rights reserved. + * Licensed under the BSD 3-Clause license. + * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause + */ + +import { Flags, loglevel, orgApiVersionFlagWithDeprecations, SfCommand } from '@salesforce/sf-plugins-core'; +import { Messages } from '@salesforce/core/messages'; +import { PackageBundle } from '@salesforce/packaging'; +import { requiredHubFlag } from '../../../utils/hubFlag.js'; + +Messages.importMessagesDirectoryFromMetaUrl(import.meta.url); +const messages = Messages.loadMessages('@salesforce/plugin-packaging', 'package_bundle_delete'); + +export class PackageBundleDeleteCommand extends SfCommand { + public static readonly summary = messages.getMessage('summary'); + public static readonly description = messages.getMessage('description'); + public static readonly examples = messages.getMessages('examples'); + public static readonly flags = { + loglevel, + 'target-dev-hub': requiredHubFlag, + 'api-version': orgApiVersionFlagWithDeprecations, + 'no-prompt': Flags.boolean({ + char: 'n', + deprecateAliases: true, + aliases: ['noprompt'], + summary: messages.getMessage('flags.no-prompt.summary'), + }), + bundle: Flags.string({ + char: 'p', + summary: messages.getMessage('flags.bundle.summary'), + required: true, + }), + undelete: Flags.boolean({ + summary: messages.getMessage('flags.undelete.summary'), + hidden: true, + default: false, + }), + }; + + public async run(): Promise { + const { flags } = await this.parse(PackageBundleDeleteCommand); + const message = messages.getMessage(flags.undelete ? 'prompt-undelete' : 'prompt-delete'); + const accepted = flags['no-prompt'] || flags.json ? true : await this.confirm({ message }); + if (!accepted) { + throw messages.createError('prompt-delete-deny'); + } + + const connection = flags['target-dev-hub'].getConnection(flags['api-version']); + await PackageBundle.delete(connection, flags.bundle); + this.display(); + } + + private display(): void { + this.log(); + this.logSuccess(messages.getMessage('humanSuccess')); + } +} From 55df236643369ea1e71a0ac7e0efb6185a5b284a Mon Sep 17 00:00:00 2001 From: Dawson David Date: Mon, 30 Jun 2025 09:02:20 -0600 Subject: [PATCH 2/4] feat: created package bundle delete additionally made package bundle version create report flags make more sense --- command-snapshot.json | 14 +++- messages/bundle_version_create_report.md | 6 +- messages/package_bundle_delete.md | 6 +- schemas/package-bundle-delete.json | 72 +++++++++++++++++++ src/commands/package/bundle/delete.ts | 22 +++--- .../package/bundle/version/create/report.ts | 14 ++-- .../bundle/bundleCreateAndDelete.nut.ts | 58 +++++++++++++++ .../bundle/bundleVersionCreateReport.test.ts | 8 +-- 8 files changed, 173 insertions(+), 27 deletions(-) create mode 100644 schemas/package-bundle-delete.json create mode 100644 test/commands/bundle/bundleCreateAndDelete.nut.ts diff --git a/command-snapshot.json b/command-snapshot.json index f3cf6586..99fb9ce1 100644 --- a/command-snapshot.json +++ b/command-snapshot.json @@ -63,6 +63,14 @@ "flags": ["api-version", "description", "flags-dir", "json", "loglevel", "name", "target-dev-hub"], "plugin": "@salesforce/plugin-packaging" }, + { + "alias": [], + "command": "package:bundle:delete", + "flagAliases": ["apiversion", "noprompt", "target-hub-org", "targetdevhubusername"], + "flagChars": ["b", "n", "v"], + "flags": ["api-version", "bundle", "flags-dir", "json", "loglevel", "no-prompt", "target-dev-hub", "undelete"], + "plugin": "@salesforce/plugin-packaging" + }, { "alias": ["force:package:bundle:list"], "command": "package:bundle:list", @@ -109,11 +117,11 @@ "plugin": "@salesforce/plugin-packaging" }, { - "alias": ["force:package:bundle:version:create:report"], + "alias": [], "command": "package:bundle:version:create:report", - "flagAliases": ["apiversion", "packagecreaterequestid", "target-hub-org", "targetdevhubusername"], + "flagAliases": ["apiversion", "bundleversioncreaterequestid", "target-hub-org", "targetdevhubusername"], "flagChars": ["i", "v"], - "flags": ["api-version", "flags-dir", "json", "loglevel", "package-create-request-id", "target-dev-hub"], + "flags": ["api-version", "bundle-version-create-request-id", "flags-dir", "json", "loglevel", "target-dev-hub"], "plugin": "@salesforce/plugin-packaging" }, { diff --git a/messages/bundle_version_create_report.md b/messages/bundle_version_create_report.md index bf8d68d0..c57c777c 100644 --- a/messages/bundle_version_create_report.md +++ b/messages/bundle_version_create_report.md @@ -16,7 +16,7 @@ Use this command to check the status of a package bundle version creation reques <%= config.bin %> force:package:bundle:version:create:report -i 0Ho0x0000000000000 -# flags.package-create-request-id.summary +# flags.bundle-version-create-request-id.summary The ID of the package bundle version creation request to report on. @@ -28,11 +28,11 @@ ID Status -# package-bundle-id +# bundle-id Package Bundle ID -# package-bundle-version-id +# bundle-version-id Package Bundle Version ID diff --git a/messages/package_bundle_delete.md b/messages/package_bundle_delete.md index d49fdd98..f6e982cd 100644 --- a/messages/package_bundle_delete.md +++ b/messages/package_bundle_delete.md @@ -48,4 +48,8 @@ The request to delete this package bundle was canceled # humanSuccess -Successfully deleted the package bundle. +Successfully deleted the package bundle %s. + +# humanError + +Failed to delete the package bundle. diff --git a/schemas/package-bundle-delete.json b/schemas/package-bundle-delete.json new file mode 100644 index 00000000..4e4c10ea --- /dev/null +++ b/schemas/package-bundle-delete.json @@ -0,0 +1,72 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$ref": "#/definitions/BundleSaveResult", + "definitions": { + "BundleSaveResult": { + "$ref": "#/definitions/SaveResult" + }, + "SaveResult": { + "anyOf": [ + { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "const": true + }, + "id": { + "type": "string" + }, + "errors": { + "type": "array", + "items": { + "not": {} + } + } + }, + "required": ["success", "id", "errors"], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "const": false + }, + "id": { + "not": {} + }, + "errors": { + "type": "array", + "items": { + "$ref": "#/definitions/SaveError" + } + } + }, + "required": ["success", "errors"], + "additionalProperties": false + } + ] + }, + "SaveError": { + "type": "object", + "properties": { + "errorCode": { + "type": "string" + }, + "message": { + "type": "string" + }, + "fields": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": ["errorCode", "message"], + "additionalProperties": false + } + } +} diff --git a/src/commands/package/bundle/delete.ts b/src/commands/package/bundle/delete.ts index c4d7a285..80886592 100644 --- a/src/commands/package/bundle/delete.ts +++ b/src/commands/package/bundle/delete.ts @@ -7,16 +7,17 @@ import { Flags, loglevel, orgApiVersionFlagWithDeprecations, SfCommand } from '@salesforce/sf-plugins-core'; import { Messages } from '@salesforce/core/messages'; -import { PackageBundle } from '@salesforce/packaging'; +import { PackageBundle, BundleSaveResult } from '@salesforce/packaging'; import { requiredHubFlag } from '../../../utils/hubFlag.js'; Messages.importMessagesDirectoryFromMetaUrl(import.meta.url); const messages = Messages.loadMessages('@salesforce/plugin-packaging', 'package_bundle_delete'); -export class PackageBundleDeleteCommand extends SfCommand { +export class PackageBundleDeleteCommand extends SfCommand { public static readonly summary = messages.getMessage('summary'); public static readonly description = messages.getMessage('description'); public static readonly examples = messages.getMessages('examples'); + public static readonly requiresProject = true; public static readonly flags = { loglevel, 'target-dev-hub': requiredHubFlag, @@ -28,7 +29,7 @@ export class PackageBundleDeleteCommand extends SfCommand { summary: messages.getMessage('flags.no-prompt.summary'), }), bundle: Flags.string({ - char: 'p', + char: 'b', summary: messages.getMessage('flags.bundle.summary'), required: true, }), @@ -39,7 +40,7 @@ export class PackageBundleDeleteCommand extends SfCommand { }), }; - public async run(): Promise { + public async run(): Promise { const { flags } = await this.parse(PackageBundleDeleteCommand); const message = messages.getMessage(flags.undelete ? 'prompt-undelete' : 'prompt-delete'); const accepted = flags['no-prompt'] || flags.json ? true : await this.confirm({ message }); @@ -48,12 +49,17 @@ export class PackageBundleDeleteCommand extends SfCommand { } const connection = flags['target-dev-hub'].getConnection(flags['api-version']); - await PackageBundle.delete(connection, flags.bundle); - this.display(); + const result = await PackageBundle.delete(connection, this.project!, flags.bundle); + this.display(result); + return result; } - private display(): void { + private display(result: BundleSaveResult): void { this.log(); - this.logSuccess(messages.getMessage('humanSuccess')); + if ((result as { success: boolean }).success) { + this.logSuccess(messages.getMessage('humanSuccess', [(result as { id: string }).id])); + } else { + this.error(messages.getMessage('humanError')); + } } } diff --git a/src/commands/package/bundle/version/create/report.ts b/src/commands/package/bundle/version/create/report.ts index a4a4c0f0..cb822c71 100644 --- a/src/commands/package/bundle/version/create/report.ts +++ b/src/commands/package/bundle/version/create/report.ts @@ -21,19 +21,17 @@ export class PackageBundleVersionCreateReportCommand extends SfCommand { const { flags } = await this.parse(PackageBundleVersionCreateReportCommand); const result = await PackageBundleVersionCreate.getCreateStatus( - flags['package-create-request-id'], + flags['bundle-version-create-request-id'], flags['target-dev-hub'].getConnection(flags['api-version']) ); this.display(result); @@ -59,11 +57,11 @@ export class PackageBundleVersionCreateReportCommand extends SfCommand { + let session: TestSession; + let bundleName: string; + before(async () => { + session = await TestSession.create({ + devhubAuthStrategy: 'AUTO', + project: { name: 'bundleCreateDelete' }, + }); + }); + + after(async () => { + await session?.clean(); + }); + describe('create/delete - human results', () => { + before(async () => { + bundleName = `test-bundle-${Date.now()}`; + }); + it('should create a bundle - human readable results', () => { + const command = `package:bundle:create --name ${bundleName} -v ${session.hubOrg.username}`; + const output = execCmd(command, { ensureExitCode: 0 }).shellOutput.stdout; + expect(output).to.contain('Ids'); + expect(output).to.match(/Bundle Id\s+?|1Fl/); + }); + it('should delete a bundle - human readable results', () => { + const command = `package:bundle:delete -b ${bundleName} -v ${session.hubOrg.username} --no-prompt`; + const output = execCmd(command, { ensureExitCode: 0 }).shellOutput.stdout; + expect(output).to.contain('Successfully deleted the package bundle'); + }); + }); + describe('create/delete - json results', () => { + before(async () => { + bundleName = `test-bundle-${Date.now()}`; + }); + it('should create a bundle - json results', () => { + const command = `package:bundle:create --name ${bundleName} -v ${session.hubOrg.username} --json`; + const output = execCmd<{ Id: string }>(command, { ensureExitCode: 0 }).jsonOutput; + expect(output?.status).to.equal(0); + expect(output?.result).to.have.property('Id'); + expect(output?.result?.Id).to.match(/1Fl.{12,15}/); + }); + it('should delete a bundle - json results', () => { + const command = `package:bundle:delete -b ${bundleName} -v ${session.hubOrg.username} --json`; + const output = execCmd<{ id: string; success: boolean; errors: [] }>(command, { ensureExitCode: 0 }).jsonOutput; + expect(output?.result?.id).to.match(/1Fl.{12,15}/); + expect(output?.result?.success).to.be.true; + }); + }); +}); diff --git a/test/commands/bundle/bundleVersionCreateReport.test.ts b/test/commands/bundle/bundleVersionCreateReport.test.ts index e7d1abfa..b6f1c971 100644 --- a/test/commands/bundle/bundleVersionCreateReport.test.ts +++ b/test/commands/bundle/bundleVersionCreateReport.test.ts @@ -51,7 +51,7 @@ describe('force:package:bundle:version:create:report - tests', () => { getCreateStatusStub.resolves(mockResult); const cmd = new PackageBundleVersionCreateReportCommand( - ['--package-create-request-id', requestId, '--target-dev-hub', testOrg.username], + ['--bundle-version-create-request-id', requestId, '--target-dev-hub', testOrg.username], config ); @@ -83,7 +83,7 @@ describe('force:package:bundle:version:create:report - tests', () => { getCreateStatusStub.resolves(mockResult); const cmd = new PackageBundleVersionCreateReportCommand( - ['-i', requestId, '--target-dev-hub', testOrg.username], + ['--bundle-version-create-request-id', requestId, '--target-dev-hub', testOrg.username], config ); @@ -108,7 +108,7 @@ describe('force:package:bundle:version:create:report - tests', () => { it('should throw error when target-dev-hub flag is missing', async () => { const requestId = '0Ho0x0000000000000'; - const cmd = new PackageBundleVersionCreateReportCommand(['--package-create-request-id', requestId], config); + const cmd = new PackageBundleVersionCreateReportCommand(['--bundle-version-create-request-id', requestId], config); try { await cmd.run(); @@ -125,7 +125,7 @@ describe('force:package:bundle:version:create:report - tests', () => { getCreateStatusStub.rejects(new Error(errorMessage)); const cmd = new PackageBundleVersionCreateReportCommand( - ['--package-create-request-id', requestId, '--target-dev-hub', testOrg.username], + ['--bundle-version-create-request-id', requestId, '--target-dev-hub', testOrg.username], config ); From 51e4187e3177971f603fa44db56fea1d89076048 Mon Sep 17 00:00:00 2001 From: Dawson David Date: Mon, 30 Jun 2025 14:19:23 -0600 Subject: [PATCH 3/4] fix: removed undelete --- command-snapshot.json | 8 -------- messages/package_delete.md | 4 ---- 2 files changed, 12 deletions(-) diff --git a/command-snapshot.json b/command-snapshot.json index 99fb9ce1..5052bad9 100644 --- a/command-snapshot.json +++ b/command-snapshot.json @@ -193,14 +193,6 @@ ], "plugin": "@salesforce/plugin-packaging" }, - { - "alias": ["force:package:delete"], - "command": "package:delete", - "flagAliases": ["apiversion", "noprompt", "target-hub-org", "targetdevhubusername"], - "flagChars": ["n", "p", "v"], - "flags": ["api-version", "flags-dir", "json", "loglevel", "no-prompt", "package", "target-dev-hub", "undelete"], - "plugin": "@salesforce/plugin-packaging" - }, { "alias": ["force:package:install"], "command": "package:install", diff --git a/messages/package_delete.md b/messages/package_delete.md index b0901367..ad00f093 100644 --- a/messages/package_delete.md +++ b/messages/package_delete.md @@ -22,10 +22,6 @@ Delete unlocked and second-generation managed packages. Before you delete a pack ID (starts with 0Ho) or alias of the package to delete. -# flags.undelete.summary - -Undelete a deleted package. - # flags.no-prompt.summary Don’t prompt before deleting the package. From f46d1cab792f6bce1c24166387668f8c50ba8c7f Mon Sep 17 00:00:00 2001 From: Dawson David Date: Mon, 30 Jun 2025 14:31:06 -0600 Subject: [PATCH 4/4] fix: deleted message from wrong file --- command-snapshot.json | 10 +++++++++- messages/package_bundle_delete.md | 10 ---------- messages/package_delete.md | 8 ++++++-- src/commands/package/bundle/delete.ts | 7 +------ 4 files changed, 16 insertions(+), 19 deletions(-) diff --git a/command-snapshot.json b/command-snapshot.json index 5052bad9..0ebd7ca3 100644 --- a/command-snapshot.json +++ b/command-snapshot.json @@ -68,7 +68,7 @@ "command": "package:bundle:delete", "flagAliases": ["apiversion", "noprompt", "target-hub-org", "targetdevhubusername"], "flagChars": ["b", "n", "v"], - "flags": ["api-version", "bundle", "flags-dir", "json", "loglevel", "no-prompt", "target-dev-hub", "undelete"], + "flags": ["api-version", "bundle", "flags-dir", "json", "loglevel", "no-prompt", "target-dev-hub"], "plugin": "@salesforce/plugin-packaging" }, { @@ -193,6 +193,14 @@ ], "plugin": "@salesforce/plugin-packaging" }, + { + "alias": ["force:package:delete"], + "command": "package:delete", + "flagAliases": ["apiversion", "noprompt", "target-hub-org", "targetdevhubusername"], + "flagChars": ["n", "p", "v"], + "flags": ["api-version", "flags-dir", "json", "loglevel", "no-prompt", "package", "target-dev-hub", "undelete"], + "plugin": "@salesforce/plugin-packaging" + }, { "alias": ["force:package:install"], "command": "package:install", diff --git a/messages/package_bundle_delete.md b/messages/package_bundle_delete.md index f6e982cd..5e6f5cfc 100644 --- a/messages/package_bundle_delete.md +++ b/messages/package_bundle_delete.md @@ -22,10 +22,6 @@ Delete package bundles. Before you delete a package bundle, first delete all ass ID (starts with 1Fl) or alias of the package bundle to delete. -# flags.undelete.summary - -Undelete a deleted package bundle. - # flags.no-prompt.summary Don't prompt before deleting the package bundle. @@ -36,12 +32,6 @@ Deleted package bundles can't be recovered. Do you want to continue? (y/n) -# prompt-undelete - -This will undelete the package bundle, which may result in unintended consequences for customers. Proceed with caution. - -Do you want to continue? (y/n) - # prompt-delete-deny The request to delete this package bundle was canceled diff --git a/messages/package_delete.md b/messages/package_delete.md index ad00f093..c3f37800 100644 --- a/messages/package_delete.md +++ b/messages/package_delete.md @@ -24,11 +24,15 @@ ID (starts with 0Ho) or alias of the package to delete. # flags.no-prompt.summary -Don’t prompt before deleting the package. +Don't prompt before deleting the package. + +# flags.undelete.summary + +Undelete a deleted package. # prompt-delete -Deleted packages can’t be recovered. +Deleted packages can't be recovered. Do you want to continue? (y/n) diff --git a/src/commands/package/bundle/delete.ts b/src/commands/package/bundle/delete.ts index 80886592..cdfbeabf 100644 --- a/src/commands/package/bundle/delete.ts +++ b/src/commands/package/bundle/delete.ts @@ -33,16 +33,11 @@ export class PackageBundleDeleteCommand extends SfCommand { summary: messages.getMessage('flags.bundle.summary'), required: true, }), - undelete: Flags.boolean({ - summary: messages.getMessage('flags.undelete.summary'), - hidden: true, - default: false, - }), }; public async run(): Promise { const { flags } = await this.parse(PackageBundleDeleteCommand); - const message = messages.getMessage(flags.undelete ? 'prompt-undelete' : 'prompt-delete'); + const message = messages.getMessage('prompt-delete'); const accepted = flags['no-prompt'] || flags.json ? true : await this.confirm({ message }); if (!accepted) { throw messages.createError('prompt-delete-deny');