@flxbl-io/sfp
Version:
sfp is a CLI tool to help you manage your Salesforce projects in an artifact centric model
496 lines • 55.3 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.ValidationMode = exports.ValidateAgainst = void 0;
const BuildImpl_1 = __importDefault(require("../parallelBuilder/BuildImpl"));
const DeployImpl_1 = __importStar(require("../deploy/DeployImpl"));
const ArtifactGenerator_1 = __importDefault(require("../../core/artifacts/generators/ArtifactGenerator"));
const Stage_1 = require("../Stage");
const sfp_logger_1 = __importStar(require("@flxbl-io/sfp-logger"));
const PackageInstallationResult_1 = require("../../core/package/packageInstallers/PackageInstallationResult");
const PackageDiffImpl_1 = require("../../core/package/diff/PackageDiffImpl");
const PoolFetchImpl_1 = __importDefault(require("../../core/scratchorg/pool/PoolFetchImpl"));
const InstalledArtifactsDisplayer_1 = __importDefault(require("../../core/display/InstalledArtifactsDisplayer"));
const ValidateError_1 = __importDefault(require("../../errors/ValidateError"));
const sfp_logger_2 = require("@flxbl-io/sfp-logger");
const sfp_logger_3 = require("@flxbl-io/sfp-logger");
const sfp_logger_4 = require("@flxbl-io/sfp-logger");
const sfp_logger_5 = require("@flxbl-io/sfp-logger");
const sfp_logger_6 = require("@flxbl-io/sfp-logger");
const sfp_logger_7 = require("@flxbl-io/sfp-logger");
const SFPStatsSender_1 = __importDefault(require("../../core/stats/SFPStatsSender"));
const ScratchOrgInfoFetcher_1 = __importDefault(require("../../core/scratchorg/pool/services/fetchers/ScratchOrgInfoFetcher"));
const ScratchOrgInfoAssigner_1 = __importDefault(require("../../core/scratchorg/pool/services/updaters/ScratchOrgInfoAssigner"));
const PoolOrgDeleteImpl_1 = __importDefault(require("../../core/scratchorg/pool/PoolOrgDeleteImpl"));
const SFPOrg_1 = __importDefault(require("../../core/org/SFPOrg"));
const SfpPackage_1 = require("../../core/package/SfpPackage");
const GetFormattedTime_1 = __importDefault(require("../../core/utils/GetFormattedTime"));
const rimraf = __importStar(require("rimraf"));
const ProjectConfig_1 = __importDefault(require("../../core/project/ProjectConfig"));
const InstallUnlockedPackageCollection_1 = __importDefault(require("../../core/package/packageInstallers/InstallUnlockedPackageCollection"));
const ExternalPackage2DependencyResolver_1 = __importDefault(require("../../core/package/dependencies/ExternalPackage2DependencyResolver"));
const ExternalDependencyDisplayer_1 = __importDefault(require("../../core/display/ExternalDependencyDisplayer"));
const GroupConsoleLogs_1 = __importDefault(require("../../ui/GroupConsoleLogs"));
const FetchArtifactsFromOrg_1 = require("../../utils/FetchArtifactsFromOrg");
const ApexTestValidator_1 = require("./ApexTestValidator");
const OrgInfoDisplayer_1 = __importDefault(require("../../ui/OrgInfoDisplayer"));
const FileOutputHandler_1 = __importDefault(require("../../outputs/FileOutputHandler"));
const ReleaseConfigAggregator_1 = require("../release/ReleaseConfigAggregator");
const ImpactedPackagesResolver_1 = __importDefault(require("../impact/ImpactedPackagesResolver"));
const ImpactedPackagesDisplayer_1 = __importDefault(require("../../core/display/ImpactedPackagesDisplayer"));
var ValidateAgainst;
(function (ValidateAgainst) {
ValidateAgainst["PROVIDED_ORG"] = "PROVIDED_ORG";
ValidateAgainst["PRECREATED_POOL"] = "PRECREATED_POOL";
})(ValidateAgainst || (exports.ValidateAgainst = ValidateAgainst = {}));
var ValidationMode;
(function (ValidationMode) {
ValidationMode["INDIVIDUAL"] = "individual";
ValidationMode["FAST_FEEDBACK"] = "fastfeedback";
ValidationMode["THOROUGH"] = "thorough";
ValidationMode["FASTFEEDBACK_LIMITED_BY_RELEASE_CONFIG"] = "ff-release-config";
ValidationMode["THOROUGH_LIMITED_BY_RELEASE_CONFIG"] = "thorough-release-config";
})(ValidationMode || (exports.ValidationMode = ValidationMode = {}));
class ValidateImpl {
constructor(props) {
this.props = props;
this.logger = new sfp_logger_1.ConsoleLogger();
}
async exec() {
rimraf.sync('artifacts');
let deploymentResult;
let targetUserName;
try {
if (this.props.validateAgainst === ValidateAgainst.PROVIDED_ORG) {
targetUserName = this.props.targetOrg;
}
else if (this.props.validateAgainst === ValidateAgainst.PRECREATED_POOL) {
if (process.env.SFPOWERSCRIPTS_DEBUG_PREFETCHED_SCRATCHORG)
targetUserName = process.env.SFPOWERSCRIPTS_DEBUG_PREFETCHED_SCRATCHORG;
else
targetUserName = await this.fetchScratchOrgFromPool(this.props.pools, this.props.orgInfo);
}
else
throw new Error(`Unknown mode ${this.props.validateAgainst}`);
//Create Org
this.orgAsSFPOrg = await SFPOrg_1.default.create({
aliasOrUsername: targetUserName,
});
//Print Org Info for validateAgainstOrg modes
//TODO: Not ideal need to unify sfpOrg and scratchOrg and then make this a global method
if (this.props.orgInfo && this.props.validateAgainst === ValidateAgainst.PROVIDED_ORG) {
OrgInfoDisplayer_1.default.printOrgInfo(this.orgAsSFPOrg);
OrgInfoDisplayer_1.default.writeOrgInfoToMarkDown(this.orgAsSFPOrg);
}
//Fetch Artifacts in the org
let packagesInstalledInOrgMappedToCommits;
if (this.props.validationMode !== ValidationMode.INDIVIDUAL) {
let installedArtifacts = await this.orgAsSFPOrg.getInstalledArtifacts();
if (installedArtifacts.length == 0) {
sfp_logger_1.default.log((0, sfp_logger_4.COLOR_ERROR)('Failed to query org for sfp Artifacts'));
}
packagesInstalledInOrgMappedToCommits = await (0, FetchArtifactsFromOrg_1.mapInstalledArtifactstoPkgAndCommits)(installedArtifacts);
this.printArtifactVersions(this.orgAsSFPOrg, installedArtifacts);
}
//In individual mode, always build changed packages only especially for validateAgainstOrg
if (this.props.validationMode == ValidationMode.INDIVIDUAL) {
this.props.diffcheck = true;
}
// Figure Impacted packages as per the PR
this.impactedPackagesAsPerBranch = await this.computePackagesChangedAgainstBaseBranch();
if (this.impactedPackagesAsPerBranch) {
sfp_logger_1.default.log((0, sfp_logger_2.COLOR_KEY_MESSAGE)(`Packages impacted in ${this.props.branch} vs ${this.props.baseBranch}`), sfp_logger_1.LoggerLevel.INFO, new sfp_logger_1.ConsoleLogger());
ImpactedPackagesDisplayer_1.default.displayImpactedPackages(this.impactedPackagesAsPerBranch, this.logger);
}
await this.buildImpactedPackages(packagesInstalledInOrgMappedToCommits);
deploymentResult = await this.deployPackages(targetUserName);
if (deploymentResult.failed.length > 0 || deploymentResult.error)
throw new ValidateError_1.default('Validation failed', { deploymentResult });
return {
deploymentResult,
};
}
catch (error) {
if (error.message?.includes(`No changes detected in the packages to be built`)) {
sfp_logger_1.default.log(`WARNING: No changes detected in any of the packages, Validation is treated as a success`, sfp_logger_1.LoggerLevel.WARN);
return;
}
else if (error instanceof ValidateError_1.default)
sfp_logger_1.default.log(`Validation failed due to : ${error}`, sfp_logger_1.LoggerLevel.DEBUG);
else
sfp_logger_1.default.log(`Failure Reason: ${error}`, sfp_logger_1.LoggerLevel.ERROR);
throw error;
}
finally {
await this.handleScratchOrgStatus(targetUserName, deploymentResult, this.props.isDeleteScratchOrg);
}
}
async computePackagesChangedAgainstBaseBranch() {
if (this.props.branch && this.props.baseBranch) {
const impactedPackageDiffProps = {
branch: this.props.branch,
currentStage: Stage_1.Stage.VALIDATE,
baseBranch: this.props.baseBranch,
diffOptions: {
useLatestGitTags: false,
skipPackageDescriptorChange: true,
useBranchCompare: true,
branch: this.props.branch,
baseBranch: this.props.baseBranch,
},
};
sfp_logger_1.default.log((0, sfp_logger_2.COLOR_KEY_MESSAGE)(`Computing impacted packages as per the PR.Please wait..`), sfp_logger_1.LoggerLevel.INFO, this.logger);
const impactedPackageResolver = new ImpactedPackagesResolver_1.default(impactedPackageDiffProps, this.logger);
return impactedPackageResolver.getImpactedPackages();
}
}
async printArtifactVersions(orgAsSFPOrg, installedArtifacts) {
let groupSection = new GroupConsoleLogs_1.default(`Artifacts installed in the Org ${orgAsSFPOrg.getUsername()}`).begin();
InstalledArtifactsDisplayer_1.default.printInstalledArtifacts(installedArtifacts, null);
groupSection.end();
}
async installPackageDependencies(sfdxProjectConfig, scratchOrgAsSFPOrg, sfpPackage, deployedPackages) {
let deployedPackagesAsStringArray = [];
for (const deployedPackage of deployedPackages) {
deployedPackagesAsStringArray.push(deployedPackage.package_name);
}
//Resolve external package dependencies
let externalPackageResolver = new ExternalPackage2DependencyResolver_1.default(this.props.hubOrg.getConnection(), sfdxProjectConfig, this.props.keys);
let externalPackage2s = await externalPackageResolver.resolveExternalPackage2DependenciesToVersions([sfpPackage.packageName], deployedPackagesAsStringArray);
sfp_logger_1.default.log(`Installing package dependencies of this ${sfpPackage.packageName} in ${scratchOrgAsSFPOrg.getUsername()}`, sfp_logger_1.LoggerLevel.INFO, new sfp_logger_1.ConsoleLogger());
//Display resolved dependenencies
let externalDependencyDisplayer = new ExternalDependencyDisplayer_1.default(externalPackage2s, new sfp_logger_1.ConsoleLogger());
externalDependencyDisplayer.display();
let packageCollectionInstaller = new InstallUnlockedPackageCollection_1.default(scratchOrgAsSFPOrg, new sfp_logger_1.ConsoleLogger());
await packageCollectionInstaller.install(externalPackage2s, true, true);
sfp_logger_1.default.log((0, sfp_logger_2.COLOR_KEY_MESSAGE)(`Successfully completed external dependencies of this ${sfpPackage.packageName} in ${scratchOrgAsSFPOrg.getUsername()}`));
}
async handleScratchOrgStatus(scratchOrgUsername, deploymentResult, isToDelete) {
//No scratch org available.. just return
if (scratchOrgUsername == undefined)
return;
if (isToDelete) {
//If deploymentResult is not available, or there is 0 packages deployed, we can reuse the org
if (!deploymentResult || deploymentResult.deployed.length == 0) {
sfp_logger_1.default.log(`Attempting to return scratch org ${scratchOrgUsername} back to pool`, sfp_logger_1.LoggerLevel.INFO);
const scratchOrgInfoAssigner = new ScratchOrgInfoAssigner_1.default(this.props.hubOrg);
try {
const result = await scratchOrgInfoAssigner.setScratchOrgStatus(scratchOrgUsername, 'Return');
if (result)
sfp_logger_1.default.log(`Succesfully returned ${scratchOrgUsername} back to pool`, sfp_logger_1.LoggerLevel.INFO);
else
sfp_logger_1.default.log((0, sfp_logger_3.COLOR_WARNING)(`Unable to return scratch org to pool, Please check permissions or update sfpower-pool-package to latest`));
}
catch (error) {
sfp_logger_1.default.log((0, sfp_logger_3.COLOR_WARNING)(`Unable to return scratch org to pool, Please check permissions or update sfpower-pool-package to latest`));
}
}
else {
try {
if (scratchOrgUsername && this.props.hubOrg.getUsername()) {
await deleteScratchOrg(this.props.hubOrg, scratchOrgUsername);
}
}
catch (error) {
sfp_logger_1.default.log((0, sfp_logger_3.COLOR_WARNING)(error.message));
}
}
}
async function deleteScratchOrg(hubOrg, scratchOrgUsername) {
sfp_logger_1.default.log(`Deleting scratch org ${scratchOrgUsername}`, sfp_logger_1.LoggerLevel.INFO);
const poolOrgDeleteImpl = new PoolOrgDeleteImpl_1.default(hubOrg, scratchOrgUsername);
await poolOrgDeleteImpl.execute();
}
}
async deployPackages(scratchOrgUsername) {
const deployStartTime = Date.now();
const deployProps = {
targetUsername: scratchOrgUsername,
artifactDir: 'artifacts',
waitTime: 120,
deploymentMode: this.props.disableSourcePackageOverride == true ? DeployImpl_1.DeploymentMode.NORMAL : DeployImpl_1.DeploymentMode.SOURCEPACKAGES,
isTestsToBeTriggered: true,
skipIfPackageInstalled: false,
logsGroupSymbol: this.props.logsGroupSymbol,
currentStage: Stage_1.Stage.VALIDATE,
disableArtifactCommit: true, //always set to true, let post deploy determine
impactedPackagesAsPerBranch: this.impactedPackagesAsPerBranch,
selectiveComponentDeployment: this.props.validationMode == ValidationMode.FAST_FEEDBACK ||
this.props.validationMode == ValidationMode.FASTFEEDBACK_LIMITED_BY_RELEASE_CONFIG,
};
const deployImpl = new DeployImpl_1.default(deployProps);
deployImpl.postDeployHook = this;
deployImpl.preDeployHook = this;
const deploymentResult = await deployImpl.exec();
const deploymentElapsedTime = Date.now() - deployStartTime;
printDeploySummary(deploymentResult, deploymentElapsedTime);
return deploymentResult;
function printDeploySummary(deploymentResult, totalElapsedTime) {
let groupSection = new GroupConsoleLogs_1.default(`Deployment Summary`).begin();
sfp_logger_1.default.printHeaderLine('', sfp_logger_5.COLOR_HEADER, sfp_logger_1.LoggerLevel.INFO);
sfp_logger_1.default.log((0, sfp_logger_6.COLOR_SUCCESS)(`${deploymentResult.deployed.length} packages deployed in ${(0, sfp_logger_7.COLOR_TIME)((0, GetFormattedTime_1.default)(totalElapsedTime))} with {${(0, sfp_logger_4.COLOR_ERROR)(deploymentResult.failed.length)}} failed deployments`));
if (deploymentResult.failed.length > 0) {
sfp_logger_1.default.log((0, sfp_logger_4.COLOR_ERROR)(`\nPackages Failed to Deploy`, deploymentResult.failed.map((packageInfo) => packageInfo.sfpPackage.packageName)));
FileOutputHandler_1.default.getInstance().appendOutput(`validation-error.md`, `### 💣 Deployment Failed 💣`);
let firstPackageFailedToValdiate = deploymentResult.failed[0];
FileOutputHandler_1.default.getInstance().appendOutput(`validation-error.md`, `Package validation failed for **${firstPackageFailedToValdiate.sfpPackage.packageName}** due to`);
FileOutputHandler_1.default.getInstance().appendOutput(`validation-error.md`, '');
FileOutputHandler_1.default.getInstance().appendOutput(`validation-error.md`, deploymentResult.error);
FileOutputHandler_1.default.getInstance().appendOutput(`validation-error.md`, `Package that are not validated:`);
deploymentResult.failed.map((packageInfo, index) => {
if (index != 0)
FileOutputHandler_1.default.getInstance().appendOutput(`validation-error.md`, `**${packageInfo.sfpPackage.packageName}**`);
});
}
sfp_logger_1.default.printHeaderLine('', sfp_logger_5.COLOR_HEADER, sfp_logger_1.LoggerLevel.INFO);
groupSection.end();
}
}
async buildImpactedPackages(packagesInstalledInOrgMappedToCommits) {
let groupSection = new GroupConsoleLogs_1.default('Building packages for Synchronization+Validation').begin();
const buildStartTime = Date.now();
const buildProps = {
buildNumber: 1,
executorcount: 10,
waitTime: 120,
isDiffCheckEnabled: this.props.diffcheck,
isQuickBuild: true,
isBuildAllAsSourcePackages: !this.props.disableSourcePackageOverride,
currentStage: Stage_1.Stage.VALIDATE,
baseBranch: this.props.baseBranch,
devhubAlias: this.props.hubOrg?.getUsername(),
baselineOrgAlias: this.props.targetOrg,
impactedPackagesAsPerBranch: this.impactedPackagesAsPerBranch,
ref: this.props.branch,
};
//Build DiffOptions
const diffOptions = buildDiffOption(this.props);
buildProps.diffOptions = diffOptions;
//compute pkg overides
buildProps.overridePackageTypes = computePackageOverrides(this.props);
//Compute packages to be included
buildProps.includeOnlyPackages = fetchPackagesAsPerReleaseConfig(this.logger, this.props);
const buildImpl = new BuildImpl_1.default(buildProps);
const { generatedPackages, failedPackages } = await buildImpl.exec();
if (failedPackages.length > 0)
throw new Error(`Failed to create packages ${failedPackages}`);
if (generatedPackages.length === 0) {
throw new Error(`No changes detected in the packages to be built\nvalidate will only execute if there is a change in atleast one of the packages`);
}
for (const generatedPackage of generatedPackages) {
try {
await ArtifactGenerator_1.default.generateArtifact(generatedPackage, process.cwd(), 'artifacts');
}
catch (error) {
sfp_logger_1.default.log((0, sfp_logger_4.COLOR_ERROR)(`Unable to create artifact for ${generatedPackage.packageName}`));
throw error;
}
}
const buildElapsedTime = Date.now() - buildStartTime;
printBuildSummary(generatedPackages, failedPackages, buildElapsedTime);
groupSection.end();
return generatedPackages;
function computePackageOverrides(props) {
let overridedPackages = {};
const allPackages = ProjectConfig_1.default.getAllPackages(null);
const projectConfig = ProjectConfig_1.default.getSFDXProjectConfig(null);
for (const pkg of allPackages) {
if (ProjectConfig_1.default.getPackageType(projectConfig, pkg) !== SfpPackage_1.PackageType.Data) {
if (!props.disableSourcePackageOverride) {
if (ProjectConfig_1.default.getPackageType(projectConfig, pkg) == SfpPackage_1.PackageType.Unlocked) {
overridedPackages[pkg] = SfpPackage_1.PackageType.Source;
}
}
}
}
return overridedPackages;
}
function fetchPackagesAsPerReleaseConfig(logger, props) {
if (props.validationMode === ValidationMode.FASTFEEDBACK_LIMITED_BY_RELEASE_CONFIG ||
props.validationMode === ValidationMode.THOROUGH_LIMITED_BY_RELEASE_CONFIG) {
let includeOnlyPackages = [];
if (props.releaseConfigPaths?.length > 0) {
let releaseConfigAggregatedLoader = new ReleaseConfigAggregator_1.ReleaseConfigAggregator(logger);
releaseConfigAggregatedLoader.addReleaseConfigs(props.releaseConfigPaths, true);
includeOnlyPackages = releaseConfigAggregatedLoader.getAllPackages();
printIncludeOnlyPackages(includeOnlyPackages);
}
return includeOnlyPackages;
function printIncludeOnlyPackages(includeOnlyPackages) {
sfp_logger_1.default.log((0, sfp_logger_2.COLOR_KEY_MESSAGE)(`Validate will include the below packages release configs (domain(s))(domain)`), sfp_logger_1.LoggerLevel.INFO);
sfp_logger_1.default.log((0, sfp_logger_1.COLOR_KEY_VALUE)(`${includeOnlyPackages.toString()}`), sfp_logger_1.LoggerLevel.INFO);
}
}
}
//generate diff Option
function buildDiffOption(props) {
const diffOptions = new PackageDiffImpl_1.PackageDiffOptions();
//In fast feedback ignore package descriptor changes
if (props.validationMode === ValidationMode.FAST_FEEDBACK) {
diffOptions.skipPackageDescriptorChange = true;
diffOptions.useLatestGitTags = false;
diffOptions.packagesMappedToLastKnownCommitId = packagesInstalledInOrgMappedToCommits;
}
else if (props.validationMode === ValidationMode.THOROUGH) {
diffOptions.skipPackageDescriptorChange = false;
diffOptions.useLatestGitTags = false;
diffOptions.packagesMappedToLastKnownCommitId = packagesInstalledInOrgMappedToCommits;
}
else if (props.validationMode === ValidationMode.INDIVIDUAL) {
diffOptions.skipPackageDescriptorChange = false;
//Dont send whats installed in orgs, use only the changed package from last know git tags
diffOptions.useLatestGitTags = true;
diffOptions.packagesMappedToLastKnownCommitId = null;
}
else if (props.validationMode === ValidationMode.THOROUGH_LIMITED_BY_RELEASE_CONFIG) {
diffOptions.skipPackageDescriptorChange = false;
diffOptions.useLatestGitTags = false;
diffOptions.packagesMappedToLastKnownCommitId = packagesInstalledInOrgMappedToCommits;
}
else if (props.validationMode === ValidationMode.FASTFEEDBACK_LIMITED_BY_RELEASE_CONFIG) {
diffOptions.skipPackageDescriptorChange = true;
diffOptions.useLatestGitTags = false;
diffOptions.packagesMappedToLastKnownCommitId = packagesInstalledInOrgMappedToCommits;
}
//It's validate.. review orgs may have bad commits.. so fall back
diffOptions.fallBackToNoTag = true;
return diffOptions;
}
function printBuildSummary(generatedPackages, failedPackages, totalElapsedTime) {
sfp_logger_1.default.printHeaderLine('', sfp_logger_5.COLOR_HEADER, sfp_logger_1.LoggerLevel.INFO);
sfp_logger_1.default.log((0, sfp_logger_6.COLOR_SUCCESS)(`${generatedPackages.length} artifacts created in ${(0, sfp_logger_7.COLOR_TIME)((0, GetFormattedTime_1.default)(totalElapsedTime))} with {${(0, sfp_logger_4.COLOR_ERROR)(failedPackages.length)}} errors`));
if (failedPackages.length > 0) {
sfp_logger_1.default.log((0, sfp_logger_4.COLOR_ERROR)(`Packages Failed To Build`, failedPackages));
}
sfp_logger_1.default.printHeaderLine('', sfp_logger_5.COLOR_HEADER, sfp_logger_1.LoggerLevel.INFO);
}
}
async fetchScratchOrgFromPool(pools, displayOrgInfo) {
let scratchOrgUsername;
for (const pool of pools) {
let scratchOrg;
try {
const poolFetchImpl = new PoolFetchImpl_1.default(this.props.hubOrg, pool.trim(), false, true);
scratchOrg = (await poolFetchImpl.execute());
}
catch (error) {
sfp_logger_1.default.log(error.message, sfp_logger_1.LoggerLevel.TRACE);
}
if (scratchOrg && scratchOrg.status === 'Assigned') {
scratchOrgUsername = scratchOrg.username;
sfp_logger_1.default.log((0, sfp_logger_2.COLOR_KEY_MESSAGE)(`Fetched scratch org ${scratchOrgUsername} from ${(0, sfp_logger_1.COLOR_KEY_VALUE)(pool)}`), sfp_logger_1.LoggerLevel.INFO, this.logger);
if (displayOrgInfo) {
OrgInfoDisplayer_1.default.printScratchOrgInfo(scratchOrg);
OrgInfoDisplayer_1.default.writeScratchOrgInfoToMarkDown(scratchOrg);
}
this.getCurrentRemainingNumberOfOrgsInPoolAndReport(scratchOrg.tag);
break;
}
}
if (scratchOrgUsername)
return scratchOrgUsername;
else
throw new Error(`Failed to fetch scratch org from ${pools}, Are you sure you created this pool using a DevHub authenticated using auth:sfdxurl or auth:web or auth:accesstoken:store`);
}
async getCurrentRemainingNumberOfOrgsInPoolAndReport(tag) {
try {
const results = await new ScratchOrgInfoFetcher_1.default(this.props.hubOrg).getScratchOrgsByTag(tag, false, true);
const availableSo = results.records.filter((soInfo) => soInfo.Allocation_status__c === 'Available');
SFPStatsSender_1.default.logGauge('pool.available', availableSo.length, {
poolName: tag,
});
}
catch (error) {
//do nothing, we are not reporting anything if anything goes wrong here
}
}
async preDeployPackage(sfpPackage, targetUsername, deployedPackages, devhubUserName) {
const shouldInstallDependencies = (mode) => {
if (this.props.validateAgainst === ValidateAgainst.PROVIDED_ORG &&
!this.props.installExternalDependencies) {
return false;
}
const isThoroughValidation = mode === ValidationMode.THOROUGH || mode === ValidationMode.THOROUGH_LIMITED_BY_RELEASE_CONFIG;
const isFastFeedbackWithExternalDependencies = (mode === ValidationMode.FASTFEEDBACK_LIMITED_BY_RELEASE_CONFIG ||
mode === ValidationMode.FAST_FEEDBACK) &&
this.props.installExternalDependencies;
return isThoroughValidation || mode === ValidationMode.INDIVIDUAL || isFastFeedbackWithExternalDependencies;
};
if (shouldInstallDependencies(this.props.validationMode)) {
const projectConfig = this.props.validationMode === ValidationMode.INDIVIDUAL
? ProjectConfig_1.default.cleanupMPDFromProjectDirectory(null, sfpPackage.package_name)
: ProjectConfig_1.default.getSFDXProjectConfig(null);
await this.installPackageDependencies(projectConfig, this.orgAsSFPOrg, sfpPackage, deployedPackages);
}
return { isToFailDeployment: false };
}
async postDeployPackage(sfpPackage, packageInstallationResult, targetUsername, deployedPackages, devhubUserName) {
//Trigger Tests after installation of each package
let isPackageImpacted = this.impactedPackagesAsPerBranch
? this.impactedPackagesAsPerBranch.get(sfpPackage.package_name)
: true;
if (isPackageImpacted) {
if (sfpPackage.packageType && sfpPackage.packageType != SfpPackage_1.PackageType.Data) {
if (packageInstallationResult.result === PackageInstallationResult_1.PackageInstallationStatus.Succeeded) {
//Get Changed Components
const apextestValidator = new ApexTestValidator_1.ApexTestValidator(targetUsername, sfpPackage, this.props, this.logger);
const testResult = await apextestValidator.validateApexTests();
if (!testResult.result) {
FileOutputHandler_1.default.getInstance().appendOutput(`validation-error.md`, `### 💣 Validation Failed 💣`);
FileOutputHandler_1.default.getInstance().appendOutput(`validation-error.md`, `Package validation failed for **${sfpPackage.packageName}**`);
FileOutputHandler_1.default.getInstance().appendOutput(`validation-error.md`, `Reasons:`);
FileOutputHandler_1.default.getInstance().appendOutput(`validation-error.md`, `${testResult.message}`);
}
else {
await this.updateOrgWithArtifact(targetUsername, sfpPackage);
}
return {
isToFailDeployment: !testResult.result,
message: testResult.message,
};
}
}
else if (sfpPackage.packageType && sfpPackage.packageType == SfpPackage_1.PackageType.Data) {
await this.updateOrgWithArtifact(targetUsername, sfpPackage);
}
}
else {
sfp_logger_1.default.log((0, sfp_logger_2.COLOR_KEY_MESSAGE)(`Syncing ${sfpPackage.package_name} to the org, Tests will be skipped`), sfp_logger_1.LoggerLevel.INFO, this.logger);
await this.updateOrgWithArtifact(targetUsername, sfpPackage);
}
return { isToFailDeployment: false };
}
async updateOrgWithArtifact(targetUsername, sfpPackage) {
if (!this.props.disableArtifactCommit) {
const sfpOrg = await SFPOrg_1.default.create({ aliasOrUsername: targetUsername });
await sfpOrg.updateArtifactInOrg(this.logger, sfpPackage);
}
}
}
exports.default = ValidateImpl;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVmFsaWRhdGVJbXBsLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2ltcGwvdmFsaWRhdGUvVmFsaWRhdGVJbXBsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsNkVBQXFFO0FBQ3JFLG1FQUFpRztBQUNqRywwR0FBa0Y7QUFDbEYsb0NBQWlDO0FBQ2pDLG1FQUFzRztBQUN0Ryw4R0FHd0U7QUFDeEUsNkVBQTZFO0FBQzdFLDZGQUFxRTtBQUVyRSxpSEFBeUY7QUFDekYsK0VBQXVEO0FBRXZELHFEQUF5RDtBQUN6RCxxREFBcUQ7QUFDckQscURBQW1EO0FBQ25ELHFEQUFvRDtBQUNwRCxxREFBcUQ7QUFDckQscURBQWtEO0FBQ2xELHFGQUE2RDtBQUM3RCwrSEFBdUc7QUFDdkcsaUlBQXlHO0FBRXpHLHFHQUE2RTtBQUM3RSxtRUFBMkM7QUFDM0MsOERBQXdFO0FBRXhFLHlGQUFpRTtBQUVqRSwrQ0FBaUM7QUFDakMscUZBQTZEO0FBQzdELDZJQUFxSDtBQUNySCw0SUFBb0g7QUFDcEgsaUhBQXlGO0FBRXpGLGlGQUF5RDtBQUN6RCw2RUFBeUY7QUFDekYsMkRBQXdEO0FBQ3hELGlGQUF5RDtBQUN6RCx3RkFBZ0U7QUFDaEUsZ0ZBQTZFO0FBQzdFLGtHQUF5RTtBQUN6RSw2R0FBcUY7QUFFckYsSUFBWSxlQUdYO0FBSEQsV0FBWSxlQUFlO0lBQ3ZCLGdEQUE2QixDQUFBO0lBQzdCLHNEQUFtQyxDQUFBO0FBQ3ZDLENBQUMsRUFIVyxlQUFlLCtCQUFmLGVBQWUsUUFHMUI7QUFDRCxJQUFZLGNBTVg7QUFORCxXQUFZLGNBQWM7SUFDdEIsMkNBQXlCLENBQUE7SUFDekIsZ0RBQThCLENBQUE7SUFDOUIsdUNBQXFCLENBQUE7SUFDckIsOEVBQTRELENBQUE7SUFDNUQsZ0ZBQThELENBQUE7QUFDbEUsQ0FBQyxFQU5XLGNBQWMsOEJBQWQsY0FBYyxRQU16QjtBQXdCRCxN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