Files
nyaterm/scripts/release/GPUI_CUTOVER.md
T

181 lines
11 KiB
Markdown

# GPUI cutover and release readiness
This is the execution record and runbook for the **draft** cutover PR. Version
`2.0.0` in Cargo is a stable-identity candidate, not evidence of publication.
Do not merge main, create `v2.0.0`, or publish channels as part of preparation.
## Frozen sources and history
| Reference | Commit / disposition |
| --- | --- |
| Former main / `archive/tauri-v1` | `18e6f2dafee9a70b4cdb55cad7b32108460ed4f3` |
| GPUI / `migration/gpui` | `25ec4166af2ec53761fcf67406d559a6d7079385` |
| History-only ours merge | `8f76a60ceba9a6c177963aec17754637e4f3bcbe` |
| Candidate C | The full `cutover/gpui` PR head SHA recorded with its CI/rehearsal run |
The ours merge was checked for an identical tree to the GPUI baseline and for
ancestry of both frozen sources. Preparation commits intentionally change that
tree; compare the eventual main tree with **C**, not with the original baseline.
Do not use squash or rebase merging for this PR.
Before merging, fetch both branches again. If either source advanced, review the
new work, reconcile the cutover without force-pushing shared history, and repeat
CI, rehearsal, review and tree checks for the new candidate. Never silently mark
new legacy changes as integrated by adding an unreviewed ours merge.
## Legacy change classification
`git log --no-merges <GPUI>..<old-main>` contains 883 commits. This is a history
difference, not a list of 883 missing GPUI fixes. The application was rewritten;
do not cherry-pick the legacy implementation wholesale.
| Class / examples | Disposition and evidence |
| --- | --- |
| Tauri/WebView and Windows 7 UI (`30f6463fa`, `df6448dc7`) | Legacy platform-specific implementation; GPUI has no WebView and requires Windows 10+. Validate remote-desktop Ctrl+R using GPUI input handling. |
| Version/release (`6af18f59b`) | Superseded by workspace version 2.0.0 and the native package workflow. Preserve updater signature identity and data paths. |
| tmux control mode (`42d45c35c`, `f612a904b`, `34dc74768`) | Legacy protocol behavior; no assumption of equivalent GPUI support. Keep special-key, bracketed-paste and protocol-state cases in the feature-gap review before release. |
| AI command capture/custom instructions (`7d9ce7d24`, `43ab3c2d7`) | Do not claim parity from the presence of an AI feature. Explicit feature-gap review and heredoc command-capture regression remain required before release. |
| Cloud sync (`cbc57fc93`, `898a27a5c`) | GPUI has `features/sync/auto_sync.rs` and core cloud-sync regression tests. Startup/retry, pending local edits and partial merges still require isolated end-to-end validation. |
| Terminal echo/history and external MCP approvals (`69c9e89d3`, `327c59bea`) | GPUI owns different state and input paths. Keep wrapped history and repeated approval cases in the release regression matrix. |
| Other old UI, translations, documentation and domain work | Retain archive for comparison; the classification above is a preparation review, not a claim of exhaustive behavioral equivalence. Remaining feature-gap review is a release gate. |
No pending PR is included in the frozen candidate:
| PR | Existing base | Follow-up |
| --- | --- | --- |
| #991 WSL UNC working directories | migration/gpui | Re-evaluate/rebase for GPUI main after cutover |
| #974 VS16 emoji width | migration/gpui | Re-evaluate/rebase; retain terminal rendering regression |
| #972 SQL prompts / highlighting / save errors | migration/gpui | Re-evaluate/rebase by concern |
| #990 MCP notification audit | main | Port relevant behavior to GPUI, not Tauri source files |
| #854 NyaScript | main | Separate GPUI feature proposal |
| #853 Windows Mosh | main | Separate GPUI feature proposal |
| #718 terminal glyph painting | main | Compare with GPUI terminal renderer before porting |
Leave these PRs open and unchanged during preparation.
## Reproducible signed rehearsal
Run from PowerShell after committing and pushing C. Dispatch the workflow on the
same candidate branch, with the actual full checkout SHA as `source_ref`:
```powershell
$candidateSha = git rev-parse HEAD
gh workflow run release.yml --repo nyakang/nyaterm --ref cutover/gpui -f version=2.0.0 -f source_ref=$candidateSha -f upload_release=false -f verify_release=true
```
`verify_release=false` remains the default build-only behavior. Verification
uses the existing updater signing secret and public key, but no GitHub release,
tag, R2 object or downstream package is written. The existing downstream
workflows only publish after `Publish Cloudflare R2 mirror` succeeds; that job
must be skipped in a rehearsal. Before cutover the old main workflows listen to
`Build and Release`, not this `Release` workflow.
`release-candidate` retains `dist-release/`, `provenance/`, and
`release-notes.md` for 30 days. The six per-target provenance records bind actual
checkout SHA, Cargo version, producing run ID and package SHA-256 values. The
candidate contains 14 package files plus checksums and manifests. Signing is
verified with minisign before `.sig` sidecars are removed; signatures remain in
`latest.json`. Keep the full artifact and its run link in the PR evidence.
An optional `source_run_id` must identify a successful completed run of this
repository's Release workflow. It is accepted only for verification or
publication. Source SHA and version must match the requested checkout, all six
records must exist, and every package hash must match. The run's `head_sha` is
not used as a substitute for the actual checkout SHA. Old runs without these
records must be rebuilt. A later merge commit has a different SHA: build and
validate that final source again rather than reusing C's packages under it.
The rehearsal validates manifest structure, package hashes and signatures
offline. Its canonical release URLs are not expected to exist yet. Network
asset probes and downstream distribution remain post-publication checks.
## Validation evidence and outstanding acceptance
Record command, OS/architecture, full source SHA, run URL, artifact hashes,
result and any limitation in the PR. Re-run checks after candidate changes.
Required automated checks:
```powershell
cargo check --workspace --locked
cargo test --workspace --locked --no-fail-fast
cargo fmt --all -- --check
cargo clippy --workspace --all-targets --locked -- -D warnings
python -m unittest scripts.tests.test_check_release_assets scripts.tests.test_prepare_conpty scripts.tests.test_package_native scripts.tests.test_verify_native_package scripts.tests.test_generate_release_metadata scripts.tests.test_bump_version scripts.tests.test_release_provenance scripts.tests.test_release_workflow scripts.tests.test_verify_updater_signatures
python scripts/ci/check_docs_translations.py
pnpm --dir docs-site install --frozen-lockfile
pnpm --dir docs-site build
```
Run actionlint 1.7.7 as well. Signature integration tests require minisign;
the signed rehearsal installs it and runs them without skipping. The former
baseline Rust run `40272634203` failed fetching vnc-rs over SSL and is not a pass.
| Acceptance scenario | Required evidence / current disposition |
| --- | --- |
| Windows x64/ARM64 NSIS upgrade from 1.3.1 | Isolated OS installation, data/key preservation, shortcuts/uninstaller; pending real-machine validation |
| Windows old MSI → NSIS | Backup, uninstall without data removal, same-architecture install, no duplicate entries; pending |
| Windows portable manual overwrite | Full payload including RDP/VNC/MCP/ConPTY, preserved data and keys, helper launch; pending |
| macOS Intel/Apple Silicon | Same-identity bundle replacement and Homebrew path; pending |
| Linux x64/ARM64 | AppImage replacement and deb/rpm package-manager upgrades; pending |
| Legacy data and backups | With/without master password, wrong password, corrupt backup, credentials, known hosts, OTP, unknown-field retention, old `.nya`, restart persistence and full-copy restoration; pending end-to-end fixtures |
| Cloud sync | Dedicated remote namespace, no production credentials; startup/retry/merge and restored backups; pending |
| Sessions/input | SSH/SFTP, local shell, IME, RDP/VNC startup and disconnect; pending interactive validation |
Use synthetic or explicitly supplied sanitized 1.3.1 data in isolated accounts
or VMs. Do not install over the operator's application or open their real data
for acceptance. Cross-compilation and unit tests do not satisfy these rows.
Missing machines or fixtures remain visible blockers for stable publication,
not blockers to creating the draft cutover PR.
## Merge and publication gates (outside preparation)
1. Complete outstanding migration, feature-gap and platform acceptance. Freeze
both source branches for the merge window. Record the exact reviewed C.
2. Require one approval and successful `Rust gate` / `Docs gate` for C. Configure
those two required checks before merge; do not weaken the existing ruleset.
3. Merge with a Merge Commit, fetch main, then verify in PowerShell:
```powershell
git diff --exit-code $candidateSha origin/main
git merge-base --is-ancestor 18e6f2dafee9a70b4cdb55cad7b32108460ed4f3 origin/main
git merge-base --is-ancestor 25ec4166af2ec53761fcf67406d559a6d7079385 origin/main
```
Every command must exit zero. Verify the main CI and signed rehearsal again
for its final SHA; do not publish a tag against a different tree.
4. Save the current root `latest.json` and `downloads.json` from the R2 bucket,
their public responses and SHA-256 values, current GitHub Latest tag,
Homebrew/AUR revisions and Gitee release state in a dated operator backup.
Record object existence at the R2 origin as well: a public 404 alone does not
prove the object is absent. At preparation time the public `latest.json` was
1.3.1, while root `downloads.json` returned 404. If an origin object is absent,
record that fact rather than inventing a backup. Keep URLs/configuration only
in the record, never credentials.
5. Only after all gates pass, create the matching formal tag on final main.
Tag push automatically starts public publishing; it is not a dry run.
6. Verify GitHub Latest, all signed update/download URLs, public manifests,
website downloads, Homebrew, AUR and Gitee. Do not call downstream workflows
during preparation. Keep archive and migration branches through stabilization.
## Stop distribution and recover
Stop/cancel the affected Release and downstream publishing runs first so that
they cannot reapply the faulty channel. Preserve the failed run and evidence.
Restore **both** root R2 manifests from the saved pre-release copies, with JSON
content type and `public, max-age=60, must-revalidate`. If an origin manifest
was absent before publication, remove only that newly created root manifest to
restore its recorded absence; do not delete versioned assets. Verify origin bytes and
public responses, allowing for cache expiration or explicitly purge those URLs.
Recheck the website's download redirects and manifest-driven links.
Restore the prior GitHub release as Latest; mark the bad release as prerelease
or withdraw it as appropriate. Handle Gitee and package-manager updates
separately: restore the recorded downstream metadata or ship a forward fix,
and verify their actual public state. Hiding a GitHub release does not restore
R2 manifests or roll back already installed packages.
Do not overwrite immutable versioned artifacts with different bytes. Prefer
`2.0.1` for a correction. Users recover from their complete pre-migration copy;
never instruct 1.x to open data that 2.0 has already modified.