Files
dohooo__helmor/scripts/verify-release-config.mjs
Caspian 東澔 cad2390d5e Extend platform boundary: PTY and CLI-install seams (#747)
* Extend platform boundary: PTY and CLI-install seams

Behavior-preserving extraction of two OS-divergent surfaces behind the
platform/ seam. The macOS/Unix reference path is unchanged; Windows arms
are stubbed (Unsupported) so this is fully verifiable on macOS.

- platform::pty — PTY session lifecycle: openpty, session-leader
  (setsid + TIOCSCTTY), non-blocking poll(2) read, TIOCSWINSZ resize.
  workspace::scripts now drives the PTY through the seam instead of raw
  libc; the run/terminal orchestration and macOS behavior are unchanged.
- platform::cli_install — managed CLI launcher target path, symlink
  classification, and link creation. commands::system_commands routes
  through the seam instead of inline cfg(unix).

Also harden release:verify with a createUpdaterArtifacts===true assertion
so a platform bundle cannot silently disable the macOS updater pipeline.

* fix(pty): drop fragile live-PTY resize test that hung CI

resize_succeeds_on_a_live_pty called child.wait() on a sleeping child
attached to an undrained PTY — a classic hang (the test never returned,
stalling nextest until the job timeout). resize is already covered
end-to-end by the passing workspace::scripts::resize_updates_pty_winsize
integration test, so the standalone seam test was redundant as well.

* refactor(pty): expose the PTY seam as OS-agnostic trait objects

Per review feedback (#747) on the seam shape: PtySession now returns
Box<dyn PtyChild> / Box<dyn PtyReader> / Box<dyn PtyWriter> instead of
std::process::Child + File, so a Windows ConPTY (or portable_pty) adapter
can supply its own handle types without the shared workspace::scripts
orchestration touching File / libc / poll(2). PtyChild exposes id()+wait();
PtyWriter is Write + resize(); PtyReader is Read + poll_readable().

macOS/Unix behavior is unchanged. The reference impl keeps the non-blocking
openpty master, poll(2)-driven reads, and the reader's stop-flag exit. It is
deliberately NOT a pure blocking-read model: a held slave dup keeps the
master from EOF, so a blocking read could never be interrupted and would
hang a run-action whose script backgrounds a process and then exits. poll /
TIOCSWINSZ / EIO now live behind the PtyReader/PtyWriter impls.
2026-06-07 22:50:51 -07:00

54 lines
1.8 KiB
JavaScript

import fs from "node:fs";
import path from "node:path";
function fail(message) {
console.error(message);
process.exit(1);
}
const root = process.cwd();
const packageJson = JSON.parse(
fs.readFileSync(path.join(root, "package.json"), "utf8"),
);
const tauriConfig = JSON.parse(
fs.readFileSync(path.join(root, "src-tauri", "tauri.conf.json"), "utf8"),
);
const cargoToml = fs.readFileSync(
path.join(root, "src-tauri", "Cargo.toml"),
"utf8",
);
const cargoVersionMatch = cargoToml.match(/^version = "(.*)"$/m);
if (!cargoVersionMatch) {
fail("Unable to find version in src-tauri/Cargo.toml");
}
const versions = {
package: packageJson.version,
cargo: cargoVersionMatch[1],
tauri: tauriConfig.version,
};
if (new Set(Object.values(versions)).size !== 1) {
fail(
`Release versions are out of sync: package=${versions.package}, cargo=${versions.cargo}, tauri=${versions.tauri}`,
);
}
// Guard the macOS updater release contract. `bundle.createUpdaterArtifacts`
// is what tells Tauri to emit the signed `.app.tar.gz` + signature that
// publish.yml feeds into `latest.json` and updater-dry-run.yml validates;
// shipped macOS users' in-app auto-update depends on it. It is a shared,
// top-level flag — a platform that does not want updater artifacts (e.g. a
// Windows NSIS bundle) must opt out inside its own `bundle.<os>` block rather
// than flipping this global off, which would silently break macOS releases.
if (tauriConfig.bundle?.createUpdaterArtifacts !== true) {
fail(
"src-tauri/tauri.conf.json: bundle.createUpdaterArtifacts must be `true`. " +
"The macOS release + auto-update pipeline depends on signed updater artifacts; " +
"disable updater artifacts per-bundle (bundle.<os>), never via this global flag.",
);
}
console.log(`Release configuration verified for version ${versions.package}`);