Skip to content

Commit 3a064dd

Browse files
committed
test: Add E2E test workflow for all binary platforms
Add automated E2E testing for Windows, macOS, and Linux builds (x64, ARM64, ARMv7). The workflow validates binary builds, startup, API endpoints, and graceful shutdown across all platforms.
1 parent 727a192 commit 3a064dd

1 file changed

Lines changed: 214 additions & 0 deletions

File tree

.github/workflows/e2e-tests.yml

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
name: E2E Test Binaries
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
workflow_dispatch:
9+
10+
jobs:
11+
test:
12+
name: Test ${{ matrix.platform }} ${{ matrix.arch }}
13+
runs-on: ${{ matrix.os }}
14+
strategy:
15+
fail-fast: false
16+
max-parallel: 6
17+
matrix:
18+
include:
19+
- os: windows-latest
20+
platform: win
21+
arch: x64
22+
output: flashforge-webui-win-x64.exe
23+
- os: macos-15-intel
24+
platform: mac
25+
arch: x64
26+
output: flashforge-webui-macos-x64.bin
27+
- os: macos-latest
28+
platform: mac
29+
arch: arm64
30+
output: flashforge-webui-macos-arm64.bin
31+
- os: ubuntu-latest
32+
platform: linux
33+
arch: x64
34+
output: flashforge-webui-linux-x64.bin
35+
- os: ubuntu-24.04-arm
36+
platform: linux
37+
arch: arm64
38+
output: flashforge-webui-linux-arm64.bin
39+
- os: ubuntu-latest
40+
platform: linux
41+
arch: armv7
42+
output: flashforge-webui-linux-armv7.bin
43+
44+
steps:
45+
- name: Checkout code
46+
uses: actions/checkout@v4
47+
48+
- name: Setup Node.js 20
49+
uses: actions/setup-node@v4
50+
with:
51+
node-version: 20
52+
cache: 'npm'
53+
54+
- name: Cache pkg fetch
55+
uses: actions/cache@v4
56+
with:
57+
path: ~/.pkg-cache
58+
key: ${{ runner.os }}-pkg-${{ hashFiles('package.json') }}
59+
restore-keys: |
60+
${{ runner.os }}-pkg-
61+
62+
- name: Configure GitHub Packages
63+
shell: bash
64+
run: |
65+
echo "@ghosttypes:registry=https://npm.pkg.github.com" >> .npmrc
66+
echo "@parallel-7:registry=https://npm.pkg.github.com" >> .npmrc
67+
echo "//npm.pkg.github.com/:_authToken=${{ secrets.GITHUB_TOKEN }}" >> .npmrc
68+
env:
69+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
70+
71+
- name: Install dependencies
72+
run: npm ci
73+
env:
74+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
75+
76+
- name: Pre-download ARMv7 Node.js Binary
77+
if: matrix.arch == 'armv7'
78+
run: |
79+
mkdir -p ~/.pkg-cache/v3.5
80+
curl -L -o ~/.pkg-cache/v3.5/fetched-v20.18.0-linuxstatic-armv7 \
81+
https://github.com/yao-pkg/pkg-binaries/releases/download/node20/node-v20.18.0-linuxstatic-armv7
82+
chmod +x ~/.pkg-cache/v3.5/fetched-v20.18.0-linuxstatic-armv7
83+
84+
- name: Build application
85+
shell: bash
86+
run: |
87+
npm run build
88+
if [[ "${{ matrix.platform }}" == "win" ]]; then
89+
npx @yao-pkg/pkg . --targets node20-win-${{ matrix.arch }} --output dist/${{ matrix.output }}
90+
elif [[ "${{ matrix.platform }}" == "mac" ]]; then
91+
npx @yao-pkg/pkg . --targets node20-macos-${{ matrix.arch }} --output dist/${{ matrix.output }}
92+
elif [[ "${{ matrix.arch }}" == "armv7" ]]; then
93+
npx @yao-pkg/pkg . --targets node20-linuxstatic-armv7 --output dist/${{ matrix.output }}
94+
else
95+
npx @yao-pkg/pkg . --targets node20-linux-${{ matrix.arch }} --output dist/${{ matrix.output }}
96+
fi
97+
98+
- name: Verify binary size
99+
shell: bash
100+
run: |
101+
size=$(stat -c%s "dist/${{ matrix.output }}" 2>/dev/null || stat -f% "dist/${{ matrix.output }}")
102+
if [ $size -lt 40000000 ]; then
103+
echo "::error::Binary size ($size bytes) is too small - assets may not be embedded"
104+
exit 1
105+
fi
106+
echo "✓ Binary size: $size bytes"
107+
108+
- name: Start binary in background
109+
shell: bash
110+
run: |
111+
if [[ "${{ runner.os }}" == "Windows" ]]; then
112+
powershell -Command "Start-Process -FilePath '.\dist\${{ matrix.output }}' -ArgumentList '--no-printers' -RedirectStart 'startup.log'"
113+
else
114+
chmod +x dist/${{ matrix.output }}
115+
./dist/${{ matrix.output }} --no-printers > startup.log 2>&1 &
116+
echo $! > binary.pid
117+
fi
118+
119+
- name: Wait for startup
120+
shell: bash
121+
run: sleep 15
122+
123+
- name: Validate startup
124+
shell: bash
125+
run: |
126+
if grep -iE "\[Error\]|\[Fatal\]|exception" startup.log; then
127+
echo "::error::Errors detected during startup"
128+
cat startup.log
129+
exit 1
130+
fi
131+
132+
if ! grep -q "\[Ready\] FlashForgeWebUI is ready" startup.log; then
133+
echo "::error::Startup did not complete - missing ready marker"
134+
tail -n 50 startup.log
135+
exit 1
136+
fi
137+
138+
echo "✓ Startup successful"
139+
140+
- name: Test API endpoints
141+
shell: bash
142+
run: |
143+
# Test 1: Auth status (public endpoint)
144+
response=$(curl -s http://localhost:3000/api/auth/status)
145+
authenticated=$(echo "$response" | jq -r '.authenticated')
146+
if [ "$authenticated" != "false" ]; then
147+
echo "::error::Auth status API returned unexpected value: $authenticated"
148+
exit 1
149+
fi
150+
151+
# Test 2: Serve index.html
152+
if ! curl -s http://localhost:3000/ | grep -q "FlashForge Web UI"; then
153+
echo "::error::Failed to serve index.html"
154+
exit 1
155+
fi
156+
157+
# Test 3: Login endpoint
158+
login_response=$(curl -s -X POST http://localhost:3000/api/auth/login \
159+
-H "Content-Type: application/json" \
160+
-d '{"password":"changeme"}')
161+
success=$(echo "$login_response" | jq -r '.success')
162+
if [ "$success" != "true" ]; then
163+
echo "::error::Login API failed: $login_response"
164+
exit 1
165+
fi
166+
167+
echo "✓ All API tests passed"
168+
169+
- name: Stop binary
170+
shell: bash
171+
run: |
172+
if [[ "${{ runner.os }}" == "Windows" ]]; then
173+
powershell -Command "Stop-Process -Name '${{ matrix.output }}' -Force -ErrorAction SilentlyContinue"
174+
else
175+
if [ -f binary.pid ]; then
176+
kill -TERM $(cat binary.pid) || true
177+
rm binary.pid
178+
fi
179+
pkill -TERM -f "${{ matrix.output }}" || true
180+
fi
181+
sleep 3
182+
183+
- name: Verify cleanup
184+
shell: bash
185+
run: |
186+
if [[ "${{ runner.os }}" == "Windows" ]]; then
187+
powershell -Command "if (Get-Process -Name '${{ matrix.output }}' -ErrorAction SilentlyContinue) { exit 1 }"
188+
else
189+
if pgrep -f "${{ matrix.output }}"; then
190+
echo "::error::Binary left zombie processes"
191+
exit 1
192+
fi
193+
fi
194+
echo "✓ Cleanup successful"
195+
196+
- name: Upload test binary
197+
uses: actions/upload-artifact@v4
198+
if: always()
199+
with:
200+
name: ${{ matrix.output }}
201+
path: dist/${{ matrix.output }}
202+
retention-days: 7
203+
compression-level: 6
204+
205+
- name: Generate summary
206+
if: always()
207+
run: |
208+
echo "## ${{ matrix.platform }} ${{ matrix.arch }}" >> $GITHUB_STEP_SUMMARY
209+
echo "" >> $GITHUB_STEP_SUMMARY
210+
if [[ "${{ job.status }}" == "success" ]]; then
211+
echo "✅ All tests passed" >> $GITHUB_STEP_SUMMARY
212+
else
213+
echo "❌ Tests failed" >> $GITHUB_STEP_SUMMARY
214+
fi

0 commit comments

Comments
 (0)