1name: "Run tests on Windows"
2description: "Runs the tests on Windows"
3
4inputs:
5 working-directory:
6 description: "The working directory"
7 required: true
8 default: "."
9
10runs:
11 using: "composite"
12 steps:
13 - name: Install test runner
14 shell: powershell
15 working-directory: ${{ inputs.working-directory }}
16 run: cargo install cargo-nextest --locked
17
18 - name: Install Node
19 uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
20 with:
21 node-version: "18"
22
23 - name: Configure crash dumps
24 shell: powershell
25 run: |
26 # Record the start time for this CI run
27 $runStartTime = Get-Date
28 $runStartTimeStr = $runStartTime.ToString("yyyy-MM-dd HH:mm:ss")
29 Write-Host "CI run started at: $runStartTimeStr"
30
31 # Save the timestamp for later use
32 echo "CI_RUN_START_TIME=$($runStartTime.Ticks)" >> $env:GITHUB_ENV
33
34 # Create crash dump directory in workspace (non-persistent)
35 $dumpPath = "$env:GITHUB_WORKSPACE\crash_dumps"
36 New-Item -ItemType Directory -Force -Path $dumpPath | Out-Null
37
38 Write-Host "Setting up crash dump detection..."
39 Write-Host "Workspace dump path: $dumpPath"
40
41 # Note: We're NOT modifying registry on stateful runners
42 # Instead, we'll check default Windows crash locations after tests
43
44 - name: Run tests
45 shell: powershell
46 working-directory: ${{ inputs.working-directory }}
47 run: |
48 $env:RUST_BACKTRACE = "full"
49
50 # Enable Windows debugging features
51 $env:_NT_SYMBOL_PATH = "srv*https://msdl.microsoft.com/download/symbols"
52
53 # .NET crash dump environment variables (ephemeral)
54 $env:COMPlus_DbgEnableMiniDump = "1"
55 $env:COMPlus_DbgMiniDumpType = "4"
56 $env:COMPlus_CreateDumpDiagnostics = "1"
57
58 cargo nextest run --workspace --no-fail-fast
59
60 - name: Analyze crash dumps
61 if: always()
62 shell: powershell
63 run: |
64 Write-Host "Checking for crash dumps..."
65
66 # Get the CI run start time from the environment
67 $runStartTime = [DateTime]::new([long]$env:CI_RUN_START_TIME)
68 Write-Host "Only analyzing dumps created after: $($runStartTime.ToString('yyyy-MM-dd HH:mm:ss'))"
69
70 # Check all possible crash dump locations
71 $searchPaths = @(
72 "$env:GITHUB_WORKSPACE\crash_dumps",
73 "$env:LOCALAPPDATA\CrashDumps",
74 "$env:TEMP",
75 "$env:GITHUB_WORKSPACE",
76 "$env:USERPROFILE\AppData\Local\CrashDumps",
77 "C:\Windows\System32\config\systemprofile\AppData\Local\CrashDumps"
78 )
79
80 $dumps = @()
81 foreach ($path in $searchPaths) {
82 if (Test-Path $path) {
83 Write-Host "Searching in: $path"
84 $found = Get-ChildItem "$path\*.dmp" -ErrorAction SilentlyContinue | Where-Object {
85 $_.CreationTime -gt $runStartTime
86 }
87 if ($found) {
88 $dumps += $found
89 Write-Host " Found $($found.Count) dump(s) from this CI run"
90 }
91 }
92 }
93
94 if ($dumps) {
95 Write-Host "Found $($dumps.Count) crash dump(s)"
96
97 # Install debugging tools if not present
98 $cdbPath = "C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\cdb.exe"
99 if (-not (Test-Path $cdbPath)) {
100 Write-Host "Installing Windows Debugging Tools..."
101 $url = "https://go.microsoft.com/fwlink/?linkid=2237387"
102 Invoke-WebRequest -Uri $url -OutFile winsdksetup.exe
103 Start-Process -Wait winsdksetup.exe -ArgumentList "/features OptionId.WindowsDesktopDebuggers /quiet"
104 }
105
106 foreach ($dump in $dumps) {
107 Write-Host "`n=================================="
108 Write-Host "Analyzing crash dump: $($dump.Name)"
109 Write-Host "Size: $([math]::Round($dump.Length / 1MB, 2)) MB"
110 Write-Host "Time: $($dump.CreationTime)"
111 Write-Host "=================================="
112
113 # Set symbol path
114 $env:_NT_SYMBOL_PATH = "srv*C:\symbols*https://msdl.microsoft.com/download/symbols"
115
116 # Run analysis
117 $analysisOutput = & $cdbPath -z $dump.FullName -c "!analyze -v; ~*k; lm; q" 2>&1 | Out-String
118
119 # Extract key information
120 if ($analysisOutput -match "ExceptionCode:\s*([\w]+)") {
121 Write-Host "Exception Code: $($Matches[1])"
122 if ($Matches[1] -eq "c0000005") {
123 Write-Host "Exception Type: ACCESS VIOLATION"
124 }
125 }
126
127 if ($analysisOutput -match "EXCEPTION_RECORD:\s*(.+)") {
128 Write-Host "Exception Record: $($Matches[1])"
129 }
130
131 if ($analysisOutput -match "FAULTING_IP:\s*\n(.+)") {
132 Write-Host "Faulting Instruction: $($Matches[1])"
133 }
134
135 # Save full analysis
136 $analysisFile = "$($dump.FullName).analysis.txt"
137 $analysisOutput | Out-File -FilePath $analysisFile
138 Write-Host "`nFull analysis saved to: $analysisFile"
139
140 # Print stack trace section
141 Write-Host "`n--- Stack Trace Preview ---"
142 $stackSection = $analysisOutput -split "STACK_TEXT:" | Select-Object -Last 1
143 $stackLines = $stackSection -split "`n" | Select-Object -First 20
144 $stackLines | ForEach-Object { Write-Host $_ }
145 Write-Host "--- End Stack Trace Preview ---"
146 }
147
148 Write-Host "`nā ļø Crash dumps detected! Download the 'crash-dumps' artifact for detailed analysis."
149
150 # Copy dumps to workspace for artifact upload
151 $artifactPath = "$env:GITHUB_WORKSPACE\crash_dumps_collected"
152 New-Item -ItemType Directory -Force -Path $artifactPath | Out-Null
153
154 foreach ($dump in $dumps) {
155 $destName = "$($dump.Directory.Name)_$($dump.Name)"
156 Copy-Item $dump.FullName -Destination "$artifactPath\$destName"
157 if (Test-Path "$($dump.FullName).analysis.txt") {
158 Copy-Item "$($dump.FullName).analysis.txt" -Destination "$artifactPath\$destName.analysis.txt"
159 }
160 }
161
162 Write-Host "Copied $($dumps.Count) dump(s) to artifact directory"
163 } else {
164 Write-Host "No crash dumps from this CI run found"
165 }
166
167 - name: Upload crash dumps
168 if: always()
169 uses: actions/upload-artifact@v4
170 with:
171 name: crash-dumps-${{ github.run_id }}-${{ github.run_attempt }}
172 path: |
173 crash_dumps_collected/*.dmp
174 crash_dumps_collected/*.txt
175 if-no-files-found: ignore
176 retention-days: 7
177
178 - name: Check test results
179 shell: powershell
180 working-directory: ${{ inputs.working-directory }}
181 run: |
182 # Re-check test results to fail the job if tests failed
183 if ($LASTEXITCODE -ne 0) {
184 Write-Host "Tests failed with exit code: $LASTEXITCODE"
185 exit $LASTEXITCODE
186 }