@auto-it/exec
Version:
Tap into select hooks and run a command on the terminal
182 lines (179 loc) • 6.86 kB
JavaScript
;
/* 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