diff --git a/src/package/package.ts b/src/package/package.ts index a8a59aa8e..f7f21694a 100644 --- a/src/package/package.ts +++ b/src/package/package.ts @@ -97,6 +97,11 @@ export class Package extends AsyncCreatable implements IPackage return Promise.resolve(undefined); } + public async getPackage(packageId: string): Promise { + const package2 = await this.options.connection.tooling.sobject('Package2').retrieve(packageId); + return package2 as unknown as PackagingSObjects.Package2; + } + public async getExternalSites( subscriberPackageVersionId: string, installationKey?: string diff --git a/src/package/packageVersion.ts b/src/package/packageVersion.ts index 8b5b27c7e..77c4b86be 100644 --- a/src/package/packageVersion.ts +++ b/src/package/packageVersion.ts @@ -5,7 +5,15 @@ * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ -import { Connection, Messages, SfProject, PollingClient, Lifecycle, StatusResult } from '@salesforce/core'; +import { + Connection, + Messages, + SfProject, + PollingClient, + Lifecycle, + StatusResult, + NamedPackageDir, +} from '@salesforce/core'; import { Duration } from '@salesforce/kit'; import { PackageVersionCreateRequestResult, @@ -13,16 +21,18 @@ import { PackageVersionCreateOptions, PackageVersionOptions, PackageVersionReportResult, + PackagingSObjects, } from '../interfaces'; import * as pkgUtils from '../utils/packageUtils'; import { combineSaveErrors } from '../utils'; +import { generatePackageAliasEntry, getConfigPackageDirectory } from '../utils/packageUtils'; import { PackageVersionCreate } from './packageVersionCreate'; import { getPackageVersionReport } from './packageVersionReport'; import { getCreatePackageVersionCreateRequestReport } from './packageVersionCreateRequestReport'; +import { Package } from './package'; Messages.importMessagesDirectory(__dirname); // const messages = Messages.loadMessages('@salesforce/packaging', 'messages'); - // const logger = Logger.childFromRoot('packageVersionCreate'); export class PackageVersion { // @ts-ignore @@ -44,6 +54,7 @@ export class PackageVersion { const pvc = new PackageVersionCreate({ ...options, ...this.options }); const createResult = await pvc.createPackageVersion(); const waitResult = await this.waitForCreateVersion( + createResult.Package2Id, createResult.Id, options.wait ?? Duration.milliseconds(0), options.pollInterval ? options.pollInterval : Duration.seconds(30) @@ -120,6 +131,7 @@ export class PackageVersion { * @param interval - frequency of checking for the package version to be created */ public async waitForCreateVersion( + packageId: string, createPackageVersionRequestId: string, wait: Duration = Duration.milliseconds(0), interval: Duration = Duration.milliseconds(0) @@ -128,6 +140,7 @@ export class PackageVersion { const result = await this.getCreateVersionReport(createPackageVersionRequestId); return result; } + const resolvedWait = await this.resolveOrgDependentPollingTime(packageId, wait, interval); let remainingWaitTime: Duration = wait; let report: PackageVersionCreateRequestResult; const pollingClient = await PollingClient.create({ @@ -154,6 +167,7 @@ export class PackageVersion { payload: report, }; case 'Success': + await this.updateProjectWithPackageVersion(this.project, report); await Lifecycle.getInstance().emit('success', report); return { completed: true, payload: report }; case 'Error': @@ -162,7 +176,7 @@ export class PackageVersion { } }, frequency: interval, - timeout: wait, + timeout: resolvedWait, }); try { return pollingClient.subscribe(); @@ -217,4 +231,72 @@ export class PackageVersion { updateResult.id = await pkgUtils.getSubscriberPackageVersionId(packageVersionId, this.connection); return updateResult; } + + /** + * Increase the wait time for a package version that is org dependent. + * + * @param resolvedPackageId + * @param pollInterval + * @param wait + * @private + */ + private async resolveOrgDependentPollingTime( + resolvedPackageId: string, + wait: Duration, + pollInterval: Duration + ): Promise { + // If we are polling check to see if the package is Org-Dependent, if so, update the poll time + if (wait.milliseconds > 0) { + const query = `SELECT IsOrgDependent FROM Package2 WHERE Id = '${resolvedPackageId}'`; + try { + const pkgQueryResult = await this.connection.singleRecordQuery(query, { + tooling: true, + }); + if (pkgQueryResult.IsOrgDependent) { + return Duration.seconds((60 / pollInterval.seconds) * wait.seconds); + } + } catch { + // do nothing + } + } + return wait; + } + + private async updateProjectWithPackageVersion( + withProject: SfProject, + results: PackageVersionCreateRequestResult + ): Promise { + if (withProject && !process.env.SFDX_PROJECT_AUTOUPDATE_DISABLE_FOR_PACKAGE_VERSION_CREATE) { + const query = `SELECT Name, Package2Id, MajorVersion, MinorVersion, PatchVersion, BuildNumber, Description, Branch FROM Package2Version WHERE Id = '${results.Package2VersionId}'`; + const packageVersion = await this.connection.singleRecordQuery(query, { + tooling: true, + }); + const packageVersionVersionString = `${packageVersion.MajorVersion}.${packageVersion.MinorVersion}.${packageVersion.PatchVersion}.${packageVersion.BuildNumber}`; + await this.generatePackageDirectory(packageVersion, withProject, packageVersionVersionString); + const newConfig = await generatePackageAliasEntry( + this.connection, + withProject, + packageVersion.SubscriberPackageVersionId, + packageVersionVersionString, + packageVersion.Branch, + packageVersion.Package2Id + ); + withProject.getSfProjectJson().set('packageAliases', newConfig); + await withProject.getSfProjectJson().write(); + } + } + + private async generatePackageDirectory( + packageVersion: PackagingSObjects.Package2Version, + withProject: SfProject, + packageVersionVersionString: string + ) { + const pkg = await (await Package.create({ connection: this.connection })).getPackage(packageVersion.Package2Id); + const pkgDir = + getConfigPackageDirectory(withProject.getPackageDirectories(), 'id', pkg.Id) ?? ({} as NamedPackageDir); + pkgDir.versionNumber = packageVersionVersionString; + pkgDir.versionDescription = packageVersion.Description; + const packageDirs = withProject.getPackageDirectories().map((pd) => (pkgDir['id'] === pd['id'] ? pkgDir : pd)); + withProject.getSfProjectJson().set('packageDirectories', packageDirs); + } } diff --git a/src/package/packageVersionCreate.ts b/src/package/packageVersionCreate.ts index a5c4079cf..51d6dbd78 100644 --- a/src/package/packageVersionCreate.ts +++ b/src/package/packageVersionCreate.ts @@ -22,7 +22,6 @@ import { ComponentSetBuilder, ConvertResult, MetadataConverter } from '@salesfor import { uniqid } from '@salesforce/core/lib/testSetup'; import SettingsGenerator from '@salesforce/core/lib/org/scratchOrgSettingsGenerator'; import * as xml2js from 'xml2js'; -import { Duration } from '@salesforce/kit'; import { PackageDirDependency } from '@salesforce/core/lib/sfProject'; import * as pkgUtils from '../utils/packageUtils'; import { consts } from '../constants'; @@ -44,8 +43,6 @@ const logger = Logger.childFromRoot('packageVersionCreate'); const DESCRIPTOR_FILE = 'package2-descriptor.json'; -const POLL_INTERVAL_WITHOUT_VALIDATION_SECONDS = 5; - type PackageDescriptorJson = Partial & Partial<{ id: string; @@ -811,21 +808,6 @@ export class PackageVersionCreate { errStr.toString(), ]); } - let pollInterval = Duration.seconds(pkgUtils.POLL_INTERVAL_SECONDS); - let maxRetries = 0; - - if (options.wait?.milliseconds > 0) { - if (options.skipvalidation === true) { - pollInterval = Duration.seconds(POLL_INTERVAL_WITHOUT_VALIDATION_SECONDS); - } - maxRetries = (60 / pollInterval.seconds) * options.wait.seconds; - } - [pollInterval, maxRetries] = await this.resolveOrgDependentPollingTime( - resolvedPackageId, - options, - pollInterval, - maxRetries - ); return (await this.listRequestById(createResult.id, this.connection))[0]; } @@ -938,32 +920,6 @@ export class PackageVersionCreate { }); } - private async resolveOrgDependentPollingTime( - resolvedPackageId: string, - options: PackageVersionCreateOptions, - pollInterval: Duration, - maxRetries: number - ): Promise<[Duration, number]> { - let pi = pollInterval; - let mr = maxRetries; - // If we are polling check to see if the package is Org-Dependent, if so, update the poll time - if (options.wait) { - const query = `SELECT IsOrgDependent FROM Package2 WHERE Id = '${resolvedPackageId}'`; - try { - const pkgQueryResult = await this.connection.singleRecordQuery(query, { - tooling: true, - }); - if (pkgQueryResult.IsOrgDependent) { - pi = Duration.seconds(POLL_INTERVAL_WITHOUT_VALIDATION_SECONDS); - mr = (60 / pollInterval.seconds) * options.wait.seconds; - } - } catch { - // do nothing - } - } - return [pi, mr]; - } - private async validateFlagsForPackageType(packageId: string, options: PackageVersionCreateOptions): Promise { const packageType = await pkgUtils.getPackageType(packageId, this.connection); diff --git a/src/utils/packageUtils.ts b/src/utils/packageUtils.ts index 9e7719e98..9d7362c1d 100644 --- a/src/utils/packageUtils.ts +++ b/src/utils/packageUtils.ts @@ -859,7 +859,7 @@ export async function pollForStatusWithInterval( const record = pkgQueryResult.records[0]; return `${record.MajorVersion}.${record.MinorVersion}.${record.PatchVersion}-${record.BuildNumber}`; }); - const newConfig = await _generatePackageAliasEntry( + const newConfig = await generatePackageAliasEntry( connection, withProject, results[0].SubscriberPackageVersionId, @@ -870,7 +870,7 @@ export async function pollForStatusWithInterval( withProject.getSfProjectJson().set('packageAliases', newConfig); await withProject.getSfProjectJson().write(); } - Lifecycle.getInstance().emit(Package2VersionStatus.success, { + await Lifecycle.getInstance().emit(Package2VersionStatus.success, { id, packageVersionCreateRequestResult: results[0], projectUpdated, @@ -889,12 +889,12 @@ export async function pollForStatusWithInterval( } status = errors.length !== 0 ? errors.join('\n') : results[0].Error.join('\n'); } - Lifecycle.getInstance().emit(Package2VersionStatus.error, { id, status }); + await Lifecycle.getInstance().emit(Package2VersionStatus.error, { id, status }); throw new SfError(status); } } else { const remainingTime = Duration.milliseconds(interval.milliseconds * remainingRetries); - Lifecycle.getInstance().emit(Package2VersionStatus.inProgress, { + await Lifecycle.getInstance().emit(Package2VersionStatus.inProgress, { id, packageVersionCreateRequestResult: results[0], message: '', @@ -927,7 +927,7 @@ export async function pollForStatusWithInterval( * @param packageId the 0Ho id * @private */ -async function _generatePackageAliasEntry( +export async function generatePackageAliasEntry( connection: Connection, project: SfProject, packageVersionId: string, @@ -942,9 +942,8 @@ async function _generatePackageAliasEntry( let packageName; if (!aliasForPackageId || aliasForPackageId.length === 0) { const query = `SELECT Name FROM Package2 WHERE Id = '${packageId}'`; - packageName = await connection.tooling - .query(query) - .then((pkgQueryResult) => pkgQueryResult.records[0]?.Name); + const package2 = await connection.singleRecordQuery(query, { tooling: true }); + packageName = package2.Name; } else { packageName = aliasForPackageId[0]; } diff --git a/test/package/packageTest.nut.ts b/test/package/packageTest.nut.ts index 53ab9d2a7..f81636ef4 100644 --- a/test/package/packageTest.nut.ts +++ b/test/package/packageTest.nut.ts @@ -138,6 +138,7 @@ describe('Integration tests for #salesforce/packaging library', function () { `\n${JSON.stringify(result, undefined, 2)}` ); pkgCreateVersionRequestId = result.Id; + pkgId = result.Package2Id; }); it('get package version create report', async () => { @@ -165,6 +166,7 @@ describe('Integration tests for #salesforce/packaging library', function () { expect(results.Status).to.equal(PackagingSObjects.Package2VersionStatus.success); }); const result = await pv.waitForCreateVersion( + pkgId, pkgCreateVersionRequestId, Duration.minutes(10), Duration.seconds(30) @@ -210,10 +212,10 @@ describe('Integration tests for #salesforce/packaging library', function () { // eslint-disable-next-line no-console console.log(`projectFile: ${JSON.stringify(projectFile, undefined, 2)}`); - // expect(result.Description).to.equal( - // projectFile.packageDirectories[0].versionDescription, - // `'force:package:version:report' Description mismatch: expected '${projectFile.packageDirectories[0].versionDescription}', got '${result.Description}'` - // ); + expect(result.Description).to.equal( + projectFile.packageDirectories[0].versionDescription, + `'force:package:version:report' Description mismatch: expected '${projectFile.packageDirectories[0].versionDescription}', got '${result.Description}'` + ); expect(result.Name).to.equal( projectFile.packageDirectories[0].versionName,