@flxbl-io/sfp
Version:
sfp is a CLI tool to help you manage your Salesforce projects in an artifact centric model
272 lines • 27.8 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 });
const IsValidSfdxAuthUrl_1 = __importDefault(require("../../core/scratchorg/pool/prequisitecheck/IsValidSfdxAuthUrl"));
const sfp_logger_1 = __importStar(require("@flxbl-io/sfp-logger"));
const ArtifactGenerator_1 = __importDefault(require("../../core/artifacts/generators/ArtifactGenerator"));
const ProjectConfig_1 = __importDefault(require("../../core/project/ProjectConfig"));
const FetchArtifactSelector_1 = __importDefault(require("../artifacts/FetchArtifactSelector"));
const BuildImpl_1 = __importDefault(require("../parallelBuilder/BuildImpl"));
const PoolCreateImpl_1 = __importDefault(require("../../core/scratchorg/pool/PoolCreateImpl"));
const Stage_1 = require("../Stage");
const PrepareOrgJob_1 = __importDefault(require("./PrepareOrgJob"));
const rimraf = __importStar(require("rimraf"));
const fs = __importStar(require("fs-extra"));
const Git_1 = __importDefault(require("../../core/git/Git"));
const GitTags_1 = __importDefault(require("../../core/git/GitTags"));
const OrgDetailsFetcher_1 = __importDefault(require("../../core/org/OrgDetailsFetcher"));
const SFPOrg_1 = __importDefault(require("../../core/org/SFPOrg"));
const os_1 = require("os");
const SFPStatsSender_1 = __importDefault(require("../../core/stats/SFPStatsSender"));
const ExternalPackage2DependencyResolver_1 = __importDefault(require("../../core/package/dependencies/ExternalPackage2DependencyResolver"));
const ExternalDependencyDisplayer_1 = __importDefault(require("../../core/display/ExternalDependencyDisplayer"));
const ReleaseDefinitionGenerator_1 = __importDefault(require("../release/ReleaseDefinitionGenerator"));
const TableConstants_1 = require("../../ui/TableConstants");
const GroupConsoleLogs_1 = __importDefault(require("../../ui/GroupConsoleLogs"));
const ReleaseConfigLoader_1 = __importDefault(require("../release/ReleaseConfigLoader"));
const sfp_logger_2 = require("@flxbl-io/sfp-logger");
const Table = require('cli-table');
class PrepareImpl {
constructor(hubOrg, pool, logLevel) {
this.hubOrg = hubOrg;
this.pool = pool;
this.logLevel = logLevel;
this.artifactFetchedCount = 0;
// set defaults
if (!this.pool.expiry)
this.pool.expiry = 2;
if (!this.pool.batchSize)
this.pool.batchSize = 5;
if (this.pool.succeedOnDeploymentErrors === undefined)
this.pool.succeedOnDeploymentErrors = true;
if (!this.pool.waitTime)
this.pool.waitTime = 6;
if (!this.pool.maxRetryCount)
this.pool.maxRetryCount = 2;
}
async exec() {
sfp_logger_1.default.log((0, sfp_logger_1.COLOR_KEY_MESSAGE)('Validating Org Authentication Mechanism..'), sfp_logger_1.LoggerLevel.INFO);
let orgDisplayResult = await new OrgDetailsFetcher_1.default(this.hubOrg.getUsername()).getOrgDetails();
if (!(orgDisplayResult.sfdxAuthUrl && (0, IsValidSfdxAuthUrl_1.default)(orgDisplayResult.sfdxAuthUrl)))
throw new Error(`Pools have to be created using a DevHub authenticated with auth:web or auth:store or auth:accesstoken:store`);
return this.poolScratchOrgs();
}
async poolScratchOrgs() {
//Create Artifact Directory
rimraf.sync('artifacts');
fs.mkdirpSync('artifacts');
let restrictedPackages = null;
let projectConfig = ProjectConfig_1.default.getSFDXProjectConfig(null);
if (this.pool.releaseConfigFile) {
restrictedPackages = await getArtifactsByGeneratingReleaseDefinitionFromConfig(this.pool.releaseConfigFile);
sfp_logger_1.default.log(`Restricted Packages: ${restrictedPackages}`, sfp_logger_1.LoggerLevel.INFO);
projectConfig = ProjectConfig_1.default.cleanupPackagesFromProjectDirectory(null, restrictedPackages);
}
if (this.pool.installAll) {
await this.getPackageArtifacts(restrictedPackages);
}
let checkpointPackages = this.getcheckPointPackages(projectConfig, new sfp_logger_1.ConsoleLogger());
let externalPackageResolver = new ExternalPackage2DependencyResolver_1.default(this.hubOrg.getConnection(), projectConfig, this.pool.keys);
let externalPackage2s = await externalPackageResolver.resolveExternalPackage2DependenciesToVersions();
//Display resolved dependencies
let externalDependencyDisplayer = new ExternalDependencyDisplayer_1.default(externalPackage2s, new sfp_logger_1.ConsoleLogger());
externalDependencyDisplayer.display();
let prepareASingleOrgImpl = new PrepareOrgJob_1.default(this.pool, checkpointPackages, externalPackage2s);
let createPool = new PoolCreateImpl_1.default(this.hubOrg, this.pool, prepareASingleOrgImpl, this.logLevel);
let pool = (await createPool.execute());
if (pool.isOk()) {
await this.displayPoolSummary(pool.value);
}
return pool;
async function getArtifactsByGeneratingReleaseDefinitionFromConfig(releaseConfigFile) {
let releaseDefinitionGenerator = new ReleaseDefinitionGenerator_1.default(new sfp_logger_1.ConsoleLogger(), 'HEAD', releaseConfigFile, 'prepare', 'test', undefined, undefined, true, false, true);
let releaseDefinition = (await releaseDefinitionGenerator.exec());
return Object.keys(releaseDefinition.artifacts);
}
}
//Fetch all checkpoints
getcheckPointPackages(projectConfig, logger) {
sfp_logger_1.default.log('Fetching checkpoints for prepare if any.....', sfp_logger_1.LoggerLevel.INFO, logger);
let checkPointPackages = [];
ProjectConfig_1.default.getAllPackageDirectoriesFromConfig(projectConfig).forEach((pkg) => {
if (pkg.checkpointForPrepare)
checkPointPackages.push(pkg['package']);
});
return checkPointPackages;
}
async displayPoolSummary(pool) {
let table = new Table({
head: [
'Scratch Org Alias Id',
'Scratch Org Username',
'Installed/Requested Count',
'Last Installed Package',
],
chars: TableConstants_1.ZERO_BORDER_TABLE
});
for (const scratchOrg of pool.scratchOrgs) {
try {
let scratchOrgAsSFPOrg = await SFPOrg_1.default.create({ aliasOrUsername: scratchOrg.username });
let installedArtifacts = await scratchOrgAsSFPOrg.getInstalledArtifacts();
if (installedArtifacts && installedArtifacts.length >= 1) {
let installationCount = installedArtifacts.length;
let lastInstalledArifact = installedArtifacts[installedArtifacts.length - 1];
table.push([
scratchOrg.alias,
scratchOrg.username,
`${installationCount}/${this.artifactFetchedCount}`,
lastInstalledArifact.Name,
]);
SFPStatsSender_1.default.logGauge(`so.packages.requested`, this.artifactFetchedCount, {
pool: this.pool.tag,
scratchOrg: scratchOrg.alias,
});
SFPStatsSender_1.default.logGauge(`so.packages.installed`, installationCount, {
pool: this.pool.tag,
scratchOrg: scratchOrg.alias,
});
}
else {
table.push([scratchOrg.alias, scratchOrg.username, `NA`, `NA`]);
SFPStatsSender_1.default.logGauge(`so.packages.requested`, 0, {
pool: this.pool.tag,
scratchOrg: scratchOrg.alias,
});
SFPStatsSender_1.default.logGauge(`so.packages.installed`, 0, {
pool: this.pool.tag,
scratchOrg: scratchOrg.alias,
});
}
}
catch (error) {
SFPStatsSender_1.default.logGauge(`so.packages.requested`, 0, {
pool: this.pool.tag,
scratchOrg: scratchOrg.alias,
});
SFPStatsSender_1.default.logGauge(`so.packages.installed`, 0, {
pool: this.pool.tag,
scratchOrg: scratchOrg.alias,
});
table.push([scratchOrg.alias, scratchOrg.username, `Unable to compute`, `Unable to fetch`]);
}
}
if (table.length >= 1) {
sfp_logger_1.default.log(os_1.EOL, sfp_logger_1.LoggerLevel.INFO);
sfp_logger_1.default.log((0, sfp_logger_1.COLOR_KEY_MESSAGE)('Pool Summary:'), sfp_logger_1.LoggerLevel.INFO);
sfp_logger_1.default.log(table.toString(), sfp_logger_1.LoggerLevel.INFO);
}
}
async getPackageArtifacts(restrictedPackages) {
//Filter Packages to be ignored from prepare to be fetched
let packages = ProjectConfig_1.default.getAllPackageDirectoriesFromDirectory(null).filter((pkg) => {
return isPkgToBeInstalled(pkg, restrictedPackages);
});
let artifactFetcher;
if (this.pool.fetchArtifacts) {
let fetchArtifactsLogGroup = new GroupConsoleLogs_1.default(`Fetching Artifacts`);
fetchArtifactsLogGroup.begin();
artifactFetcher = new FetchArtifactSelector_1.default(this.pool.fetchArtifacts.artifactFetchScript, this.pool.fetchArtifacts.npm?.scope, this.pool.fetchArtifacts.npm?.npmrcPath).getArtifactFetcher();
const git = await Git_1.default.initiateRepo();
//During Prepare, there could be a race condition where a main is merged with a new package
//but the package is not yet available in the validated package list and can cause prepare to fail
for (const pkg of packages) {
try {
let latestGitTagVersion = new GitTags_1.default(git, pkg.package);
let version = await latestGitTagVersion.getVersionFromLatestTag();
artifactFetcher.fetchArtifact(pkg.package, 'artifacts', version, true);
this.artifactFetchedCount++;
}
catch (error) {
sfp_logger_1.default.log((0, sfp_logger_1.COLOR_WARNING)(`Git Tag for ${pkg.package} missing, This might result in deployment failures`));
}
}
fetchArtifactsLogGroup.end();
}
else {
let buildArtifactsLogGroup = new GroupConsoleLogs_1.default(`Building Artifacts`);
buildArtifactsLogGroup.begin();
//Build All Artifacts
sfp_logger_1.default.log(`${os_1.EOL}`);
sfp_logger_1.default.printHeaderLine('WARNING!!!', sfp_logger_1.COLOR_WARNING, sfp_logger_1.LoggerLevel.INFO);
sfp_logger_1.default.log('Building packages, as script to fetch artifacts was not provided', sfp_logger_1.LoggerLevel.WARN);
sfp_logger_1.default.log('This is not ideal, as the artifacts are built from the current head of the provided branch', sfp_logger_1.LoggerLevel.WARN);
sfp_logger_1.default.log('Pools should be prepared with previously validated packages', sfp_logger_1.LoggerLevel.WARN);
sfp_logger_1.default.printHeaderLine('', sfp_logger_1.COLOR_WARNING, sfp_logger_1.LoggerLevel.INFO);
let buildProps = {
configFilePath: this.pool.configFilePath,
devhubAlias: this.hubOrg.getUsername(),
waitTime: 120,
isQuickBuild: true,
isDiffCheckEnabled: false,
buildNumber: 1,
executorcount: 10,
isBuildAllAsSourcePackages: this.pool.disableSourcePackageOverride ? false : true,
branch: null,
currentStage: Stage_1.Stage.PREPARE,
};
buildProps = includeOnlyPackagesAsPerReleaseConfig(this.pool.releaseConfigFile, buildProps);
let buildImpl = new BuildImpl_1.default(buildProps);
let { generatedPackages, failedPackages } = await buildImpl.exec();
if (failedPackages.length > 0)
throw new Error('Unable to build packages, Following packages failed to build' + failedPackages);
for (let generatedPackage of generatedPackages) {
await ArtifactGenerator_1.default.generateArtifact(generatedPackage, process.cwd(), 'artifacts');
this.artifactFetchedCount++;
}
buildArtifactsLogGroup.end();
}
function isPkgToBeInstalled(pkg, restrictedPackages) {
let ignoreOnStageFound = pkg.ignoreOnStage?.find((stage) => {
stage = stage.toLowerCase();
if (stage === 'prepare')
return true;
});
//if ignored .. skip
if (ignoreOnStageFound)
return false;
if (restrictedPackages)
return restrictedPackages.includes(pkg.package);
else
return true;
}
function includeOnlyPackagesAsPerReleaseConfig(releaseConfigFilePath, buildProps, logger) {
if (releaseConfigFilePath) {
let releaseConfigLoader = new ReleaseConfigLoader_1.default(logger, releaseConfigFilePath);
buildProps.includeOnlyPackages = releaseConfigLoader.getPackagesAsPerReleaseConfig();
printIncludeOnlyPackages(buildProps.includeOnlyPackages);
}
return buildProps;
function printIncludeOnlyPackages(includeOnlyPackages) {
sfp_logger_1.default.log((0, sfp_logger_1.COLOR_KEY_MESSAGE)(`Build will include the below packages release configs (domain(s))(domain)`), sfp_logger_1.LoggerLevel.INFO);
sfp_logger_1.default.log((0, sfp_logger_2.COLOR_KEY_VALUE)(`${includeOnlyPackages.toString()}`), sfp_logger_1.LoggerLevel.INFO);
}
}
}
}
exports.default = PrepareImpl;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUHJlcGFyZUltcGwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvaW1wbC9wcmVwYXJlL1ByZXBhcmVJbXBsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFFQSx1SEFBK0Y7QUFDL0YsbUVBQXVIO0FBQ3ZILDBHQUFrRjtBQUNsRixxRkFBNkQ7QUFHN0QsK0ZBQXVFO0FBQ3ZFLDZFQUFxRTtBQUNyRSwrRkFBdUU7QUFFdkUsb0NBQWlDO0FBQ2pDLG9FQUE0QztBQUM1QywrQ0FBaUM7QUFDakMsNkNBQStCO0FBQy9CLDZEQUFxQztBQUNyQyxxRUFBNkM7QUFDN0MseUZBQWlFO0FBQ2pFLG1FQUEyQztBQUMzQywyQkFBeUI7QUFDekIscUZBQTZEO0FBQzdELDRJQUFvSDtBQUNwSCxpSEFBeUY7QUFDekYsdUdBQStFO0FBRS9FLDREQUE0RDtBQUM1RCxpRkFBeUQ7QUFDekQseUZBQWlFO0FBQ2pFLHFEQUF1RDtBQUV2RCxNQUFNLEtBQUssR0FBRyxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUM7QUFFbkMsTUFBcUIsV0FBVztJQUc1QixZQUEyQixNQUFjLEVBQVUsSUFBZ0IsRUFBVSxRQUFxQjtRQUF2RSxXQUFNLEdBQU4sTUFBTSxDQUFRO1FBQVUsU0FBSSxHQUFKLElBQUksQ0FBWTtRQUFVLGFBQVEsR0FBUixRQUFRLENBQWE7UUFGMUYseUJBQW9CLEdBQVcsQ0FBQyxDQUFDO1FBR3JDLGVBQWU7UUFDZixJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNO1lBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO1FBRTVDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVM7WUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxDQUFDLENBQUM7UUFFbEQsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLHlCQUF5QixLQUFL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