From d0cf53522f87c349e75cc51930562ab32cf0385a Mon Sep 17 00:00:00 2001 From: l0ng-ai <24760907+l0ng-ai@users.noreply.github.com> Date: Tue, 7 Jul 2026 16:14:44 +0800 Subject: [PATCH] feat(release): ship a Windows Inno Setup installer alongside the portable zip bundle-windows.ps1 now compiles windows-installer.iss (ISCC is preinstalled on windows-latest) from the same staged payload as the zip, producing tty7--windows-x86_64-setup.exe: per-user install by default with an all-users option, Start Menu shortcut, Apps uninstall entry, optional desktop icon. Release workflow uploads the new artifact; READMEs and CHANGELOG updated. --- .github/scripts/bundle-windows.ps1 | 24 +++++++++-- .github/scripts/windows-installer.iss | 59 +++++++++++++++++++++++++++ .github/workflows/release.yml | 11 ++--- CHANGELOG.md | 11 +++++ README.md | 4 +- README.zh-CN.md | 3 +- 6 files changed, 101 insertions(+), 11 deletions(-) create mode 100644 .github/scripts/windows-installer.iss diff --git a/.github/scripts/bundle-windows.ps1 b/.github/scripts/bundle-windows.ps1 index 743fe81e..91ad133a 100644 --- a/.github/scripts/bundle-windows.ps1 +++ b/.github/scripts/bundle-windows.ps1 @@ -1,11 +1,13 @@ # Usage: bundle-windows.ps1 -# Package the release binary into a zip: -# dist/tty7--windows-.zip +# Package the release binary twice from one staged payload: +# dist/tty7--windows-.zip portable (unzip anywhere) +# dist/tty7--windows--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 archive is tty7.exe plus a +# 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. This is an unsigned build — SmartScreen will +# license/readme. Both artifacts are unsigned builds — SmartScreen will # warn on first launch. $ErrorActionPreference = 'Stop' @@ -25,5 +27,19 @@ Copy-Item LICENSE "$Stage/LICENSE.txt" Copy-Item README.md "$Stage/README.md" 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" diff --git a/.github/scripts/windows-installer.iss b/.github/scripts/windows-installer.iss new file mode 100644 index 00000000..18e505cd --- /dev/null +++ b/.github/scripts/windows-installer.iss @@ -0,0 +1,59 @@ +; tty7 Windows installer (Inno Setup 6 — preinstalled on GitHub's +; windows-latest runners). Compiled by bundle-windows.ps1, which stages the +; payload and passes every path in via /D defines: +; +; /DAppVersion= version parsed from Cargo.toml +; /DStageDir= staged payload (tty7.exe, completions\, LICENSE.txt, README.md) +; /DOutputDir= where the setup exe is written +; /DOutputName= setup exe filename, without ".exe" +; +; Defaults to a per-user install ({localappdata}\Programs\tty7 — no UAC +; prompt), with an "install for all users" escape hatch in the dialog. The +; build is unsigned, so SmartScreen warns on first launch either way — same as +; the portable zip. + +#ifndef AppVersion + #error Missing /DAppVersion — this script is meant to be compiled via bundle-windows.ps1 +#endif + +[Setup] +; Never change AppId: it is how Windows ties upgrades + the uninstall entry +; to previous installs of tty7. +AppId={{9A3F6C1E-4B7D-4E2A-8C5F-D01B92E64A37} +AppName=tty7 +AppVersion={#AppVersion} +AppPublisher=tty7 contributors +AppPublisherURL=https://github.com/l0ng-ai/tty7 +AppSupportURL=https://github.com/l0ng-ai/tty7/issues +AppUpdatesURL=https://github.com/l0ng-ai/tty7/releases +DefaultDirName={autopf}\tty7 +DisableProgramGroupPage=yes +PrivilegesRequired=lowest +PrivilegesRequiredOverridesAllowed=dialog +ArchitecturesAllowed=x64compatible +ArchitecturesInstallIn64BitMode=x64compatible +MinVersion=10.0 +LicenseFile={#StageDir}\LICENSE.txt +SetupIconFile=..\..\assets\favicon.ico +UninstallDisplayIcon={app}\tty7.exe +OutputDir={#OutputDir} +OutputBaseFilename={#OutputName} +Compression=lzma2 +SolidCompression=yes +WizardStyle=modern + +[Tasks] +Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked + +[Files] +Source: "{#StageDir}\tty7.exe"; DestDir: "{app}"; Flags: ignoreversion +Source: "{#StageDir}\completions\*"; DestDir: "{app}\completions"; Flags: ignoreversion recursesubdirs +Source: "{#StageDir}\LICENSE.txt"; DestDir: "{app}"; Flags: ignoreversion +Source: "{#StageDir}\README.md"; DestDir: "{app}"; Flags: ignoreversion + +[Icons] +Name: "{autoprograms}\tty7"; Filename: "{app}\tty7.exe" +Name: "{autodesktop}\tty7"; Filename: "{app}\tty7.exe"; Tasks: desktopicon + +[Run] +Filename: "{app}\tty7.exe"; Description: "{cm:LaunchProgram,tty7}"; Flags: nowait postinstall skipifsilent diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2f1f56ad..40e71101 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -65,10 +65,10 @@ jobs: run: cargo build --release --target ${{ matrix.target }} # ---- Packaging: one step per OS ---------------------------------------- - # macOS gets a signed + notarized drag-to-Applications DMG. Windows and - # Linux are unsigned archives of the self-contained binary - # (fonts are embedded via include_bytes!; the Windows icon is compiled in - # via build.rs). + # macOS gets a signed + notarized drag-to-Applications DMG. Windows gets + # an Inno Setup installer plus a portable zip; Linux a tarball — both + # unsigned, of the self-contained binary (fonts are embedded via + # include_bytes!; the Windows icon is compiled in via build.rs). - name: Bundle macOS DMG if: matrix.os == 'macos' working-directory: tty7 @@ -89,7 +89,7 @@ jobs: working-directory: tty7 run: bash .github/scripts/bundle-linux.sh "${{ matrix.target }}" "${{ matrix.arch }}" - - name: Package Windows zip + - name: Package Windows installer + zip if: matrix.os == 'windows' working-directory: tty7 shell: pwsh @@ -103,3 +103,4 @@ jobs: tty7/dist/*.dmg tty7/dist/*.tar.gz tty7/dist/*.zip + tty7/dist/*-setup.exe diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c6562e8..7e0c55b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Windows releases now ship an Inno Setup installer + (`tty7--windows-x86_64-setup.exe`) alongside the portable zip. It + installs per-user by default (no admin prompt, with an all-users option), + adds a Start Menu shortcut and an "Apps" uninstall entry, and offers an + optional desktop icon. Still unsigned, so SmartScreen warns on first launch. - Startup update check: tty7 asks GitHub once, in the background, whether a newer release has shipped. If so, it pops a one-time "Update available" dialog (once per version — remembered in `update.json`, so it never nags twice for @@ -32,6 +37,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 default), making room for fullscreen on the bare chord. An existing `ToggleMaximizePane` override in `keybindings` still wins. +### Fixed + +- Windows: launching tty7 no longer opens a stray console window behind the + app. Release builds are now linked with the `windows` subsystem; debug + builds keep the console so `println!` output stays visible. (#10) + ## [0.3.0] - 2026-07-07 ### Added diff --git a/README.md b/README.md index fd58afb3..24848c59 100644 --- a/README.md +++ b/README.md @@ -93,7 +93,9 @@ Grab the build for your platform from [**Releases**](https://github.com/l0ng-ai/ - **macOS** — `tty7--macos-arm64.dmg` (Apple Silicon) or `…-x86_64.dmg` (Intel); open it and drag `tty7.app` into Applications. -- **Windows** — `…-windows-x86_64.zip`; unzip and run `tty7.exe`. +- **Windows** — `…-windows-x86_64-setup.exe` (installer: Start Menu shortcut + + uninstall entry), or `…-windows-x86_64.zip` (portable: unzip and run + `tty7.exe`). - **Linux** — `…-linux-x86_64.tar.gz`; extract and run `./tty7` (needs the usual x11/wayland runtime libraries). diff --git a/README.zh-CN.md b/README.zh-CN.md index 935f74d5..68e74fc4 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -84,7 +84,8 @@ tty7 以设备速度读取 PTY,并在渲染路径之外成批解析输出, - **macOS** —— `tty7--macos-arm64.dmg`(Apple Silicon)或 `…-x86_64.dmg` (Intel);打开后把 `tty7.app` 拖进「应用程序」即可。 -- **Windows** —— `…-windows-x86_64.zip`;解压后运行 `tty7.exe`。 +- **Windows** —— `…-windows-x86_64-setup.exe`(安装包:带开始菜单快捷方式和 + 卸载入口),或 `…-windows-x86_64.zip`(便携版:解压后运行 `tty7.exe`)。 - **Linux** —— `…-linux-x86_64.tar.gz`;解压后运行 `./tty7`(需要常见的 x11/wayland 运行时库)。