Skip to content

Commit 8db94c2

Browse files
fix: add package:beta:version:promote and NUT
1 parent f9d3c9d commit 8db94c2

File tree

5 files changed

+193
-74
lines changed

5 files changed

+193
-74
lines changed

messages/package_version_promote.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ Promotes a package version to released status.
1010

1111
Supply the ID or alias of the package version you want to promote. Promotes the package version to released status.
1212

13-
Examples:
13+
# examples
14+
1415
$ sfdx force:package:version:promote -p 04t...
1516
$ sfdx force:package:version:promote -p awesome_package_alias
1617
$ sfdx force:package:version:promote -p "Awesome Package Alias"
@@ -23,7 +24,7 @@ ID (starts with 04t) or alias of the package version to promote
2324

2425
The ID (starts with 04t) or alias of the package version to promote.
2526

26-
# packageVersionPromoteSetAsReleasedYesNo
27+
# packageVersionPromoteConfirm
2728

2829
Are you sure you want to release package version %s? You can't undo this action. Release package (y/n)?
2930

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
"@oclif/core": "^1.13.10",
1010
"@oclif/plugin-version": "^1.1.1",
1111
"@salesforce/command": "^5.2.4",
12-
"@salesforce/core": "^3.26.1",
13-
"@salesforce/kit": "^1.5.45",
12+
"@salesforce/core": "^3.26.2",
13+
"@salesforce/kit": "^1.6.0",
1414
"@salesforce/packaging": "^0.0.17",
1515
"tslib": "^2"
1616
},

src/commands/force/package/beta/version/promote.ts

Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,29 @@
55
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
66
*/
77

8+
import * as os from 'os';
89
import { flags, FlagsConfig, SfdxCommand } from '@salesforce/command';
9-
import { Messages, SfdxPropertyKeys } from '@salesforce/core';
10+
import { Messages, SfError } from '@salesforce/core';
11+
import { SaveResult } from 'jsforce';
12+
import {
13+
BY_LABEL,
14+
getHasMetadataRemoved,
15+
getPackageIdFromAlias,
16+
getPackageVersionId,
17+
Package,
18+
validateId,
19+
} from '@salesforce/packaging';
1020

1121
Messages.importMessagesDirectory(__dirname);
1222
const messages = Messages.loadMessages('@salesforce/plugin-packaging', 'package_version_promote');
1323

24+
export type PackageVersionPromoteResponse = { id: string; success: boolean; errors: Error[] };
25+
1426
export class PackageVersionPromoteCommand extends SfdxCommand {
1527
public static readonly description = messages.getMessage('cliDescription');
1628
public static readonly longDescription = messages.getMessage('cliDescriptionLong');
1729
public static readonly help = messages.getMessage('help');
18-
public static readonly orgType = SfdxPropertyKeys.DEFAULT_DEV_HUB_USERNAME;
30+
public static readonly examples = messages.getMessage('examples').split(os.EOL);
1931
public static readonly requiresDevhubUsername = true;
2032
public static readonly requiresProject = true;
2133
public static readonly flagsConfig: FlagsConfig = {
@@ -32,8 +44,48 @@ export class PackageVersionPromoteCommand extends SfdxCommand {
3244
}),
3345
};
3446

