UNPKG

@auto-it/exec

Version:

Tap into select hooks and run a command on the terminal

182 lines (179 loc) 6.86 kB
"use strict"; /* eslint-disable @typescript-eslint/no-explicit-any */ Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const core_1 = require("@auto-it/core"); const make_hooks_1 = require("@auto-it/core/dist/utils/make-hooks"); const t = tslib_1.__importStar(require("io-ts")); const fromentries_1 = tslib_1.__importDefault(require("fromentries")); const endent_1 = tslib_1.__importDefault(require("endent")); const child_process_1 = require("child_process"); /** Safely trim the value if it's a string */ function trim(val) { if (typeof val === "string") { return val.trim(); } } /** Convert a "makeHooks" function into an io-ts interface */ function makeHooksType(hookCreatorFn, exclude) { const hooks = Object.keys(hookCreatorFn()); return t.partial(fromentries_1.default(hooks .map((name) => [name, t.string]) .filter(([hook]) => !exclude.includes(hook)))); } const onCreateChangelog = makeHooksType(make_hooks_1.makeChangelogHooks, []); const onCreateLogParse = makeHooksType(make_hooks_1.makeLogParseHooks, []); const onCreateRelease = makeHooksType(make_hooks_1.makeReleaseHooks, [ "onCreateChangelog", "onCreateLogParse", ]); const rootOptions = makeHooksType(make_hooks_1.makeHooks, [ "onCreateRelease", "onCreateChangelog", "onCreateLogParse", "validateConfig", ]); const pluginOptions = t.intersection([ rootOptions, t.partial({ onCreateRelease, onCreateLogParse, onCreateChangelog }), ]); /** Put args in envirnment */ const createEnv = (args) => (Object.assign(Object.assign({}, process.env), fromentries_1.default(args.map((arg, index) => [`ARG_${index}`, JSON.stringify(arg)])))); /** Wraps execSync around debugging and error handling */ const runExecSync = (command, options, auto) => { let execResult; try { auto.logger.verbose.info(`Running command: ${command}`); auto.logger.veryVerbose.info(endent_1.default ` Supplied Environment (name and char size): ${Object.entries((options === null || options === void 0 ? void 0 : options.env) || {}) .map(([key, value]) => `\t${key}=${value ? value.length : 0}`) .join("\n")} `); execResult = trim(child_process_1.execSync(command, options)); } catch (e) { if (e && e.code === "E2BIG") { auto.logger.log.error(endent_1.default ` Received E2BIG from execSync. This usually occurs when the argument list is too large for the command you are trying to run. Please consider disabling your 'auto-exec' usage and following this issue for updates: https://github.com/intuit/auto/issues/1294 `); } else { auto.logger.log.error(e); } process.exit(1); } return execResult; }; /** Tap a hook if possible */ const tapHook = (name, hook, command, auto) => { if (!hook) { return; } const hookType = hook.constructor.name; if (name === "getRepository" || name === "getAuthor" || name === "makeRelease" || name === "modifyConfig" || name === "next" || name === "canary" || name === "parseCommit" || name === "addToBody" || name === "renderChangelogLine" || name === "renderChangelogTitle" || name === "renderChangelogAuthor" || name === "renderChangelogAuthorLine") { hook.tap(`exec ${name}`, (...args) => { const value = trim(runExecSync(command, { stdio: ["ignore", "pipe", "inherit"], encoding: "utf8", env: createEnv(args), }, auto)); if (!value) { return; } if (name !== "canary") { return JSON.parse(value); } try { return JSON.parse(value); } catch (error) { // canary hook can just return a string return value; } }); } else if (name === "omitCommit" || name === "omitReleaseNotes") { hook.tap(`exec ${name}`, (...args) => { const value = trim(runExecSync(command, { stdio: ["ignore", "pipe", "inherit"], encoding: "utf8", env: createEnv(args), }, auto)); if (value === "true") { return true; } }); } else if (hookType === "SyncHook" || hookType === "AsyncSeriesHook" || hookType === "AsyncParallelHook" || name === "createChangelogTitle" || name === "getPreviousVersion") { hook.tap(`exec ${name}`, (...args) => trim(runExecSync(command, { encoding: "utf8", env: createEnv(args), stdio: name === "createChangelogTitle" || name === "getPreviousVersion" ? ["ignore", "pipe", "inherit"] : "inherit", }, auto))); } }; /** Tap into select hooks and run a command on the terminal */ class ExecPlugin { /** Initialize the plugin with it's options */ constructor(options) { /** The name of the plugin */ this.name = "exec"; this.options = options; } /** Tap into auto plugin points. */ apply(auto) { auto.hooks.validateConfig.tapPromise(this.name, async (name, options) => { if (name === this.name || name === `@auto-it/${this.name}`) { return core_1.validatePluginConfiguration(this.name, pluginOptions, options); } }); Object.entries(this.options).forEach(([name, command]) => command && this.applyHook(auto, name, command)); } /** Apply a hook to auto */ applyHook(auto, key, command) { const name = key; if (name === "onCreateRelease") { auto.hooks.onCreateRelease.tap(this.name, (release) => { Object.entries(command).map(([key, command]) => command && tapHook(key, release.hooks[key], command, auto)); }); } else if (name === "onCreateChangelog") { auto.hooks.onCreateChangelog.tap(this.name, (changelog) => { Object.entries(command).map(([key, command]) => command && tapHook(key, changelog.hooks[key], command, auto)); }); } else if (name === "onCreateLogParse") { auto.hooks.onCreateLogParse.tap(this.name, (logParse) => { Object.entries(command).map(([key, command]) => command && tapHook(key, logParse.hooks[key], command, auto)); }); } else { tapHook(name, auto.hooks[name], command, auto); } } } exports.default = ExecPlugin; //# sourceMappingURL=index.js.map