@flxbl-io/sfp
Version:
sfp is a CLI tool to help you manage your Salesforce projects in an artifact centric model
198 lines • 20.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 });
exports.PackageDiffOptions = void 0;
const fs = require('fs');
const path = require('path');
const Git_1 = __importDefault(require("../../git/Git"));
const IgnoreFiles_1 = __importDefault(require("../../ignore/IgnoreFiles"));
const sfp_logger_1 = __importStar(require("@flxbl-io/sfp-logger"));
const ProjectConfig_1 = __importDefault(require("../../project/ProjectConfig"));
const GitTags_1 = __importDefault(require("../../git/GitTags"));
const lodash = require("lodash");
const os_1 = require("os");
const SfpPackage_1 = require("../SfpPackage");
const dedent_1 = __importDefault(require("dedent"));
class PackageDiffOptions {
constructor() {
this.skipPackageDescriptorChange = false;
//If not set, utlize latest git tags
this.useLatestGitTags = true;
this.useBranchCompare = false; // Compare among branches
this.fallBackToNoTag = false;
}
}
exports.PackageDiffOptions = PackageDiffOptions;
class PackageDiffImpl {
constructor(logger, sfdx_package, project_directory, diffOptions) {
this.logger = logger;
this.sfdx_package = sfdx_package;
this.project_directory = project_directory;
this.diffOptions = diffOptions;
}
async exec() {
let git = await Git_1.default.initiateRepo(this.logger, this.project_directory);
let projectConfig = ProjectConfig_1.default.getSFDXProjectConfig(this.project_directory);
let pkgDescriptor = ProjectConfig_1.default.getPackageDescriptorFromConfig(this.sfdx_package, projectConfig);
sfp_logger_1.default.log((0, sfp_logger_1.COLOR_KEY_MESSAGE)(`${os_1.EOL}Checking last known tags for ${this.sfdx_package} to determine whether package is to be built...`), sfp_logger_1.LoggerLevel.TRACE, this.logger);
let tag;
if (!this.diffOptions?.useLatestGitTags && this.diffOptions?.packagesMappedToLastKnownCommitId != null) {
tag = this.getLatestCommitFromMap(this.sfdx_package, this.diffOptions?.packagesMappedToLastKnownCommitId);
}
else {
tag = await this.getLatestTagFromGit(git, this.sfdx_package);
}
if (tag) {
sfp_logger_1.default.log((0, sfp_logger_1.COLOR_KEY_MESSAGE)(`\nUtilizing tag ${tag} for ${this.sfdx_package}`), sfp_logger_1.LoggerLevel.TRACE, this.logger);
// Get the list of modified files between the tag and HEAD refs
let modified_files;
try {
if (this.diffOptions?.useBranchCompare) {
const mergeBase = await git.raw(['merge-base', this.diffOptions.branch, this.diffOptions.baseBranch]);
modified_files = await git.diff(['--no-renames', '--name-only', this.diffOptions.branch, mergeBase.trim()]);
}
else {
modified_files = await git.diff([`${tag}`, `HEAD`, `--no-renames`, `--name-only`]);
}
}
catch (error) {
if (this.diffOptions?.fallBackToNoTag) {
sfp_logger_1.default.log((0, sfp_logger_1.COLOR_WARNING)((0, dedent_1.default)(`Unable to compute diff,
The head of the branch is not reachable from the commit id ${tag} for ${this.sfdx_package}
Attempting to build the package without diffing against the previous version`)), sfp_logger_1.LoggerLevel.INFO, this.logger);
return { isToBeBuilt: true, reason: `Previous version is from an earlier branch` };
}
else {
sfp_logger_1.default.log((0, sfp_logger_1.COLOR_ERROR)(`Unable to compute diff, The head of the branch is not reachable from the commit id ${tag}`));
sfp_logger_1.default.log((0, sfp_logger_1.COLOR_ERROR)(`Check your current branch (in case of build) or the review org in case of validate command`));
sfp_logger_1.default.log((0, sfp_logger_1.COLOR_ERROR)(`Actual error received:`));
sfp_logger_1.default.log((0, sfp_logger_1.COLOR_ERROR)(error));
throw new Error(`Failed to compute git diff for package ${this.sfdx_package} against commit id ${tag}`);
}
}
let packageType = ProjectConfig_1.default.getPackageType(projectConfig, this.sfdx_package);
if (packageType !== SfpPackage_1.PackageType.Data)
modified_files = this.applyForceIgnoreToModifiedFiles(modified_files);
sfp_logger_1.default.log(`Checking for changes in source directory ${path.normalize(pkgDescriptor.path)}`, sfp_logger_1.LoggerLevel.TRACE, this.logger);
// Check whether the package has been modified
for (let filename of modified_files) {
let normalizedPkgPath = path.normalize(pkgDescriptor.path);
let normalizedFilename = path.normalize(filename);
let relativePath = path.relative(normalizedPkgPath, normalizedFilename);
if (!relativePath.startsWith('..')) {
sfp_logger_1.default.log(`Found change(s) in ${filename}`, sfp_logger_1.LoggerLevel.TRACE, this.logger);
return { isToBeBuilt: true, reason: `Found change(s) in package`, tag: tag };
}
}
sfp_logger_1.default.log(`Checking for changes to package descriptor in sfdx-project.json`, sfp_logger_1.LoggerLevel.TRACE, this.logger);
let isPackageDescriptorChanged = await this.isPackageDescriptorChanged(git, tag, pkgDescriptor);
if (isPackageDescriptorChanged) {
return { isToBeBuilt: true, reason: `Package Descriptor Changed`, tag: tag };
}
return { isToBeBuilt: false, reason: `No changes found`, tag: tag };
}
else {
if (this.diffOptions?.useBranchCompare) {
const mergeBase = await git.raw(['merge-base', this.diffOptions.branch, this.diffOptions.baseBranch]);
let modified_files = await git.diff(['--no-renames', '--name-only', this.diffOptions.branch, mergeBase.trim()]);
// Check whether the package has been modified
for (let filename of modified_files) {
let normalizedPkgPath = path.normalize(pkgDescriptor.path);
let normalizedFilename = path.normalize(filename);
let relativePath = path.relative(normalizedPkgPath, normalizedFilename);
if (!relativePath.startsWith('..')) {
sfp_logger_1.default.log(`Found change(s) in ${filename}`, sfp_logger_1.LoggerLevel.TRACE, this.logger);
return { isToBeBuilt: true, reason: `Found change(s) in package`, tag: tag };
}
}
return { isToBeBuilt: false, reason: `No changes found`, tag: tag };
}
else {
sfp_logger_1.default.log(`Tag missing for ${this.sfdx_package}...marking package for build anyways`, sfp_logger_1.LoggerLevel.TRACE, this.logger);
return { isToBeBuilt: true, reason: `Previous version not found` };
}
}
}
applyForceIgnoreToModifiedFiles(modified_files) {
let forceignorePath;
if (this.diffOptions?.pathToReplacementForceIgnore)
forceignorePath = this.diffOptions?.pathToReplacementForceIgnore;
else if (this.project_directory != null)
forceignorePath = path.join(this.project_directory, '.forceignore');
else
forceignorePath = '.forceignore';
let ignoreFiles = new IgnoreFiles_1.default(fs.readFileSync(forceignorePath).toString());
// Filter the list of modified files with .forceignore
modified_files = ignoreFiles.filter(modified_files);
return modified_files;
}
async getLatestTagFromGit(git, sfdx_package) {
const gitTags = new GitTags_1.default(git, sfdx_package);
let tags = await gitTags.listTagsOnBranch();
sfp_logger_1.default.log('Analysing tags:', sfp_logger_1.LoggerLevel.DEBUG);
if (tags.length > 10) {
sfp_logger_1.default.log(tags.slice(-10).toString().replace(/,/g, '\n'), sfp_logger_1.LoggerLevel.TRACE, this.logger);
}
else {
sfp_logger_1.default.log(tags.toString().replace(/,/g, '\n'), sfp_logger_1.LoggerLevel.TRACE, this.logger);
}
return tags.pop();
}
async isPackageDescriptorChanged(git, latestTag, packageDescriptor) {
let projectConfigJson = await git.show([`${latestTag}:sfdx-project.json`]);
let projectConfig = JSON.parse(projectConfigJson);
let packageDescriptorFromLatestTag;
for (let dir of projectConfig['packageDirectories']) {
if (this.sfdx_package === dir.package) {
packageDescriptorFromLatestTag = dir;
}
}
if (!lodash.isEqual(packageDescriptor, packageDescriptorFromLatestTag)) {
sfp_logger_1.default.log(`Found change in ${this.sfdx_package} package descriptor`, sfp_logger_1.LoggerLevel.TRACE, this.logger);
//skip check and ignore
if (this.diffOptions?.skipPackageDescriptorChange) {
sfp_logger_1.default.log(`Ignoring changes in package desriptor as asked to..`, sfp_logger_1.LoggerLevel.TRACE, this.logger);
return false;
}
else
return true;
}
else
return false;
}
getLatestCommitFromMap(sfdx_package, packagesToCommits) {
if (packagesToCommits[sfdx_package] != null) {
return packagesToCommits[sfdx_package];
}
else {
return null;
}
}
}
exports.default = PackageDiffImpl;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUGFja2FnZURpZmZJbXBsLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2NvcmUvcGFja2FnZS9kaWZmL1BhY2thZ2VEaWZmSW1wbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLE1BQU0sRUFBRSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztBQUN6QixNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDN0Isd0RBQWdDO0FBQ2hDLDJFQUFtRDtBQUNuRCxtRUFBcUg7QUFDckgsZ0ZBQXdEO0FBQ3hELGdFQUF3QztBQUN4QyxpQ0FBa0M7QUFDbEMsMkJBQXlCO0FBQ3pCLDhDQUE0QztBQUM1QyxvREFBNEI7QUFFNUIsTUFBYSxrQkFBa0I7SUFBL0I7UUFDSSxnQ0FBMkIsR0FBYSxLQUFLLENBQUM7UUFDOUMsb0NBQW9DO1FBQ3BDLHFCQUFnQixHQUFVLElBQUksQ0FBQztRQUcvQixxQkFBZ0IsR0FBYSxLQUFLLENBQUMsQ0FBQyx5QkFBeUI7UUFHN0Qsb0JBQWUsR0FBYSxLQUFLLENBQUM7SUFDdEMsQ0FBQztDQUFBO0FBVkQsZ0RBVUM7QUFFRCxNQUFxQixlQUFlO0lBQ2hDLFlBQ1ksTUFBYyxFQUNkLFlBQW9CLEVBQ3BCLGlCQUE4QixFQUM5QixXQUFnQztRQUhoQyxXQUFNLEdBQU4sTUFBTSxDQUFRO1FBQ2QsaUJBQVksR0FBWixZQUFZLENBQVE7UUFDcEIsc0JBQWlCLEdBQWpCLGlCQUFpQixDQUFhO1FBQzlCLGdCQUFXLEdBQVgsV0FBVyxDQUFxQjtJQUN6QyxDQUFDO0lBRUcsS0FBSyxDQUFDLElBQUk7UUFDYixJQUFJLEdBQUcsR0FBUSxNQUFNLGFBQUcsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQztRQUUxRSxJQUFJLGFBQWEsR0FBRyx1QkFBYSxD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