chore: consolidate CI and expand Windows test coverage (#2498)

Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
This commit is contained in:
Jan-Otto Kröpke
2026-10-06 17:47:21 +02:00
committed by GitHub
parent 824fdb1d00
commit 72e10af92d
41 changed files with 2576 additions and 794 deletions
+33 -77
View File
@@ -1,85 +1,41 @@
$ErrorActionPreference = 'Stop'
Set-StrictMode -Version 3
# cd to location of script
$script_path = $MyInvocation.MyCommand.Path
$working_dir = Split-Path $script_path
Push-Location $working_dir
$binary = Join-Path $PSScriptRoot '..\windows_exporter.exe'
$logDir = if ($env:RUNNER_TEMP) { $env:RUNNER_TEMP } else { $env:TEMP }
$stdout = Join-Path $logDir 'windows_exporter.stdout.log'
$stderr = Join-Path $logDir 'windows_exporter.stderr.log'
$exporter = Start-Process -FilePath $binary -PassThru `
-ArgumentList '--web.listen-address=127.0.0.1:9182' `
-RedirectStandardOutput $stdout -RedirectStandardError $stderr
if (-not (Test-Path -Path '..\windows_exporter.exe')) {
Write-Output "..\windows_exporter.exe not found. Consider running \`go build\` first"
}
try {
$deadline = (Get-Date).AddSeconds(60)
do {
if ($exporter.HasExited) {
throw "windows_exporter exited with code $($exporter.ExitCode)"
}
$temp_dir = Join-Path $env:TEMP $([guid]::newguid()) | ForEach-Object { mkdir $_ }
$client = [System.Net.Sockets.TcpClient]::new()
try {
$client.Connect('127.0.0.1', 9182)
break
} catch {
if ((Get-Date) -ge $deadline) { throw 'windows_exporter did not start within 60 seconds' }
Start-Sleep -Milliseconds 200
} finally {
$client.Dispose()
}
} while ($true)
# Create temporary directory for textfile collector
$textfile_dir = "$($temp_dir)/textfile"
mkdir $textfile_dir | Out-Null
Copy-Item 'e2e-textfile.prom' -Destination "$($textfile_dir)/e2e-textfile.prom"
# Omit dynamic collector information that will change after each run
$skip_re = "^(go_|windows_exporter_build_info|windows_exporter_collector_duration_seconds|windows_exporter_scrape_duration_seconds|process_|windows_textfile_mtime_seconds|windows_cpu|windows_cache|windows_pagefile|windows_logical_disk|windows_physical_disk|windows_memory|windows_net|windows_os|windows_process|windows_service_process|windows_printer|windows_udp|windows_tcp|windows_system|windows_time|windows_session|windows_performancecounter|windows_performancecounter|windows_textfile_mtime_seconds)"
# Start process in background, awaiting HTTP requests.
# Use default collectors, port and address: http://localhost:9182/metrics
$exporter_proc = Start-Process `
-PassThru `
-FilePath ..\windows_exporter.exe `
-ArgumentList "--log.level=debug","--web.disable-exporter-metrics","--collectors.enabled=[defaults],cpu_info,textfile,process,pagefile,performancecounter,scheduled_task,tcp,udp,time,system,service,logical_disk,os,net,memory,cache","--collector.process.include=explorer.exe","--collector.scheduled_task.include=.*GAEvents","--collector.service.include=Themes","--collector.textfile.directories=$($textfile_dir)",@"
--collector.performancecounter.objects="[{\"name\":\"cpu\",\"object\":\"Processor Information\",\"instances\":[\"*\"],\"instance_label\":\"core\",\"counters\":[{\"name\":\"% Processor Time\",\"metric\":\"windows_performancecounter_processor_information_processor_time\",\"labels\":{\"state\":\"active\"}},{\"name\":\"% Idle Time\",\"metric\":\"windows_performancecounter_processor_information_processor_time\",\"labels\":{\"state\":\"idle\"}}]},{\"name\":\"memory\",\"object\":\"Memory\",\"counters\":[{\"name\":\"Cache Faults/sec\",\"type\":\"counter\"}]}]"
"@ `
-WindowStyle Hidden `
-RedirectStandardOutput "$($temp_dir)/windows_exporter.log" `
-RedirectStandardError "$($temp_dir)/windows_exporter_error.log"
# Exporter can take some time to start
for ($i=1; $i -le 1; $i++) {
Start-Sleep 10
$netstat_output = netstat -anp tcp | Select-String 'listening'
if ($netstat_output -like '*:9182*') {
break
# Metric validation belongs in Go tests. This is one binary smoke request.
$response = Invoke-WebRequest -UseBasicParsing -Uri 'http://127.0.0.1:9182/metrics' -TimeoutSec 30
if ($response.StatusCode -ne 200 -or [string]::IsNullOrWhiteSpace($response.Content)) {
throw 'windows_exporter returned an unsuccessful or empty metrics response'
}
Write-Host "Waiting for exporter to start"
}
try {
$response = Invoke-WebRequest -UseBasicParsing -URI http://127.0.0.1:9182/metrics
} catch {
Write-Host "STDOUT"
Get-Content "$($temp_dir)/windows_exporter.log"
Write-Host "STDERR"
Get-Content "$($temp_dir)/windows_exporter_error.log"
throw $_
}
# Response output must be split and saved as UTF-8.
$response.content -split "[`r`n]"| Select-String -NotMatch $skip_re | Set-Content -Encoding utf8 "$($temp_dir)/e2e-output.txt"
try {
Stop-Process -Id $exporter_proc.Id
} catch {
Write-Host "STDOUT"
Get-Content "$($temp_dir)/windows_exporter.log"
Write-Host "STDERR"
Get-Content "$($temp_dir)/windows_exporter_error.log"
throw $_
}
# Compare the expected and actual output
$output_diff = Compare-Object (Get-Content 'e2e-output.txt' | Where-Object { $_ -ne "" }) (Get-Content "$($temp_dir)/e2e-output.txt" | Where-Object { $_ -ne "" })
# Fail if differences in output are detected
if (-not ($null -eq $output_diff)) {
$output_diff | Format-Table -AutoSize | Out-String -Width 10000
Write-Host "STDOUT"
Get-Content "$($temp_dir)/windows_exporter.log"
Write-Host "----------------------------------------"
Write-Host "STDERR"
Get-Content "$($temp_dir)/windows_exporter_error.log"
(Get-Content "$($temp_dir)/e2e-output.txt") | Set-Content -Encoding utf8 "e2e-output.txt"
exit 1
Write-Host "windows_exporter returned HTTP $($response.StatusCode)"
} finally {
if (-not $exporter.HasExited) { Stop-Process -Id $exporter.Id }
Get-Content $stdout -ErrorAction SilentlyContinue
Get-Content $stderr -ErrorAction SilentlyContinue
}
-141
View File
@@ -1,141 +0,0 @@
$ErrorActionPreference = 'Stop'
Set-StrictMode -Version 3
if (-not (Test-Path -Path '.\windows_exporter.exe')) {
Write-Output ".\windows_exporter.exe not found. Consider running \`go build\` first"
}
# Powershell pipes & Get-Content command rather unhelpfully add a carriage return at the end of the string, so
# passing the string as bytes is a messy but necessary workaround for processes that are sensitive to
# line endings, like promtool.
function Start-RawProcess {
param(
# String to pass to $CommandName via STDIN
[Parameter(Mandatory=$true)][String]$InputVar,
# Command to run
[Parameter(Mandatory=$true)][String]$CommandName,
# Arguments provided to $CommandName
[Parameter(Mandatory=$false)][String[]]$CommandArgs
)
# Buffer & initial size of MemoryStream
$BufferSize = 4096
# Convert text to bytes and write to MemoryStream
[byte[]]$InputBytes = [Text.Encoding]::UTF8.GetBytes($InputVar)
$MemStream = New-Object -TypeName System.IO.MemoryStream -ArgumentList $BufferSize
$MemStream.Write($InputBytes, 0, $InputBytes.Length)
[Void]$MemStream.Seek(0, 'Begin')
# Setup stdin\stdout redirection for our process
if ($CommandArgs) {
$StartInfo = New-Object -TypeName System.Diagnostics.ProcessStartInfo -Property @{
FileName = $CommandName
UseShellExecute = $false
RedirectStandardInput = $true
RedirectStandardError = $true
Arguments = $CommandArgs
}
} else {
$StartInfo = New-Object -TypeName System.Diagnostics.ProcessStartInfo -Property @{
FileName = $CommandName
UseShellExecute = $false
RedirectStandardInput = $true
RedirectStandardError = $true
}
}
# Create new process
$Process = New-Object -TypeName System.Diagnostics.Process
# Assign previously created StartInfo properties
$Process.StartInfo = $StartInfo
# Start process
[void]$Process.Start()
# Pipe data
$Buffer = New-Object -TypeName byte[] -ArgumentList $BufferSize
$StdinStream = $Process.StandardInput.BaseStream
try {
do {
$ReadCount = $MemStream.Read($Buffer, 0, $Buffer.Length)
$StdinStream.Write($Buffer, 0, $ReadCount)
$StdinStream.Flush()
}
while($ReadCount -gt 0)
}
catch
{
throw 'Error streaming buffer to STDIN'
} finally {
# Close streams
$StdinStream.Close()
$MemStream.Close()
}
$Process.WaitForExit()
if ($Process.ExitCode -ne 0) {
Write-Host $Process.StandardError.ReadToEnd()
}
return $Process.ExitCode
}
# cd to location of script
$script_path = $MyInvocation.MyCommand.Path
$working_dir = Split-Path $script_path
Push-Location $working_dir
$temp_dir = Join-Path $env:TEMP $([guid]::newguid()) | ForEach-Object { mkdir $_ }
# Start process in background, awaiting HTTP requests.
# Listen on 9183/TCP, preventing conflicts with 9182/TCP used by end-to-end-test.ps1
# Not an issue when run individually, but will cause failures when run concurrently in CI.
$exporter_proc = Start-Process `
-PassThru `
-FilePath ..\windows_exporter.exe `
-ArgumentList '--web.listen-address="127.0.0.1:9183" --log.level=debug --collectors.enabled=[defaults],cpu_info,textfile,process,scheduled_task'`
-WindowStyle Hidden `
-RedirectStandardOutput "$($temp_dir)/windows_exporter.log" `
-RedirectStandardError "$($temp_dir)/windows_exporter_error.log"
# Exporter can take some time to start
for ($i=1; $i -le 5; $i++) {
Start-Sleep 10
$netstat_output = netstat -anp tcp | Select-String 'listening'
if ($netstat_output -like '*:9183*') {
break
}
Write-Host "Waiting for exporter to start"
}
# Omit metrics from client_golang library; we're not responsible for these
# windows_memory_pool_nonpaged_allocs_total is wrong for years. It's not a gauge, but a counter.
$skip_re = "^([#]?\s*(HELP|TYPE)?\s*go_|windows_memory_pool_nonpaged_allocs_total)"
try {
# Need to remove carriage returns, as promtool expects LF line endings
$output = ((Invoke-WebRequest -UseBasicParsing -URI http://127.0.0.1:9183/metrics).Content) -Split "`r?`n" | Select-String -NotMatch $skip_re | Join-String -Separator "`n"
# $output = (((Invoke-WebRequest -UseBasicParsing -URI http://127.0.0.1:9183/metrics).Content) -Split "`r?`n" | Select-String -NotMatch $skip_re) -join "`n"
# Join the split lines back to a single String (with LF line endings!)
$output = $output -Join "`n"
Stop-Process -Id $exporter_proc.Id
} catch {
Write-Host "STDOUT"
Get-Content "$($temp_dir)/windows_exporter.log"
Write-Host "STDERR"
Get-Content "$($temp_dir)/windows_exporter_error.log"
throw $_
}
$ExitCode = Start-RawProcess -InputVar $output -CommandName promtool.exe -CommandArgs @("check metrics")
if ($ExitCode -ne 0) {
Write-Host "OUTPUT"
Write-Host $output
Write-Host "Promtool command returned exit code $($ExitCode). See output for details."
EXIT 1
}