diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d64dfa351..f029b2437 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -374,10 +374,10 @@ jobs: NPM_ALIASES=$(echo "$NPM_ALIASES" | jq -c --arg name "$NAME" --arg version "$VERSION" --arg tag "$TAG" --arg alias "$ALIAS" \ '. + [{name: $name, version: $version, tag: $tag, alias: $alias}]') done < <(jq -r --arg name "$NAME" '.[$name].aliases // [] | .[]' .github/release-republish.json) - # The only three packages this workspace builds a Node SEA (single-executable application) binary for -- see packages/document-cli, document-mcp, document-rest's own tsdown.config.ts. A hardcoded literal set, not a config-file entry like the alias/GitHub-Packages maps above: those vary per package and grow independently, where this is a small, closed set unlikely to grow the same way. Two of the four legs are both macOS (macos-latest tracks the newest Apple Silicon image; macos-26-intel is GitHub's current standard, non-large-runner Intel image, since macos-latest stopped meaning Intel some time ago) -- build-sea-binary.ts's own binaryFileName disambiguates them by process.arch, not just by OS, for exactly this reason. + # The only three packages this workspace builds a Node SEA (single-executable application) binary for -- see packages/document-cli, document-mcp, document-rest's own tsdown.config.ts. A hardcoded literal set, not a config-file entry like the alias/GitHub-Packages maps above: those vary per package and grow independently, where this is a small, closed set unlikely to grow the same way. Three architecture pairs share an OS (macos-latest/macos-26-intel are both darwin; ubuntu-latest/ubuntu-24.04-arm are both linux; windows-latest/windows-11-arm are both win32) -- all of them standard, non-large-runner images, no extra cost -- so build-sea-binary.ts's own binaryFileName disambiguates every leg by process.arch, not just by OS, for exactly this reason. case "$NAME" in document-cli | document-mcp | document-rest) - for OS in ubuntu-latest macos-latest macos-26-intel windows-latest; do + for OS in ubuntu-latest ubuntu-24.04-arm macos-latest macos-26-intel windows-latest windows-11-arm; do SEA=$(echo "$SEA" | jq -c --arg name "$NAME" --arg version "$VERSION" --arg tag "$TAG" --arg os "$OS" \ '. + [{name: $name, version: $version, tag: $tag, os: $os}]') done @@ -480,10 +480,10 @@ jobs: NPM_ALIASES=$(echo "$NPM_ALIASES" | jq -c --arg name "$NAME" --arg version "$VERSION" --arg tag "$TAG" --arg alias "$ALIAS" \ '. + [{name: $name, version: $version, tag: $tag, alias: $alias}]') done < <(jq -r --arg name "$NAME" '.[$name].aliases // [] | .[]' .github/release-republish.json) - # Mirrors the release job's own identical case statement -- see that step's own comment on why this is a hardcoded literal set rather than a release-republish.json entry, and on why two of the four legs are both macOS. + # Mirrors the release job's own identical case statement -- see that step's own comment on why this is a hardcoded literal set rather than a release-republish.json entry, and on why three of the six legs share an OS with another leg. case "$NAME" in document-cli | document-mcp | document-rest) - for OS in ubuntu-latest macos-latest macos-26-intel windows-latest; do + for OS in ubuntu-latest ubuntu-24.04-arm macos-latest macos-26-intel windows-latest windows-11-arm; do SEA=$(echo "$SEA" | jq -c --arg name "$NAME" --arg version "$VERSION" --arg tag "$TAG" --arg os "$OS" \ '. + [{name: $name, version: $version, tag: $tag, os: $os}]') done diff --git a/README.md b/README.md index 6d30e65f3..ecafb87fb 100644 --- a/README.md +++ b/README.md @@ -171,7 +171,7 @@ Release configuration is **only** at the root. The orchestrator sets `tagFormat` **Post-release republishing and attestation, restored:** the separate repositories' own per-package pipelines also republished each package under one or more alternate npm names (and, for several packages, under a `@exadev/` scope to GitHub Packages), and signed an SPDX SBOM plus a build-provenance attestation against every release tarball. The orchestrator itself has no equivalent step, so three post-release jobs in the same CI workflow now provide it (previously [#732](https://github.com/ExaDev/documents.js/issues/732)): when the release job finishes, it diffs the `name@version` tags the orchestrator created and fans out over exactly the packages that released, each leg checking out its package's own release tag so a queued next release can never shift the tree under it. One matrix republishes each package that `.github/release-republish.json` maps to GitHub Packages (`npm pkg set` of the scoped name and a `publishConfig.registry` override at publish time — never a second package.json, so the mirror cannot drift from the real metadata); one matrix republishes under each alternate npm name the same map lists (`document-bytes`, `mrkdwn.js`, `pdf-codec.js`/`pdf-parser.js`, the five `document-schema.js` aliases, `js.documents`, `doculi`) via OIDC trusted publishing; one generates an SPDX SBOM (`pnpm sbom --sbom-format spdx --prod`), packs the shipped tarball, attests SBOM and build provenance against it with `actions/attest`, and attaches the raw SBOM to the package's GitHub Release. Nothing depends on these jobs, so a failure there can never block the release or the Pages deploy, and every leg skips as already-done on re-runs. -**SEA binaries:** a fourth post-release matrix builds a Node [single-executable application](https://nodejs.org/api/single-executable-applications.html) binary for `document-cli`, `document-mcp`, and `document-rest` — the three packages whose own `tsdown.config.ts` produces a fully-bundled, dependency-free entry point for it (see each package's own README for what the resulting binary covers) — for Linux (x64), Windows (x64), and macOS on both Apple Silicon and Intel, and attaches each one to that release's GitHub Release assets under a name qualified by both OS and architecture (`document-cli-macos-arm64`, `document-cli-macos-x64`, and so on), since two of the four build legs are both macOS and would otherwise collide on upload. Node's own `--build-sea` (Node 25.5.0+) copies whichever `node` binary builds it, so the job installs a second, newer Node (beyond the workspace's own pinned version) immediately before that step, specifically to get the native ESM `mainFormat` support `document-cli`'s Ink-driven bundle needs; `.github/scripts/build-sea-binary.ts` holds the platform-specific ad-hoc `codesign` signing step macOS needs (Linux and Windows ship unsigned). Like the three jobs above, nothing depends on it and a failure there can never block the release. +**SEA binaries:** a fourth post-release matrix builds a Node [single-executable application](https://nodejs.org/api/single-executable-applications.html) binary for `document-cli`, `document-mcp`, and `document-rest` — the three packages whose own `tsdown.config.ts` produces a fully-bundled, dependency-free entry point for it (see each package's own README for what the resulting binary covers) — for Linux, Windows, and macOS, each on both its standard architecture and its less common one (x64 and arm64 for Linux and Windows; Apple Silicon and Intel for macOS), and attaches each one to that release's GitHub Release assets under a name qualified by both OS and architecture (`document-cli-macos-arm64`, `document-cli-linux-x64`, and so on), since three of the six build legs share an OS with another leg and would otherwise collide on upload. Every non-standard-architecture leg (`macos-26-intel`, `ubuntu-24.04-arm`, `windows-11-arm`) is still a standard GitHub-hosted runner, not a paid "larger runner". Node's own `--build-sea` (Node 25.5.0+) copies whichever `node` binary builds it, so the job installs a second, newer Node (beyond the workspace's own pinned version) immediately before that step, specifically to get the native ESM `mainFormat` support `document-cli`'s Ink-driven bundle needs; `.github/scripts/build-sea-binary.ts` holds the platform-specific ad-hoc `codesign` signing step macOS needs (Linux and Windows ship unsigned). Like the three jobs above, nothing depends on it and a failure there can never block the release. If a release job is itself cancelled by its own timeout after the per-package publish work has already completed but before it collects the released tags into those four matrices, a plain re-run cannot recover it: the collection step diffs tags against a before/after snapshot taken within that same run, so a later run sees every already-existing tag as pre-existing, not new. `ci.yml`'s `workflow_dispatch` trigger takes an optional `backfill_tags` input (comma- or newline-separated `name@version` tags) for exactly this case: a `collect-backfill-matrix` job builds the identical four matrices directly from the given tags, without re-running the release itself, and the four post-release jobs consume whichever of it or the normal release job produced output. Trigger it with `gh workflow run ci.yml --field backfill_tags="pkg-a@1.2.3,pkg-b@4.5.6"`. diff --git a/packages/document-cli/README.md b/packages/document-cli/README.md index 8d1b926cc..9908c889a 100644 --- a/packages/document-cli/README.md +++ b/packages/document-cli/README.md @@ -72,7 +72,7 @@ npm i -g doculi Both names install the exact same package and the exact same binary — `package.json`'s `bin` field declares both `document-cli` and `doculi` pointing at the one built entry point unconditionally, so there is no "real" name and an alias; pick whichever you find easier to type. Unlike a sibling's second _npm package name_ (`documents.js`'s own `js.documents` — see that package's README, and note the older per-repo pipeline's GitHub Packages republish this pattern used to mirror is no longer running, per [ExaDev/documents.js#732](https://github.com/ExaDev/documents.js/issues/732)), this is one package with two `bin` entries: a second name for the same build, not a second build, and unaffected by that gap. -Every release also attaches a Node [single-executable application](https://nodejs.org/api/single-executable-applications.html) build for Linux, Windows, and macOS (both Apple Silicon and Intel) to that release's own GitHub Release assets — a standalone binary with the entire package and its dependencies embedded, needing no Node.js install or `npm i` at all. It covers every subcommand except the TUI, which needs a real terminal session rather than a spawned subprocess and stays npm-only; running `tui` against the binary prints a message pointing back at the npm-installed package instead of attempting to launch it. Download the asset matching your platform from the package's tag on the [Releases page](https://github.com/ExaDev/documents.js/releases) and run it directly (`chmod +x` on Linux/macOS first). +Every release also attaches a Node [single-executable application](https://nodejs.org/api/single-executable-applications.html) build for Linux (x64 and arm64), Windows (x64 and arm64), and macOS (Apple Silicon and Intel) to that release's own GitHub Release assets — a standalone binary with the entire package and its dependencies embedded, needing no Node.js install or `npm i` at all. It covers every subcommand except the TUI, which needs a real terminal session rather than a spawned subprocess and stays npm-only; running `tui` against the binary prints a message pointing back at the npm-installed package instead of attempting to launch it. Download the asset matching your platform from the package's tag on the [Releases page](https://github.com/ExaDev/documents.js/releases) and run it directly (`chmod +x` on Linux/macOS first). ## Usage diff --git a/packages/document-mcp/README.md b/packages/document-mcp/README.md index 7ce1026b0..f51783c67 100644 --- a/packages/document-mcp/README.md +++ b/packages/document-mcp/README.md @@ -189,7 +189,7 @@ Then add the server URL (e.g., `https://your-host:3000/mcp`) as a connector in C ### Standalone binary -Every release also attaches a Node [single-executable application](https://nodejs.org/api/single-executable-applications.html) build for Linux, Windows, and macOS (both Apple Silicon and Intel) to that release's own GitHub Release assets — the entire server and its dependencies embedded in one file, needing no Node.js install or `npx` at all. It supports both `stdio` and `--transport http` exactly as above; point an MCP client's `command` at the downloaded binary directly instead of `npx`/`node`. Download the asset matching your platform from the package's tag on the [Releases page](https://github.com/ExaDev/documents.js/releases) and run it directly (`chmod +x` on Linux/macOS first). +Every release also attaches a Node [single-executable application](https://nodejs.org/api/single-executable-applications.html) build for Linux (x64 and arm64), Windows (x64 and arm64), and macOS (Apple Silicon and Intel) to that release's own GitHub Release assets — the entire server and its dependencies embedded in one file, needing no Node.js install or `npx` at all. It supports both `stdio` and `--transport http` exactly as above; point an MCP client's `command` at the downloaded binary directly instead of `npx`/`node`. Download the asset matching your platform from the package's tag on the [Releases page](https://github.com/ExaDev/documents.js/releases) and run it directly (`chmod +x` on Linux/macOS first). ### Development diff --git a/packages/document-rest/README.md b/packages/document-rest/README.md index ae4afd815..3989c8b98 100644 --- a/packages/document-rest/README.md +++ b/packages/document-rest/README.md @@ -20,7 +20,7 @@ This binds a plain `node:http` listener to `127.0.0.1` (loopback only) on the gi ### Standalone binary -Every release also attaches a Node [single-executable application](https://nodejs.org/api/single-executable-applications.html) build for Linux, Windows, and macOS (both Apple Silicon and Intel) to that release's own GitHub Release assets — the entire server and its dependencies embedded in one file, needing no Node.js install or `npx` at all. For the "a caller with no Node runtime of its own" case this package exists for in the first place, this removes the last Node dependency too: download the asset matching your platform from the package's tag on the [Releases page](https://github.com/ExaDev/documents.js/releases), run it directly (`chmod +x` on Linux/macOS first), and it takes the identical `--port` flag. +Every release also attaches a Node [single-executable application](https://nodejs.org/api/single-executable-applications.html) build for Linux (x64 and arm64), Windows (x64 and arm64), and macOS (Apple Silicon and Intel) to that release's own GitHub Release assets — the entire server and its dependencies embedded in one file, needing no Node.js install or `npx` at all. For the "a caller with no Node runtime of its own" case this package exists for in the first place, this removes the last Node dependency too: download the asset matching your platform from the package's tag on the [Releases page](https://github.com/ExaDev/documents.js/releases), run it directly (`chmod +x` on Linux/macOS first), and it takes the identical `--port` flag. ## API