Skip to content

Commit

Permalink
Merge pull request #416 from forcedotcom/sh/package-scope-profiles
Browse files Browse the repository at this point in the history
fix: add scopeProfiles feature to package version create
  • Loading branch information
shetzel authored Oct 31, 2023
2 parents 973e6ed + 5bc4197 commit 81b7e1e
Show file tree
Hide file tree
Showing 6 changed files with 386 additions and 887 deletions.
1,136 changes: 268 additions & 868 deletions CHANGELOG.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@
],
"dependencies": {
"@oclif/core": "^2.15.0",
"@salesforce/core": "^5.3.9",
"@salesforce/core": "^5.3.14",
"@salesforce/kit": "^3.0.15",
"@salesforce/schemas": "^1.6.0",
"@salesforce/schemas": "^1.6.1",
"@salesforce/source-deploy-retrieve": "^9.7.28",
"@salesforce/ts-types": "^2.0.9",
"fast-xml-parser": "^4.3.1",
Expand Down
2 changes: 1 addition & 1 deletion src/package/packageProfileApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export class PackageProfileApi extends AsyncCreatable<ProfileApiOptions> {
.filter(({ hasContent, profileName, removedSettings, profilePath, xmlFileLocation, adjustedProfile }) => {
if (!hasContent) {
logger.warn(
`Profile ${profileName} has no content after filtering. It will still be part of the package but you can remove if it it's not needed.`
`Profile ${profileName} has no content after filtering. It will still be part of the package but you can remove it if it's not needed.`
);
return true;
} else {
Expand Down
45 changes: 32 additions & 13 deletions src/package/packageVersionCreate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -504,11 +504,33 @@ export class PackageVersionCreate {
);
}

// don't package the profiles from any un-packagedMetadata dir in the project
const profileExcludeDirs = this.project
.getPackageDirectories()
.map((packageDir) => (packageDir as PackageDescriptorJson).unpackagedMetadata?.path)
.filter((packageDirPath) => packageDirPath) as string[];
let profileExcludeDirs: string[] = [];
if (this.packageObject.scopeProfiles) {
this.logger.debug(
`packageDirectory: ${this.packageObject.name} has 'scopeProfiles' set, so only including profiles from within this directory`
);
// exclude all package dirs except the one being packaged
profileExcludeDirs = this.project
.getPackageDirectories()
.map((packageDir) => {
if (packageDir.path !== this.packageObject.path) {
return packageDir.path;
}
})
.filter((packageDirPath) => packageDirPath) as string[];
} else {
// don't package the profiles from any un-packagedMetadata dir in the project
profileExcludeDirs = this.project
.getPackageDirectories()
.map((packageDir) => (packageDir as PackageDescriptorJson).unpackagedMetadata?.path)
.filter((packageDirPath) => packageDirPath) as string[];

let debugMsg = 'Searching for profiles to include from all packageDirectories';
if (profileExcludeDirs?.length) {
debugMsg += ` excluding these unpackagedMetadata dirs: ${profileExcludeDirs.toString()}`;
}
this.logger.debug(debugMsg);
}

const typesArr =
this.options?.profileApi?.filterAndGenerateProfilesForManifest(packageXmlAsJson.types, profileExcludeDirs) ??
Expand Down Expand Up @@ -629,7 +651,10 @@ export class PackageVersionCreate {

this.packageId = this.project.getPackageIdFromAlias(packageName) ?? packageName;

this.options.profileApi = await this.resolveUserLicenses(!!this.packageObject.includeProfileUserLicenses);
this.options.profileApi = await PackageProfileApi.create({
project: this.project,
includeUserLicenses: !!this.packageObject.includeProfileUserLicenses,
});

// At this point, the packageIdFromAlias should have been resolved to an Id. Now, we
// need to validate that the Id is correct.
Expand Down Expand Up @@ -687,13 +712,6 @@ export class PackageVersionCreate {
return this.pkg.getType();
}

private async resolveUserLicenses(includeUserLicenses: boolean): Promise<PackageProfileApi> {
return PackageProfileApi.create({
project: this.project,
includeUserLicenses,
});
}

private async validateOptionsForPackageType(): Promise<void> {
if ((await this.getPackageType()) === 'Unlocked') {
// Don't allow scripts in unlocked packages
Expand All @@ -720,6 +738,7 @@ export class PackageVersionCreate {
delete packageDescriptorJson.branch; // for client-side use only, not needed
delete packageDescriptorJson.fullPath; // for client-side use only, not needed
delete packageDescriptorJson.name; // for client-side use only, not needed
delete packageDescriptorJson.scopeProfiles; // for client-side use only, not needed
return packageDescriptorJson;
}

Expand Down
82 changes: 81 additions & 1 deletion test/package/packageVersionCreate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import * as path from 'node:path';
import * as fs from 'node:fs';
import { instantiateContext, MockTestOrgData, restoreContext, stubContext } from '@salesforce/core/lib/testSetup';
import { assert, expect } from 'chai';
import { Connection, SfProject } from '@salesforce/core';
import { Connection, Logger, SfProject } from '@salesforce/core';
import {
MetadataResolver,
PackageVersionCreate,
Expand Down Expand Up @@ -120,6 +120,7 @@ describe('Package Version Create', () => {
const pvc = new PackageVersionCreate({ connection, project, packageId });
try {
await pvc.createPackageVersion();
expect(false, 'package version create should have failed').to.be.true;
} catch (e) {
assert(e instanceof Error);
expect(e.message).to.equal(
Expand Down Expand Up @@ -774,6 +775,85 @@ describe('Package Version Create', () => {
expect(excludedDirsFilter).to.contain('unpackaged-force-app');
});

it('should only package profiles in the package dir when scopeProfiles = true', async () => {
await project.getSfProjectJson().write({
packageDirectories: [
{
path: 'pkg',
package: 'dep',
versionName: 'ver 0.1',
versionNumber: '0.1.0.NEXT',
default: false,
name: 'pkg',
unpackagedMetadata: {
path: 'unpackaged-pkg',
},
},
{
path: 'force-app',
package: 'TEST',
versionName: 'ver 0.1',
versionNumber: '0.1.0.NEXT',
default: true,
ancestorId: 'TEST2',
scopeProfiles: true,
unpackagedMetadata: {
path: 'unpackaged-force-app',
},
seedMetadata: {
path: 'seed',
},
dependencies: [
{
package: 'DEP@0.1.0-1',
},
],
},
{
path: 'unpackaged-pkg',
},
{
path: 'unpackaged-force-app',
},
],
packageAliases: {
TEST: packageId,
TEST2: '05i3i000000Gmj6XXX',
DEP: '05i3i000000Gmj6XXX',
'DEP@0.1.0-1': '04t3i000002eyYXXXX',
},
});
const loggerSpy = $$.SANDBOX.spy(Logger.prototype, 'debug');
const pvc = new PackageVersionCreate({ connection, project, packageId });
const profileSpyGenerate = $$.SANDBOX.spy(PackageProfileApi.prototype, 'generateProfiles');
const profileSpyFilter = $$.SANDBOX.spy(PackageProfileApi.prototype, 'filterAndGenerateProfilesForManifest');
stubConvert();
const result = await pvc.createPackageVersion();

expect(result).to.have.all.keys(
'Branch',
'ConvertedFromVersionId',
'CreatedBy',
'CreatedDate',
'Error',
'HasMetadataRemoved',
'Id',
'Package2Id',
'Package2VersionId',
'Status',
'SubscriberPackageVersionId',
'Tag'
);
expect(loggerSpy.called).to.be.true;
const logMsg =
"packageDirectory: force-app has 'scopeProfiles' set, so only including profiles from within this directory";
expect(loggerSpy.calledWith(logMsg)).to.be.true;
expect(profileSpyGenerate.called).to.be.true;
expect(profileSpyGenerate.firstCall.args[2]).to.deep.equal(['pkg', 'unpackaged-pkg', 'unpackaged-force-app']);
expect(profileSpyFilter.called).to.be.true;
expect(profileSpyFilter.firstCall.args[1]).to.deep.equal(['pkg', 'unpackaged-pkg', 'unpackaged-force-app']);
});

it('should not package profiles from outside of project package directories', async () => {
const pkgProfileApi = await PackageProfileApi.create({ project, includeUserLicenses: false });
const types = [
Expand Down
4 changes: 2 additions & 2 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,7 @@
strip-ansi "6.0.1"
ts-retry-promise "^0.7.1"

"@salesforce/core@^5.3.10", "@salesforce/core@^5.3.5", "@salesforce/core@^5.3.9":
"@salesforce/core@^5.3.10", "@salesforce/core@^5.3.14", "@salesforce/core@^5.3.5":
version "5.3.14"
resolved "https://registry.yarnpkg.com/@salesforce/core/-/core-5.3.14.tgz#a5a3d02be6727492469ed39b23eaf3c56675496b"
integrity sha512-IFmLZCpFBcreTFEaH+Rn4BozUpFx3vvf43yWuXWdOvALz4ad18yU3Kzk9GxwzablrQxPFmJ43ClQG10dmoh/ig==
Expand Down Expand Up @@ -663,7 +663,7 @@
resolved "https://registry.yarnpkg.com/@salesforce/prettier-config/-/prettier-config-0.0.3.tgz#ba648d4886bb38adabe073dbea0b3a91b3753bb0"
integrity sha512-hYOhoPTCSYMDYn+U1rlEk16PoBeAJPkrdg4/UtAzupM1mRRJOwEPMG1d7U8DxJFKuXW3DMEYWr2MwAIBDaHmFg==

"@salesforce/schemas@^1.6.0", "@salesforce/schemas@^1.6.1":
"@salesforce/schemas@^1.6.1":
version "1.6.1"
resolved "https://registry.yarnpkg.com/@salesforce/schemas/-/schemas-1.6.1.tgz#7d1c071e1e509ca9d2d8a6e48ac7447dd67a534d"
integrity sha512-eVy947ZMxCJReKJdgfddUIsBIbPTa/i8RwQGwxq4/ss38H5sLOAeSTaun9V7HpJ1hkpDznWKfgzYvjsst9K6ig==
Expand Down

0 comments on commit 81b7e1e

Please sign in to comment.