Commit Graph

7 Commits

Author SHA1 Message Date
ethernet
31a26c5896 feat(release): shared assembly, scoped publication, harness fold (rounds 2 cont.)
Checkpoint remainder: the unstaged half of the reduction work.

- channel_artifacts.py becomes the single native manifest/feed writer;
  release_artifacts.py and channel release paths delegate to it
- r2_scope fork isolation binds namespace before credential access;
  disposable runs refuse unscoped requests
- canary bootstrap verifies canary's own promoted outputs
- retained-link inventory + empty-directory preservation in strict
  migration snapshots; connection-collision resolution and URL-credential
  rejection in retirement connection adoption
- harness controller test relocated to tests/scripts/ (canonical pytest
  name); channel-retirement install-e2e jobs wired
- S/T receiver candidates build with stable update ownership
- test fixture updates across release/source-channel suites
2026-09-14 10:26:48 -04:00
ethernet
b37acb8389 feat(release): dynamic R2-owned channels and preview retirement (rounds 1-2)
Checkpoint before round-3 reduction (two-tier retirement derived from
product identity). Includes:

- R2 channel protocol (release_channels.py, channel-protocol.ts): records,
  builds, manifests, retired channels with pinned destinationHead and
  receiverProtocol; fail-closed readers in both languages
- One shared native manifest/feed writer (scripts/bundles/channel_artifacts.py)
- Scoped/disposable R2 publication, fork isolation before credential
  access, canary bootstrap verification of its own promoted outputs
- Channel source CLI: typed SourceTarget, source-channel resolution,
  retirement downgrade refusal
- Desktop channel resolver/strategy, install-stamp/build-stamp receiver
  ownership (stable-owned S/T candidates), single-flight updater operation
- Cross-package retirement machinery (receiver/host/preservation/
  compatibility/connections/dialog/discovery, backup_migration strict
  snapshots with retained-link inventory, empty-dir preservation,
  connection-collision resolution, URL-credential rejection)
- Native install harness (tests/install/channel-retirement-*) and
  install-e2e retirement jobs
- checkout-source.test.ts transport shim now covers build_opener().open
  (was silently hitting the real network in CI)

Removed secondary certification protocol (channel_qualification.py) per
approved round-2 plan. All focused suites green at checkpoint; native
cross-package journeys unverified (to be deleted in round 3).
2026-09-14 10:26:36 -04:00
ethernet
0b4cd35915 test: consolidate release publication around receipt and HTTP contracts 2026-09-13 15:10:31 -04:00
ethernet
86efc1f945 fix(release): allow explicit environment clears in commit bundles
An inherited HERMES_HOME can defeat a test bundle's data-directory suffix.
Older Windows installers also persisted that variable in the user registry.
This gives the app fresh UI state while its backend reads existing sessions.

Add --bundle-unset NAME, encoded as null in the existing bundle environment
object. Apply each clear as an explicit empty value before module startup.
Do not restore an explicitly empty HERMES_HOME from the Windows registry.
Ordinary defaults still preserve runtime overrides.

Verified the release parser, builder handoff, compiled startup ordering,
registry opt-out, and child environment with focused regression tests.
A native Windows probe passed with an inherited home. No MSIX was rebuilt.
2026-09-11 15:59:08 -04:00
ethernet
7d326adf9d feat(release): bake explicit environment defaults into commit bundles 2026-09-11 14:25:12 -04:00
ethernet
d233b6d7a9 feat(release): publish downloads pages to the release bucket
The builds table only ever existed inside a GitHub release body. Emit the
same rows as a tiny standalone page in R2, so a build is readable straight
from the download origin:

  releases/<channel>/index.html     latest stable / canary builds, every
                                    variant, replaced by each tag run
  releases/commit/<sha>/index.html  every expected binary of one commit
                                    build, built or not

scripts/render-builds-table.py keeps ONE row set per mode and renders it
into two sinks (release body markdown, page HTML), so the page can never
list different artifacts than the release. A channel page is a mutable
pointer written from a per-tag job, so it records its release tag and the
writer compares that against scripts/releases/semver.py before replacing:
re-running an older tag cannot regress a newer channel page.

Pages need two registrations to be usable: `.html` maps to
text/html; charset=utf-8 in release-content-types.json (unregistered, R2
serves the object as an octet-stream download) and to no-store in
r2.cache_control_for (the page is a pointer, not an artifact). Page keys
and public URLs come from new r2 layout helpers, shared with
`release.py --build-commit`, which now prints the commit page URL before
dispatching. No workflow change: the existing renderer jobs already carry
the R2 credentials.

Verified: 76 tests over the renderer/release/transport files, including a
loopback R2 PUT proving the page object lands as text/html with no-store.
2026-09-10 11:15:36 -04:00
ethernet
11c65c4f33 feat(release): dispatch exact-commit builds and bind their stamps
Resolve pushed revisions before dispatching the default-branch workflow.
Reject release-mode flags and untrusted admission contexts. A dry run
never dispatches or creates a tag. Preserve Git's effective push URL
when choosing the GitHub repository.

Commit-build stamps check the actual checkout, including an explicit
Python --commit argument. The workflow SHA cannot replace build identity.
Direct Git argv also avoids the Windows command-shell PATH limit.

Real temporary Git CLI and stamp tests pass: 60 Python tests and 22 JS
tests, with no failures. GitHub authorization and dispatch are intercepted
at their process boundary. Workflow guards and native assembly remain
separate work. No live dispatch, signature, or package acceptance claimed.
2026-09-10 03:45:03 -04:00