Skip to content

Commit 8d2ca50

Browse files
committed
ci: add Windows build (MSI + NSIS installer) to release workflow
1 parent 5ae301b commit 8d2ca50

3 files changed

Lines changed: 136 additions & 1 deletion

File tree

.github/workflows/release.yml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,5 +71,52 @@ jobs:
7171
src-tauri/target/release/bundle/appimage/*.AppImage
7272
src-tauri/target/release/bundle/deb/*.deb
7373
74+
build-windows:
75+
runs-on: windows-latest
76+
steps:
77+
- uses: actions/checkout@v4
78+
79+
- uses: pnpm/action-setup@v4
80+
with:
81+
version: 9
82+
83+
- uses: actions/setup-node@v4
84+
with:
85+
node-version: 20
86+
cache: 'pnpm'
87+
88+
- uses: dtolnay/rust-toolchain@stable
89+
90+
- uses: Swatinem/rust-cache@v2
91+
with:
92+
workspaces: src-tauri
93+
94+
- name: Install dependencies
95+
run: pnpm install --frozen-lockfile
96+
97+
- name: Install Tauri CLI
98+
run: cargo install tauri-cli --version "^2"
99+
100+
- name: Build Tauri (Windows)
101+
run: cargo tauri build --bundles msi,nsis
102+
env:
103+
CI: 'true'
104+
105+
- name: Upload Windows artifacts
106+
uses: actions/upload-artifact@v4
107+
with:
108+
name: windows-builds
109+
path: |
110+
src-tauri/target/release/bundle/msi/*.msi
111+
src-tauri/target/release/bundle/nsis/*.exe
112+
113+
- name: Upload to release
114+
if: startsWith(github.ref, 'refs/tags/')
115+
uses: softprops/action-gh-release@v2
116+
with:
117+
files: |
118+
src-tauri/target/release/bundle/msi/*.msi
119+
src-tauri/target/release/bundle/nsis/*.exe
120+
74121
# macOS builds are signed + notarized locally (requires Developer ID certificate)
75122
# See scripts/sign-and-deploy.sh for the local release workflow

capture-screenshots.js

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
const puppeteer = require('puppeteer');
2+
const path = require('path');
3+
const fs = require('fs');
4+
5+
async function captureScreenshots() {
6+
const browser = await puppeteer.launch({
7+
headless: true,
8+
args: ['--no-sandbox', '--disable-setuid-sandbox']
9+
});
10+
11+
const page = await browser.newPage();
12+
await page.setViewport({ width: 1920, height: 1080 });
13+
14+
const screenshotDir = path.join(__dirname, 'public', 'screenshots');
15+
if (!fs.existsSync(screenshotDir)) {
16+
fs.mkdirSync(screenshotDir, { recursive: true });
17+
}
18+
19+
console.log('Opening http://localhost:3080...');
20+
await page.goto('http://localhost:3080', { waitUntil: 'networkidle2', timeout: 30000 });
21+
22+
// Wait a bit for the app to fully load
23+
await page.waitForTimeout(2000);
24+
25+
// Screenshot 1: Main workspace
26+
console.log('Capturing main workspace...');
27+
const screenshot1 = path.join(screenshotDir, 'main-workspace.png');
28+
await page.screenshot({ path: screenshot1, fullPage: false });
29+
console.log(`Saved: ${screenshot1}`);
30+
31+
// Try to open agent panel (look for button/element)
32+
try {
33+
await page.waitForTimeout(1000);
34+
35+
// Screenshot 2: Try to capture with agent panel visible
36+
// Look for common selectors that might open the agent panel
37+
const agentButton = await page.$('[data-panel="agent"]') ||
38+
await page.$('button:has-text("Agent")') ||
39+
await page.$('[aria-label*="agent" i]');
40+
41+
if (agentButton) {
42+
await agentButton.click();
43+
await page.waitForTimeout(1000);
44+
console.log('Capturing agent panel...');
45+
const screenshot2 = path.join(screenshotDir, 'agent-panel.png');
46+
await page.screenshot({ path: screenshot2, fullPage: false });
47+
console.log(`Saved: ${screenshot2}`);
48+
}
49+
} catch (e) {
50+
console.log('Could not open agent panel, taking another workspace shot...');
51+
const screenshot2 = path.join(screenshotDir, 'workspace-view.png');
52+
await page.screenshot({ path: screenshot2, fullPage: false });
53+
console.log(`Saved: ${screenshot2}`);
54+
}
55+
56+
// Try to open terminal or settings
57+
try {
58+
await page.waitForTimeout(1000);
59+
60+
const terminalButton = await page.$('[data-panel="terminal"]') ||
61+
await page.$('button:has-text("Terminal")') ||
62+
await page.$('[aria-label*="terminal" i]');
63+
64+
if (terminalButton) {
65+
await terminalButton.click();
66+
await page.waitForTimeout(1000);
67+
console.log('Capturing terminal panel...');
68+
const screenshot3 = path.join(screenshotDir, 'terminal-panel.png');
69+
await page.screenshot({ path: screenshot3, fullPage: false });
70+
console.log(`Saved: ${screenshot3}`);
71+
} else {
72+
// Just take another screenshot of current state
73+
const screenshot3 = path.join(screenshotDir, 'editor-view.png');
74+
await page.screenshot({ path: screenshot3, fullPage: false });
75+
console.log(`Saved: ${screenshot3}`);
76+
}
77+
} catch (e) {
78+
console.log('Taking final screenshot...');
79+
const screenshot3 = path.join(screenshotDir, 'app-overview.png');
80+
await page.screenshot({ path: screenshot3, fullPage: false });
81+
console.log(`Saved: ${screenshot3}`);
82+
}
83+
84+
await browser.close();
85+
console.log('\nScreenshot capture complete!');
86+
}
87+
88+
captureScreenshots().catch(console.error);

src-tauri/tauri.conf.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
},
3232
"bundle": {
3333
"active": true,
34-
"targets": ["dmg", "appimage", "deb"],
34+
"targets": ["dmg", "appimage", "deb", "msi", "nsis"],
3535
"icon": [
3636
"icons/32x32.png",
3737
"icons/128x128.png",

0 commit comments

Comments
 (0)