mirror of
https://github.com/BigBodyCobain/Shadowbroker.git
synced 2026-08-10 04:30:36 +02:00
release: prepare v0.9.7
This commit is contained in:
+168
-7
@@ -1,15 +1,176 @@
|
||||
const { spawn } = require("child_process");
|
||||
const { spawn, spawnSync } = require("child_process");
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
|
||||
const backendDir = path.resolve(__dirname, "backend");
|
||||
const venvBin = process.platform === "win32"
|
||||
? path.join(backendDir, "venv", "Scripts", "python.exe")
|
||||
: path.join(backendDir, "venv", "bin", "python3");
|
||||
const isWindows = process.platform === "win32";
|
||||
const configuredBasePython = String(process.env.BACKEND_BASE_PYTHON || process.env.PYTHON || "").trim();
|
||||
const configuredVenvDir = String(process.env.BACKEND_VENV_DIR || "").trim();
|
||||
const canonicalVenvDir = path.join(backendDir, "venv");
|
||||
const venvMarkerPath = path.join(backendDir, ".venv-dir");
|
||||
|
||||
if (!fs.existsSync(venvBin)) {
|
||||
console.error(`[!] Python venv not found at: ${venvBin}`);
|
||||
console.error("[!] Run start.sh (Mac/Linux) or start.bat (Windows) first to create the venv.");
|
||||
function venvPythonPath(dir) {
|
||||
return isWindows
|
||||
? path.join(dir, "Scripts", "python.exe")
|
||||
: path.join(dir, "bin", "python3");
|
||||
}
|
||||
|
||||
function readPersistedVenvDir() {
|
||||
try {
|
||||
const value = fs.readFileSync(venvMarkerPath, "utf8").trim();
|
||||
if (!value) {
|
||||
return "";
|
||||
}
|
||||
return path.isAbsolute(value) ? value : path.join(backendDir, value);
|
||||
} catch {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
function persistSelectedVenv(pythonBin) {
|
||||
const envDir = path.dirname(path.dirname(pythonBin));
|
||||
const relativeDir = path.relative(backendDir, envDir);
|
||||
if (!relativeDir || relativeDir.startsWith("..") || path.isAbsolute(relativeDir)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
fs.writeFileSync(venvMarkerPath, `${relativeDir}\n`, "utf8");
|
||||
} catch {
|
||||
// Best effort only. Startup should still succeed if the marker cannot be updated.
|
||||
}
|
||||
}
|
||||
|
||||
const explicitVenvCandidate = configuredVenvDir
|
||||
? venvPythonPath(path.isAbsolute(configuredVenvDir) ? configuredVenvDir : path.join(backendDir, configuredVenvDir))
|
||||
: "";
|
||||
const persistedVenvDir = readPersistedVenvDir();
|
||||
const persistedVenvCandidate = persistedVenvDir ? venvPythonPath(persistedVenvDir) : "";
|
||||
|
||||
const venvCandidates = [
|
||||
explicitVenvCandidate,
|
||||
persistedVenvCandidate,
|
||||
...(isWindows
|
||||
? [
|
||||
path.join(backendDir, "venv", "Scripts", "python.exe"),
|
||||
path.join(backendDir, "venv-repair", "Scripts", "python.exe"),
|
||||
path.join(backendDir, ".venv", "Scripts", "python.exe"),
|
||||
path.join(backendDir, ".venv-repair", "Scripts", "python.exe"),
|
||||
]
|
||||
: [
|
||||
path.join(backendDir, "venv", "bin", "python3"),
|
||||
path.join(backendDir, "venv-repair", "bin", "python3"),
|
||||
path.join(backendDir, ".venv", "bin", "python3"),
|
||||
path.join(backendDir, ".venv-repair", "bin", "python3"),
|
||||
]),
|
||||
].filter(Boolean);
|
||||
const repairTargetDir = isWindows
|
||||
? path.join(backendDir, "venv-repair")
|
||||
: path.join(backendDir, "venv-repair");
|
||||
|
||||
function canRun(command, args) {
|
||||
const result = spawnSync(command, args, {
|
||||
cwd: backendDir,
|
||||
env: process.env,
|
||||
stdio: "ignore",
|
||||
});
|
||||
return !result.error && result.status === 0;
|
||||
}
|
||||
|
||||
function findBasePython() {
|
||||
const candidates = isWindows
|
||||
? [
|
||||
[configuredBasePython, []],
|
||||
["python", []],
|
||||
["py", ["-3.11"]],
|
||||
["py", ["-3"]],
|
||||
]
|
||||
: [
|
||||
[configuredBasePython, []],
|
||||
["python3", []],
|
||||
["python", []],
|
||||
];
|
||||
|
||||
for (const [command, prefixArgs] of candidates) {
|
||||
if (!command) {
|
||||
continue;
|
||||
}
|
||||
if (canRun(command, [...prefixArgs, "-V"])) {
|
||||
return { command, prefixArgs };
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function rebuildBackendVenv(targetDir, basePython) {
|
||||
console.log(`[*] Preparing backend Python environment at ${targetDir}...`);
|
||||
try {
|
||||
fs.rmSync(targetDir, { recursive: true, force: true });
|
||||
} catch (error) {
|
||||
console.warn(`[*] Could not clear ${targetDir} cleanly (${error.code || error.message}). Trying a fresh repair path...`);
|
||||
targetDir = `${targetDir}-${Date.now()}`;
|
||||
}
|
||||
|
||||
let result = spawnSync(
|
||||
basePython.command,
|
||||
[...basePython.prefixArgs, "-m", "venv", targetDir],
|
||||
{
|
||||
cwd: backendDir,
|
||||
env: process.env,
|
||||
stdio: "inherit",
|
||||
}
|
||||
);
|
||||
if (result.error || result.status !== 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const repairedBin = isWindows
|
||||
? path.join(targetDir, "Scripts", "python.exe")
|
||||
: path.join(targetDir, "bin", "python3");
|
||||
|
||||
result = spawnSync(repairedBin, ["-m", "pip", "install", "-q", "."], {
|
||||
cwd: backendDir,
|
||||
env: process.env,
|
||||
stdio: "inherit",
|
||||
});
|
||||
if (result.error || result.status !== 0) {
|
||||
return null;
|
||||
}
|
||||
return canRun(repairedBin, ["-V"]) ? repairedBin : null;
|
||||
}
|
||||
|
||||
function ensureBackendVenv() {
|
||||
for (const candidate of venvCandidates) {
|
||||
if (fs.existsSync(candidate) && canRun(candidate, ["-V"])) {
|
||||
persistSelectedVenv(candidate);
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
|
||||
const hadExisting = venvCandidates.some((candidate) => fs.existsSync(candidate));
|
||||
console.log(
|
||||
hadExisting
|
||||
? "[*] Backend venv exists but is stale. Rebuilding it automatically..."
|
||||
: "[*] Backend venv is missing. Creating it automatically..."
|
||||
);
|
||||
|
||||
const basePython = findBasePython();
|
||||
if (!basePython) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const preferredRebuildDir = persistedVenvDir || canonicalVenvDir;
|
||||
const rebuilt = rebuildBackendVenv(hadExisting ? preferredRebuildDir : canonicalVenvDir, basePython);
|
||||
if (rebuilt) {
|
||||
persistSelectedVenv(rebuilt);
|
||||
}
|
||||
return rebuilt;
|
||||
}
|
||||
|
||||
const venvBin = ensureBackendVenv();
|
||||
|
||||
if (!venvBin) {
|
||||
console.error(`[!] Unable to prepare backend Python venv. Checked: ${venvCandidates.join(", ")}`);
|
||||
console.error("[!] Install Python 3.10-3.12 and rerun start.sh/start.bat if the repair could not complete.");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user