fix: hand npm the release artifact's absolute path, so publishing finds it
CI / verify (pull_request) Successful in 1m5s
CI / infrastructure-smoke (pull_request) Successful in 37s
CI / migration-smoke (pull_request) Successful in 1m52s
CI / package-release (pull_request) Successful in 34s
CI / image-build (pull_request) Successful in 24s
CI / deploy-smoke (same-origin) (pull_request) Successful in 50s
CI / deploy-smoke (split) (pull_request) Successful in 1m30s
CI / package-publication (pull_request) Successful in 49s

The first real 0.2.0 publish failed on its first package with ENOENT:
"Publishing ekklesia-contracts-0.2.0.tgz failed: npm error code ENOENT".

The publish workflow passes a relative release path,
--release "$(find package-train …)", which is
package-train/ekklesia-packages-0.2.0. The tool validated the artifacts
relative to the job's working directory, but ran npm in its own
temporary home (cwd /tmp/ekklesia-publish-XXXXXX) with the same relative
path, package-train/ekklesia-packages-0.2.0/ekklesia-contracts-0.2.0.tgz,
which there names nothing. The disposable-registry suite always passed
an absolute path, so it never saw this.

- loadReleaseTrain resolves the release directory once; every artifact
  path is absolute from validation on, and npm is given only that exact
  file's absolute path (anything else is refused at the npm boundary).
- Just before each upload the file is checked against the validated
  bytes once more; the tool logs the absolute path it publishes, and a
  failure names it with npm's path/syscall lines (npm's temporary home
  masked, the token never shown).
- Regression tests: unit tests with a recording npm (relative nested
  release from another cwd; npm's argv, cwd, and the file's existence; a
  changed artifact refused before npm runs), which fail on the previous
  tool; and a disposable-Gitea test that runs the CLI exactly as the
  workflow does, from the Actions artifact layout, round-tripping all
  nine packages byte for byte.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
ekklesia
2026-10-08 17:51:22 -05:00
co-authored by Claude Opus 5.5
parent debb8df3ce
commit 1caffc5f26
5 changed files with 207 additions and 17 deletions
+4 -3
View File
@@ -243,9 +243,10 @@ never builds, packs, or edits a package, and it never deletes, unpublishes, or o
name, size, SHA-256, integrity, `SHA256SUMS` line, and the `package.json` inside it must match.
2. **Publishes in dependency order.** Each package comes after the train packages it depends on,
then alphabetically. For each package:
- **absent:** `npm publish <file.tgz>` under the staging dist-tag `ekklesia-staging`. npm sends the
file's own bytes and runs no script for a file; the registry checks them against their
integrity and stores them as they are;
- **absent:** `npm publish <file.tgz>` under the staging dist-tag `ekklesia-staging`, given the
artifact's absolute path (npm runs in a temporary directory of its own), after the file is
checked once more against the manifest. npm sends the file's own bytes and runs no script for a
file; the registry checks them against their integrity and stores them as they are;
- **present with the same bytes:** accepted as already published, and verified;
- **present with other bytes:** a hard stop. Nothing is deleted or overwritten, nothing after it
is published, and the version is burned ([Immutability](#immutability)).