@@ -44,30 +44,28 @@ jobs:
4444 - name : Get version from git tags
4545 id : get_version
4646 run : |
47- # Try to get version from latest git tag
47+ # Get version from backend/version.py as the source of truth
48+ $fileVersion = "1.0.0" # Default fallback
49+ if (Test-Path "backend/version.py") {
50+ $versionContent = Get-Content "backend/version.py" | Select-String -Pattern '__version__\s*=\s*[''"]([^''"]+)[''"]'
51+ if ($versionContent) {
52+ $fileVersion = $versionContent.Matches.Groups[1].Value
53+ Write-Host "Found version in backend/version.py: $fileVersion"
54+ }
55+ }
56+
57+ # Also check latest git tag for reference
4858 $gitVersion = git describe --tags --abbrev=0 2>$null
4959 if ($LASTEXITCODE -eq 0 -and $gitVersion) {
50- # Clean up version (remove 'v' prefix if present)
51- $version = $gitVersion -replace '^v', ''
52- Write-Host "Found git tag version: $version"
53- } else {
54- # Fallback to version from backend/version.py
55- if (Test-Path "backend/version.py") {
56- $versionContent = Get-Content "backend/version.py" | Select-String -Pattern '__version__\s*=\s*[''"]([^''"]+)[''"]'
57- if ($versionContent) {
58- $version = $versionContent.Matches.Groups[1].Value
59- Write-Host "Using version from backend/version.py: $version"
60- } else {
61- $version = "1.0.0"
62- Write-Host "No version found, using default: $version"
63- }
64- } else {
65- $version = "1.0.0"
66- Write-Host "No version found, using default: $version"
67- }
60+ $gitVersion = $gitVersion -replace '^v', ''
61+ Write-Host "Latest git tag version: $gitVersion"
6862 }
6963
70- # Update backend/version.py with the version
64+ # Use the version from backend/version.py as the authoritative source
65+ $version = $fileVersion
66+ Write-Host "Using version: $version"
67+
68+ # Update backend/version.py to ensure it's consistent
7169 @"
7270 # Auto-generated version file
7371 # This file is automatically updated during the build process
@@ -117,6 +115,56 @@ jobs:
117115 Write-Host "Executable size: $([math]::Round($size, 2)) MB"
118116 shell : powershell
119117
118+ - name : Install WiX Toolset v4
119+ run : |
120+ Write-Host "Installing WiX Toolset v4..."
121+ dotnet tool install --global wix
122+
123+ # Ensure WiX is in PATH
124+ $env:PATH = "$env:USERPROFILE\.dotnet\tools;$env:PATH"
125+
126+ Write-Host "Verifying WiX installation..."
127+ wix --version
128+
129+ Write-Host "Installing WiX UI extension globally..."
130+ wix extension add --global WixToolset.UI.wixext
131+
132+ Write-Host "Verifying UI extension..."
133+ wix extension list
134+ wix extension list --global
135+
136+ Write-Host "WiX installation complete"
137+ shell : powershell
138+
139+ - name : Generate installer images
140+ run : |
141+ Write-Host "Generating custom installer images..."
142+ pip install pillow
143+ python deployment/create_installer_images.py
144+ shell : powershell
145+
146+ - name : Build MSI Installer
147+ run : python deployment/build_msi.py
148+ env :
149+ VITE_APP_VERSION : ${{ steps.get_version.outputs.app_version }}
150+
151+ - name : Verify MSI exists
152+ id : msi_info
153+ run : |
154+ $msiPath = Get-ChildItem -Path "dist/msi" -Filter "*.msi" | Select-Object -First 1
155+ if (!$msiPath) {
156+ Write-Error "MSI build failed: No .msi file found in dist/msi directory"
157+ exit 1
158+ }
159+ Write-Host "[SUCCESS] MSI build successful: $($msiPath.Name) found"
160+ $size = $msiPath.Length / 1MB
161+ Write-Host "MSI size: $([math]::Round($size, 2)) MB"
162+
163+ # Store MSI info for later steps
164+ echo "msi_path=$($msiPath.FullName)" >> $env:GITHUB_OUTPUT
165+ echo "msi_name=$($msiPath.Name)" >> $env:GITHUB_OUTPUT
166+ shell : powershell
167+
120168 - name : Get version info
121169 id : version
122170 run : |
@@ -145,7 +193,9 @@ jobs:
145193 uses : actions/upload-artifact@v4
146194 with :
147195 name : ChatYapper-${{ steps.version.outputs.version }}
148- path : dist/ChatYapper.exe
196+ path : |
197+ dist/ChatYapper.exe
198+ dist/msi/*.msi
149199 retention-days : 7
150200
151201 - name : Comment PR with build status
@@ -154,19 +204,28 @@ jobs:
154204 with :
155205 script : |
156206 const fs = require('fs');
157- const stats = fs.statSync('dist/ChatYapper.exe');
158- const sizeMB = (stats.size / (1024 * 1024)).toFixed(2);
207+ const path = require('path');
208+
209+ const exeStats = fs.statSync('dist/ChatYapper.exe');
210+ const exeSizeMB = (exeStats.size / (1024 * 1024)).toFixed(2);
211+
212+ // Find MSI file
213+ const msiDir = 'dist/msi';
214+ const msiFiles = fs.readdirSync(msiDir).filter(f => f.endsWith('.msi'));
215+ const msiFile = msiFiles.length > 0 ? msiFiles[0] : null;
216+ const msiStats = msiFile ? fs.statSync(path.join(msiDir, msiFile)) : null;
217+ const msiSizeMB = msiStats ? (msiStats.size / (1024 * 1024)).toFixed(2) : 'N/A';
159218
160219 const comment = `## ✅ Build Successful
161220
162- **Executable:** \`ChatYapper.exe\`
163- **Size :** ${sizeMB} MB
221+ **Executable:** \`ChatYapper.exe\` (${exeSizeMB} MB)
222+ **MSI Installer :** \`${msiFile || 'Not found'}\` (${msiSizeMB} MB)
164223 **App Version:** \`${{ steps.get_version.outputs.app_version }}\`
165224 **Build ID:** \`${{ steps.version.outputs.version }}\`
166225 **Commit:** ${{ github.sha }}
167226
168- The executable has been built and is ready for testing.
169- Download the artifact from the workflow run to test before merging.
227+ Both the standalone executable and MSI installer have been built and are ready for testing.
228+ Download the artifacts from the workflow run to test before merging.
170229
171230 Once merged to \`main\`, an official release will be created automatically with tag \`v${{ steps.get_version.outputs.app_version }}\`.`;
172231
@@ -179,13 +238,10 @@ jobs:
179238
180239 - name : Create Release (on merge to main)
181240 if : steps.version.outputs.is_release == 'true'
182- id : create_release
183- uses : actions/create-release@v1
184- env :
185- GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
241+ uses : softprops/action-gh-release@v1
186242 with :
187243 tag_name : ${{ steps.version.outputs.version }}
188- release_name : Chat Yapper ${{ steps.version.outputs.version }}
244+ name : Chat Yapper ${{ steps.version.outputs.version }}
189245 body : |
190246 ## Chat Yapper ${{ steps.version.outputs.version }}
191247
@@ -197,34 +253,45 @@ jobs:
197253 **Build Date:** ${{ github.event.head_commit.timestamp }}
198254
199255 ### Download
200- Download `ChatYapper.exe` below to run the application.
256+ Choose one of the following installation methods:
257+
258+ #### MSI Installer (Recommended)
259+ - Download `${{ steps.msi_info.outputs.msi_name }}` for a traditional Windows installation
260+ - Double-click to install to Program Files
261+ - Creates Start Menu and Desktop shortcuts
262+ - Easily uninstall via Windows Settings
263+
264+ #### Standalone Executable
265+ - Download `ChatYapper.exe` for a portable version
266+ - No installation required
267+ - Run directly from any location
201268
202269 ### Installation
270+
271+ **MSI Installer:**
272+ 1. Download the `.msi` file below
273+ 2. Double-click to run the installer
274+ 3. Follow the installation wizard
275+ 4. Launch from Start Menu or Desktop shortcut
276+
277+ **Standalone Executable:**
203278 1. Download `ChatYapper.exe`
204279 2. Run the executable
205280 3. The application will start on `http://localhost:8008`
206281
207282 ### System Requirements
208283 - Windows 10 or later
209- - No additional dependencies required (all bundled in the executable )
284+ - No additional dependencies required (all bundled)
210285
211286 ### Support
212287 - **Issues:** https://github.com/${{ github.repository }}/issues
213288 - **Discussions:** https://github.com/${{ github.repository }}/discussions
289+ files : |
290+ dist/ChatYapper.exe
291+ ${{ steps.msi_info.outputs.msi_path }}
214292 draft : false
215293 prerelease : false
216294
217- - name : Upload Release Asset
218- if : steps.version.outputs.is_release == 'true'
219- uses : actions/upload-release-asset@v1
220- env :
221- GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
222- with :
223- upload_url : ${{ steps.create_release.outputs.upload_url }}
224- asset_path : ./dist/ChatYapper.exe
225- asset_name : ChatYapper.exe
226- asset_content_type : application/vnd.microsoft.portable-executable
227-
228295 - name : Notify release created
229296 if : steps.version.outputs.is_release == 'true'
230297 run : |
0 commit comments