UNPKG

sfdx-hardis

Version:

Swiss-army-knife Toolbox for Salesforce. Allows you to define a complete CD/CD Pipeline. Orchestrate base commands and assist users with interactive wizards

181 lines (174 loc) • 9.71 kB
/* jscpd:ignore-start */ import { SfCommand, Flags, requiredHubFlagWithDeprecations } from '@salesforce/sf-plugins-core'; import { Messages, SfError } from '@salesforce/core'; import c from 'chalk'; import { MetadataUtils } from '../../../../common/metadata-utils/index.js'; import { execSfdxJson, isCI, uxLog } from '../../../../common/utils/index.js'; import { prompts } from '../../../../common/utils/prompts.js'; import { getConfig, setConfig } from '../../../../config/index.js'; Messages.importMessagesDirectoryFromMetaUrl(import.meta.url); const messages = Messages.loadMessages('sfdx-hardis', 'org'); export default class PackageVersionCreate extends SfCommand { static title = 'Create a new version of a package'; static description = ` ## Command Behavior **Creates a new version of a Salesforce package (2GP or Unlocked) in your Dev Hub.** This command is a crucial step in the package development lifecycle, allowing you to iterate on your Salesforce functionalities and prepare them for deployment or distribution. It automates the process of creating a new, immutable package version. Key functionalities: - **Package Selection:** Prompts you to select an existing package from your \`sfdx-project.json\` file if not specified via the \`--package\` flag. - **Installation Key:** Allows you to set an installation key (password) for the package version, protecting it from unauthorized installations. This can be provided via the \`--installkey\` flag or interactively. - **Code Coverage:** Automatically includes code coverage checks during package version creation. - **Post-Creation Actions:** - **Delete After Creation (\`--deleteafter\`):** Deletes the newly created package version immediately after its creation. This is useful for testing the package creation process without accumulating unnecessary versions. - **Install After Creation (\`--install\`):** Installs the newly created package version on your default Salesforce org. This is convenient for immediate testing or validation. <details markdown="1"> <summary>Technical explanations</summary> The command's technical implementation involves: - **Package Directory Identification:** It identifies the package directory from your \`sfdx-project.json\` based on the selected package name. - **Interactive Prompts:** Uses the \`prompts\` library to guide the user through package selection and installation key input if not provided as command-line arguments. - **Configuration Persistence:** Stores the \`defaultPackageInstallationKey\` in your project's configuration (\`.sfdx-hardis.yml\`) for future use. - **Salesforce CLI Integration:** It constructs and executes the \`sf package version create\` command, passing the package ID, installation key, and other flags. - **\`execSfdxJson\`:** This utility is used to execute the Salesforce CLI command and capture its JSON output, which includes the \`SubscriberPackageVersionId\` of the newly created version. - **Post-Creation Command Execution:** If \`--deleteafter\` or \`--install\` flags are set, it executes \`sf package version delete\` or delegates to \`MetadataUtils.installPackagesOnOrg\` respectively. - **Error Handling:** Includes checks for missing package arguments and handles errors during package version creation or post-creation actions. </details> `; static examples = ['$ sf hardis:package:version:create']; // public static args = [{name: 'file'}]; static flags = { debug: Flags.boolean({ char: 'd', default: false, description: messages.getMessage('debugMode'), }), package: Flags.string({ char: 'p', default: '', description: 'Package identifier that you want to use to generate a new package version', }), installkey: Flags.string({ char: 'k', default: '', description: 'Package installation key', }), deleteafter: Flags.boolean({ default: false, description: 'Delete package version after creating it', }), install: Flags.boolean({ char: 'i', default: false, description: 'Install package version on default org after generation', }), websocket: Flags.string({ description: messages.getMessage('websocket'), }), skipauth: Flags.boolean({ description: 'Skip authentication check when a default username is required', }), 'target-dev-hub': requiredHubFlagWithDeprecations, }; // Set this to true if your command requires a project workspace; 'requiresProject' is false by default static requiresProject = true; package; deleteAfter = false; install = false; installKey = null; promote = false; /* jscpd:ignore-end */ async run() { const { flags } = await this.parse(PackageVersionCreate); this.package = flags.package || null; this.install = flags.install || false; this.installKey = flags.installkey || null; this.deleteAfter = flags.deleteafter || false; //this.promote = flags.promote || false; const debugMode = flags.debug || false; const config = await getConfig('project'); // List project packages const packageDirectories = this.project?.getUniquePackageDirectories() || []; // Ask user to select package and input install key if not sent as command arguments if (this.package == null) { if (isCI) { throw new SfError("You need to send argument 'package'"); } const packageResponse = await prompts([ { type: 'select', name: 'packageSelected', message: c.cyanBright(`Please select a package (this is not a drill, it will create an official new version !)`), description: 'Choose which package to create a new version for - this action creates a permanent version', placeholder: 'Select a package', choices: packageDirectories.map((packageDirectory) => { return { title: packageDirectory?.package || packageDirectory?.path || packageDirectory?.fullPath || packageDirectory?.name, value: packageDirectory.name, }; }), }, { type: 'text', name: 'packageInstallationKey', message: c.cyanBright('Do you want to password protect your package ? (blank means no)'), description: 'Optionally set a password to protect the package installation', placeholder: 'Ex: mySecretPassword123', initial: config.defaultPackageInstallationKey || '', }, ]); this.package = packageResponse.packageSelected; this.installKey = packageResponse.packageInstallationKey; } // Identify package directory const pckgDirectory = packageDirectories.filter((pckgDirectory) => pckgDirectory.name === this.package || pckgDirectory.package === this.package)[0]; if (config.defaultPackageInstallationKey !== this.installKey && this.installKey != null) { await setConfig('project', { defaultPackageInstallationKey: this.installKey, }); } // Create package version uxLog("action", this, c.cyan(`Generating new package version for ${c.green(pckgDirectory.package)}...`)); const createCommand = 'sf package version create' + ` --package "${pckgDirectory.package}"` + (this.installKey ? ` --installation-key "${this.installKey}"` : ' --installation-key-bypass') + ' --code-coverage' + ' --wait 60'; const createResult = await execSfdxJson(createCommand, this, { fail: true, output: true, debug: debugMode, }); const latestVersion = createResult.result.SubscriberPackageVersionId; // If delete after is true, delete package version we just created if (this.deleteAfter) { // Delete package version uxLog("action", this, c.cyan(`Delete new package version ${c.green(latestVersion)} of package ${c.green(pckgDirectory.package)}...`)); const deleteVersionCommand = 'sf package version delete --no-prompt --package ' + latestVersion; const deleteVersionResult = await execSfdxJson(deleteVersionCommand, this, { fail: true, output: true, debug: debugMode, }); if (!(deleteVersionResult.result.success === true)) { throw new SfError(`Unable to delete package version ${latestVersion}`); } } // Install package on org just after is has been generated else if (this.install) { const packagesToInstall = []; const pckg = { SubscriberPackageVersionId: latestVersion, }; if (this.installKey) { pckg.installationkey = this.installKey; } packagesToInstall.push(pckg); await MetadataUtils.installPackagesOnOrg(packagesToInstall, null, this, 'install'); } // Return an object to be displayed with --json return { outputString: 'Generated new package version', packageVersionId: latestVersion, }; } } //# sourceMappingURL=create.js.map