UNPKG

@moonwall/cli

Version:

Testing framework for the Moon family of projects

131 lines 5.46 kB
import chalk from "chalk"; import { execSync } from "node:child_process"; import fs from "node:fs"; import path from "node:path"; import { importAsyncConfig, parseZombieConfigForBins } from "../lib/configReader"; import { checkAlreadyRunning, downloadBinsIfMissing, promptAlreadyRunning } from "./fileCheckers"; import Docker from "dockerode"; import { select } from "@inquirer/prompts"; export async function commonChecks(env) { const globalConfig = await importAsyncConfig(); // TODO: This is begging for some Dependency Injection if (env.foundation.type === "dev") { await devBinCheck(env); } if (env.foundation.type === "zombie") { await zombieBinCheck(env); } if (process.env.MOON_RUN_SCRIPTS === "true" && globalConfig.scriptsDir && env.runScripts && env.runScripts.length > 0) { for (const scriptCommand of env.runScripts) { await executeScript(scriptCommand); } } } async function zombieBinCheck(env) { if (env.foundation.type !== "zombie") { throw new Error("This function is only for zombie environments"); } const bins = parseZombieConfigForBins(env.foundation.zombieSpec.configPath); const pids = bins.flatMap((bin) => checkAlreadyRunning(bin)); pids.length === 0 || process.env.CI || (await promptAlreadyRunning(pids)); } async function devBinCheck(env) { if (env.foundation.type !== "dev") { throw new Error("This function is only for dev environments"); } if (!env.foundation.launchSpec || !env.foundation.launchSpec[0]) { throw new Error("Dev environment requires a launchSpec configuration"); } if (env.foundation.launchSpec[0].useDocker) { const docker = new Docker(); const imageName = env.foundation.launchSpec[0].binPath; console.log(`Checking if ${imageName} is running...`); const matchingContainers = (await docker.listContainers({ filters: { ancestor: [imageName] }, })).flat(); if (matchingContainers.length === 0) { return; } if (!process.env.CI) { await promptKillContainers(matchingContainers); return; } const runningContainers = matchingContainers.map(({ Id, Ports }) => ({ Id: Id.slice(0, 12), Ports: Ports.map(({ PublicPort, PrivatePort }) => PublicPort ? `${PublicPort} -> ${PrivatePort}` : `${PrivatePort}`).join(", "), })); console.table(runningContainers); throw new Error(`${imageName} is already running, aborting`); } const binName = path.basename(env.foundation.launchSpec[0].binPath); const pids = checkAlreadyRunning(binName); pids.length === 0 || process.env.CI || (await promptAlreadyRunning(pids)); await downloadBinsIfMissing(env.foundation.launchSpec[0].binPath); } async function promptKillContainers(matchingContainers) { const answer = await select({ message: `The following containers are already running image ${matchingContainers[0].Image}: ${matchingContainers.map(({ Id }) => Id).join(", ")}\n Would you like to kill them?`, choices: [ { name: "🪓 Kill containers", value: "kill" }, { name: "👋 Quit", value: "goodbye" }, ], }); if (answer === "goodbye") { console.log("Goodbye!"); process.exit(0); } if (answer === "kill") { const docker = new Docker(); for (const { Id } of matchingContainers) { const container = docker.getContainer(Id); await container.stop(); await container.remove(); } const containers = await docker.listContainers({ filters: { ancestor: matchingContainers.map(({ Image }) => Image) }, }); if (containers.length > 0) { console.error(`The following containers are still running: ${containers.map(({ Id }) => Id).join(", ")}`); process.exit(1); } return; } } export async function executeScript(scriptCommand, args) { const scriptsDir = (await importAsyncConfig()).scriptsDir; if (!scriptsDir) { throw new Error("No scriptsDir found in config"); } const files = await fs.promises.readdir(scriptsDir); try { const script = scriptCommand.split(" ")[0]; const ext = path.extname(script); const scriptPath = path.join(process.cwd(), scriptsDir, scriptCommand); if (!files.includes(script)) { throw new Error(`Script ${script} not found in ${scriptsDir}`); } console.log(`========== Executing script: ${chalk.bgGrey.greenBright(script)} ==========`); const argsString = args ? ` ${args}` : ""; switch (ext) { case ".js": execSync(`node ${scriptPath}${argsString}`, { stdio: "inherit" }); break; case ".ts": execSync(`pnpm tsx ${scriptPath}${argsString}`, { stdio: "inherit" }); break; case ".sh": execSync(`${scriptPath}${argsString}`, { stdio: "inherit" }); break; default: console.log(`${ext} not supported, skipping ${script}`); } } catch (err) { console.error(`Error executing script: ${chalk.bgGrey.redBright(err)}`); throw new Error(err); } } //# sourceMappingURL=launcherCommon.js.map