35-
public async run(): Promise<unknown> {
36-
process.exitCode = 1;
37-
return Promise.resolve('Not yet implemented');
47+
public async run(): Promise<PackageVersionPromoteResponse> {
48+
const conn = this.hubOrg.getConnection();
49+
let packageId = getPackageIdFromAlias(this.flags.package, this.project) ?? (this.flags.package as string);
50+
51+
// ID can be 04t or 05i at this point
52+
validateId([BY_LABEL.SUBSCRIBER_PACKAGE_VERSION_ID, BY_LABEL.PACKAGE_VERSION_ID], packageId);
53+
54+
// lookup the 05i ID, if needed
55+
if (!packageId.startsWith('05i')) {
56+
packageId = await getPackageVersionId(packageId, conn);
57+
}
58+
59+
if (!this.flags.noprompt) {
60+
// Warn when a Managed package has removed metadata
61+
if (await getHasMetadataRemoved(packageId, conn)) {
62+
this.ux.warn(messages.getMessage('hasMetadataRemovedWarning'));
63+
}
64+
65+
// Prompt for confirmation
66+
if (!(await this.ux.confirm(messages.getMessage('packageVersionPromoteConfirm', [this.flags.package])))) {
67+
return;
68+
}
69+
}
70+
71+
const pkg = new Package({ connection: conn });
72+
let result: SaveResult;
73+
74+
try {
75+
result = await pkg.promote(packageId);
76+
if (!result.success) {
77+
throw SfError.wrap(result.errors.join(os.EOL));
78+
}
79+
} catch (e) {
80+
const err = SfError.wrap(e);
81+
if (err.name === 'DUPLICATE_VALUE' && err.message.includes('previously released')) {
82+
err.message = messages.getMessage('previouslyReleasedMessage');
83+
err.actions = [messages.getMessage('previouslyReleasedAction')];
84+
}
85+
throw err;
86+
}
87+
result.id = packageId;
88+
this.ux.log(messages.getMessage('humanSuccess', [result.id]));
89+
return result;
3890
}
3991
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Copyright (c) 2022, salesforce.com, inc.
3+
* All rights reserved.
4+
* Licensed under the BSD 3-Clause license.
5+
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6+
*/
7+
8+
import { execCmd, genUniqueString, TestSession } from '@salesforce/cli-plugins-testkit';
9+
import { expect } from 'chai';
10+
import { getPackageIdFromAlias } from '@salesforce/packaging';
11+
import { SfProject } from '@salesforce/core';
12+
import { PackageVersionPromoteResponse } from '../../../../src/commands/force/package/beta/version/promote';
13+
// TODO: enable once `package:beta:version:create` is released
14+
describe.skip('package:version:promote', () => {
15+
let session: TestSession;
16+
let packageId: string;
17+
const pkgName = genUniqueString('dancingbears-');
18+
19+
before(async () => {
20+
session = await TestSession.create({
21+
setupCommands: ['sfdx force:org:create -d 1 -s -f config/project-scratch-def.json'],
22+
project: { gitClone: 'https://github.com/trailheadapps/dreamhouse-lwc' },
23+
});
24+
execCmd(
25+
`force:package:beta:create --name ${pkgName} --packagetype Unlocked --path force-app --description "Don't ease, don't ease, don't ease me in."`,
26+
{ ensureExitCode: 0 }
27+
);
28+
// TODO: requires this command
29+
execCmd(
30+
`force:package:beta:version:create --package ${pkgName} --version 1.0.0 --codecoverage --description "Initial version"`,
31+
{ ensureExitCode: 0 }
32+
);
33+
packageId = getPackageIdFromAlias(pkgName, SfProject.getInstance());
34+
});
35+
36+
after(async () => {
37+
await session?.clean();
38+
});
39+
40+
it('should promote a package (human readable)', () => {
41+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
42+
const result = execCmd(`force:package:beta:version:promote --package ${pkgName} --noprompt`, { ensureExitCode: 0 })
43+
.shellOutput.stdout as string;
44+
expect(result).to.contain(
45+
`Successfully promoted the package version, ID: ${packageId}, to released. Starting in Winter ‘21, only unlocked package versions that have met the minimum 75% code coverage requirement can be promoted. Code coverage minimums aren’t enforced on org-dependent unlocked packages.`
46+
);
47+
});
48+
49+
it('should promote a package (--json)', () => {
50+
const result = execCmd<PackageVersionPromoteResponse>(
51+
`force:package:beta:version:promote --package ${pkgName} --noprompt --json`,
52+
{
53+
ensureExitCode: 0,
54+
}
55+
).jsonOutput.result;
56+
expect(result).to.have.all.keys('id', 'success', 'errors');
57+
expect(result.id).to.equal(packageId);
58+
expect(result.success).to.equal(true);
59+
expect(result.errors).to.equal([]);
60+
});
61+
});

0 commit comments

Comments
 (0)