@flxbl-io/sfp
Version:
sfp is a CLI tool to help you manage your Salesforce projects in an artifact centric model
672 lines • 72.5 kB
JavaScript
"use strict";
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 };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DeploymentMode = void 0;
const ArtifactFetcher_1 = __importDefault(require("../../core/artifacts/ArtifactFetcher"));
const sfp_logger_1 = __importStar(require("@flxbl-io/sfp-logger"));
const Stage_1 = require("../Stage");
const ProjectConfig_1 = __importDefault(require("../../core/project/ProjectConfig"));
const semver = require("semver");
const PromoteUnlockedPackageImpl_1 = __importDefault(require("../../core/package/promote/PromoteUnlockedPackageImpl"));
const DeploymentExecutor_1 = require("../../core/deployers/DeploymentExecutor");
const sfp_logger_2 = require("@flxbl-io/sfp-logger");
const PackageInstallationResult_1 = require("../../core/package/packageInstallers/PackageInstallationResult");
const SFPOrg_1 = __importDefault(require("../../core/org/SFPOrg"));
const SfpPackage_1 = require("../../core/package/SfpPackage");
const SfpPackageInquirer_1 = __importDefault(require("../../core/package/SfpPackageInquirer"));
const SfpPackageBuilder_1 = __importDefault(require("../../core/package/SfpPackageBuilder"));
const SfpPackageInstaller_1 = __importDefault(require("../../core/package/SfpPackageInstaller"));
const InstallPackage_1 = require("../../core/package/packageInstallers/InstallPackage");
const _ = __importStar(require("lodash"));
const GroupConsoleLogs_1 = __importDefault(require("../../ui/GroupConsoleLogs"));
const TableConstants_1 = require("../../ui/TableConstants");
const VersionNumberConverter_1 = __importDefault(require("../../core/utils/VersionNumberConverter"));
const ReleaseConfigLoader_1 = __importDefault(require("../release/ReleaseConfigLoader"));
const markdown_table_ts_1 = require("markdown-table-ts");
const FileOutputHandler_1 = __importDefault(require("../../outputs/FileOutputHandler"));
const Table = require('cli-table');
const retry = require('async-retry');
var DeploymentMode;
(function (DeploymentMode) {
DeploymentMode[DeploymentMode["NORMAL"] = 0] = "NORMAL";
DeploymentMode[DeploymentMode["SOURCEPACKAGES"] = 1] = "SOURCEPACKAGES";
DeploymentMode[DeploymentMode["SOURCEPACKAGES_PUSH"] = 2] = "SOURCEPACKAGES_PUSH";
})(DeploymentMode || (exports.DeploymentMode = DeploymentMode = {}));
class DeployImpl {
constructor(props) {
this.props = props;
//Set defaults
if (!this.props.maxRetryCount)
this.props.maxRetryCount = 1;
}
set postDeployHook(hook) {
this._postDeployHook = hook;
}
set preDeployHook(hook) {
this._preDeployHook = hook;
}
async exec() {
let deployed = [];
let failed = [];
let queue = [];
let packagesToPackageInfo;
try {
//Create Org
this.targetOrg = await SFPOrg_1.default.create({ aliasOrUsername: this.props.targetUsername });
let artifacts = ArtifactFetcher_1.default.fetchArtifacts(this.props.artifactDir, null, this.props.logger);
if (artifacts.length === 0)
throw new Error(`No artifacts to install found in ${this.props.artifactDir}`);
//Convert artifacts to SfpPackages
let sfpPackages = await this.generateSfpPackageFromArtifacts(artifacts);
//Filter artifacts based on release config
if (this.props.releaseConfigPath)
sfpPackages = this.filterSfPPackagesBasedOnReleaseConfig(sfpPackages, this.props.releaseConfigPath, this.props.logger);
else if (this.props.filterByProvidedArtifacts)
sfpPackages = this.filterSfPPackagesBasedOnArtifacts(sfpPackages, this.props.filterByProvidedArtifacts, this.props.logger);
if (sfpPackages.length <= 0 && (this.props.releaseConfigPath || this.props.filterByProvidedArtifacts)) {
sfp_logger_1.default.log(`Skipping deployment, no artifacts found based on filters defined in ${this.props.releaseConfigPath ? ' release config' : '--artifacts parameter'}`, sfp_logger_1.LoggerLevel.INFO, this.props.logger);
return {
scheduled: 0,
deployed: deployed,
failed: failed,
queue: queue,
packagesToPackageInfo: null,
error: null,
};
}
//Grab the latest projectConfig from Packages
let sfpPackageInquirer = new SfpPackageInquirer_1.default(sfpPackages, this.props.logger);
let sfdxProjectConfig = sfpPackageInquirer.getLatestProjectConfig();
if (sfdxProjectConfig == null) {
// If unable to find latest package manifest in artifacts, use package manifest in project directory
sfdxProjectConfig = ProjectConfig_1.default.getSFDXProjectConfig(null);
}
sfp_logger_1.default.log('Artifacts' + sfpPackages.length, sfp_logger_1.LoggerLevel.TRACE, this.props.logger);
packagesToPackageInfo = await this.getPackagesToPackageInfo(sfpPackages);
sfp_logger_1.default.log('Artifacts' + JSON.stringify(packagesToPackageInfo), sfp_logger_1.LoggerLevel.TRACE, this.props.logger);
queue = this.getPackagesToDeploy(sfdxProjectConfig, packagesToPackageInfo);
sfp_logger_1.default.log('queue:' + JSON.stringify(queue), sfp_logger_1.LoggerLevel.TRACE, this.props.logger);
if (this.props.skipIfPackageInstalled) {
//Filter the queue based on what is deployed in the target org
let isBaselinOrgModeActivated;
if (this.props.baselineOrg) {
isBaselinOrgModeActivated = true;
}
else {
isBaselinOrgModeActivated = false;
this.props.baselineOrg = this.props.targetUsername; //Change baseline to the target one itself
}
let filteredDeploymentQueue = await this.filterByPackagesInstalledInTheOrg(sfdxProjectConfig, queue, packagesToPackageInfo, this.props.baselineOrg);
sfp_logger_1.default.log('filtered queue:' + JSON.stringify(filteredDeploymentQueue), sfp_logger_1.LoggerLevel.TRACE, this.props.logger);
this.printArtifactVersionsWhenSkipped(queue, packagesToPackageInfo, isBaselinOrgModeActivated, this.props);
queue = filteredDeploymentQueue;
}
else {
this.printArtifactVersions(queue, packagesToPackageInfo);
}
for (let i = 0; i < queue.length; i++) {
let packageInfo = packagesToPackageInfo[queue[i].packageName];
let sfpPackage = packageInfo.sfpPackage;
let packageType = sfpPackage.packageType;
let pkgDescriptor = ProjectConfig_1.default.getPackageDescriptorFromConfig(queue[i].packageName, sfdxProjectConfig);
let groupSection;
if (this.props.currentStage == Stage_1.Stage.VALIDATE) {
groupSection = new GroupConsoleLogs_1.default(`Validating/Synchronizing: ${i + 1}/${queue.length} ${queue[i].packageName}`, this.props.logger).begin();
}
else
groupSection = new GroupConsoleLogs_1.default(`Installing: ${i + 1}/${queue.length} ${queue[i].packageName}`, this.props.logger).begin();
//Display Header
this.displayHeader(sfpPackage, pkgDescriptor, queue[i].packageName);
let preHookStatus = await this._preDeployHook?.preDeployPackage(sfpPackage, this.props.targetUsername, sfpPackages, this.props.devhubUserName, this.props.logger);
if (preHookStatus?.isToFailDeployment) {
failed = queue.slice(i).map((pkg) => packagesToPackageInfo[pkg.packageName]);
throw new Error(preHookStatus.message
? preHookStatus.message
: 'Hook Failed to execute, but didnt provide proper message');
}
let isToBeRetried = this.props.isRetryOnFailure;
let packageInstallationResult = await retry(async (bail, attemptCount) => {
try {
try {
await this.promotePackagesBeforeInstallation(packageInfo.sourceDirectory, sfpPackage);
}
catch (error) {
//skip packages already promoted
sfp_logger_1.default.log(`Artifact already promoted .. skipping`, sfp_logger_1.LoggerLevel.WARN);
}
this.displayRetryHeader(isToBeRetried, attemptCount);
let installPackageResult = await this.installPackage(packageType, queue[i], this.targetOrg, queue[i].packageDescriptor.skipTesting, this.props.waitTime.toString(), pkgDescriptor, false, //Queue already filtered by deploy, there is no further need for individual
//commands to decide the skip logic. TODO: fix this incorrect pattern
sfpPackage.apiVersion || sfpPackage.payload?.Package?.version // Use package.xml version for backwards compat with old artifacts
);
//Handle specific error condition which need a retry, overriding the set value
isToBeRetried = handleRetryOnSpecificConditions(isToBeRetried, installPackageResult, attemptCount, this.props.maxRetryCount);
if (isToBeRetried) {
throw new Error(installPackageResult.message);
}
else
return installPackageResult;
}
catch (error) {
if (isToBeRetried) {
throw error;
}
else {
// Any other exception, in regular cases dont retry, just bail out
let failedPackageInstallationResult = {
result: PackageInstallationResult_1.PackageInstallationStatus.Failed,
message: error,
};
FileOutputHandler_1.default.getInstance().writeOutput(`deployment-error.md`, `### 💣 Deployment Failed 💣`);
FileOutputHandler_1.default.getInstance().appendOutput(`deployment-error.md`, `Artifact Installation failed for **${queue[i].packageName}**`);
FileOutputHandler_1.default.getInstance().appendOutput(`deployment-error.md`, `Reasons:`);
FileOutputHandler_1.default.getInstance().appendOutput(`deployment-error.md`, `${error}`);
return failedPackageInstallationResult;
}
}
function handleRetryOnSpecificConditions(isToBeRetried, installPackageResult, retryCount, maxRetryCount) {
//override current value when encountering such issue
if (installPackageResult.result === PackageInstallationResult_1.PackageInstallationStatus.Failed) {
if (installPackageResult.message?.includes('ongoing background job'))
return true;
else if (isToBeRetried && retryCount <= maxRetryCount)
return true;
else
return false;
}
else
return false;
}
}, { retries: 10, minTimeout: 30000 });
if (packageInstallationResult.result === PackageInstallationResult_1.PackageInstallationStatus.Succeeded) {
deployed.push(packageInfo);
}
else if (packageInstallationResult.result === PackageInstallationResult_1.PackageInstallationStatus.Skipped) {
continue;
}
else if (packageInstallationResult.result === PackageInstallationResult_1.PackageInstallationStatus.Failed) {
failed = queue.slice(i).map((pkg) => packagesToPackageInfo[pkg.packageName]);
}
// Only deploy post hook when package installation is successful
if (packageInstallationResult.result === PackageInstallationResult_1.PackageInstallationStatus.Succeeded) {
let postHookStatus = await this._postDeployHook?.postDeployPackage(sfpPackage, packageInstallationResult, this.props.targetUsername, sfpPackages, this.props.devhubUserName, this.props.logger);
if (postHookStatus?.isToFailDeployment) {
failed = queue.slice(i).map((pkg) => packagesToPackageInfo[pkg.packageName]);
throw new Error(postHookStatus.message
? postHookStatus.message
: 'Hook Failed to execute, but didnt provide proper message');
}
}
if (packageInstallationResult.result === PackageInstallationResult_1.PackageInstallationStatus.Failed) {
failed = queue.slice(i).map((pkg) => packagesToPackageInfo[pkg.packageName]);
throw new Error(packageInstallationResult.message);
}
groupSection.end();
}
return {
scheduled: queue.length,
deployed: deployed,
failed: failed,
queue: queue,
packagesToPackageInfo: packagesToPackageInfo,
error: null,
};
}
catch (err) {
sfp_logger_1.default.log(err, sfp_logger_1.LoggerLevel.ERROR, this.props.logger);
return {
scheduled: queue?.length ? queue.length : 0,
deployed: deployed,
failed: failed,
queue: queue,
packagesToPackageInfo: packagesToPackageInfo,
error: err.message,
};
}
}
filterSfPPackagesBasedOnReleaseConfig(sfpPackages, releaseConfigPath, logger) {
if (!releaseConfigPath)
return sfpPackages;
else {
sfp_logger_1.default.log((0, sfp_logger_2.COLOR_KEY_MESSAGE)(`Filtering packages to be deployed based on release config ${(0, sfp_logger_2.COLOR_KEY_VALUE)(releaseConfigPath)}`), sfp_logger_1.LoggerLevel.INFO, logger);
let releaseConfigLoader = new ReleaseConfigLoader_1.default(logger, releaseConfigPath);
let packages = releaseConfigLoader.getPackagesAsPerReleaseConfig();
//Filter artifacts based on packages
let filteredSfPPackages = [];
for (const sfpPackage of sfpPackages) {
if (packages.includes(sfpPackage.packageName)) {
filteredSfPPackages.push(sfpPackage);
}
}
return filteredSfPPackages;
}
}
filterSfPPackagesBasedOnArtifacts(sfpPackages, artifacts, logger) {
if (!artifacts || artifacts.length == 0)
return sfpPackages;
else {
sfp_logger_1.default.log((0, sfp_logger_2.COLOR_KEY_MESSAGE)(`Filtering packages to be deployed based on provided artifacts ${(0, sfp_logger_2.COLOR_KEY_VALUE)(artifacts)}`), sfp_logger_1.LoggerLevel.INFO, logger);
//Filter artifacts based on packages
let filteredSfPPackages = [];
for (const sfpPackage of sfpPackages) {
if (artifacts.includes(sfpPackage.packageName)) {
filteredSfPPackages.push(sfpPackage);
}
}
return filteredSfPPackages;
}
}
async generateSfpPackageFromArtifacts(artifacts) {
let sfpPackages = [];
for (const artifact of artifacts) {
let sfpPackage = await SfpPackageBuilder_1.default.buildPackageFromArtifact(artifact, this.props.logger);
sfpPackages.push(sfpPackage);
}
return sfpPackages;
}
async promotePackagesBeforeInstallation(sourceDirectory, sfpPackage) {
if (this.props.promotePackagesBeforeDeploymentToOrg === this.props.targetUsername) {
if (sfpPackage.packageType === SfpPackage_1.PackageType.Unlocked) {
console.log((0, sfp_logger_2.COLOR_KEY_MESSAGE)(`Attempting to promote artifact ${sfpPackage.packageName} before installation`));
if (!this.props.isDryRun) {
let promoteUnlockedPackageImpl = new PromoteUnlockedPackageImpl_1.default(sourceDirectory, sfpPackage.package_version_id, this.props.devhubUserName);
await promoteUnlockedPackageImpl.promote();
}
}
}
}
displayRetryHeader(isRetryOnFailure, count) {
if (isRetryOnFailure && count > 1) {
sfp_logger_1.default.printHeaderLine('', sfp_logger_2.COLOR_HEADER, sfp_logger_1.LoggerLevel.INFO, this.props.logger);
sfp_logger_1.default.log(`Retrying On Failure Attempt: ${count}`, sfp_logger_1.LoggerLevel.INFO, this.props.logger);
sfp_logger_1.default.printHeaderLine('', sfp_logger_2.COLOR_HEADER, sfp_logger_1.LoggerLevel.INFO, this.props.logger);
}
}
displayHeader(sfpPackage, pkgDescriptor, pkg) {
let alwaysDeployMessage;
if (this.props.skipIfPackageInstalled) {
if (pkgDescriptor.alwaysDeploy)
alwaysDeployMessage = `Always Deploy: ${(0, sfp_logger_2.COLOR_KEY_MESSAGE)(`True`)}`;
else
alwaysDeployMessage = `Always Deploy: ${(0, sfp_logger_2.COLOR_KEY_MESSAGE)(`False`)}`;
}
else
alwaysDeployMessage = undefined;
//Display header
let message = 'Installing';
if (this.props.currentStage == Stage_1.Stage.VALIDATE) {
if (this.props.impactedPackagesAsPerBranch) {
let isPackageImpacted = this.props.impactedPackagesAsPerBranch?.get(pkg);
message = isPackageImpacted ? 'Validating' : 'Synchronizing';
}
else {
message = 'Validating';
}
}
sfp_logger_1.default.printHeaderLine(`${message} artifact:${pkg}`, sfp_logger_2.COLOR_HEADER, sfp_logger_1.LoggerLevel.INFO, this.props.logger);
sfp_logger_1.default.log((0, sfp_logger_2.COLOR_HEADER)(`Name: ${(0, sfp_logger_2.COLOR_KEY_MESSAGE)(pkg)}`), sfp_logger_1.LoggerLevel.INFO, this.props.logger);
sfp_logger_1.default.log(`Type: ${(0, sfp_logger_2.COLOR_KEY_MESSAGE)(sfpPackage.packageType)}`, sfp_logger_1.LoggerLevel.INFO, this.props.logger);
sfp_logger_1.default.log(`Version Number: ${(0, sfp_logger_2.COLOR_KEY_MESSAGE)(sfpPackage.versionNumber)}`, sfp_logger_1.LoggerLevel.INFO, this.props.logger);
this.displayTestInfoHeader(sfpPackage);
if (pkgDescriptor.aliasfy)
sfp_logger_1.default.log(`Aliasified Package: ${(0, sfp_logger_2.COLOR_KEY_MESSAGE)(`True`)}`, sfp_logger_1.LoggerLevel.INFO, this.props.logger);
if (sfpPackage.isApexFound)
sfp_logger_1.default.log(`Contains Apex Classes/Triggers: ${(0, sfp_logger_2.COLOR_KEY_MESSAGE)(sfpPackage.isApexFound)}`, sfp_logger_1.LoggerLevel.INFO, this.props.logger);
if (sfpPackage.packageType == SfpPackage_1.PackageType.Source || sfpPackage.packageType == SfpPackage_1.PackageType.Unlocked) {
if (!pkgDescriptor.aliasfy) {
sfp_logger_1.default.log(`Metadata to be deployed: ${(0, sfp_logger_2.COLOR_KEY_MESSAGE)(sfpPackage.metadataCount)}`, sfp_logger_1.LoggerLevel.INFO, this.props.logger);
}
}
if (pkgDescriptor.skipTesting) {
sfp_logger_1.default.log(`Skip Testing: ${(0, sfp_logger_2.COLOR_KEY_MESSAGE)('true')}`, sfp_logger_1.LoggerLevel.INFO, this.props.logger);
}
else {
sfp_logger_1.default.log(`Skip Testing: ${(0, sfp_logger_2.COLOR_KEY_MESSAGE)('false')}`, sfp_logger_1.LoggerLevel.INFO, this.props.logger);
}
if (alwaysDeployMessage)
sfp_logger_1.default.log(alwaysDeployMessage, sfp_logger_1.LoggerLevel.INFO, this.props.logger);
sfp_logger_1.default.printHeaderLine('', sfp_logger_2.COLOR_HEADER, sfp_logger_1.LoggerLevel.INFO, this.props.logger);
}
displayTestInfoHeader(sfpPackage) {
if (sfpPackage.packageType == SfpPackage_1.PackageType.Source) {
if (!sfpPackage.isTriggerAllTests)
sfp_logger_1.default.log(`Optimized Deployment: ${(0, sfp_logger_2.COLOR_KEY_MESSAGE)(this.isOptimizedDeploymentForSourcePackage(sfpPackage.packageDescriptor))}`, sfp_logger_1.LoggerLevel.INFO, this.props.logger);
else
sfp_logger_1.default.log(`Trigger All Tests: ${(0, sfp_logger_2.COLOR_KEY_MESSAGE)(`true`)}`, sfp_logger_1.LoggerLevel.INFO, this.props.logger);
}
}
printArtifactVersionsWhenSkipped(queue, packagesToPackageInfo, isBaselinOrgModeActivated, props) {
let groupSection = new GroupConsoleLogs_1.default(`Full Installation Breakdown`, this.props.logger).begin();
let maxTable = new Table({
head: [
'Artifact',
'Incoming Version',
isBaselinOrgModeActivated ? 'Version in baseline org' : 'Version in org',
'To be installed?',
],
chars: TableConstants_1.ZERO_BORDER_TABLE,
});
queue.forEach((pkg) => {
maxTable.push(processColoursForAllPackages(pkg));
});
sfp_logger_1.default.log(maxTable.toString(), sfp_logger_1.LoggerLevel.INFO, this.props.logger);
//Insane Hack
//TODO: Export the value to the caller
printDeploymentBreakDownInMarkdown();
groupSection.end();
groupSection = new GroupConsoleLogs_1.default(`Artifacts to be installed`, this.props.logger).begin();
let minTable = new Table({
head: [
'Artifact',
'Incoming Version',
isBaselinOrgModeActivated ? 'Version in baseline org' : 'Version in org',
],
chars: TableConstants_1.ZERO_BORDER_TABLE,
});
queue.forEach((pkg) => {
if (!packagesToPackageInfo[pkg.packageName].isPackageInstalled)
minTable.push([
(0, sfp_logger_2.COLOR_KEY_MESSAGE)(pkg.packageName),
(0, sfp_logger_2.COLOR_KEY_MESSAGE)(pkg.versionNumber),
packagesToPackageInfo[pkg.packageName].versionInstalledInOrg
? (0, sfp_logger_2.COLOR_KEY_MESSAGE)(packagesToPackageInfo[pkg.packageName].versionInstalledInOrg)
: (0, sfp_logger_2.COLOR_KEY_MESSAGE)('N/A'),
]);
});
sfp_logger_1.default.log(minTable.toString(), sfp_logger_1.LoggerLevel.INFO, this.props.logger);
groupSection.end();
function printDeploymentBreakDownInMarkdown() {
let tableData = {
table: {
head: [
'Artifact',
'Incoming Version',
isBaselinOrgModeActivated ? 'Version in baseline org' : 'Version in org',
'To be installed?',
'Promotion Status',
],
body: [],
},
alignment: [markdown_table_ts_1.Align.Left, markdown_table_ts_1.Align.Left, markdown_table_ts_1.Align.Left, markdown_table_ts_1.Align.Right],
};
for (const pkg of queue) {
tableData.table.body.push(getRowForMarkdownTable(pkg, props));
}
const table = (0, markdown_table_ts_1.getMarkdownTable)(tableData);
const outputHandler = FileOutputHandler_1.default.getInstance();
outputHandler.appendOutput('deployment-breakdown.md', table);
}
function processColoursForAllPackages(pkg) {
const pkgInfo = packagesToPackageInfo[pkg.packageName];
let packageName = pkg.packageName;
let versionNumber = pkg.versionNumber;
let versionInstalledInOrg = pkgInfo.versionInstalledInOrg ? pkgInfo.versionInstalledInOrg : 'N/A';
let isPackageInstalled = pkgInfo.isPackageInstalled ? 'No' : 'Yes';
if (pkgInfo.isPackageInstalled) {
packageName = (0, sfp_logger_1.COLOR_SUCCESS)(packageName);
versionNumber = (0, sfp_logger_1.COLOR_SUCCESS)(versionNumber);
versionInstalledInOrg = (0, sfp_logger_1.COLOR_SUCCESS)(versionInstalledInOrg);
isPackageInstalled = (0, sfp_logger_1.COLOR_SUCCESS)(isPackageInstalled);
}
else {
packageName = (0, sfp_logger_1.COLOR_ERROR)(packageName);
versionNumber = (0, sfp_logger_1.COLOR_ERROR)(versionNumber);
versionInstalledInOrg = (0, sfp_logger_1.COLOR_ERROR)(versionInstalledInOrg);
isPackageInstalled = (0, sfp_logger_1.COLOR_ERROR)(isPackageInstalled);
}
return [packageName, versionNumber, versionInstalledInOrg, isPackageInstalled];
}
function getRowForMarkdownTable(pkg, props) {
const pkgInfo = packagesToPackageInfo[pkg.packageName];
let packageName = pkg.packageName;
let versionNumber = pkg.versionNumber;
let versionInstalledInOrg = pkgInfo.versionInstalledInOrg ? pkgInfo.versionInstalledInOrg : 'N/A';
let isPackageToBeInstalled = pkgInfo.isPackageInstalled ? 'No' : 'Yes';
let promotionStatus = 'N/A';
if (isPackageToBeInstalled == 'Yes') {
isPackageToBeInstalled = ``;
packageName = `**${packageName}**`;
if (pkg.packageType == SfpPackage_1.PackageType.Unlocked) {
if (props.promotePackagesBeforeDeploymentToOrg == props.targetUsername &&
versionInstalledInOrg == 'N/A') {
promotionStatus = '';
}
else if (props.promotePackagesBeforeDeploymentToOrg == props.targetUsername) {
let versionInstalledInOrgConvertedToSemver = (0, VersionNumberConverter_1.default)(versionInstalledInOrg);
let versionNumberConvertedToSemver = (0, VersionNumberConverter_1.default)(versionNumber);
if (semver.diff(versionInstalledInOrgConvertedToSemver, versionNumberConvertedToSemver) ==
'prerelease') {
promotionStatus =
'';
}
else {
promotionStatus = '';
}
}
else {
promotionStatus = 'N/A';
}
}
versionNumber = `**${versionNumber}**`;
versionInstalledInOrg = `**${versionInstalledInOrg}**`;
}
else {
versionNumber = `**${versionNumber}**`;
versionInstalledInOrg = `**${versionInstalledInOrg}**`;
}
return [packageName, versionNumber, versionInstalledInOrg, isPackageToBeInstalled, promotionStatus];
}
}
printArtifactVersions(queue, packagesToPackageInfo) {
let groupSection = new GroupConsoleLogs_1.default(`Packages to be deployed`, this.props.logger).begin();
let table = new Table({
head: ['Package', 'Version to be installed'],
chars: TableConstants_1.ZERO_BORDER_TABLE,
});
queue.forEach((pkg) => {
table.push([pkg.packageName, pkg.versionNumber]);
});
sfp_logger_1.default.log(table.toString(), sfp_logger_1.LoggerLevel.INFO, this.props.logger);
groupSection.end();
printDeploymentBreakDownInMarkdown(this.props);
function printDeploymentBreakDownInMarkdown(props) {
let tableData = {
table: {
head: ['Package', props.currentStage == Stage_1.Stage.VALIDATE ? `Version` : `Commit Id`, 'Reason?'],
body: [],
},
alignment: [markdown_table_ts_1.Align.Left, markdown_table_ts_1.Align.Left, markdown_table_ts_1.Align.Left, markdown_table_ts_1.Align.Left],
};
for (const pkg of queue) {
tableData.table.body.push(getRowForMarkdownTable(pkg, props));
}
const outputHandler = FileOutputHandler_1.default.getInstance();
outputHandler.writeOutput('deployment-breakdown.md', `Please find the artifacts that will be installed below`);
outputHandler.appendOutput('deployment-breakdown.md', `\n\n${(0, markdown_table_ts_1.getMarkdownTable)(tableData)}`);
}
function getRowForMarkdownTable(pkg, props) {
let packageName = pkg.packageName;
if (props.currentStage == Stage_1.Stage.VALIDATE) {
if (props.impactedPackagesAsPerBranch &&
props.impactedPackagesAsPerBranch.get(pkg.packageName))
return [packageName, pkg.sourceVersion, ''];
else
return [packageName, pkg.sourceVersion, ``];
}
else {
return [packageName, pkg.versionNumber, 'Deploy'];
}
}
}
async filterByPackagesInstalledInTheOrg(packageManifest, queue, packagesToPackageInfo, targetUsername) {
let targetOrg = await SFPOrg_1.default.create({ aliasOrUsername: targetUsername });
const clonedQueue = _.clone(queue);
for (let i = queue.length - 1; i >= 0; i--) {
let packageInfo = packagesToPackageInfo[clonedQueue[i].packageName];
let sfpPackage = packageInfo.sfpPackage;
let pkgDescriptor = ProjectConfig_1.default.getPackageDescriptorFromConfig(clonedQueue[i].packageName, packageManifest);
let packageInstalledInTheOrg = await targetOrg.isArtifactInstalledInOrg(this.props.logger, sfpPackage);
if (packageInstalledInTheOrg.versionNumber)
packageInfo.versionInstalledInOrg = packageInstalledInTheOrg.versionNumber;
if (packageInstalledInTheOrg.isInstalled) {
if (!pkgDescriptor.alwaysDeploy) {
packageInfo.isPackageInstalled = true;
clonedQueue.splice(i, 1);
}
}
}
return clonedQueue;
}
/**
* Returns map of package name to package info
* @param artifacts
*/
async getPackagesToPackageInfo(sfpPackages) {
let packagesToPackageInfo = {};
for (let sfpPackage of sfpPackages) {
if (packagesToPackageInfo[sfpPackage.packageName]) {
let previousVersionNumber = (0, VersionNumberConverter_1.default)(packagesToPackageInfo[sfpPackage.packageName].sfpPackage.versionNumber);
let currentVersionNumber = (0, VersionNumberConverter_1.default)(sfpPackage.versionNumber);
// replace existing packageInfo if package version number is newer
if (semver.gt(currentVersionNumber, previousVersionNumber)) {
packagesToPackageInfo[sfpPackage.packageName] = {
sourceDirectory: sfpPackage.sourceDir,
sfpPackage: sfpPackage,
};
}
}
else {
packagesToPackageInfo[sfpPackage.packageName] = {
sourceDirectory: sfpPackage.sourceDir,
sfpPackage: sfpPackage,
};
}
}
return packagesToPackageInfo;
}
/**
* Decider for which package installation type to run
*/
async installPackage(packageType, sfpPackage, targetOrg, skipTesting, waitTime, pkgDescriptor, skipIfPackageInstalled, apiVersion) {
//Compute Deployment Type
let deploymentType = this.props.deploymentMode === DeploymentMode.SOURCEPACKAGES_PUSH
? DeploymentExecutor_1.DeploymentType.SOURCE_PUSH
: DeploymentExecutor_1.DeploymentType.MDAPI_DEPLOY;
//Add Installation Options
let installationOptions = new InstallPackage_1.SfpPackageInstallationOptions();
(installationOptions.installationkey = null), (installationOptions.apexcompile = 'package');
installationOptions.waitTime = waitTime;
installationOptions.apiVersion = apiVersion;
installationOptions.publishWaitTime = 60;
installationOptions.isInstallingForValidation =
this.props.deploymentMode != DeploymentMode.NORMAL &&
(this.props.currentStage === Stage_1.Stage.PREPARE || this.props.currentStage === Stage_1.Stage.VALIDATE);
installationOptions.optimizeDeployment = this.isOptimizedDeploymentForSourcePackage(pkgDescriptor);
installationOptions.skipTesting = skipTesting;
installationOptions.deploymentType = deploymentType;
installationOptions.disableArtifactCommit = this.props.disableArtifactCommit;
//During validate, if optimizeDeploymentMode is false, use full local tests to validate
//but respect skipTesting #issue 1075
//During Prepare (push), dont trigger tests
if (this.props.currentStage == Stage_1.Stage.VALIDATE) {
//Always enable skipTest as the default installation option during validate
//as test are run subsequently
installationOptions.skipTesting = true;
if (!this.isOptimizedDeploymentForSourcePackage(pkgDescriptor)) {
if (sfpPackage.packageDescriptor.skipTesting)
installationOptions.skipTesting = sfpPackage.packageDescriptor.skipTesting;
else
installationOptions.skipTesting = false;
}
}
else if (this.props.currentStage === Stage_1.Stage.PREPARE) {
installationOptions.optimizeDeployment = false;
installationOptions.skipTesting = true;
}
installationOptions.skipIfPackageInstalled = skipIfPackageInstalled;
installationOptions.isDryRun = this.props.isDryRun;
return SfpPackageInstaller_1.default.installPackage(this.props.logger, sfpPackage, targetOrg, installationOptions, {
currentStage: this.props.currentStage,
}, sfpPackage.packageType == SfpPackage_1.PackageType.Unlocked && installationOptions.isInstallingForValidation
? SfpPackage_1.PackageType.Source
: undefined //Override to source
);
}
/**
* Checks if package should be installed to target username
* @param packageDescriptor
*/
isSkipDeployment(packageDescriptor, targetUsername) {
let skipDeployOnOrgs = packageDescriptor.skipDeployOnOrgs;
if (packageDescriptor.skipInstallOnOrgs) {
skipDeployOnOrgs = packageDescriptor.skipInstallOnOrgs;
}
if (skipDeployOnOrgs) {
if (!(skipDeployOnOrgs instanceof Array))
throw new Error(`Property 'skipDeployOnOrgs' or 'skipInstallOnOrgs' must be of type Array`);
else
return skipDeployOnOrgs.includes(targetUsername);
}
else
return false;
}
// Allow individual packages to use non optimized path
isOptimizedDeploymentForSourcePackage(pkgDescriptor) {
if (pkgDescriptor.isOptimizedDeployment == null)
return true;
else
return pkgDescriptor.isOptimizedDeployment;
}
/**
* Returns the packages in the project config that have an artifact
*/
getPackagesToDeploy(sfdxProjectConfig, packagesToPackageInfo) {
let packagesToDeploy = [];
let packages = sfdxProjectConfig['packageDirectories'];
// Filter package manifest by whats available in artifacts
for (const pkg of packages) {
if (packagesToPackageInfo[pkg.package])
packagesToDeploy.push(packagesToPackageInfo[pkg.package].sfpPackage);
}
// Filter out packages that are to be skipped on the target org
packagesToDeploy = packagesToDeploy.filter((sfpPackage) => !this.isSkipDeployment(sfpPackage.packageDescriptor, this.props.targetUsername));
//Ignore packages based on stage
packagesToDeploy = packagesToDeploy.filter((pkg) => {
if (pkg.packageDescriptor.ignoreOnStage?.find((stage) => {
stage = stage.toLowerCase();
return stage === this.props.currentStage;
}))
return false;
else
return true;
});
return packagesToDeploy;
}
}
exports.default = DeployImpl;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRGVwbG95SW1wbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9pbXBsL2RlcGxveS9EZXBsb3lJbXBsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsMkZBQWlGO0FBQ2pGLG1FQUFrRztBQUNsRyxvQ0FBaUM7QUFDakMscUZBQTZEO0FBQzdELGlDQUFrQztBQUNsQyx1SEFBK0Y7QUFDL0YsZ0ZBQXlFO0FBQ3pFLHFEQUF3RjtBQUN4Riw4R0FHd0U7QUFDeEUsbUVBQTJDO0FBQzNDLDhEQUF3RTtBQUN4RSwrRkFBdUU7QUFHdkUsNkZBQXFFO0FBQ3JFLGlHQUF5RTtBQUN6RSx3RkFBb0c7QUFDcEcsMENBQTRCO0FBQzVCLGlGQUF5RDtBQUN6RCw0REFBNEQ7QUFDNUQscUdBQXNGO0FBQ3RGLHlGQUFpRTtBQUNqRSx5REFBNEQ7QUFDNUQsd0ZBQWdFO0FBRWhFLE1BQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0FBQztBQUNuQyxNQUFNLEtBQUssR0FBRyxPQUFPLENBQUMsYUFBYSxDQUFDLENBQUM7QUFFckMsSUFBWSxjQUlYO0FBSkQsV0FBWSxjQUFjO0lBQ3RCLHVEQUFNLENBQUE7SUFDTix1RUFBYyxDQUFBO0lBQ2QsaUZBQW1CLENBQUE7QUFDdkIsQ0FBQyxFQUpXLGNBQWMsOEJBQWQsY0FBYyxRQUl6QjtBQTBCRCxNQUFxQixVQUFVO0lBSzNCLFlBQW9CLEtBQWtCO1FBQWxCLFVBQUssR0FBTCxLQUFLLENBQWE7UUFDbEMsY0FBYztRQUNkLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLGFBQWE7WUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLGFBQWEsR0FBRyxDQUFDLENBQUM7SUFDaEUsQ0FBQztJQUVELElBQVcsY0FBYyxDQUFDLElBQW9CO1FBQzFDLElBQUksQ0FBQyxlQUFlLEdBQUcsSUFBSSxDQUFDO0lBQ2hDLENBQUM7SUFFRCxJ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