From 11e8f7ef3f8a97b4f7cbbe783fc21f15da123da7 Mon Sep 17 00:00:00 2001 From: Dawson David Date: Tue, 10 Jun 2025 14:47:07 -0600 Subject: [PATCH 1/2] feat: added bundle create decided to to add tests yet because package create only has nut and we don't have delete yet --- command-snapshot.json | 8 ++++ messages/bundle_create.md | 24 +++++++++++ schemas/package-bundles-create.json | 16 ++++++++ src/commands/package/bundles/create.ts | 57 ++++++++++++++++++++++++++ 4 files changed, 105 insertions(+) create mode 100644 messages/bundle_create.md create mode 100644 schemas/package-bundles-create.json create mode 100644 src/commands/package/bundles/create.ts diff --git a/command-snapshot.json b/command-snapshot.json index d5918a66..c0d0b8db 100644 --- a/command-snapshot.json +++ b/command-snapshot.json @@ -55,6 +55,14 @@ "flags": ["api-version", "flags-dir", "json", "loglevel", "package-id", "target-org"], "plugin": "@salesforce/plugin-packaging" }, + { + "alias": ["force:bundle:create"], + "command": "package:bundles:create", + "flagAliases": ["apiversion", "target-hub-org", "targetdevhubusername"], + "flagChars": ["d", "n", "v"], + "flags": ["api-version", "description", "flags-dir", "json", "loglevel", "name", "target-dev-hub"], + "plugin": "@salesforce/plugin-packaging" + }, { "alias": ["force:package:convert"], "command": "package:convert", diff --git a/messages/bundle_create.md b/messages/bundle_create.md new file mode 100644 index 00000000..be02d894 --- /dev/null +++ b/messages/bundle_create.md @@ -0,0 +1,24 @@ +# summary + +Create a bundle. + +# description + +First, use this command to create a bunle. Then create a bundle version. + +Your --name value must be unique within your namespace. + +Run '<%= config.bin %> bundle list to list all bundles in the Dev Hub org. + +# examples + +- Default Use Case + <%= config.bin %> <%= command.id %> --name --description "" --target-dev-hub ` + +# flags.name.summary + +Name of the bundle to create. + +# flags.description.summary + +Description of the bundle diff --git a/schemas/package-bundles-create.json b/schemas/package-bundles-create.json new file mode 100644 index 00000000..2049f257 --- /dev/null +++ b/schemas/package-bundles-create.json @@ -0,0 +1,16 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$ref": "#/definitions/BundleCreate", + "definitions": { + "BundleCreate": { + "type": "object", + "properties": { + "Id": { + "type": "string" + } + }, + "required": ["Id"], + "additionalProperties": false + } + } +} diff --git a/src/commands/package/bundles/create.ts b/src/commands/package/bundles/create.ts new file mode 100644 index 00000000..7d43a0a2 --- /dev/null +++ b/src/commands/package/bundles/create.ts @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2018, 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 { BundleCreateOptions, PackageBundle } from '@salesforce/packaging'; +import { Messages } from '@salesforce/core'; +import { requiredHubFlag } from '../../../utils/hubFlag.js'; + +Messages.importMessagesDirectoryFromMetaUrl(import.meta.url); +const messages = Messages.loadMessages('@salesforce/plugin-packaging', 'bundle_create'); +export type BundleCreate = { Id: string }; + +export class PackageBundlesCreate 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 aliases = ['force:bundle:create']; + public static readonly requiresProject = true; + public static readonly flags = { + loglevel, + name: Flags.string({ + char: 'n', + summary: messages.getMessage('flags.name.summary'), + required: true, + }), + description: Flags.string({ + char: 'd', + summary: messages.getMessage('flags.description.summary'), + }), + 'target-dev-hub': requiredHubFlag, + 'api-version': orgApiVersionFlagWithDeprecations, + }; + + public async run(): Promise { + const { flags } = await this.parse(PackageBundlesCreate); + + const options: BundleCreateOptions = { + Description: flags.description ?? '', + BundleName: flags.name, + }; + this.spinner.start(`Creating Bundle with name ${options.BundleName}`); + const result = await PackageBundle.create( + flags['target-dev-hub'].getConnection(flags['api-version']), + this.project!, + options + ); + + this.spinner.stop(); + this.table({ data: [{ name: 'Bundle Id', value: result.Id }], title: 'Ids' }); + + return result; + } +} From f4061d3649275829ee6074c469659647e12be5a2 Mon Sep 17 00:00:00 2001 From: Dawson David Date: Wed, 11 Jun 2025 12:54:28 -0600 Subject: [PATCH 2/2] feat: test for bundle create changed comments, added test for bundle create --- src/commands/package/bundles/create.ts | 2 +- test/commands/bundle/bundleCreate.test.ts | 72 +++++++++++++++++++++++ 2 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 test/commands/bundle/bundleCreate.test.ts diff --git a/src/commands/package/bundles/create.ts b/src/commands/package/bundles/create.ts index 7d43a0a2..42dab556 100644 --- a/src/commands/package/bundles/create.ts +++ b/src/commands/package/bundles/create.ts @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, salesforce.com, inc. + * Copyright (c) 2025, 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 diff --git a/test/commands/bundle/bundleCreate.test.ts b/test/commands/bundle/bundleCreate.test.ts new file mode 100644 index 00000000..fcdf8402 --- /dev/null +++ b/test/commands/bundle/bundleCreate.test.ts @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2025, 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 { Config } from '@oclif/core'; +import { TestContext, MockTestOrgData } from '@salesforce/core/testSetup'; +import * as sinon from 'sinon'; +import { expect } from 'chai'; +import { BundleCreateOptions, PackageBundle } from '@salesforce/packaging'; +import { stubSfCommandUx } from '@salesforce/sf-plugins-core'; +import { Connection, SfProject } from '@salesforce/core'; +import { PackageBundlesCreate } from '../../../src/commands/package/bundles/create.js'; + +describe('force:bundle:create - tests', () => { + const $$ = new TestContext(); + const testOrg = new MockTestOrgData(); + let sfCommandStubs: ReturnType; + let createStub: sinon.SinonStub<[Connection, SfProject, BundleCreateOptions], Promise<{ Id: string }>>; + const config = new Config({ root: import.meta.url }); + + beforeEach(async () => { + await $$.stubAuths(testOrg); + await config.load(); + sfCommandStubs = stubSfCommandUx($$.SANDBOX); + + createStub = $$.SANDBOX.stub(PackageBundle, 'create'); + }); + + afterEach(() => { + $$.restore(); + }); + + it('should create a bundle', async () => { + const bundleName = 'dummyPackageId'; + const cmd = new PackageBundlesCreate(['-v', testOrg.username, '--name', bundleName], config); + + createStub.resolves({ Id: 'test-id' }); + + await cmd.run(); + + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + expect(sfCommandStubs.table.calledOnce).to.be.true; + }); + + it('should throw error when name flag is missing', async () => { + const cmd = new PackageBundlesCreate(['-v', testOrg.username], config); + + createStub.resolves({ Id: 'test-id' }); + + try { + await cmd.run(); + expect.fail('Expected error was not thrown'); + } catch (error) { + expect((error as Error).message).to.include('Missing required flag name'); + } + }); + + it('should throw error when test org flag is missing', async () => { + const cmd = new PackageBundlesCreate(['--name', 'dummyPackageId'], config); + + createStub.resolves({ Id: 'test-id' }); + + try { + await cmd.run(); + expect.fail('Expected error was not thrown'); + } catch (error) { + expect((error as Error).message).to.include('No default dev hub found'); + } + }); +});