Commit Graph

4 Commits

Author SHA1 Message Date
ethernet
627196d746 fix(release): link incomplete build rows to their workflow run 2026-09-11 20:05:11 -04:00
ethernet
c4e2d937f7 fix(desktop): isolate canary and commit package identities
Canary and commit builds must not replace stable or share its desktop
state. Package names alone are insufficient because Electron reads the
product name before main initializes its paths. Pin nonstable userData
before the first lookup, and keep the packaged identity independent of
runtime build variables.

Keep release artifact filenames unchanged. Qualify payload CLI names,
route each nonstable MSIX alias to its own entrypoint, and copy the
immutable desktop provenance into the embedded Python checkout. Only
stable releases can use the official Store identity.

Targeted validation: 75 JavaScript tests passed, 2 platform skips;
15 Python tests passed with file retries disabled. Native Windows SDK
manifest proof is tracked separately. Full app install, signing and macOS
launch validation are not claimed.
2026-09-11 19:59:38 -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
1c4093fdc9 feat(release): stage commit builds with verified receipts
Commit builds use their own immutable namespace and the shared signed
transport. Publish each receipt after its files, and fetch shared files
once only when their receipt records agree.

Summary links retain the full object key. A completed row requires its
own validated receipt and listed object. Missing, corrupt and ambiguous
results remain distinct. Include both universal Windows bundles.

Verified: 85 tests passed across transfer, rendering, candidate and
promotion paths. The subprocess test fetches the rendered download URL
from loopback HTTP. Ruff and added-comment checks passed.

No live R2 writes, workflow dispatch or native package build ran.
The commit-build CLI and workflow changes remain separate drafts.
2026-09-09 21:29:34 -04:00