@flxbl-io/sfp
Version:
sfp is a CLI tool to help you manage your Salesforce projects in an artifact centric model
262 lines • 24.2 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 simple_git_1 = require("simple-git");
const fs = __importStar(require("fs-extra"));
const ProjectConfig_1 = __importDefault(require("../../core/project/ProjectConfig"));
const ajv_1 = __importDefault(require("ajv"));
const sfp_logger_1 = __importStar(require("@flxbl-io/sfp-logger"));
const lodash = require("lodash");
const sfp_logger_2 = require("@flxbl-io/sfp-logger");
const Git_1 = __importDefault(require("../../core/git/Git"));
const GitTags_1 = __importDefault(require("../../core/git/GitTags"));
const retry = require('async-retry');
const yaml = require('js-yaml');
const path = require('path');
class ReleaseDefinitionGenerator {
get releaseConfiguration() {
// Return clone of releaseDefinition for immutability
return lodash.cloneDeep(this._releaseConfiguration);
}
constructor(logger, gitRef, pathToReleaseDefinition, releaseName, branch, metadata, directory, noPush = false, forcePush = false, inMemoryMode = false) {
this.logger = logger;
this.gitRef = gitRef;
this.releaseName = releaseName;
this.branch = branch;
this.metadata = metadata;
this.directory = directory;
this.noPush = noPush;
this.forcePush = forcePush;
this.inMemoryMode = inMemoryMode;
this._releaseConfiguration = yaml.load(fs.readFileSync(pathToReleaseDefinition, 'utf8'));
this.validateReleaseDefinitionGeneratorConfig(this._releaseConfiguration);
//Attempt to parse metadata flag into JSON
if (this.metadata) {
try {
this.metadata = JSON.parse(this.metadata);
}
catch (error) {
throw new Error(`Invalid JSON for metadata flag: ${error}`);
}
}
// Easy to handle here than with schema
if (this._releaseConfiguration.includeOnlyArtifacts &&
this.releaseConfiguration.excludeArtifacts) {
throw new Error('Error: Invalid schema: either use includeArtifacts or excludeArtifacts');
}
// Easy to handle here than with schema
if (this._releaseConfiguration.includeOnlyPackageDependencies &&
this.releaseConfiguration.excludePackageDependencies) {
throw new Error('Error: Invalid schema: either use includePackageDependencies or excludePackageDependencies');
}
// Workaround for jsonschema not supporting validation based on dependency value
if (this._releaseConfiguration.releasedefinitionProperties?.baselineOrg &&
!this._releaseConfiguration.releasedefinitionProperties?.skipIfAlreadyInstalled)
throw new Error("Release option 'skipIfAlreadyInstalled' must be true for 'baselineOrg'");
}
async exec() {
return retry(async (bail, retryNum) => {
try {
return await this.execHandler();
}
catch (err) {
if (err instanceof simple_git_1.GitError) {
if (!err.message.includes('failed to push some refs')) {
// Do not retry for Git errors that are not related to push
bail(err);
}
else {
sfp_logger_1.default.log('Failed to push definition', sfp_logger_2.LoggerLevel.WARN, this.logger);
sfp_logger_1.default.log(`Retrying...(${retryNum})`, sfp_logger_2.LoggerLevel.WARN, this.logger);
throw err;
}
}
else {
// Do not retry for non-Git errors
bail(err);
}
}
}, {
retries: 10,
minTimeout: 5,
randomize: true,
});
}
async execHandler() {
let repoDir;
let git;
try {
sfp_logger_1.default.log(`Processing Artifacts from reference.. ${this.gitRef}`, sfp_logger_2.LoggerLevel.INFO, this.logger);
git = await Git_1.default.initiateRepoAtTempLocation(this.logger);
repoDir = git.getRepositoryPath();
let fetchedArtifacts = await this.fetchFromGitRef(git);
let releaseDefiniton = await this.generateReleaseDefintion(fetchedArtifacts.artifacts, fetchedArtifacts.packageDependencies, git);
return releaseDefiniton;
}
catch (error) {
sfp_logger_1.default.log(error, sfp_logger_2.LoggerLevel.ERROR, this.logger);
}
finally {
git.deleteTempoRepoIfAny();
}
}
async fetchFromGitRef(git) {
let artifacts = {};
let packageDependencies = {};
//Create A copy of repository to a particular commit
//If already a duplicate directory switch to the passed git ref
//then switch it back
let headCommit = await git.getCurrentCommitId();
await git.checkout(this.gitRef, true);
let projectConfig = ProjectConfig_1.default.getSFDXProjectConfig(git.getRepositoryPath());
//Read sfdx project json
let sfdxPackages = ProjectConfig_1.default.getAllPackagesFromProjectConfig(projectConfig);
for (const sfdxPackage of sfdxPackages) {
let latestGitTagVersion = new GitTags_1.default(git, sfdxPackage);
try {
let version = await latestGitTagVersion.getVersionFromLatestTag();
if (this.getArtifactPredicate(sfdxPackage)) {
artifacts[sfdxPackage] = version;
}
}
catch (error) {
sfp_logger_1.default.log(`Unable to capture version of ${sfdxPackage} due to ${error}`, sfp_logger_2.LoggerLevel.WARN, this.logger);
}
}
if (!this.releaseConfiguration.excludeAllPackageDependencies) {
let allExternalPackages = ProjectConfig_1.default.getAllExternalPackages(projectConfig);
for (const externalPackage of allExternalPackages) {
if (this.getDependencyPredicate(externalPackage.alias) &&
externalPackage.Package2IdOrSubscriberPackageVersionId.startsWith('04t')) {
packageDependencies[externalPackage.alias] = externalPackage.Package2IdOrSubscriberPackageVersionId;
}
}
}
return { artifacts, packageDependencies };
}
async generateReleaseDefintion(artifacts, packageDependencies, git) {
artifacts = Object.keys(artifacts)
.sort()
.reduce((obj, key) => {
obj[key] = artifacts[key];
return obj;
}, {});
packageDependencies = Object.keys(packageDependencies)
.sort()
.reduce((obj, key) => {
obj[key] = packageDependencies[key];
return obj;
}, {});
let releaseDefinition = {
release: this.releaseName,
releaseConfigName: this.releaseConfiguration?.releaseName,
metadata: this.metadata,
skipIfAlreadyInstalled: true,
skipArtifactUpdate: false,
artifacts: artifacts,
};
//Add package dependencies
if (Object.keys(packageDependencies).length > 0)
releaseDefinition.packageDependencies = packageDependencies;
//add promotePackagesBeforeDeploymentToOrg
releaseDefinition.promotePackagesBeforeDeploymentToOrg = this.releaseConfiguration.releasedefinitionProperties?.promotePackagesBeforeDeploymentToOrg;
//override skip if already installed
if (this.releaseConfiguration.releasedefinitionProperties?.skipIfAlreadyInstalled)
releaseDefinition.skipIfAlreadyInstalled = this.releaseConfiguration.releasedefinitionProperties?.skipIfAlreadyInstalled;
//override skip artifact update
if (this.releaseConfiguration.releasedefinitionProperties?.skipArtifactUpdate)
releaseDefinition.skipArtifactUpdate = this.releaseConfiguration.releasedefinitionProperties?.skipArtifactUpdate;
//Add changelog info
releaseDefinition.changelog = this.releaseConfiguration.releasedefinitionProperties?.changelog;
if (this.inMemoryMode)
return releaseDefinition;
let releaseDefinitonYAML = yaml.dump(releaseDefinition, {
styles: {
'!!null': 'canonical', // dump null as ~
},
sortKeys: false, // sort object keys
});
sfp_logger_1.default.log((0, sfp_logger_1.COLOR_HEADER)(`------------Generated Release Definition for ${this.releaseName}----------------`));
sfp_logger_1.default.log(``);
sfp_logger_1.default.log((0, sfp_logger_1.COLOR_KEY_MESSAGE)(releaseDefinitonYAML));
let pathToReleaseDefnDirectory = this.createDirectory(this.directory, git.getRepositoryPath());
fs.writeFileSync(path.join(pathToReleaseDefnDirectory, `${this.releaseName}.yml`), releaseDefinitonYAML);
if (this.branch) {
sfp_logger_1.default.log(`Checking out branch ${this.branch}`);
await git.createBranch(this.branch);
await git.commitFile([path.join(pathToReleaseDefnDirectory, `${this.releaseName}.yml`)]);
if (!this.noPush)
await git.pushToRemote(this.branch, this.forcePush);
}
return { releaseDefinitonYAML, pathToReleaseDefnDirectory };
}
createDirectory(directory, repoDir) {
if (this.directory) {
if (!fs.pathExistsSync(path.join(repoDir, directory))) {
fs.mkdirpSync(path.join(repoDir, directory));
}
repoDir = path.join(repoDir, this.directory);
}
return repoDir;
}
validateReleaseDefinitionGeneratorConfig(releaseDefinitionGeneratorSchema) {
let schema = fs.readJSONSync(path.join(__dirname, '..', '..', '..', 'resources', 'schemas', 'release-config.schema.json'), { encoding: 'UTF-8' });
let validator = new ajv_1.default({ allErrors: true }).compile(schema);
let validationResult = validator(releaseDefinitionGeneratorSchema);
if (!validationResult) {
let errorMsg = `Release definition generation config does not meet schema requirements, ` +
`found ${validator.errors.length} validation errors:\n`;
validator.errors.forEach((error, errorNum) => {
errorMsg += `\n${errorNum + 1}: ${error.instancePath}: ${error.message} ${JSON.stringify(error.params, null, 4)}`;
});
throw new Error(errorMsg);
}
}
getArtifactPredicate(artifact) {
if (this.releaseConfiguration.includeOnlyArtifacts) {
return this.releaseConfiguration.includeOnlyArtifacts?.includes(artifact);
}
else if (this.releaseConfiguration.excludeArtifacts) {
return !this.releaseConfiguration.excludeArtifacts?.includes(artifact);
}
else
return true;
}
getDependencyPredicate(artifact) {
if (this.releaseConfiguration.includeOnlyPackageDependencies) {
return this.releaseConfiguration.includeOnlyPackageDependencies?.includes(artifact);
}
else if (this.releaseConfiguration.excludePackageDependencies) {
return !this.releaseConfiguration.excludePackageDependencies?.includes(artifact);
}
else
return true;
}
}
exports.default = ReleaseDefinitionGenerator;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUmVsZWFzZURlZmluaXRpb25HZW5lcmF0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvaW1wbC9yZWxlYXNlL1JlbGVhc2VEZWZpbml0aW9uR2VuZXJhdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSwyQ0FBc0M7QUFDdEMsNkNBQStCO0FBRS9CLHFGQUE2RDtBQUM3RCw4Q0FBNkI7QUFDN0IsbUVBQTBGO0FBRTFGLGlDQUFrQztBQUNsQyxxREFBbUQ7QUFDbkQsNkRBQXFDO0FBQ3JDLHFFQUE2QztBQUM3QyxNQUFNLEtBQUssR0FBRyxPQUFPLENBQUMsYUFBYSxDQUFDLENBQUM7QUFDckMsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0FBQ2hDLE1BQU0sSUFBSSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUU3QixNQUFxQiwwQkFBMEI7SUFHM0MsSUFBSSxvQkFBb0I7UUFDcEIscURBQXFEO1FBQ3JELE9BQU8sTUFBTSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMscUJBQXFCLENBQUMsQ0FBQztJQUN4RCxDQUFDO0lBRUQsWUFDWSxNQUFjLEVBQ2QsTUFBYyxFQUN0Qix1QkFBK0IsRUFDdkIsV0FBbUIsRUFDbkIsTUFBYyxFQUNkLFFBQWEsRUFDYixTQUFrQixFQUNsQixTQUFrQixLQUFLLEVBQ3ZCLFlBQXFCLEtBQUssRUFDMUIsZUFBdUIsS0FBSztRQVQ1QixXQUFNLEdBQU4sTUFBTSxDQUFRO1FBQ2QsV0FBTSxHQUFOLE1BQU0sQ0FBUTtRQUVkLGdCQUFXLEdBQVgsV0FBVyxDQUFRO1FBQ25CLFdBQU0sR0FBTixNQUFNLENBQVE7UUFDZCxhQUFRLEdBQVIsUUFBUSxDQUFLO1FBQ2IsY0FBUyxHQUFULFNBQVMsQ0FBUztRQUNsQixXQUFNLEdBQU4sTUFBTSxDQUFpQjtRQUN2QixjQUFTLEdBQVQsU0FBUyxDQUFp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