Plato on Github
Report Home
lib/release-schemes/rtk.js
Maintainability
66.55
Lines of code
252
Difficulty
35.72
Estimated Errors
1.43
Function weight
By Complexity
By SLOC
"use strict"; /** * @module release-schemes/rtk */ import async from "async"; import bag from "bagofcli"; import stringFormat from "string-format"; import util from "util"; import semverVersionScheme from "../version-schemes/semver.js"; import gitScmScheme from "../scm-schemes/git.js"; import hclResourceType from "../resource-types/hcl.js"; import jsonResourceType from "../resource-types/json.js"; import keepAChangelogResourceType from "../resource-types/keep-a-changelog.js"; import makefileResourceType from "../resource-types/makefile.js"; import textResourceType from "../resource-types/text.js"; import tomlResourceType from "../resource-types/toml.js"; import yamlResourceType from "../resource-types/yaml.js"; /** * Default release scheme for RTK, consisting of three steps: * pre (set and commit release version), release (tag release version), * and post (set and commit next pre-release version). */ class Rtk { /** * Construct release scheme with the version and SCM schemes to use. * * @param {String} [versionSchemeName=semver] - version scheme name * @param {String} [scmSchemeName=git] - SCM scheme name * @param {String} preReleaseVersion - current pre-release version * @param {Object} opts - release settings * @param {Boolean} [opts.dryRun] - when true, no change will be made * @param {String} [opts.releaseIncrementType] - major, minor, or patch * @param {String} [opts.postReleaseIncrementType] - major, minor, or patch */ constructor(versionSchemeName, scmSchemeName, preReleaseVersion, opts) { versionSchemeName = versionSchemeName || "semver"; scmSchemeName = scmSchemeName || "git"; this.versionSchemes = { semver: semverVersionScheme, }; this.scmSchemes = { git: gitScmScheme, }; this.resourceTypes = { hcl: hclResourceType, json: jsonResourceType, makefile: makefileResourceType, text: textResourceType, toml: tomlResourceType, yaml: yamlResourceType, }; this.resourceTypes["keep-a-changelog"] = keepAChangelogResourceType; const VersionSchemeClass = this.versionSchemes[versionSchemeName]; this.versionScheme = new VersionSchemeClass( preReleaseVersion, opts.releaseIncrementType, opts.postReleaseIncrementType, ); this.scmScheme = this.scmSchemes[scmSchemeName]; this.logOpts = {}; if (opts.dryRun) { this.logOpts["labels"] = ["dry run"]; } } /** * Pre step: set release version on all resources, then commit the changes. * A resource's params.release_value overrides the release version, and * params.release_format formats it, e.g. v{version}. * * @param {Array<Object>} resources - resources which contain version value * @param {Object} opts - release settings * @param {Boolean} [opts.dryRun] - when true, no change will be made * @param {Function} cb - standard cb(err, result) callback */ pre(resources, opts, cb) { const self = this; bag.logStepHeading( "Executing pre step of rtk release scheme...", self.logOpts, ); const tasks = []; const paths = []; resources.forEach((resource) => { function resourceTask(cb) { let releaseVersion = resource.params && resource.params.release_value ? resource.params.release_value : self.versionScheme.getReleaseVersion(); if (resource.params && resource.params.release_format) { releaseVersion = stringFormat(resource.params.release_format, { version: releaseVersion, }); } const message = util.format( "Setting release version %s on %s resource located at %s", releaseVersion, resource.type, resource.path, ); bag.logStepItemSuccess(message, self.logOpts); self.resourceTypes[resource.type].setReleaseVersion( releaseVersion, resource, opts, cb, ); } tasks.push(resourceTask); paths.push(resource.path); }); function scmTask(cb) { const message = util.format( "Committing release version changes made to %s...", paths.join(", "), ); bag.logStepItemSuccess(message, self.logOpts); if (!opts.dryRun) { self.scmScheme.saveChanges( util.format( "Release version %s", self.versionScheme.getReleaseVersion(), ), paths, cb, ); } else { cb(); } } tasks.push(scmTask); async.series(tasks, cb); } /** * Release step: tag the release version. * * @param {Array<Object>} resources - resources which contain version value * @param {Object} opts - release settings * @param {Boolean} [opts.dryRun] - when true, no change will be made * @param {String} opts.tagFormat - SCM tag format, e.g. v{version} * @param {Function} cb - standard cb(err, result) callback */ release(resources, opts, cb) { const self = this; bag.logStepHeading( "Executing release step of rtk release scheme...", self.logOpts, ); const tasks = []; function scmTask(cb) { // Use tagFormat option to format the version to be used as SCM tag const formattedVersion = stringFormat(opts.tagFormat, { version: self.versionScheme.getReleaseVersion(), }); const message = util.format( "Adding release version tag %s ...", formattedVersion, ); bag.logStepItemSuccess(message, self.logOpts); if (!opts.dryRun) { self.scmScheme.addVersion(formattedVersion, cb); } else { cb(); } } tasks.push(scmTask); async.series(tasks, cb); } /** * Post step: set next pre-release version on all resources, then commit * the changes. A resource's params.post_release_value overrides the * post-release version. * * @param {Array<Object>} resources - resources which contain version value * @param {Object} opts - release settings * @param {Boolean} [opts.dryRun] - when true, no change will be made * @param {Function} cb - standard cb(err, result) callback */ post(resources, opts, cb) { const self = this; bag.logStepHeading( "Executing post step of rtk release scheme...", self.logOpts, ); const tasks = []; const paths = []; resources.forEach((resource) => { function resourceTask(cb) { const postReleaseVersion = resource.params && resource.params.post_release_value ? resource.params.post_release_value : self.versionScheme.getPostReleaseVersion(); const message = util.format( "Setting next pre-release version %s on %s resource located at %s", postReleaseVersion, resource.type, resource.path, ); bag.logStepItemSuccess(message, self.logOpts); self.resourceTypes[resource.type].setPostReleaseVersion( postReleaseVersion, resource, opts, cb, ); } tasks.push(resourceTask); paths.push(resource.path); }); function scmTask(cb) { const message = util.format( "Committing next pre-release version changes made to %s...", paths.join(", "), ); bag.logStepItemSuccess(message, self.logOpts); if (!opts.dryRun) { self.scmScheme.saveChanges( util.format( "Bump up to next pre-release version %s", self.versionScheme.getPostReleaseVersion(), ), paths, cb, ); } else { cb(); } } tasks.push(scmTask); async.series(tasks, cb); } } export { Rtk as default };