UNPKG

@decaf-ts/utils

Version:

module management utils for decaf-ts

168 lines 7.08 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ReleaseScript = void 0; /* istanbul ignore file */ const utils_1 = require("./../../utils/utils.cjs"); const constants_1 = require("./../../utils/constants.cjs"); const input_1 = require("./../../input/input.cjs"); const command_1 = require("./../command.cjs"); const options = { ci: { type: "boolean", default: true, }, message: { type: "string", short: "m", }, tag: { type: "string", short: "t", default: undefined, }, }; /** * @class ReleaseScript * @extends {Command} * @cavegory scripts * @description A command-line script for managing releases and version updates. * @summary This script automates the process of creating and pushing new releases. It handles version updates, * commit messages, and optionally publishes to NPM. The script supports semantic versioning and can work in both CI and non-CI environments. * * @param {Object} options - Configuration options for the script * @param {boolean} options.ci - Whether the script is running in a CI environment (default: true) * @param {string} options.message - The release message (short: 'm') * @param {string} options.tag - The version tag to use (short: 't', default: undefined) */ class ReleaseScript extends command_1.Command { constructor() { super("ReleaseScript", options); } /** * @description Prepares the version for the release. * @summary This method validates the provided tag or prompts the user for a new one if not provided or invalid. * It also displays the latest git tags for reference. * @param {string} tag - The version tag to prepare * @returns {Promise<string>} The prepared version tag * * @mermaid * sequenceDiagram * participant R as ReleaseScript * participant T as TestVersion * participant U as UserInput * participant G as Git * R->>T: testVersion(tag) * alt tag is valid * T-->>R: return tag * else tag is invalid or not provided * R->>G: List latest git tags * R->>U: Prompt for new tag * U-->>R: return new tag * end */ async prepareVersion(tag) { const log = this.log.for(this.prepareVersion); tag = this.testVersion(tag || ""); if (!tag) { log.verbose("No release message provided. Prompting for one:"); log.info(`Listing latest git tags:`); await (0, utils_1.runCommand)("git tag --sort=-taggerdate | head -n 5").promise; return await input_1.UserInput.insistForText("tag", "Enter the new tag number (accepts v*.*.*[-...])", (val) => !!val.toString().match(/^v[0-9]+\.[0-9]+.[0-9]+(-[0-9a-zA-Z-]+)?$/)); } return tag; } /** * @description Tests if the provided version is valid. * @summary This method checks if the version is a valid semantic version or a predefined update type (PATCH, MINOR, MAJOR). * @param {string} version - The version to test * @returns {string | undefined} The validated version or undefined if invalid */ testVersion(version) { const log = this.log.for(this.testVersion); version = version.trim().toLowerCase(); switch (version) { case constants_1.SemVersion.PATCH: case constants_1.SemVersion.MINOR: case constants_1.SemVersion.MAJOR: log.verbose(`Using provided SemVer update: ${version}`, 1); return version; default: log.verbose(`Testing provided version for SemVer compatibility: ${version}`, 1); if (!new RegExp(constants_1.SemVersionRegex).test(version)) { log.debug(`Invalid version number: ${version}`); return undefined; } log.verbose(`version approved: ${version}`, 1); return version; } } /** * @description Prepares the release message. * @summary This method either returns the provided message or prompts the user for a new one if not provided. * @param {string} [message] - The release message * @returns {Promise<string>} The prepared release message */ async prepareMessage(message) { const log = this.log.for(this.prepareMessage); if (!message) { log.verbose("No release message provided. Prompting for one"); return await input_1.UserInput.insistForText("message", "What should be the release message/ticket?", (val) => !!val && val.toString().length > 5); } return message; } /** * @description Runs the release script. * @summary This method orchestrates the entire release process, including version preparation, message creation, * git operations, and npm publishing (if not in CI environment). * @param {ParseArgsResult} args - The parsed command-line arguments * @returns {Promise<void>} * * @mermaid * sequenceDiagram * participant R as ReleaseScript * participant V as PrepareVersion * participant M as PrepareMessage * participant N as NPM * participant G as Git * participant U as UserInput * R->>V: prepareVersion(tag) * R->>M: prepareMessage(message) * R->>N: Run prepare-release script * R->>G: Check git status * alt changes exist * R->>U: Ask for confirmation * U-->>R: Confirm * R->>G: Add and commit changes * end * R->>N: Update npm version * R->>G: Push changes and tags * alt not CI environment * R->>N: Publish to npm * end */ async run(args) { let result; const { ci } = args; let { tag, message } = args; tag = await this.prepareVersion(tag); message = await this.prepareMessage(message); result = await (0, utils_1.runCommand)(`npm run prepare-release -- ${tag} ${message}`, { cwd: process.cwd(), }).promise; result = await (0, utils_1.runCommand)("git status --porcelain").promise; await result; if (result.logs.length && (await input_1.UserInput.askConfirmation("git-changes", "Do you want to push the changes to the remote repository?", true))) { await (0, utils_1.runCommand)("git add .").promise; await (0, utils_1.runCommand)(`git commit -m "${tag} - ${message} - after release preparation${ci ? "" : constants_1.NoCIFLag}"`).promise; } await (0, utils_1.runCommand)(`npm version "${tag}" -m "${message}${ci ? "" : constants_1.NoCIFLag}"`).promise; await (0, utils_1.runCommand)("git push --follow-tags").promise; if (!ci) { await (0, utils_1.runCommand)("NPM_TOKEN=$(cat .npmtoken) npm publish --access public") .promise; } } } exports.ReleaseScript = ReleaseScript; //# sourceMappingURL=tag-release.js.map