-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathci-local.ps1
More file actions
373 lines (326 loc) · 17 KB
/
ci-local.ps1
File metadata and controls
373 lines (326 loc) · 17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
# ci-local.ps1 - Cross-platform CI Test Runner for PowerShell
# Run all CI checks locally before pushing
$ErrorActionPreference = "Stop"
Write-Host "=== CI Local Test Runner ===" -ForegroundColor Cyan
# Try to find cargo in common locations
if (-not (Get-Command cargo -ErrorAction SilentlyContinue)) {
# Try common cargo locations across platforms
$cargoPaths = @(
"$env:USERPROFILE\.cargo\bin\cargo.exe",
"$env:HOME\.cargo\bin\cargo.exe",
"$env:HOME\.cargo\bin\cargo",
"C:\Users\$env:USERNAME\.cargo\bin\cargo.exe"
)
$cargoFound = $false
foreach ($cargoPath in $cargoPaths) {
if (Test-Path $cargoPath) {
$env:PATH = "$(Split-Path $cargoPath);$env:PATH"
Write-Host "* Found cargo at: $cargoPath" -ForegroundColor Green
$cargoFound = $true
break
}
}
# Final check
if (-not $cargoFound -and -not (Get-Command cargo -ErrorAction SilentlyContinue)) {
Write-Host "ERROR: cargo not found. Make sure Rust is installed." -ForegroundColor Red
Write-Host ""
Write-Host "To run CI tests:" -ForegroundColor Yellow
Write-Host " * Make sure 'cargo --version' works in your terminal" -ForegroundColor Yellow
Write-Host " * Or install Rust from https://rustup.rs/" -ForegroundColor Yellow
exit 1
}
}
Write-Host "* Using cargo: $(Get-Command cargo | Select-Object -ExpandProperty Source)" -ForegroundColor Green
# Check Rust version and warn about nightly vs stable differences
$rustVersion = & rustc --version
Write-Host "Rust version: $rustVersion" -ForegroundColor Magenta
if ($rustVersion -match "nightly") {
Write-Host "WARNING: You're using nightly Rust, but GitHub Actions uses stable!" -ForegroundColor Yellow
Write-Host " Some nightly-only APIs might work locally but fail in CI." -ForegroundColor Yellow
Write-Host " Consider testing with: rustup default stable" -ForegroundColor Yellow
} elseif ($rustVersion -match "1\.(8[8-9]|9[0-9]|\d{3})") {
Write-Host "WARNING: You're using a newer Rust version than GitHub Actions stable!" -ForegroundColor Yellow
Write-Host " GitHub Actions uses the latest stable release." -ForegroundColor Yellow
}
Write-Host ""
Write-Host "Auto-fixing common issues before CI checks" -ForegroundColor Cyan
Write-Host ""
function Run-Check {
param(
[string]$Name,
[string]$Command
)
Write-Host "Running: $Name" -ForegroundColor Blue
Write-Host "Command: $Command" -ForegroundColor Gray
$startTime = Get-Date
# Temporarily allow errors so we can check $LASTEXITCODE manually
# (cargo writes progress to stderr which triggers $ErrorActionPreference = "Stop")
$oldErrorAction = $ErrorActionPreference
$ErrorActionPreference = "Continue"
try {
Invoke-Expression "$Command 2>&1" | ForEach-Object { Write-Host $_ }
$exitCode = $LASTEXITCODE
$ErrorActionPreference = $oldErrorAction
if ($exitCode -ne 0) {
throw "Command failed with exit code $exitCode"
}
$endTime = Get-Date
$duration = ($endTime - $startTime).TotalSeconds
Write-Host "SUCCESS: $Name completed in $([math]::Round($duration))s" -ForegroundColor Green
Write-Host ""
return $true
} catch {
$ErrorActionPreference = $oldErrorAction
$endTime = Get-Date
$duration = ($endTime - $startTime).TotalSeconds
Write-Host "FAILED: $Name failed after $([math]::Round($duration))s" -ForegroundColor Red
Write-Host "ERROR: CI checks failed. Fix issues before pushing." -ForegroundColor Red
exit 1
}
}
function Run-Fix {
param(
[string]$Name,
[string]$Command
)
Write-Host "Auto-fixing: $Name" -ForegroundColor Blue
Write-Host "Command: $Command" -ForegroundColor Gray
$startTime = Get-Date
# Temporarily allow errors so we can check $LASTEXITCODE manually
$oldErrorAction = $ErrorActionPreference
$ErrorActionPreference = "Continue"
try {
Invoke-Expression "$Command 2>&1" | ForEach-Object { Write-Host $_ }
$exitCode = $LASTEXITCODE
$ErrorActionPreference = $oldErrorAction
if ($exitCode -ne 0) {
throw "Command failed with exit code $exitCode"
}
$endTime = Get-Date
$duration = ($endTime - $startTime).TotalSeconds
Write-Host "SUCCESS: $Name auto-fix completed in $([math]::Round($duration))s" -ForegroundColor Green
Write-Host ""
return $true
} catch {
$ErrorActionPreference = $oldErrorAction
$endTime = Get-Date
$duration = ($endTime - $startTime).TotalSeconds
Write-Host "WARNING: $Name auto-fix failed after $([math]::Round($duration))s" -ForegroundColor Yellow
Write-Host "WARNING: Continuing with CI checks anyway..." -ForegroundColor Yellow
Write-Host ""
return $false
}
}
# Check if we're in the right directory
if (-not (Test-Path "Cargo.toml")) {
Write-Host "ERROR: Cargo.toml not found. Are you in the project root?" -ForegroundColor Red
exit 1
}
# Validate file encodings first (critical for Cargo publish)
Write-Host "Validating UTF-8 encoding for critical files..." -ForegroundColor Cyan
function Test-Utf8Encoding {
param([string]$FilePath)
if (-not (Test-Path $FilePath)) {
Write-Host "ERROR: File not found: $FilePath" -ForegroundColor Red
return $false
}
try {
# Try to read the file as UTF-8
$content = Get-Content $FilePath -Encoding UTF8 -ErrorAction Stop
# Check for UTF-8 BOM (which should not be present)
$bytes = [System.IO.File]::ReadAllBytes($FilePath)
if ($bytes.Length -ge 3 -and $bytes[0] -eq 0xEF -and $bytes[1] -eq 0xBB -and $bytes[2] -eq 0xBF) {
Write-Host "ERROR: $FilePath contains UTF-8 BOM (should be UTF-8 without BOM)" -ForegroundColor Red
Write-Host " This can cause issues with Cargo publish and GitHub Actions" -ForegroundColor Yellow
Write-Host " Fix with: Get-Content '$FilePath' -Encoding UTF8 | Set-Content '$FilePath' -Encoding UTF8NoBOM" -ForegroundColor Yellow
return $false
}
Write-Host "SUCCESS: $FilePath - UTF-8 encoding verified, no BOM" -ForegroundColor Green
return $true
} catch {
Write-Host "ERROR: $FilePath - Not valid UTF-8 - $($_.Exception.Message)" -ForegroundColor Red
return $false
}
}
# Check critical files for encoding issues
Write-Host "Checking README.md..." -ForegroundColor Blue
if (-not (Test-Utf8Encoding "README.md")) { exit 1 }
Write-Host "Checking Cargo.toml..." -ForegroundColor Blue
if (-not (Test-Utf8Encoding "Cargo.toml")) { exit 1 }
Write-Host "Checking Rust source files..." -ForegroundColor Blue
if (Test-Path "src") {
$rustFiles = Get-ChildItem -Path "src" -Filter "*.rs" -Recurse
if ($rustFiles.Count -gt 0) {
foreach ($file in $rustFiles) {
if (-not (Test-Utf8Encoding $file.FullName)) { exit 1 }
}
Write-Host "SUCCESS: All Rust source files - UTF-8 encoding verified" -ForegroundColor Green
} else {
Write-Host "WARNING: No Rust source files found in src/" -ForegroundColor Yellow
}
} else {
Write-Host "WARNING: src/ directory not found" -ForegroundColor Yellow
}
Write-Host "SUCCESS: All file encoding checks passed!" -ForegroundColor Green
Write-Host ""
# Auto-fix common issues first
Write-Host "Auto-fixing common issues..." -ForegroundColor Cyan
Run-Fix "Format" "cargo fmt --all"
Run-Fix "Clippy Fixable Issues" "cargo clippy --fix --allow-dirty --allow-staged --all-targets --all-features"
Write-Host "Now running CI checks (same as GitHub Actions)..." -ForegroundColor Cyan
Write-Host ""
# Run all CI checks in order
Run-Check "Format Check" "cargo fmt --all -- --check"
Run-Check "Clippy Lint" "cargo clippy --all-targets --all-features -- -D warnings"
# Cross-platform Clippy: host clippy skips files gated for the OTHER platform
# (e.g., tests starting with `#![cfg(unix)]` compile to nothing on Windows, so
# clippy never lints them). Run clippy against the complement target so issues
# like `needless_borrow` in cross-platform test files are caught before CI.
if ($env:OS -eq "Windows_NT") {
$crossTarget = "x86_64-unknown-linux-gnu"
} else {
$crossTarget = "x86_64-pc-windows-gnu"
}
Write-Host "Ensuring cross-platform target '$crossTarget' is installed..." -ForegroundColor Cyan
$oldEA = $ErrorActionPreference; $ErrorActionPreference = "Continue"
& rustup target add $crossTarget 2>&1 | Out-Null
$ErrorActionPreference = $oldEA
Run-Check "Cross-platform Clippy ($crossTarget)" "cargo clippy --target $crossTarget --all-targets --all-features -- -D warnings"
# Skip 'cargo check' since 'cargo test' compiles everything anyway
# Set SKIP_PERMISSION_TESTS for local testing (symlinks may require admin/Developer Mode)
$env:SKIP_PERMISSION_TESTS = "1"
Run-Check "Tests" "cargo test --verbose"
# Test feature combinations
Write-Host ""
Write-Host "🧪 Testing feature combinations explicitly..." -ForegroundColor Cyan
Write-Host ""
Write-Host "1️⃣ Testing: anchored only" -ForegroundColor Yellow
& cargo test --features anchored --verbose
if ($LASTEXITCODE -ne 0) {
Write-Host "ERROR: Tests failed for anchored feature" -ForegroundColor Red
exit 1
}
Write-Host ""
Write-Host "2️⃣ Testing: anchored + dunce (Windows-only feature)" -ForegroundColor Yellow
& cargo test --features anchored,dunce --verbose
if ($LASTEXITCODE -ne 0) {
Write-Host "ERROR: Tests failed for anchored+dunce features" -ForegroundColor Red
exit 1
}
Write-Host ""
Write-Host "✅ Both feature combinations passed!" -ForegroundColor Green
Write-Host ""
# Doc tests are included in 'cargo test --verbose', so no separate --doc run needed
$env:RUSTDOCFLAGS = "-D warnings"
Run-Check "Documentation" "cargo doc --no-deps --document-private-items --all-features"
# Security audit (same as GitHub Actions)
Write-Host "Running security audit..." -ForegroundColor Cyan
if (Get-Command cargo-audit -ErrorAction SilentlyContinue) {
Run-Check "Security Audit" "cargo audit"
} else {
Write-Host "WARNING: cargo-audit not found. Installing..." -ForegroundColor Yellow
try {
& cargo install cargo-audit --locked
if ($LASTEXITCODE -eq 0) {
Write-Host "SUCCESS: cargo-audit installed successfully" -ForegroundColor Green
Run-Check "Security Audit" "cargo audit"
} else {
throw "cargo-audit installation failed"
}
} catch {
Write-Host "ERROR: Failed to install cargo-audit. Skipping security audit." -ForegroundColor Red
Write-Host "INFO: To install manually: cargo install cargo-audit" -ForegroundColor Yellow
}
}
# Check MSRV compatibility (same as GitHub Actions)
Write-Host "Checking Minimum Supported Rust Version (1.70.0)..." -ForegroundColor Cyan
if (Get-Command rustup -ErrorAction SilentlyContinue) {
$toolchains = & rustup toolchain list
if ($toolchains -match "1\.70\.0") {
Write-Host "SUCCESS: Found Rust 1.70.0 toolchain, checking MSRV compatibility..." -ForegroundColor Green
# Ensure Clippy is installed for MSRV
if (-not (& rustup component list --toolchain 1.70.0 | Select-String "clippy.*(installed)")) {
Write-Host "Installing Clippy for Rust 1.70.0..." -ForegroundColor Blue
& rustup component add clippy --toolchain 1.70.0
}
# Regenerate Cargo.lock with MSRV to avoid version conflicts
Write-Host "Regenerating Cargo.lock with MSRV Rust 1.70.0..." -ForegroundColor Blue
if (Test-Path "Cargo.lock") {
Write-Host " * Removing existing Cargo.lock" -ForegroundColor Gray
Remove-Item "Cargo.lock" -Force
}
Write-Host " * Generating new Cargo.lock with Rust 1.70.0" -ForegroundColor Gray
try {
& rustup run 1.70.0 cargo generate-lockfile
if ($LASTEXITCODE -eq 0) {
Write-Host " SUCCESS: Cargo.lock regenerated successfully" -ForegroundColor Green
Run-Check "MSRV Check (Rust 1.70.0)" "rustup run 1.70.0 cargo check --verbose"
Run-Check "MSRV Clippy Lint" "rustup run 1.70.0 cargo clippy --all-targets --all-features -- -D warnings"
$oldEA2 = $ErrorActionPreference; $ErrorActionPreference = "Continue"
& rustup target add $crossTarget --toolchain 1.70.0 2>&1 | Out-Null
$ErrorActionPreference = $oldEA2
Run-Check "MSRV Cross-platform Clippy ($crossTarget)" "rustup run 1.70.0 cargo clippy --target $crossTarget --all-targets --all-features -- -D warnings"
} else {
throw "generate-lockfile failed"
}
} catch {
Write-Host " WARNING: Failed to generate Cargo.lock with Rust 1.70.0" -ForegroundColor Yellow
Write-Host " INFO: Trying fallback: cargo update then check" -ForegroundColor Yellow
Run-Check "MSRV Check (Rust 1.70.0)" "rustup run 1.70.0 cargo check --verbose"
Run-Check "MSRV Clippy Lint" "rustup run 1.70.0 cargo clippy --all-targets --all-features -- -D warnings"
& rustup target add $crossTarget --toolchain 1.70.0 2>&1 | Out-Null
Run-Check "MSRV Cross-platform Clippy ($crossTarget)" "rustup run 1.70.0 cargo clippy --target $crossTarget --all-targets --all-features -- -D warnings"
}
} else {
Write-Host "WARNING: Rust 1.70.0 not installed. Installing for MSRV check..." -ForegroundColor Yellow
try {
& rustup toolchain install 1.70.0
if ($LASTEXITCODE -eq 0) {
Write-Host "Installing Clippy for Rust 1.70.0..." -ForegroundColor Blue
& rustup component add clippy --toolchain 1.70.0
Write-Host "Regenerating Cargo.lock with MSRV Rust 1.70.0..." -ForegroundColor Blue
if (Test-Path "Cargo.lock") {
Write-Host " * Removing existing Cargo.lock" -ForegroundColor Gray
Remove-Item "Cargo.lock" -Force
}
Write-Host " * Generating new Cargo.lock with Rust 1.70.0" -ForegroundColor Gray
try {
& rustup run 1.70.0 cargo generate-lockfile
if ($LASTEXITCODE -eq 0) {
Write-Host " SUCCESS: Cargo.lock regenerated successfully" -ForegroundColor Green
Run-Fix "MSRV Clippy Auto-fix" "rustup run 1.70.0 cargo clippy --fix --allow-dirty --allow-staged --all-targets --all-features"
Run-Check "MSRV Check (Rust 1.70.0)" "rustup run 1.70.0 cargo check --verbose"
Run-Check "MSRV Clippy Lint" "rustup run 1.70.0 cargo clippy --all-targets --all-features -- -D warnings"
$oldEA2 = $ErrorActionPreference; $ErrorActionPreference = "Continue"
& rustup target add $crossTarget --toolchain 1.70.0 2>&1 | Out-Null
$ErrorActionPreference = $oldEA2
Run-Check "MSRV Cross-platform Clippy ($crossTarget)" "rustup run 1.70.0 cargo clippy --target $crossTarget --all-targets --all-features -- -D warnings"
} else {
throw "generate-lockfile failed"
}
} catch {
Write-Host " WARNING: Failed to generate Cargo.lock with Rust 1.70.0" -ForegroundColor Yellow
Write-Host " INFO: Trying fallback: cargo update then check" -ForegroundColor Yellow
Run-Fix "MSRV Clippy Auto-fix" "rustup run 1.70.0 cargo clippy --fix --allow-dirty --allow-staged --all-targets --all-features"
Run-Check "MSRV Check (Rust 1.70.0)" "rustup run 1.70.0 cargo check --verbose"
Run-Check "MSRV Clippy Lint" "rustup run 1.70.0 cargo clippy --all-targets --all-features -- -D warnings"
$oldEA2 = $ErrorActionPreference; $ErrorActionPreference = "Continue"
& rustup target add $crossTarget --toolchain 1.70.0 2>&1 | Out-Null
$ErrorActionPreference = $oldEA2
Run-Check "MSRV Cross-platform Clippy ($crossTarget)" "rustup run 1.70.0 cargo clippy --target $crossTarget --all-targets --all-features -- -D warnings"
}
} else {
throw "toolchain install failed"
}
} catch {
Write-Host "ERROR: Failed to install Rust 1.70.0. Skipping MSRV check." -ForegroundColor Red
Write-Host "INFO: To install manually: rustup toolchain install 1.70.0" -ForegroundColor Yellow
}
}
} else {
Write-Host "WARNING: rustup not found. Skipping MSRV check." -ForegroundColor Yellow
Write-Host "INFO: MSRV check requires rustup to install Rust 1.70.0" -ForegroundColor Yellow
}
Write-Host "SUCCESS: All CI checks passed!" -ForegroundColor Green
Write-Host "INFO: Remember to review and commit any auto-fixes made." -ForegroundColor Blue
Write-Host "Ready to push to remote." -ForegroundColor Green