UNPKG

@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
"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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