@melaya/runner 1.1.32 → 1.1.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/uvBootstrap.js +41 -9
- package/package.json +1 -1
package/dist/uvBootstrap.js
CHANGED
|
@@ -57,9 +57,10 @@ function findOnPath(bin) {
|
|
|
57
57
|
}
|
|
58
58
|
// Inactivity-bounded child runner (mirrors pythonEnv.runProc): a managed-CPython
|
|
59
59
|
// download legitimately takes a while but streams progress, so we bound silence.
|
|
60
|
-
function run(cmd, args, onLine,
|
|
60
|
+
function run(cmd, args, onLine, opts = {}) {
|
|
61
|
+
const inactivityMs = opts.inactivityMs ?? 5 * 60_000;
|
|
61
62
|
return new Promise((resolve) => {
|
|
62
|
-
const child = spawn(cmd, args, { stdio: ["ignore", "pipe", "pipe"], env: process.env });
|
|
63
|
+
const child = spawn(cmd, args, { stdio: ["ignore", "pipe", "pipe"], env: { ...process.env, ...opts.env }, cwd: opts.cwd });
|
|
63
64
|
let done = false;
|
|
64
65
|
let timer;
|
|
65
66
|
const finish = (c) => { if (done)
|
|
@@ -85,15 +86,38 @@ function run(cmd, args, onLine, inactivityMs = 5 * 60_000) {
|
|
|
85
86
|
bump();
|
|
86
87
|
});
|
|
87
88
|
}
|
|
88
|
-
function capture(cmd, args) {
|
|
89
|
+
function capture(cmd, args, env = {}) {
|
|
89
90
|
return new Promise((resolve) => {
|
|
90
91
|
let out = "";
|
|
91
|
-
const child = spawn(cmd, args, { stdio: ["ignore", "pipe", "pipe"], env: process.env });
|
|
92
|
+
const child = spawn(cmd, args, { stdio: ["ignore", "pipe", "pipe"], env: { ...process.env, ...env } });
|
|
92
93
|
child.stdout?.on("data", (b) => { out += b.toString(); });
|
|
93
94
|
child.on("exit", () => resolve(out.trim()));
|
|
94
95
|
child.on("error", () => resolve(""));
|
|
95
96
|
});
|
|
96
97
|
}
|
|
98
|
+
// Extract the downloaded uv archive. uv ships .tar.gz for macOS/Linux and .zip
|
|
99
|
+
// for Windows, so extraction must branch by type — a single `tar` call can't
|
|
100
|
+
// cover both portably (a shell's `tar` may be MSYS GNU tar, which can't read
|
|
101
|
+
// zip). destDir already contains the archive; we extract in place.
|
|
102
|
+
async function extractArchive(archivePath, asset, destDir, onLine) {
|
|
103
|
+
if (asset.endsWith(".zip")) {
|
|
104
|
+
// Windows only. PowerShell's Expand-Archive is always present and reliably
|
|
105
|
+
// reads zips, unlike whatever `tar` happens to be on PATH.
|
|
106
|
+
const ps = `Expand-Archive -LiteralPath '${archivePath.replace(/'/g, "''")}' -DestinationPath '${destDir.replace(/'/g, "''")}' -Force`;
|
|
107
|
+
let code = await run("powershell", ["-NoProfile", "-NonInteractive", "-Command", ps], onLine);
|
|
108
|
+
if (code === 0)
|
|
109
|
+
return true;
|
|
110
|
+
// Fallback: Windows' bundled bsdtar (System32\tar.exe) also handles zip.
|
|
111
|
+
const sys32 = join(process.env.SystemRoot || "C:\\Windows", "System32", "tar.exe");
|
|
112
|
+
code = await run(existsSync(sys32) ? sys32 : "tar", ["-xf", asset, "-C", "."], onLine, { cwd: destDir });
|
|
113
|
+
return code === 0;
|
|
114
|
+
}
|
|
115
|
+
// macOS/Linux: .tar.gz — bsdtar (macOS) and GNU tar (Linux) both read gz.
|
|
116
|
+
// cwd + bare relative name keeps args colon-free (harmless on unix, required
|
|
117
|
+
// on Windows for the fallback path above).
|
|
118
|
+
const code = await run("tar", ["-xf", asset, "-C", "."], onLine, { cwd: destDir });
|
|
119
|
+
return code === 0;
|
|
120
|
+
}
|
|
97
121
|
function findBinaryRecursive(dir, name) {
|
|
98
122
|
let entries;
|
|
99
123
|
try {
|
|
@@ -154,9 +178,9 @@ async function downloadUv(onLine) {
|
|
|
154
178
|
return null;
|
|
155
179
|
}
|
|
156
180
|
onLine("extracting uv");
|
|
157
|
-
const
|
|
158
|
-
if (
|
|
159
|
-
onLine("
|
|
181
|
+
const extracted = await extractArchive(archivePath, asset, tmp, onLine);
|
|
182
|
+
if (!extracted) {
|
|
183
|
+
onLine("extraction of the uv archive failed");
|
|
160
184
|
return null;
|
|
161
185
|
}
|
|
162
186
|
const found = findBinaryRecursive(tmp, uvBinName());
|
|
@@ -200,12 +224,20 @@ export async function provisionPython(version, onLine) {
|
|
|
200
224
|
if (!uv)
|
|
201
225
|
return null;
|
|
202
226
|
onLine(`installing a managed Python ${version} (one-time; ~30-60s)`);
|
|
203
|
-
|
|
227
|
+
// UV_SYSTEM_CERTS makes uv verify against the OS trust store instead of its
|
|
228
|
+
// bundled webpki roots — required behind TLS-intercepting proxies/antivirus
|
|
229
|
+
// (else "invalid peer certificate: UnknownIssuer") and on networks whose
|
|
230
|
+
// issuer isn't in webpki. Set as an env var (not the CLI flag) so it's a
|
|
231
|
+
// no-op on uv versions that don't know it rather than an unknown-flag error;
|
|
232
|
+
// the flag was also renamed from --native-tls, and env vars dodge that churn.
|
|
233
|
+
// UV_HTTP_TIMEOUT lifts the per-request timeout for the ~20MB CPython download.
|
|
234
|
+
const uvEnv = { UV_SYSTEM_CERTS: "1", UV_HTTP_TIMEOUT: "300" };
|
|
235
|
+
const code = await run(uv, ["python", "install", version], onLine, { env: uvEnv });
|
|
204
236
|
if (code !== 0) {
|
|
205
237
|
onLine(`uv python install ${version} failed`);
|
|
206
238
|
return null;
|
|
207
239
|
}
|
|
208
|
-
const path = await capture(uv, ["python", "find", version]);
|
|
240
|
+
const path = await capture(uv, ["python", "find", version], uvEnv);
|
|
209
241
|
if (path && existsSync(path))
|
|
210
242
|
return path;
|
|
211
243
|
onLine(`uv could not resolve a Python ${version} interpreter path after install`);
|