@@ -2,35 +2,230 @@ name: Build Check
22on : [pull_request, push]
33permissions :
44 contents : read
5+ pull-requests : write # Required to post comments on PRs
56jobs :
6- build-windows :
7- runs-on : windows-latest
7+ # Matrix job that compiles and tests all architectures
8+ build-and-test :
9+ strategy :
10+ fail-fast : false # Continue testing other architectures even if one fails
11+ matrix :
12+ include :
13+ # x64 architecture - native runner
14+ - arch : x64
15+ runner : windows-latest
16+ vcvars_arch : x64
17+ # x86 architecture - runs on x64 via WoW64
18+ - arch : x86
19+ runner : windows-latest
20+ vcvars_arch : x64_x86
21+ # ARM64 architecture - native ARM runner for testing
22+ - arch : arm64
23+ runner : windows-11-arm
24+ vcvars_arch : arm64
25+
26+ runs-on : ${{ matrix.runner }}
27+
828 steps :
929 - uses : actions/checkout@v4
1030
11- - name : Setup MSVC
31+ - name : Setup MSVC for ${{ matrix.arch }}
1232 uses : ilammy/msvc-dev-cmd@v1
33+ with :
34+ arch : ${{ matrix.vcvars_arch }}
1335
14- - name : Compile
36+ - name : Compile for ${{ matrix.arch }}
1537 shell : pwsh
1638 run : |
17- cl /O2 /std:c++20 /EHsc main.cpp /DUNICODE /D_UNICODE /Fe:win-witr.exe
18- # Add the current directory (where win-witr.exe was compiled) to PATH
19- $env:PATH = "$PWD;$env:PATH"
20-
21- # Verify the exe is accessible
22- Write-Host "Checking win-witr.exe availability..."
23- win-witr --version
24- - name : Run Tests
39+ # Compile the executable with architecture-specific name
40+ cl /O2 /std:c++20 /EHsc main.cpp /DUNICODE /D_UNICODE /Fe:win-witr-${{ matrix.arch }}.exe
41+
42+ # Create a copy with the standard name for tests
43+ Copy-Item -Path "win-witr-${{ matrix.arch }}.exe" -Destination "win-witr.exe"
44+
45+ # Add the current directory to PATH
46+ $env:PATH = "$PWD;$env:PATH"
47+
48+ # Verify the exe is accessible
49+ Write-Host "Checking win-witr-${{ matrix.arch }}.exe availability..."
50+ .\win-witr-${{ matrix.arch }}.exe --version
51+
52+ - name : Run Tests for ${{ matrix.arch }}
53+ id : run_tests
2554 shell : pwsh
2655 run : |
56+ # Initialize test counters
57+ $totalTests = 0
58+ $passedTests = 0
59+ $failedTests = 0
60+ $testResults = @()
61+
62+ # Add the current directory to PATH
63+ $env:PATH = "$PWD;$env:PATH"
64+
2765 # Run all test .bat files
2866 Get-ChildItem -Path tests -Recurse -Filter *.bat | ForEach-Object {
29- Write-Host "Running test: $($_.FullName)"
30- & $_.FullName
31- if ($LASTEXITCODE -ne 0) {
32- Write-Error "Test failed: $($_.Name)"
33- exit 1
67+ $totalTests++
68+ $testName = $_.Name
69+ Write-Host "Running test: $testName"
70+
71+ # Initialize output variable outside try block
72+ $output = $null
73+
74+ try {
75+ # Run the test and capture output and exit code
76+ $output = & $_.FullName 2>&1
77+ $exitCode = $LASTEXITCODE
78+
79+ if ($exitCode -eq 0) {
80+ $passedTests++
81+ # Include output in the result
82+ $outputText = if ($output) { "`n Output: $($output -join "`n ")" } else { "" }
83+ $testResults += "✅ $testName - PASSED$outputText"
84+ Write-Host "✅ Test passed: $testName"
85+ } else {
86+ $failedTests++
87+ # Include output and exit code in the result
88+ $outputText = if ($output) { "`n Output: $($output -join "`n ")" } else { "" }
89+ $testResults += "❌ $testName - FAILED (Exit code: $exitCode)$outputText"
90+ Write-Host "❌ Test failed: $testName (Exit code: $exitCode)"
91+ }
92+ } catch {
93+ $failedTests++
94+ # Include exception and any captured output
95+ $outputText = if ($output) { "`n Output: $($output -join "`n ")" } else { "" }
96+ $testResults += "❌ $testName - FAILED (Exception: $_)$outputText"
97+ Write-Host "❌ Test failed with exception: $testName"
3498 }
3599 }
36-
100+
101+ # Output test summary
102+ Write-Host "`n=== Test Summary for ${{ matrix.arch }} ==="
103+ Write-Host "Total: $totalTests"
104+ Write-Host "Passed: $passedTests"
105+ Write-Host "Failed: $failedTests"
106+
107+ # Store results for PR comment
108+ $results = @{
109+ total = $totalTests
110+ passed = $passedTests
111+ failed = $failedTests
112+ details = $testResults -join "`n"
113+ }
114+
115+ # Export results to GitHub output using multiline format
116+ "total=$totalTests" >> $env:GITHUB_OUTPUT
117+ "passed=$passedTests" >> $env:GITHUB_OUTPUT
118+ "failed=$failedTests" >> $env:GITHUB_OUTPUT
119+ $delimiter = "EOF_DETAILS_$(Get-Date -Format 'yyyyMMddHHmmss')"
120+ "details<<$delimiter" >> $env:GITHUB_OUTPUT
121+ $testResults -join "`n" >> $env:GITHUB_OUTPUT
122+ "$delimiter" >> $env:GITHUB_OUTPUT
123+
124+ # Exit with error if any tests failed
125+ if ($failedTests -gt 0) {
126+ Write-Error "Some tests failed for ${{ matrix.arch }}"
127+ exit 1
128+ }
129+
130+ # Upload test results as artifacts for the comment job
131+ - name : Save test results
132+ if : always()
133+ shell : pwsh
134+ run : |
135+ # Determine job status based on previous steps
136+ $jobStatus = if ("${{ steps.run_tests.outcome }}" -eq "success") { "success" } else { "failure" }
137+
138+ $results = @{
139+ arch = "${{ matrix.arch }}"
140+ status = $jobStatus
141+ total = "${{ steps.run_tests.outputs.total }}"
142+ passed = "${{ steps.run_tests.outputs.passed }}"
143+ failed = "${{ steps.run_tests.outputs.failed }}"
144+ details = "${{ steps.run_tests.outputs.details }}"
145+ }
146+
147+ $results | ConvertTo-Json | Out-File -FilePath "test-results-${{ matrix.arch }}.json"
148+
149+ - name : Upload test results artifact
150+ if : always()
151+ uses : actions/upload-artifact@v4
152+ with :
153+ name : test-results-${{ matrix.arch }}
154+ path : test-results-${{ matrix.arch }}.json
155+
156+ # Job to post test results as a PR comment
157+ post-test-results :
158+ needs : build-and-test
159+ if : always() && github.event_name == 'pull_request'
160+ runs-on : ubuntu-latest
161+ permissions :
162+ pull-requests : write
163+
164+ steps :
165+ - name : Download all test results
166+ uses : actions/download-artifact@v4
167+ with :
168+ pattern : test-results-*
169+ merge-multiple : true
170+
171+ - name : Generate and post comment
172+ uses : actions/github-script@v7
173+ with :
174+ script : |
175+ const fs = require('fs');
176+
177+ // Read all test result files
178+ const files = fs.readdirSync('.').filter(f => f.startsWith('test-results-') && f.endsWith('.json'));
179+
180+ let commentBody = '## 🧪 Test Results\n\n';
181+ let allPassed = true;
182+
183+ // Process each architecture
184+ for (const file of files) {
185+ const data = JSON.parse(fs.readFileSync(file, 'utf8'));
186+ const arch = data.arch;
187+ const status = data.status || 'unknown';
188+ const total = data.total || 0;
189+ const passed = data.passed || 0;
190+ const failed = data.failed || 0;
191+
192+ // Mark as failed if either tests failed OR job status is not success
193+ if (failed > 0 || status !== 'success') {
194+ allPassed = false;
195+ }
196+
197+ // Determine emoji based on both test results and job status
198+ const emoji = (failed === 0 && status === 'success') ? '✅' : '❌';
199+ commentBody += `### ${emoji} ${arch.toUpperCase()}\n`;
200+
201+ // Show appropriate message based on job status
202+ if (status !== 'success') {
203+ commentBody += `**Job failed** - Tests may not have run due to compile or setup failure\n\n`;
204+ } else {
205+ commentBody += `**${passed}/${total} tests passed**\n\n`;
206+ }
207+
208+ if (data.details && data.details.trim()) {
209+ commentBody += '<details>\n';
210+ commentBody += '<summary>Test Details</summary>\n\n';
211+ commentBody += '```\n';
212+ commentBody += data.details;
213+ commentBody += '\n```\n';
214+ commentBody += '</details>\n\n';
215+ }
216+ }
217+
218+ if (allPassed) {
219+ commentBody += '\n✨ All tests passed across all architectures!\n';
220+ } else {
221+ commentBody += '\n⚠️ Some tests failed. Please review the details above.\n';
222+ }
223+
224+ // Post comment to PR
225+ await github.rest.issues.createComment({
226+ owner: context.repo.owner,
227+ repo: context.repo.repo,
228+ issue_number: context.issue.number,
229+ body: commentBody
230+ });
231+
0 commit comments