@flxbl-io/sfp
Version:
sfp is a CLI tool to help you manage your Salesforce projects in an artifact centric model
363 lines • 36.3 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
const SfpCommand_1 = __importDefault(require("../SfpCommand"));
const core_1 = require("@salesforce/core");
const fs = __importStar(require("fs-extra"));
const path = require("path");
const ArtifactFetcher_1 = __importDefault(require("../core/artifacts/ArtifactFetcher"));
const SFPStatsSender_1 = __importDefault(require("../core/stats/SFPStatsSender"));
const sfp_logger_1 = __importStar(require("@flxbl-io/sfp-logger"));
const GetFormattedTime_1 = __importDefault(require("../core/utils/GetFormattedTime"));
const DefaultShell_1 = __importDefault(require("../core/utils/DefaultShell"));
const SfpPackage_1 = require("../core/package/SfpPackage");
const sfp_logger_2 = require("@flxbl-io/sfp-logger");
const SfpPackageBuilder_1 = __importDefault(require("../core/package/SfpPackageBuilder"));
const Git_1 = __importDefault(require("../core/git/Git"));
const GroupConsoleLogs_1 = __importDefault(require("../ui/GroupConsoleLogs"));
const PackageVersionLister_1 = __importDefault(require("../core/package/version/PackageVersionLister"));
const SFPOrg_1 = __importDefault(require("../core/org/SFPOrg"));
const ExecuteCommand_1 = __importDefault(require("@flxbl-io/sfdx-process-wrapper/lib/commandExecutor/ExecuteCommand"));
const sfp_logger_3 = require("@flxbl-io/sfp-logger");
const GitTags_1 = __importDefault(require("../core/git/GitTags"));
const sfdxflags_1 = require("../flags/sfdxflags");
const core_2 = require("@oclif/core");
core_1.Messages.importMessagesDirectory(__dirname);
const messages = core_1.Messages.loadMessages('@flxbl-io/sfp', 'publish');
class Publish extends SfpCommand_1.default {
async execute() {
let nPublishedArtifacts = 0;
let failedArtifacts = [];
let executionStartTime = Date.now();
let succesfullyPublishedPackageNamesForTagging = [];
let npmrcFilesToCleanup = [];
this.git = await Git_1.default.initiateRepo(new sfp_logger_2.ConsoleLogger());
try {
sfp_logger_1.default.log((0, sfp_logger_1.COLOR_HEADER)(`command: ${(0, sfp_logger_1.COLOR_KEY_MESSAGE)(`publish`)}`));
sfp_logger_1.default.log((0, sfp_logger_1.COLOR_HEADER)(`target: ${this.flags.scriptpath ? this.flags.scriptpath : 'NPM'}`));
sfp_logger_1.default.log((0, sfp_logger_1.COLOR_HEADER)(`Publish promoted artifacts only: ${this.flags.publishpromotedonly ? true : false}`));
sfp_logger_1.default.printHeaderLine('', sfp_logger_1.COLOR_HEADER, sfp_logger_3.LoggerLevel.INFO);
let packageVersionList;
if (this.flags.publishpromotedonly) {
let hubOrg = await SFPOrg_1.default.create({ aliasOrUsername: this.flags.devhubalias });
let packageVersionLister = new PackageVersionLister_1.default(hubOrg);
packageVersionList = await packageVersionLister.listAllReleasedVersions(process.cwd());
}
let artifacts = ArtifactFetcher_1.default.findArtifacts(this.flags.artifactdir);
let artifactFilePaths = ArtifactFetcher_1.default.fetchArtifacts(this.flags.artifactdir);
// Pattern captures two named groups, the "package" name and "version" number
let pattern = new RegExp('(?<package>^.*)(?:_sfpowerscripts_artifact_)(?<version>.*)(?:\\.zip)');
for (let artifact of artifacts) {
let packageName;
let packageVersionNumber;
let match = path.basename(artifact).match(pattern);
if (match !== null) {
packageName = match.groups.package;
packageVersionNumber = match.groups.version;
}
else {
// artifact filename doesn't match pattern
continue;
}
let sfpPackage = await this.getPackageInfo(artifactFilePaths, packageName, packageVersionNumber);
let packageType = sfpPackage.package_type;
let packageVersionId = sfpPackage.package_version_id;
if (this.flags.publishpromotedonly && packageType === SfpPackage_1.PackageType.Unlocked) {
let isReleased = this.isPackageVersionIdReleased(packageVersionList, packageVersionId);
if (!isReleased) {
failedArtifacts.push(`${packageName} v${packageVersionNumber}`);
sfp_logger_1.default.log(`Skipping ${packageName} Version ${packageVersionNumber}. Package Version Id ${packageVersionId} has not been promoted.`);
process.exitCode = 1;
continue;
}
}
try {
if (this.flags.npm) {
await this.publishUsingNpm(sfpPackage, packageVersionNumber, npmrcFilesToCleanup);
}
else {
await this.publishUsingScript(packageName, packageVersionNumber, artifact);
}
succesfullyPublishedPackageNamesForTagging.push({
name: packageName,
version: packageVersionNumber.replace('-', '.'),
type: packageType,
tag: `${packageName}_v${packageVersionNumber.replace('-', '.')}`,
commitId: sfpPackage.sourceVersion
});
nPublishedArtifacts++;
}
catch (err) {
failedArtifacts.push(`${packageName} v${packageVersionNumber}`);
sfp_logger_1.default.log(err.message);
process.exitCode = 1;
}
}
if (this.flags.gittag) {
await this.createGitTags(succesfullyPublishedPackageNamesForTagging);
await this.pushGitTags(succesfullyPublishedPackageNamesForTagging);
}
if (this.flags.gittagage && this.flags.gittaglimit) {
await this.deleteGitTagsOlderThan(succesfullyPublishedPackageNamesForTagging, this.flags.gittagage, this.flags.gittaglimit);
}
else if (this.flags.gittagage) {
await this.deleteGitTagsOlderThan(succesfullyPublishedPackageNamesForTagging, this.flags.gittagage);
}
else if (this.flags.gittaglimit) {
await this.deleteExcessGitTags(succesfullyPublishedPackageNamesForTagging, this.flags.gittaglimit);
}
}
catch (err) {
sfp_logger_1.default.log(err.message);
// Fail the task when an error occurs
process.exitCode = 1;
}
finally {
if (npmrcFilesToCleanup.length > 0) {
npmrcFilesToCleanup.forEach((npmrcFile) => {
fs.unlinkSync(npmrcFile);
});
}
let totalElapsedTime = Date.now() - executionStartTime;
sfp_logger_1.default.printHeaderLine('', sfp_logger_1.COLOR_HEADER, sfp_logger_3.LoggerLevel.INFO);
sfp_logger_1.default.log((0, sfp_logger_1.COLOR_SUCCESS)(`${nPublishedArtifacts} artifacts published in ${(0, sfp_logger_1.COLOR_TIME)((0, GetFormattedTime_1.default)(totalElapsedTime))} with {${(0, sfp_logger_1.COLOR_ERROR)(failedArtifacts.length)}} errors`));
if (failedArtifacts.length > 0) {
sfp_logger_1.default.log((0, sfp_logger_1.COLOR_ERROR)(`Packages Failed to Publish`, failedArtifacts));
}
sfp_logger_1.default.printHeaderLine('', sfp_logger_1.COLOR_HEADER, sfp_logger_3.LoggerLevel.INFO);
let tags = {
publish_promoted_only: this.flags.publishpromotedonly ? 'true' : 'false',
};
if (this.flags.tag != null) {
tags['tag'] = this.flags.tag;
}
SFPStatsSender_1.default.logGauge('publish.duration', totalElapsedTime, tags);
SFPStatsSender_1.default.logGauge('publish.succeeded', nPublishedArtifacts, tags);
if (failedArtifacts.length > 0) {
SFPStatsSender_1.default.logGauge('publish.failed', failedArtifacts.length, tags);
}
}
}
async publishUsingNpm(sfpPackage, packageVersionNumber, npmrcFilesToCleanup) {
let publishGroupSection = new GroupConsoleLogs_1.default(`Publishing ${sfpPackage.packageName}`).begin();
let artifactRootDirectory = path.dirname(sfpPackage.sourceDir);
// NPM does not accept packages with uppercase characters
let name = sfpPackage.packageName.toLowerCase() + '_sfpowerscripts_artifact';
//Check whether the user has already passed in @
if (this.flags.scope) {
let scope = this.flags.scope.replace(/@/g, '').toLowerCase();
name = `@${scope}/` + name;
}
let packageJson = {
name: name,
version: packageVersionNumber,
repository: sfpPackage.repository_url,
};
fs.writeFileSync(path.join(artifactRootDirectory, 'package.json'), JSON.stringify(packageJson, null, 4));
if (this.flags.npmrcpath) {
fs.copyFileSync(this.flags.npmrcpath, path.join(artifactRootDirectory, '.npmrc'));
npmrcFilesToCleanup.push(path.join(artifactRootDirectory, '.npmrc'));
}
let cmd = `npm publish`;
//Do a tag based on the branch
if (sfpPackage.branch) {
cmd += ` --tag ${sfpPackage.branch}`;
sfp_logger_1.default.log((0, sfp_logger_1.COLOR_KEY_MESSAGE)(`Publishing ${sfpPackage.packageName} Version ${packageVersionNumber} with tag ${sfpPackage.branch}...`));
}
let npmPublishExecutor = new ExecuteCommand_1.default(new sfp_logger_2.ConsoleLogger(), sfp_logger_3.LoggerLevel.INFO, true);
await npmPublishExecutor.execCommand(cmd, artifactRootDirectory);
publishGroupSection.end();
}
async publishUsingScript(packageName, packageVersionNumber, artifact) {
let publishGroupSection = new GroupConsoleLogs_1.default(`Publishing ${packageName}`).begin();
let cmd;
if (process.platform !== 'win32') {
cmd = `${(0, DefaultShell_1.default)()} -e ${this.flags.scriptpath} ${packageName} ${packageVersionNumber} ${artifact} ${this.flags.publishpromotedonly ? true : false}`;
}
else {
cmd = `cmd.exe /c ${this.flags.scriptpath} ${packageName} ${packageVersionNumber} ${artifact} ${this.flags.publishpromotedonly ? true : false}`;
}
sfp_logger_1.default.log((0, sfp_logger_1.COLOR_KEY_MESSAGE)(`Publishing ${packageName} Version ${packageVersionNumber}...`));
let scriptExecutor = new ExecuteCommand_1.default(new sfp_logger_2.ConsoleLogger(), sfp_logger_3.LoggerLevel.INFO, true);
await scriptExecutor.execCommand(cmd, process.cwd());
publishGroupSection.end();
}
validateFlags() {
if (this.flags.scriptpath === undefined && this.flags.npm === undefined)
throw new Error('Either --scriptpath or --npm flag must be provided');
if (this.flags.scriptpath && !fs.existsSync(this.flags.scriptpath))
throw new Error(`Script path ${this.flags.scriptpath} does not exist`);
if (this.flags.npm && !this.flags.scope)
throw new Error('--scope parameter is required for NPM');
}
async pushGitTags(sucessfullyPublishedPackages) {
if (this.flags.pushgittag) {
let tagsForPushing = [];
for (let succesfullyPublishedPackage of sucessfullyPublishedPackages) {
sfp_logger_1.default.log((0, sfp_logger_1.COLOR_KEY_MESSAGE)(`Pushing Git Tags to Repo ${succesfullyPublishedPackage.tag}`));
tagsForPushing.push(succesfullyPublishedPackage.tag);
}
await this.git.pushTags(tagsForPushing);
}
}
async createGitTags(sucessfullyPublishedPackages) {
for (let sucessFullyPublishedPackage of sucessfullyPublishedPackages) {
sfp_logger_1.default.log((0, sfp_logger_1.COLOR_KEY_MESSAGE)(`Creating Git Tags in Repo ${sucessFullyPublishedPackage.tag}`));
await this.git.addAnnotatedTag(sucessFullyPublishedPackage.tag, `${sucessFullyPublishedPackage.name} ${sucessFullyPublishedPackage.type} Package ${sucessFullyPublishedPackage.version}`, sucessFullyPublishedPackage.commitId);
}
}
//Exclude the latest git tag up to a specified number of tags, and then deletes the excess tags that exceed that limit.
async deleteExcessGitTags(tags, limit) {
//const pkgs = ProjectConfig.getAllPackages(this.git.getRepositoryPath());
const tagsToDelete = [];
await Promise.all(tags.map(async (tag) => {
const gitTags = new GitTags_1.default(this.git, tag.name);
const tags = await gitTags.limitTags(limit);
tagsToDelete.push(...tags);
}));
if (tagsToDelete.length > 0) {
sfp_logger_1.default.log((0, sfp_logger_1.COLOR_KEY_MESSAGE)('Removing the following Git tag(s):'));
for (let tag of tagsToDelete) {
sfp_logger_1.default.log((0, sfp_logger_1.COLOR_KEY_MESSAGE)(tag));
}
await this.git.deleteTags(tagsToDelete);
}
}
//Deletes Git tags that are older than a specified number of days.
async deleteGitTagsOlderThan(tags, daysToKeep, limit) {
const tagsToDelete = [];
await Promise.all(tags.map(async (tag) => {
const gitTags = new GitTags_1.default(this.git, tag.name);
const tags = await gitTags.filteredOldTags(daysToKeep, limit);
tagsToDelete.push(...tags);
}));
if (tagsToDelete.length > 0) {
sfp_logger_1.default.log((0, sfp_logger_1.COLOR_KEY_MESSAGE)('Removing the following Git tag(s):'));
for (let tag of tagsToDelete) {
sfp_logger_1.default.log((0, sfp_logger_1.COLOR_KEY_MESSAGE)(tag));
}
await this.git.deleteTags(tagsToDelete);
}
}
isPackageVersionIdReleased(packageVersionList, packageVersionId) {
let packageVersion = packageVersionList.find((pkg) => {
return pkg.SubscriberPackageVersionId === packageVersionId;
});
if (packageVersion)
return true;
else
return false;
}
/**
* Get sourceDirectory and packageMetadata of artifact with package name and version
* @param artifacts
* @param packageName
* @param packageVersionNumber
*/
async getPackageInfo(artifacts, packageName, packageVersionNumber) {
for (let artifact of artifacts) {
let sfpPackage = await SfpPackageBuilder_1.default.buildPackageFromArtifact(artifact, new sfp_logger_2.ConsoleLogger());
if (sfpPackage.packageName === packageName &&
sfpPackage.versionNumber === packageVersionNumber.replace('-', '.')) {
return sfpPackage;
}
}
throw new Error(`Unable to find artifact metadata for ${packageName} Version ${packageVersionNumber.replace('-', '.')}`);
}
}
_a = Publish;
Publish.description = messages.getMessage('commandDescription');
Publish.aliases = ['orchestrator:publish'];
Publish.examples = [
`$ sfp publish --npm`,
];
Publish.requiresUsername = false;
Publish.requiresDevhubUsername = false;
Publish.flags = {
artifactdir: core_2.Flags.directory({
required: true,
char: 'd',
description: messages.getMessage('artifactDirectoryFlagDescription'),
default: 'artifacts',
}),
publishpromotedonly: core_2.Flags.boolean({
char: 'p',
description: messages.getMessage('publishPromotedOnlyFlagDescription'),
dependsOn: ['devhubalias'],
}),
'devhubalias': sfdxflags_1.optionalDevHubFlag,
scriptpath: core_2.Flags.file({
char: 'f',
description: messages.getMessage('scriptPathFlagDescription'),
}),
tag: core_2.Flags.string({
char: 't',
description: messages.getMessage('tagFlagDescription'),
}),
gittag: core_2.Flags.boolean({
description: messages.getMessage('gitTagFlagDescription'),
default: false,
}),
gittaglimit: core_2.Flags.integer({
description: messages.getMessage('gitTagLimitFlagDescription'),
}),
gittagage: core_2.Flags.integer({
description: messages.getMessage('gitTagAgeFlagDescription'),
}),
pushgittag: core_2.Flags.boolean({
description: messages.getMessage('gitPushTagFlagDescription'),
default: false,
}),
npm: core_2.Flags.boolean({
description: messages.getMessage('npmFlagDescription'),
exclusive: ['scriptpath'],
}),
scope: core_2.Flags.string({
description: messages.getMessage('scopeFlagDescription'),
dependsOn: ['npm'],
parse: async (scope) => scope.replace(/@/g, '').toLowerCase(),
}),
npmtag: core_2.Flags.string({
description: messages.getMessage('npmTagFlagDescription'),
dependsOn: ['npm'],
required: false,
deprecated: {
message: '--npmtag is deprecated, sfp will automatically tag the artifact with the branch name',
},
}),
npmrcpath: core_2.Flags.file({
description: messages.getMessage('npmrcPathFlagDescription'),
dependsOn: ['npm'],
required: false,
}),
logsgroupsymbol: sfdxflags_1.logsgroupsymbol,
loglevel: sfdxflags_1.loglevel
};
exports.default = Publish;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVibGlzaC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb21tYW5kcy9wdWJsaXNoLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsK0RBQXVDO0FBQ3ZDLDJDQUE0QztBQUM1Qyw2Q0FBK0I7QUFDL0IsNkJBQThCO0FBQzlCLHdGQUE4RTtBQUM5RSxrRkFBMEQ7QUFDMUQsbUVBTThCO0FBQzlCLHNGQUE4RDtBQUM5RCw4RUFBc0Q7QUFDdEQsMkRBQXFFO0FBQ3JFLHFEQUFxRDtBQUNyRCwwRkFBa0U7QUFDbEUsMERBQWtDO0FBQ2xDLDhFQUFzRDtBQUN0RCx3R0FBZ0Y7QUFDaEYsZ0VBQXdDO0FBQ3hDLHVIQUErRjtBQUMvRixxREFBbUQ7QUFDbkQsa0VBQTBDO0FBQzFDLGtEQUF1RztBQUN2RyxzQ0FBb0M7QUFFcEMsZUFBUSxDQUFDLHVCQUF1QixDQUFDLFNBQVMsQ0FBQyxDQUFDO0FBQzVDLE1BQU0sUUFBUSxHQUFHLGVBQVEsQ0FBQyxZQUFZLENBQUMsZUFBZSxFQUFFLFNBQVMsQ0FBQyxDQUFDO0FBRW5FLE1BQXFCLE9BQVEsU0FBUSxvQkFBVTtJQTBFcEMsS0FBSyxDQUFDLE9BQU87UUFDaEIsSUFBSSxtQkFBbUIsR0FBVyxDQUFDLENBQUM7UUFDcEMsSUFBSSxlQUFlLEdBQWEsRUFBRSxDQUFDO1FBRW5DLElBQUksa0JBQWtCLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBRXBDLElBQUksMENBQTBDLEdBTXhDLEVBQUUsQ0FBQztRQUVULElBQUksbUJBQW1CLEdBQWEsRUFBRSxDQUFDO1FBQ3ZDLElBQUksQ0FBQyxHQUFHLEdBQUcsTUFBTSxhQUFHLENBQUMsWUFBWSxDQUFDLElBQUksMEJBQWEsRUFBRSxDQUFDLENBQUM7UUFFdkQsSUFBSSxDQUFDO1lBQ0Qsb0JBQVMsQ0FBQyxHQUFHLENBQUMsSUFBQSx5QkFBWSxFQUFDLFlBQVksSUFBQSw4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