Files
tty7/.github/scripts/bundle-windows.ps1
T
l0ng-ai 208454e202 feat(remote): remote workspaces — a window that is one machine
Split the framework-free half of tty7 into `tty7-core` and add a headless
`tty7-server` built on it, so a workspace's filesystem, git and session state
can live on another machine while the GUI stays where it is.

- `crates/tty7-core`: wire protocol, session daemon, PTY, native SSH engine and
  the domain model, with no gpui dependency. Module paths are unchanged.
- `crates/tty7-server`: the same daemon with no GUI attached, linked fully
  static against musl and pushed onto the remote box. One dependency, on
  purpose — a second one the GUI also needs belongs in core.
- `Host` trait + `HostId`/`HostRegistry`: every fs/git/watch call a workspace
  makes goes through the machine it belongs to. `LocalHost` answers on this
  box, `RemoteHost` over a routed control connection.
- `ui::host_ops`: the GUI's single door to a `Host`. Host calls block, so all
  of them run on the background executor with the result landed on the UI
  thread; de-duplication, staleness and error reporting live here rather than
  at each call site. Enforced by a CI grep.
- Connect flow: home page → pick a configured SSH host → the machine's own
  workspace list → a window bound to one workspace on it. Workspace switcher
  groups by machine, this computer included.
- CI: static musl builds of `tty7-server` for x86_64/aarch64 via
  cargo-zigbuild, a host-boundary grep, and version stamping factored out of
  the nightly workflow. Both new jobs are non-required so branch protection
  does not wedge open PRs.

Design and the interface contract it was built to are in
`docs/2026-07-27-remote-workspace-{design,impl-contract}.md`.
2026-07-28 10:59:46 +08:00

63 lines
2.9 KiB
PowerShell

# Usage: bundle-windows.ps1 <target-triple> <arch-label>
# Package the release binary twice from one staged payload:
# dist/tty7-<version>-windows-<arch>.zip portable (unzip anywhere)
# dist/tty7-<version>-windows-<arch>-setup.exe Inno Setup installer
# (Program Files or per-user, Start Menu shortcut, "Apps" uninstall entry)
#
# Fonts are embedded via include_bytes! and the app icon is compiled into the
# executable as a resource (see build.rs). So the payload is tty7.exe plus a
# sibling completions\ dir (loaded at runtime — see terminal::signature) and the
# license/readme. Both artifacts are unsigned builds — SmartScreen will
# warn on first launch.
$ErrorActionPreference = 'Stop'
$Target = $args[0]
$Arch = $args[1]
$Version = (Select-String -Path Cargo.toml -Pattern '^version\s*=\s*"([^"]+)"').Matches[0].Groups[1].Value
$Name = "tty7-$Version-windows-$Arch"
$Stage = "dist/$Name"
Remove-Item -Recurse -Force dist -ErrorAction SilentlyContinue
New-Item -ItemType Directory -Force -Path $Stage | Out-Null
Copy-Item "target/$Target/release/tty7.exe" "$Stage/tty7.exe"
New-Item -ItemType Directory -Force -Path "$Stage/completions" | Out-Null
Copy-Item "assets/completions/*.json" "$Stage/completions/"
Copy-Item LICENSE "$Stage/LICENSE.txt"
Copy-Item README.md "$Stage/README.md"
# The Linux musl `tty7-server`, staged at server/ so a WSL distro can be handed
# the binary this client shipped with (design §12: WSL downloads nothing). The
# lookup path is a contract with `daemon::install::wsl` — it searches
# <dir of tty7.exe>/server/<asset> first — so this directory name is not free to
# change on its own. Missing is a warning, not an error, matching `server-musl`'s
# own skip-don't-fail probe; WSL then fails at connect time with a message
# naming the directories it searched.
$ServerAsset = "tty7-server-x86_64-unknown-linux-musl"
$ServerSrc = "bundled-server/$ServerAsset"
if (Test-Path $ServerSrc) {
New-Item -ItemType Directory -Force -Path "$Stage/server" | Out-Null
Copy-Item $ServerSrc "$Stage/server/$ServerAsset"
Write-Host "OK bundled $ServerAsset"
} else {
Write-Warning "no $ServerAsset to bundle - this build cannot serve WSL distros"
}
Compress-Archive -Path "$Stage/*" -DestinationPath "dist/$Name.zip" -Force
# Installer, built from the same staged payload. ISCC is on PATH on GitHub's
# windows-latest image; fall back to the default install location.
$Iscc = (Get-Command ISCC.exe -ErrorAction SilentlyContinue).Source
if (-not $Iscc) { $Iscc = "${env:ProgramFiles(x86)}\Inno Setup 6\ISCC.exe" }
& $Iscc `
"/DAppVersion=$Version" `
"/DStageDir=$((Resolve-Path $Stage).Path)" `
"/DOutputDir=$((Resolve-Path dist).Path)" `
"/DOutputName=$Name-setup" `
.github/scripts/windows-installer.iss
if ($LASTEXITCODE -ne 0) { throw "ISCC exited with $LASTEXITCODE" }
Remove-Item -Recurse -Force $Stage
Write-Host "OK dist/$Name.zip"
Write-Host "OK dist/$Name-setup.exe"