--- name: Build Windows on: workflow_dispatch: push: branches: [fix/windows] permissions: contents: read concurrency: group: build-windows-${{ github.ref }} cancel-in-progress: true jobs: build-windows: name: 'Desktop: Windows x64' runs-on: windows-latest env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - name: Checkout uses: actions/checkout@v5 with: fetch-depth: 1 submodules: recursive - name: Setup Node.js 24.x uses: actions/setup-node@v5 with: node-version: 24.x package-manager-cache: false - name: Install Rust (1.93.0) uses: dtolnay/rust-toolchain@1.93.0 with: targets: x86_64-pc-windows-msvc # Skip first 7 lines of Cargo.lock (workspace package version bumps) so the key tracks dependency changes only - name: Cargo.lock fingerprint (deps only) id: cargo-lock-fingerprint shell: bash run: | echo "hash=$(tail -n +8 Cargo.lock | openssl dgst -sha256 | awk '{print $2}')" >> "$GITHUB_OUTPUT" - name: Cache Cargo registry and git sources uses: actions/cache@v5 with: path: | ~/.cargo/registry ~/.cargo/git key: Windows-cargo-registry-${{ steps.cargo-lock-fingerprint.outputs.hash }} restore-keys: | Windows-cargo-registry- # CEF runtime auto-downloads via cef-dll-sys / vendored tauri-cli. Cache # it so we don't re-fetch ~400MB every run. - name: Cache CEF binary distribution uses: actions/cache@v5 with: path: ~/AppData/Local/tauri-cef key: cef-windows-${{ hashFiles('app/src-tauri/Cargo.toml') }} restore-keys: | cef-windows- - name: Cache vendored tauri-cli binary id: tauri-cli-cache uses: actions/cache@v5 with: path: ~/.cargo/bin/cargo-tauri.exe key: vendored-tauri-cli-windows-${{ hashFiles('app/src-tauri/vendor/tauri-cef/crates/tauri-cli/Cargo.toml') }} - name: Install vendored tauri-cli (cef-aware bundler) if: steps.tauri-cli-cache.outputs.cache-hit != 'true' shell: bash run: cargo install --locked --path app/src-tauri/vendor/tauri-cef/crates/tauri-cli - name: Install dependencies run: yarn install --frozen-lockfile # vite build runs via tauri.conf.json's beforeBuildCommand during the # "Build Tauri app" step below — no separate frontend build needed. # Core is linked into the Tauri binary as a path dep — no separate # sidecar build / stage / path-resolution step needed. - name: Define Tauri configuration overrides id: config-overrides # `prepareTauriConfig.js` only emits the Windows DigiCert sign # command at this point (`WITH_UPDATER` defaults to off here so # this PR-build matrix doesn't try to mint signed updater # artifacts it has no key for). uses: actions/github-script@v8 with: script: | const workspacePath = process.env.GITHUB_WORKSPACE.replace(/\\/g, '/'); const prefix = workspacePath.startsWith('/') ? 'file://' : 'file:///'; const moduleUrl = `${prefix}${workspacePath}/scripts/prepareTauriConfig.js`; const { default: prepareTauriConfig } = await import(moduleUrl); const config = prepareTauriConfig(); core.setOutput('json', JSON.stringify(config)); - name: Build Tauri app (CEF default, vendored CLI) id: tauri-build shell: bash working-directory: app env: BASE_URL: ${{ vars.BASE_URL }} VITE_BACKEND_URL: ${{ vars.BASE_URL }} VITE_SENTRY_DSN: ${{ vars.VITE_SENTRY_DSN }} VITE_DEBUG: ${{ vars.VITE_DEBUG }} VITE_MINIMUM_SUPPORTED_APP_VERSION: ${{ vars.VITE_MINIMUM_SUPPORTED_APP_VERSION }} VITE_LATEST_APP_DOWNLOAD_URL: ${{ vars.VITE_LATEST_APP_DOWNLOAD_URL }} TAURI_CONFIG_OVERRIDE: ${{ steps.config-overrides.outputs.json }} run: | NODE_OPTIONS="--max-old-space-size=8192" cargo tauri build -c "$TAURI_CONFIG_OVERRIDE" --target x86_64-pc-windows-msvc - name: Upload MSI artifact uses: actions/upload-artifact@v5 with: name: windows-msi path: | app/src-tauri/target/x86_64-pc-windows-msvc/release/bundle/msi/*.msi target/x86_64-pc-windows-msvc/release/bundle/msi/*.msi - name: Upload NSIS artifact uses: actions/upload-artifact@v5 with: name: windows-nsis path: | app/src-tauri/target/x86_64-pc-windows-msvc/release/bundle/nsis/*.exe target/x86_64-pc-windows-msvc/release/bundle/nsis/*.exe - name: Upload standalone CLI binary uses: actions/upload-artifact@v5 with: name: windows-cli path: |- ${{ steps.core-paths.outputs.core_target_dir }}/${{ steps.core-paths.outputs.core_bin_name }}.exe