UNPKG

@clickup/pg-microsharding

Version:
102 lines 4.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.isInTmuxSession = isInTmuxSession; exports.tryReattachToTmuxSession = tryReattachToTmuxSession; exports.runInTmux = runInTmux; const child_process_1 = require("child_process"); const fs_1 = require("fs"); const tmp_1 = require("tmp"); const logging_1 = require("./logging"); const quote_1 = require("./quote"); const TMUX_SESSION = "pg-microsharding-tmux"; const ACTIVE_BG = "#000033"; /** * Returns true if this script runs inside a TMUX session. */ function isInTmuxSession() { return !!process.env["TMUX"]; } /** * If there is already an active TMUX session, reattaches to it. We need to keep * the strong notion of singleton for all long-running microsharding actions, so * that e.g. if we run `pg-microsharding rebalance` in one terminal, and then * run it again in another terminal, the second run will attach to the first * one. */ async function tryReattachToTmuxSession() { if (isInTmuxSession()) { return; } try { (0, child_process_1.execSync)("which tmux", { stdio: "ignore" }); } catch { throw "TMUX is required to run this action. Please install it."; } // Try to reattach to an existing session instead of starting a new one (in // case we e.g. got disconnected). try { (0, child_process_1.execSync)(`tmux attach-session -d -t ${TMUX_SESSION} 2>/dev/null`, { stdio: "inherit", }); process.exit(0); } catch { // No such session yet. } } /** * Opens M TMUX panes, in each run N commands sequentially (panes[M][N]). If a * single command fails, then fails the whole pane. * * In case we already run it from a TMUX session, just runs all the commands * sequentially. */ async function runInTmux(panes) { if (isInTmuxSession()) { for (const { title, command } of panes.flat()) { logging_1.print.section(`\n##\n## ${title}\n##\n`); (0, child_process_1.execSync)(command.map((v) => (0, quote_1.shellQuote)(v)).join(" "), { stdio: "inherit", }); } return; } (0, tmp_1.setGracefulCleanup)(); const tmuxCommands = ["set -e"]; for (const [i, sequence] of panes.entries()) { const commands = [ "set -e", String.raw `trap 'test $? -eq 0 && printf "\033[1;32mDONE. Press ^C to close this pane..." || printf "\033[0;31mFAILURE. Press ^C to close this pane..."; sleep 100000' EXIT`, ]; for (const [i, { title, command }] of sequence.entries()) { const progress = `${i + 1} of ${sequence.length}`; commands.push(`printf '\\033]2;%s\\033\\' ' ${progress} | ${title} '`, command.map(quote_1.shellQuote).join(" "), "echo"); } // TMUX has a limit on the command total length: // https://github.com/tmux/tmux/issues/254. So instead of passing the big // script, we instead put this script in a temporary file and then run it // using the `bash this-temp-file` plain command via TMUX. Notice that the // temporary files are auto-removed, but if the script is terminated cruelly // with e.g. -9 signal, they may linger; it's not a big deal since they are // cleaned up by linux tmpwatch anyway, we just don't have a better option. const tmpFile = (0, tmp_1.fileSync)({ tmpdir: logging_1.TMP_DIR, prefix: "tmux-" + sequence .map(({ key }) => key) .slice(0, 10) .join("-"), }).name; (0, fs_1.writeFileSync)(tmpFile, commands.join("\n")); if (i === 0) { tmuxCommands.push(`tmux new-session -s ${TMUX_SESSION} -d bash ${(0, quote_1.shellQuote)(tmpFile)}`); } else { tmuxCommands.push(`tmux split-window -f bash ${(0, quote_1.shellQuote)(tmpFile)}`, "tmux select-layout tiled"); } } tmuxCommands.push('tmux bind -n "C-c" confirm-before -p "Confirm SIGINT? (y/n)" "send-keys C-c"', `tmux set -g window-active-style "bg=${ACTIVE_BG}"`, `tmux set -g pane-active-border-style "bg=${ACTIVE_BG}"`, "tmux set mouse on", "tmux set pane-border-status top", 'tmux set pane-border-format "#T"', "tmux select-layout tiled", `tmux attach-session -d -t ${TMUX_SESSION}`); (0, child_process_1.execSync)(tmuxCommands.join("\n"), { stdio: "inherit" }); } //# sourceMappingURL=runInTmux.js.map