Raw
1 name: "Release Siti AI Windows Microsoft Store"
2
3 on:
4 push:
5 branches:
6 - release/windows-microsoft-store
7 workflow_dispatch:
8
9 # Push to the release branch above to build, sign, and draft-release the
10 # Windows Microsoft Store artifacts. The signed .msi/.exe are for direct
11 # download; the MSIX is what gets submitted to Partner Center (the Store
12 # re-signs it), which is the only form that carries the package identity Store
13 # services need.
14 jobs:
15 publish-tauri:
16 permissions:
17 contents: write
18 runs-on: windows-latest
19 # Job-level env so the MSIX steps' own `if:` conditions can read these.
20 # When the MSIX identity secrets are absent the MSIX steps skip and the
21 # signed .msi/.exe still ship.
22 env:
23 MSIX_PUBLISHER: ${{ secrets.MSIX_PUBLISHER }}
24 MSIX_IDENTITY_NAME: ${{ secrets.MSIX_IDENTITY_NAME }}
25 steps:
26 - uses: actions/checkout@v7
27
28 - name: setup node
29 uses: actions/setup-node@v7
30 with:
31 node-version: 22
32
33 # No version pin: reads the exact pnpm from package.json's
34 # packageManager field (pnpm@11.8.0), matching ci.yml.
35 - uses: pnpm/action-setup@v6
36
37 - name: Install Rust stable
38 uses: dtolnay/rust-toolchain@stable
39
40 # The full dependency tree build is slow cold. Cache the cargo registry
41 # and target/ keyed on Cargo.lock so a repeat run (a manifest tweak,
42 # another Partner Center validation round) restores in minutes instead of
43 # rebuilding from scratch.
44 - name: Cache Rust build
45 uses: Swatinem/rust-cache@v2
46 with:
47 workspaces: src-tauri
48
49 # The enabled Windows chat backend pulls in native crypto/C dependencies.
50 # NASM keeps their x64 assembly path available on the Windows runner.
51 - name: Install NASM
52 run: choco install nasm -y --no-progress
53 shell: pwsh
54
55 # Validate the MSIX manifest before the long Rust build rather than after
56 # it. makeappx checks the manifest against its schema regardless of what
57 # the payload files contain, so a stub exe is enough to catch a schema
58 # error in seconds instead of after a full build. Skipped when the MSIX
59 # secrets are absent so the .msi/.exe build still ships.
60 - name: Validate MSIX manifest (fast fail)
61 if: ${{ env.MSIX_PUBLISHER != '' && env.MSIX_IDENTITY_NAME != '' }}
62 shell: pwsh
63 run: ./scripts/build-msix.ps1 -ValidateOnly
64
65 - name: Install frontend dependencies
66 run: pnpm install --frozen-lockfile
67
68 - name: Patch src-tauri/.cargo/config.toml for native Windows build
69 shell: pwsh
70 run: |
71 # The .cargo/config.toml is authored for macOS hosts: the [env]
72 # section force-sets CC/CXX to /usr/bin/clang and a macOS deployment
73 # target, none of which exist on this runner. Strip that section so
74 # Rust falls back to the runner's native MSVC toolchain. The
75 # per-Apple-target and Android sections are inert here and left alone.
76 $path = "src-tauri/.cargo/config.toml"
77 if (Test-Path $path) {
78 $lines = Get-Content $path
79 $out = [System.Collections.Generic.List[string]]::new()
80 $skipSection = $false
81
82 foreach ($line in $lines) {
83 if ($line -match '^\[env\]') {
84 $skipSection = $true
85 continue
86 }
87 if ($skipSection -and $line -match '^\[') {
88 $skipSection = $false
89 }
90 if (-not $skipSection) {
91 $out.Add($line)
92 }
93 }
94
95 $out | Set-Content $path -Encoding UTF8
96 Write-Host "Patched src-tauri/.cargo/config.toml — removed macOS-only [env] section"
97 } else {
98 Write-Host "No src-tauri/.cargo/config.toml to patch"
99 }
100
101 - name: Setup MSVC developer environment
102 uses: ilammy/msvc-dev-cmd@v1
103
104 # Fail before the long Windows build if SSL.com signing credentials are
105 # not available to this run. GitHub substitutes absent secrets as empty
106 # strings, which otherwise surfaces only after the artifacts are built.
107 - name: Validate code-signing secrets
108 shell: pwsh
109 env:
110 ES_USERNAME: ${{ secrets.ES_USERNAME }}
111 ES_PASSWORD: ${{ secrets.ES_PASSWORD }}
112 ES_CREDENTIAL_ID: ${{ secrets.ES_CREDENTIAL_ID }}
113 ES_TOTP_SECRET: ${{ secrets.ES_TOTP_SECRET }}
114 run: |
115 $required = @(
116 "ES_USERNAME",
117 "ES_PASSWORD",
118 "ES_CREDENTIAL_ID",
119 "ES_TOTP_SECRET"
120 )
121 $missing = $required | Where-Object {
122 [string]::IsNullOrWhiteSpace([Environment]::GetEnvironmentVariable($_))
123 }
124 if ($missing.Count -gt 0) {
125 throw "Missing required GitHub Actions secret(s): $($missing -join ', '). Configure them under Settings > Secrets and variables > Actions."
126 }
127
128 - name: Build App
129 shell: pwsh
130 run: |
131 pnpm tauri build -c src-tauri/tauri.prod-windows-microsoftstore.conf.json
132 # Move installer artifacts to a dedicated input directory for
133 # CodeSignTool. The MSIX is packed separately below and deliberately
134 # left unsigned for Partner Center.
135 mkdir "${env:GITHUB_WORKSPACE}\src-tauri\target\release\bundle\to-sign"
136 mkdir "${env:GITHUB_WORKSPACE}\src-tauri\target\release\bundle\signed"
137 Move-Item "${env:GITHUB_WORKSPACE}\src-tauri\target\release\bundle\msi\*" "${env:GITHUB_WORKSPACE}\src-tauri\target\release\bundle\to-sign\" -Force
138 Move-Item "${env:GITHUB_WORKSPACE}\src-tauri\target\release\bundle\nsis\*" "${env:GITHUB_WORKSPACE}\src-tauri\target\release\bundle\to-sign\" -Force
139
140 - name: Sign Artifact with CodeSignTool
141 uses: sslcom/esigner-codesign@v1.3.2
142 timeout-minutes: 20
143 with:
144 command: batch_sign
145 username: ${{ secrets.ES_USERNAME }}
146 password: ${{ secrets.ES_PASSWORD }}
147 credential_id: ${{ secrets.ES_CREDENTIAL_ID }}
148 totp_secret: ${{ secrets.ES_TOTP_SECRET }}
149 dir_path: ${GITHUB_WORKSPACE}\src-tauri\target\release\bundle\to-sign
150 output_path: ${GITHUB_WORKSPACE}\src-tauri\target\release\bundle\signed
151 malware_block: false
152 clean_logs: true
153 jvm_max_memory: 1024M
154 signing_method: v1
155
156 # The .msi/.exe above are for direct download only. A Store MSI/EXE
157 # submission is just a hosted installer URL, so it never gets package
158 # identity and Windows.Services.Store add-ons would fail from it. The MSIX
159 # below is what goes to Partner Center. It is deliberately left unsigned:
160 # the Store re-signs with the publisher cert. Skipped when the MSIX
161 # secrets are absent.
162 - name: Pack MSIX for Partner Center
163 if: ${{ env.MSIX_PUBLISHER != '' && env.MSIX_IDENTITY_NAME != '' }}
164 shell: pwsh
165 run: ./scripts/build-msix.ps1
166
167 - name: Extract version from tauri.prod-windows-microsoftstore.conf.json
168 id: get_version
169 shell: pwsh
170 run: |
171 $json = Get-Content src-tauri/tauri.prod-windows-microsoftstore.conf.json | ConvertFrom-Json
172 echo "VERSION=$($json.version)" >> $env:GITHUB_ENV
173
174 - name: Release
175 uses: softprops/action-gh-release@v2
176 with:
177 tag_name: "windows-microsoft-store-siti-ai-v${{ env.VERSION }}"
178 draft: true
179 prerelease: false
180 body: "See the assets to download this version and install."
181 name: "Siti AI v${{ env.VERSION }} (Windows Microsoft Store)"
182 files: |
183 src-tauri/target/release/bundle/signed/*.msi
184 src-tauri/target/release/bundle/signed/*.exe
185 src-tauri/target/release/bundle/msix/*.msix