@rightkit/release 0.2.34 → 0.2.35
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/build-release.mjs +16 -7
- package/package.json +1 -1
- package/release-state.mjs +16 -1
- package/release-state.test.mjs +20 -0
- package/right-suite-contract.test.mjs +1 -1
- package/rightkit-versions.json +1 -1
package/build-release.mjs
CHANGED
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
import path from "node:path";
|
|
21
21
|
import { spawn, spawnSync } from "node:child_process";
|
|
22
22
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
23
|
-
import { cacheFingerprint, commandOutputPortable, releaseEnvironment, resolveReleaseLayout, runBuildStateMachine } from "./release-state.mjs";
|
|
23
|
+
import { cacheFingerprint, commandOutputPortable, releaseEnvironment, resolveReleaseLayout, runBuildStateMachine, watchProgress } from "./release-state.mjs";
|
|
24
24
|
|
|
25
25
|
const TOOL_ROOT = path.dirname(fileURLToPath(import.meta.url));
|
|
26
26
|
const WORKER = path.join(TOOL_ROOT, "release.mjs");
|
|
@@ -145,7 +145,13 @@ try {
|
|
|
145
145
|
await runProgress(config.packageManager ?? "pnpm", ["install", "--frozen-lockfile"], appRoot, env, cacheTarget);
|
|
146
146
|
},
|
|
147
147
|
build: async () => {
|
|
148
|
-
await runProgress(
|
|
148
|
+
await runProgress(
|
|
149
|
+
process.execPath,
|
|
150
|
+
[WORKER, "--config", worktreeConfigPath, "--platform", platform, "--no-upload"],
|
|
151
|
+
appRoot,
|
|
152
|
+
env,
|
|
153
|
+
[env.CARGO_TARGET_DIR, path.join(appRoot, ".cache")],
|
|
154
|
+
);
|
|
149
155
|
checkpoint(stateRoot, "build_complete");
|
|
150
156
|
checkpoint(stateRoot, "signed");
|
|
151
157
|
checkpoint(stateRoot, "hardened");
|
|
@@ -269,22 +275,25 @@ async function runProgress(cmd, runArgs, cwd, env, watchDir) {
|
|
|
269
275
|
const inactivityMs = Number(process.env.RIGHT_RELEASE_STALL_MS ?? 10 * 60 * 1000);
|
|
270
276
|
const absoluteMs = Number(process.env.RIGHT_RELEASE_ABSOLUTE_MS ?? 90 * 60 * 1000);
|
|
271
277
|
let lastProgress = Date.now();
|
|
272
|
-
|
|
278
|
+
const watchDirs = Array.isArray(watchDir) ? watchDir : [watchDir];
|
|
279
|
+
let lastMtime = Math.max(...watchDirs.map(newestMtime));
|
|
273
280
|
const started = Date.now();
|
|
274
281
|
await new Promise((resolve, reject) => {
|
|
275
282
|
child = spawn(cmd, runArgs, { cwd, env, stdio: ["inherit", "pipe", "pipe"], windowsHide: true, shell: process.platform === "win32" });
|
|
283
|
+
const closeWatchers = watchProgress(watchDirs, () => { lastProgress = Date.now(); });
|
|
276
284
|
for (const [stream, output] of [[child.stdout, process.stdout], [child.stderr, process.stderr]]) {
|
|
277
285
|
stream.on("data", (chunk) => { lastProgress = Date.now(); output.write(chunk); });
|
|
278
286
|
}
|
|
279
287
|
const monitor = setInterval(() => {
|
|
280
|
-
const mtime = newestMtime
|
|
288
|
+
const mtime = Math.max(...watchDirs.map(newestMtime));
|
|
281
289
|
if (mtime > lastMtime) { lastMtime = mtime; lastProgress = Date.now(); }
|
|
282
290
|
if (Date.now() - started > absoluteMs) stop(`absolute limit exceeded (${Math.round(absoluteMs / 60000)}m)`);
|
|
283
291
|
else if (Date.now() - lastProgress > inactivityMs) stop(`no output or file progress for ${Math.round(inactivityMs / 60000)}m`);
|
|
284
292
|
}, Math.min(30_000, Math.max(250, Math.floor(inactivityMs / 4))));
|
|
285
|
-
const
|
|
286
|
-
|
|
287
|
-
child.once("
|
|
293
|
+
const cleanup = () => { clearInterval(monitor); closeWatchers(); };
|
|
294
|
+
const stop = (reason) => { cleanup(); killTree(child.pid); reject(new Error(`release step stalled: ${reason}`)); };
|
|
295
|
+
child.once("error", (error) => { cleanup(); reject(error); });
|
|
296
|
+
child.once("exit", (code) => { cleanup(); child = null; code === 0 ? resolve() : reject(new Error(`${cmd} exited ${code}`)); });
|
|
288
297
|
});
|
|
289
298
|
}
|
|
290
299
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rightkit/release",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.35",
|
|
4
4
|
"description": "Portable Right Suite release CLI/SDK: signed installers, updater artifacts, patch/update routing, hardening, R2 publish, and RightApps registration.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
package/release-state.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { spawnSync } from "node:child_process";
|
|
3
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
3
|
+
import { existsSync, readFileSync, watch } from "node:fs";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
|
|
6
6
|
export function cacheFingerprint({ cargoLockSha256, rustc, target, features = [] }) {
|
|
@@ -44,6 +44,21 @@ export function commandOutputPortable(cmd, args, { cwd, env = process.env } = {}
|
|
|
44
44
|
return result.stdout.trim();
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
export function watchProgress(paths, onProgress) {
|
|
48
|
+
const watchers = [];
|
|
49
|
+
for (const candidate of paths) {
|
|
50
|
+
if (!candidate || !existsSync(candidate)) continue;
|
|
51
|
+
try {
|
|
52
|
+
watchers.push(watch(candidate, { recursive: true }, onProgress));
|
|
53
|
+
} catch {
|
|
54
|
+
try { watchers.push(watch(candidate, onProgress)); } catch { /* output still counts as progress */ }
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return () => {
|
|
58
|
+
for (const watcher of watchers) watcher.close();
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
47
62
|
export function releaseEnvironment({ root, platform, cacheKey, kind = "release" }) {
|
|
48
63
|
if (kind !== "release" && kind !== "test") throw new Error(`invalid target kind: ${kind}`);
|
|
49
64
|
const targetKind = kind === "release" ? "cargo-target" : "test-target";
|
package/release-state.test.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
2
|
import { createHash } from "node:crypto";
|
|
3
3
|
import { mkdtempSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { writeFile } from "node:fs/promises";
|
|
4
5
|
import os from "node:os";
|
|
5
6
|
import path from "node:path";
|
|
6
7
|
import test from "node:test";
|
|
@@ -8,6 +9,7 @@ import test from "node:test";
|
|
|
8
9
|
import {
|
|
9
10
|
cacheFingerprint,
|
|
10
11
|
commandOutputPortable,
|
|
12
|
+
watchProgress,
|
|
11
13
|
resolveReleaseLayout,
|
|
12
14
|
releaseEnvironment,
|
|
13
15
|
runBuildStateMachine,
|
|
@@ -15,6 +17,24 @@ import {
|
|
|
15
17
|
verifySealedRelease,
|
|
16
18
|
} from "./release-state.mjs";
|
|
17
19
|
|
|
20
|
+
test("progress watcher observes writes in nested Cargo target directories", async () => {
|
|
21
|
+
const root = mkdtempSync(path.join(os.tmpdir(), "right-release-watch-"));
|
|
22
|
+
const nested = path.join(root, "release", "build", "openssl");
|
|
23
|
+
mkdirSync(nested, { recursive: true });
|
|
24
|
+
let resolveProgress;
|
|
25
|
+
const progress = new Promise((resolve) => { resolveProgress = resolve; });
|
|
26
|
+
const close = watchProgress([root], resolveProgress);
|
|
27
|
+
try {
|
|
28
|
+
await writeFile(path.join(nested, "object.lib"), "progress");
|
|
29
|
+
await Promise.race([
|
|
30
|
+
progress,
|
|
31
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error("nested progress event missing")), 2_000)),
|
|
32
|
+
]);
|
|
33
|
+
} finally {
|
|
34
|
+
close();
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
|
|
18
38
|
test("portable command capture resolves Windows command shims", { skip: process.platform !== "win32" }, () => {
|
|
19
39
|
assert.match(commandOutputPortable("pnpm", ["--version"]), /^11\.12\.0$/);
|
|
20
40
|
});
|
|
@@ -317,7 +317,7 @@ test("Cargo version contract rejects staged versions that mismatch canonical man
|
|
|
317
317
|
test("RightKit exposes one current version manifest", () => {
|
|
318
318
|
assert.equal(existsSync(versionsPath), true, "rightkit-versions.json must be the single current-version source");
|
|
319
319
|
assert.match(versions.packageManager, /^pnpm@\d+\.\d+\.\d+$/);
|
|
320
|
-
assert.equal(versions.npm["@rightkit/release"], "0.2.
|
|
320
|
+
assert.equal(versions.npm["@rightkit/release"], "0.2.35");
|
|
321
321
|
assert.equal(versions.npm["@rightkit/legal"], "0.2.0");
|
|
322
322
|
assert.equal(versions.npm["@rightkit/license"], "0.1.5");
|
|
323
323
|
assert.equal(versions.npm["@rightkit/logs"], "0.1.3");
|
package/rightkit-versions.json
CHANGED