Files
2026-05-18 00:53:22 +08:00

183 lines
5.2 KiB
Batchfile

@echo off
setlocal
set "TEST_BAT_PATH=%~f0"
powershell -NoProfile -ExecutionPolicy Bypass -Command "$path=$env:TEST_BAT_PATH; $raw=Get-Content -Raw -LiteralPath $path; $marker='# POWERSHELL'; $start=$raw.LastIndexOf($marker); if($start -lt 0){ throw 'PowerShell marker not found' }; $ps=$raw.Substring($start + $marker.Length); Set-Location -LiteralPath (Split-Path -Parent $path); Invoke-Expression $ps"
exit /b %ERRORLEVEL%
# POWERSHELL
$ErrorActionPreference = 'Stop'
if (Get-Variable -Name PSNativeCommandUseErrorActionPreference -ErrorAction SilentlyContinue) {
$PSNativeCommandUseErrorActionPreference = $false
}
$forceBuild = if ($env:FORCE_BUILD) { $env:FORCE_BUILD } else { '0' }
$verbose = if ($env:VERBOSE) { $env:VERBOSE } else { '0' }
$composeBase = @('compose', '--env-file', '.env', '-f', 'compose.yml')
function Write-TaggedLine {
param([string] $Line)
if ($Line.StartsWith('[PASS]')) {
Write-Host $Line -ForegroundColor Green
} elseif ($Line.StartsWith('[NO]') -or $Line.StartsWith('reason:')) {
Write-Host $Line -ForegroundColor Red
} elseif ($Line.StartsWith('[RUN]')) {
Write-Host $Line -ForegroundColor Cyan
} elseif ($Line.StartsWith('[INFO]')) {
Write-Host $Line -ForegroundColor DarkCyan
}
}
function Invoke-Docker {
param([string[]] $Arguments)
$previousErrorActionPreference = $ErrorActionPreference
$ErrorActionPreference = 'Continue'
try {
$output = & docker @Arguments 2>&1
$code = $LASTEXITCODE
} finally {
$ErrorActionPreference = $previousErrorActionPreference
}
$lines = @(
$output | ForEach-Object {
if ($_ -is [System.Management.Automation.ErrorRecord]) {
$_.Exception.Message
} else {
$_.ToString()
}
} | Where-Object {
$_ -and $_ -ne 'System.Management.Automation.RemoteException'
}
)
[pscustomobject]@{
Code = $code
Lines = $lines
}
}
function Print-FilteredOutput {
param([string[]] $Lines)
foreach ($line in $Lines) {
if ($verbose -eq '1') {
Write-Host $line
} else {
Write-TaggedLine $line
}
}
}
function Print-FailureDiagnostics {
param([string[]] $Lines)
$hasNoLine = $Lines | Where-Object { $_.StartsWith('[NO]') } | Select-Object -First 1
if (-not $hasNoLine) {
Write-Host '--- raw docker output ---' -ForegroundColor Yellow
$Lines | Select-Object -Last 80 | ForEach-Object { Write-Host $_ }
}
}
function Build-Image {
Write-Host ''
Write-TaggedLine '[RUN] Build Bun image'
$sourceFiles = Get-ChildItem -File Dockerfile, compose.yml, .env, .env.example
$env:SOURCE_VERSION = ($sourceFiles | Sort-Object LastWriteTimeUtc -Descending | Select-Object -First 1).LastWriteTimeUtc.Ticks
$dockerArgs = $composeBase + @('build')
if ($forceBuild -eq '1') {
$dockerArgs += '--no-cache'
}
$result = Invoke-Docker $dockerArgs
if ($result.Code -ne 0) {
Write-TaggedLine '[NO] Build Bun image'
$result.Lines | ForEach-Object { Write-Host $_ }
exit $result.Code
}
Write-TaggedLine '[PASS] Build Bun image'
if ($verbose -eq '1') {
$result.Lines | ForEach-Object { Write-Host $_ }
}
}
function Run-Case {
param(
[string] $Title,
[string] $Script
)
Write-Host ''
Write-TaggedLine "[RUN] $Title"
$casePath = Join-Path (Get-Location) ('.test-case-{0}.sh' -f ([guid]::NewGuid().ToString('N')))
Set-Content -LiteralPath $casePath -Value $Script -NoNewline -Encoding Ascii
try {
$volumeArg = "${casePath}:/tmp/test-case.sh:ro"
$dockerArgs = $composeBase + @('run', '--rm', '--no-deps', '-T', '--volume', $volumeArg, 'test', 'bash', '/tmp/test-case.sh')
$result = Invoke-Docker $dockerArgs
} finally {
Remove-Item -LiteralPath $casePath -Force -ErrorAction SilentlyContinue
}
Print-FilteredOutput $result.Lines
if ($result.Code -ne 0) {
Print-FailureDiagnostics $result.Lines
}
return $result.Code
}
if (-not (Test-Path -LiteralPath '.env')) {
Write-TaggedLine '[NO] .env exists'
Write-TaggedLine 'reason: create Bun\.env from Bun\.env.example.'
exit 1
}
$tests = @(
@{
Title = 'Bun exists'
Script = @'
set -euo pipefail
bun --version >/tmp/bun-version
echo "[PASS] bun exists ($(cat /tmp/bun-version))"
'@
}
@{
Title = 'Bun uses npmmirror registry'
Script = @'
set -euo pipefail
grep -F 'registry.npmmirror.com' /root/.bunfig.toml >/dev/null
tmpdir="$(mktemp -d)"
cd "${tmpdir}"
printf '%s\n' '{"name":"bun-registry-test","version":"0.0.0","private":true,"dependencies":{"is-number":"7.0.0"}}' > package.json
bun install --lockfile-only >/tmp/bun-install.out 2>/tmp/bun-install.err
echo '[PASS] bun install uses npmmirror registry'
'@
}
)
Build-Image
$failed = $false
foreach ($test in $tests) {
$code = Run-Case -Title $test.Title -Script $test.Script
if ($code -ne 0) {
$failed = $true
}
}
Write-Host ''
if ($failed) {
Write-TaggedLine '[NO] one or more tests failed'
exit 1
}
Write-TaggedLine '[PASS] all tests passed'
exit 0