desktop: cross-compiled Windows NSIS installer lane (task 2015)
Adds a `windows` job to desktop.yml on the new ci-tauri-win image, producing a Windows -setup.exe without any Windows hardware. A Windows container can't run on a Linux host, so cross-compilation is the only route: --runner cargo-xwin supplies the MSVC CRT/SDK (pre-warmed into the image) and links with lld-link, and makensis builds the installer. NSIS only. .msi needs WiX v3, a Windows program — per Tauri, ".msi installers can only be created on Windows". It comes back if a Windows node ever exists. Kept as a separate job so a Windows-side failure can never block the Linux artifacts, which are the primary product today. publish-release.sh now globs the windows target root too; nullglob means each job uploads only what its own workspace contains, and the release is created once and reused via the 409 path, so both jobs can publish to the same release safely. No app code changes were needed. The AppImage self-integration UI already gates on is_appimage (AccountView.vue:131, DesktopIntegrationPrompt.vue:22), and $APPIMAGE is never set on Windows, so the OOBE prompt and Settings toggle hide themselves. Recorded plainly in ci-requirements.md that this is the weakest-verified lane we have: Tauri calls Linux->Windows cross-compilation "not tested as much" and a last resort, and a Linux runner cannot execute a Windows binary. Green means it built. A real Windows machine check is mandatory before trusting a release, and installers are unsigned until a certificate exists. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SreJkbxB4gx8pPsu8QbLPi
This commit is contained in:
@@ -126,3 +126,60 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ github.token }}
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
run: bash desktop/packaging/publish-release.sh
|
run: bash desktop/packaging/publish-release.sh
|
||||||
|
|
||||||
|
# Windows installer, CROSS-COMPILED from Linux — there is no Windows build host.
|
||||||
|
# A Windows container can't run on a Linux host (containers share the host
|
||||||
|
# kernel), so cross-compiling is the only route without Windows hardware:
|
||||||
|
# cargo-xwin + LLVM's lld-link + makensis are Linux programs that emit Windows
|
||||||
|
# PE output. That toolchain is why this needs its own image rather than ci-tauri.
|
||||||
|
#
|
||||||
|
# NSIS only. `.msi` needs WiX v3, which is a Windows program — Tauri: ".msi
|
||||||
|
# installers can only be created on Windows". It returns if a Windows node does.
|
||||||
|
#
|
||||||
|
# A separate job, so a Windows-side failure never blocks the Linux artifacts that
|
||||||
|
# are the primary product today. Tauri calls this path "not tested as much" and a
|
||||||
|
# last resort, and nothing here can LAUNCH a Windows binary — green means it
|
||||||
|
# built, not that it runs. A real-machine check stays mandatory before trusting it.
|
||||||
|
windows:
|
||||||
|
name: Windows installer (cross-compiled)
|
||||||
|
if: github.ref == 'refs/heads/dev' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')
|
||||||
|
runs-on: python-ci
|
||||||
|
container:
|
||||||
|
image: git.fabledsword.com/bvandeusen/ci-tauri-win:1.97
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
|
# Same reason as the Linux job: generate_context! embeds the built frontend
|
||||||
|
# at compile time, so it must exist before cargo runs.
|
||||||
|
- name: Build the shared frontend
|
||||||
|
run: npm ci && npm run build
|
||||||
|
working-directory: frontend
|
||||||
|
|
||||||
|
# --runner cargo-xwin swaps cargo for the cross-compiling driver (it supplies
|
||||||
|
# the MSVC CRT/SDK, pre-warmed into the image, and links with lld-link).
|
||||||
|
# Frontend already built above; skip the beforeBuildCommand rebuild.
|
||||||
|
- name: Tauri build (NSIS installer)
|
||||||
|
run: |
|
||||||
|
cargo tauri build \
|
||||||
|
--runner cargo-xwin \
|
||||||
|
--target x86_64-pc-windows-msvc \
|
||||||
|
--bundles nsis \
|
||||||
|
--config '{"build":{"beforeBuildCommand":""}}'
|
||||||
|
working-directory: desktop/src-tauri
|
||||||
|
|
||||||
|
- name: Upload installer
|
||||||
|
continue-on-error: true
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: thoughtsync-windows
|
||||||
|
path: desktop/src-tauri/target/x86_64-pc-windows-msvc/release/bundle/nsis/*.exe
|
||||||
|
if-no-files-found: warn
|
||||||
|
|
||||||
|
# Publishes to the SAME release as the Linux job. Safe to run twice: the
|
||||||
|
# script reuses an existing release (409) and nullglob means each job uploads
|
||||||
|
# only the bundles present in its own workspace.
|
||||||
|
- name: Publish release
|
||||||
|
if: startsWith(github.ref, 'refs/tags/v')
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
|
run: bash desktop/packaging/publish-release.sh
|
||||||
|
|||||||
@@ -82,5 +82,29 @@ backend/frontend push.
|
|||||||
`pacman -U`-tested here. That step logs `.PKGINFO` + the full file listing so
|
`pacman -U`-tested here. That step logs `.PKGINFO` + the full file listing so
|
||||||
the package is auditable from the run log; a real Arch install is the operator's
|
the package is auditable from the run log; a real Arch install is the operator's
|
||||||
confirm.
|
confirm.
|
||||||
|
|
||||||
|
### Windows lane — second job, second image
|
||||||
|
|
||||||
|
`desktop.yml` also runs a `windows` job that cross-compiles the NSIS installer.
|
||||||
|
|
||||||
|
- **Image:** `git.fabledsword.com/bvandeusen/ci-tauri-win:1.97` (Rust + Node +
|
||||||
|
`cargo-xwin` + LLVM/`lld` + NSIS). A separate image from `ci-tauri` per
|
||||||
|
CI-Runner's `docs/process.md` fork rule — the MSVC CRT/SDK cache alone is >1 GB.
|
||||||
|
Its pins are held in lockstep with `ci-tauri`; bump them together, since both
|
||||||
|
lanes compile the same source.
|
||||||
|
- **Why cross-compile:** there is no Windows build host, and a Windows container
|
||||||
|
cannot run on a Linux host (containers share the host kernel). `cargo-xwin`,
|
||||||
|
`lld-link` and `makensis` are Linux programs that emit Windows PE output.
|
||||||
|
- **NSIS only.** `.msi` requires WiX v3, a Windows program — per Tauri, "`.msi`
|
||||||
|
installers can only be created on Windows."
|
||||||
|
- **Separate job on purpose:** a Windows failure must not block the Linux
|
||||||
|
artifacts, which are the primary product today.
|
||||||
|
- **Weakest verification of any lane.** Tauri documents this path as "not as
|
||||||
|
straight forward as compiling on Windows directly and is not tested as much",
|
||||||
|
to be used "only as a last resort" — and a Linux runner cannot execute a
|
||||||
|
Windows binary. Green means it *built*. A real Windows machine check is
|
||||||
|
mandatory before trusting a release.
|
||||||
|
- **Unsigned.** Installers will trip SmartScreen until a code-signing
|
||||||
|
certificate exists; that is a purchasing decision, not a CI one.
|
||||||
- No Postgres lane (unchanged): the desktop app's local store + sync behavior is
|
- No Postgres lane (unchanged): the desktop app's local store + sync behavior is
|
||||||
verified on the operator's machine, not in CI.
|
verified on the operator's machine, not in CI.
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
# desktop/src-tauri/target/release/bundle/appimage/*.AppImage (de-bundled)
|
# desktop/src-tauri/target/release/bundle/appimage/*.AppImage (de-bundled)
|
||||||
# desktop/src-tauri/target/release/bundle/deb/*.deb
|
# desktop/src-tauri/target/release/bundle/deb/*.deb
|
||||||
# desktop/src-tauri/target/release/bundle/arch/*.pkg.tar.* (prebuilt pacman)
|
# desktop/src-tauri/target/release/bundle/arch/*.pkg.tar.* (prebuilt pacman)
|
||||||
|
# desktop/src-tauri/target/x86_64-pc-windows-msvc/release/bundle/nsis/*.exe
|
||||||
#
|
#
|
||||||
# Instance-agnostic: server + repo come from the runner's github.* context
|
# Instance-agnostic: server + repo come from the runner's github.* context
|
||||||
# (Forgejo populates them for compatibility), so nothing is hardcoded to one host.
|
# (Forgejo populates them for compatibility), so nothing is hardcoded to one host.
|
||||||
@@ -37,13 +38,20 @@ AUTH=(-H "Authorization: token $GITHUB_TOKEN")
|
|||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||||
BUNDLE_ROOT="$REPO_ROOT/desktop/src-tauri/target/release/bundle"
|
BUNDLE_ROOT="$REPO_ROOT/desktop/src-tauri/target/release/bundle"
|
||||||
|
# Cross-compiled Windows output lands under the target triple, not the host root.
|
||||||
|
WIN_BUNDLE_ROOT="$REPO_ROOT/desktop/src-tauri/target/x86_64-pc-windows-msvc/release/bundle"
|
||||||
|
|
||||||
# --- collect the assets to upload -------------------------------------------
|
# --- collect the assets to upload -------------------------------------------
|
||||||
shopt -s nullglob
|
shopt -s nullglob
|
||||||
|
# nullglob (set above) drops the patterns that didn't match, which is what lets the
|
||||||
|
# Linux job and the Windows job each run this script against the SAME release and
|
||||||
|
# upload only what they actually built — they run in separate workspaces, so neither
|
||||||
|
# can see the other's bundles. The release is created once and reused (409 path).
|
||||||
ASSETS=(
|
ASSETS=(
|
||||||
"$BUNDLE_ROOT"/appimage/*.AppImage
|
"$BUNDLE_ROOT"/appimage/*.AppImage
|
||||||
"$BUNDLE_ROOT"/deb/*.deb
|
"$BUNDLE_ROOT"/deb/*.deb
|
||||||
"$BUNDLE_ROOT"/arch/*.pkg.tar.*
|
"$BUNDLE_ROOT"/arch/*.pkg.tar.*
|
||||||
|
"$WIN_BUNDLE_ROOT"/nsis/*.exe
|
||||||
)
|
)
|
||||||
if [ ${#ASSETS[@]} -eq 0 ]; then
|
if [ ${#ASSETS[@]} -eq 0 ]; then
|
||||||
echo "ERROR: no bundles under $BUNDLE_ROOT — did the tauri build run?" >&2
|
echo "ERROR: no bundles under $BUNDLE_ROOT — did the tauri build run?" >&2
|
||||||
|
|||||||
Reference in New Issue
Block a user