blob: e5e431e3b11c9f28d848c09800d26dc2b8dd7fd8 [file] [edit]
name: windows-integration-flaky
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
permissions:
contents: read
on:
workflow_dispatch:
pull_request:
env:
GO_VERSION: "1.26.10"
TEST_REPEAT: "10"
WINDOWS_BASE_IMAGE: mcr.microsoft.com/windows/servercore
WINDOWS_BASE_TAG_2025: ltsc2025
TEST_IMAGE_NAME: moby:test
TEST_CTN_NAME: moby
DOCKER_BUILDKIT: 0
jobs:
detect-tests:
if: ${{ github.event_name != 'pull_request' || !contains(github.event.pull_request.labels.*.name, 'ci/validate-only') }}
# Test detection only needs git, so run it on Linux; it is cheaper and
# avoids CRLF line endings that break sourcing the bash helpers, as the
# Windows runners check out with core.autocrlf=true.
runs-on: ubuntu-26.04
timeout-minutes: 10
outputs:
has_tests: ${{ steps.detect-tests.outputs.has_tests }}
test_flags: ${{ steps.detect-tests.outputs.test_flags }}
steps:
-
name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
-
# Use the shared integration flaky-test selector.
name: Detect new or modified integration tests
id: detect-tests
env:
PR_BODY: ${{ github.event.pull_request.body }}
VALIDATE_REPO: ${{ github.server_url }}/${{ github.repository }}.git
VALIDATE_BRANCH: ${{ github.event.pull_request.base.ref || 'master' }}
VALIDATE_ORIGIN_BRANCH: ${{ github.event.pull_request.base.sha || '' }}
run: |
source hack/make/.test-integration-flaky
export FLAKY_EXTRA_TESTS
FLAKY_EXTRA_TESTS=$(flaky_check_tests)
source hack/validate/.validate
test_filter=$(integration_flaky_test_filter)
if [ -z "$test_filter" ]; then
echo "No new or modified tests found in integration."
echo "has_tests=false" >> "$GITHUB_OUTPUT"
else
echo "Found new or modified integration tests: $test_filter"
echo "Running stress test for them."
# Match the Linux flaky-test job: run each test 10 times per test
# invocation, and invoke the tests TEST_REPEAT times.
test_flags="-test.count $TEST_REPEAT -test.run $test_filter"
echo "Using INTEGRATION_TESTFLAGS: $test_flags"
echo "test_flags=$test_flags" >> "$GITHUB_OUTPUT"
echo "has_tests=true" >> "$GITHUB_OUTPUT"
fi
build:
if: needs.detect-tests.outputs.has_tests == 'true'
needs:
- detect-tests
runs-on: windows-2025
timeout-minutes: 120 # guardrails timeout for the whole job
env:
GOPATH: ${{ github.workspace }}\go
GOBIN: ${{ github.workspace }}\go\bin
BIN_OUT: ${{ github.workspace }}\out
steps:
-
name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
-
name: Env
run: |
Get-ChildItem Env: | Out-String
-
name: Init
run: |
New-Item -ItemType "directory" -Path "${{ github.workspace }}\go-build"
New-Item -ItemType "directory" -Path "${{ github.workspace }}\go\pkg\mod"
echo "WINDOWS_BASE_IMAGE_TAG=${{ env.WINDOWS_BASE_TAG_2025 }}" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf-8 -Append
-
name: Docker info
run: |
$tries = 30
Write-Host "Waiting for Docker daemon..."
while ($true) {
$ErrorActionPreference = "SilentlyContinue"
docker version 2>&1 | Out-Null
$ok = ($LastExitCode -eq 0)
$ErrorActionPreference = "Stop"
if ($ok) { break }
# Check if Docker service exists and try to start it if stopped
$svc = Get-Service docker -ErrorAction SilentlyContinue
if ($svc) {
if ($svc.Status -ne 'Running') {
Write-Host "Docker service status: $($svc.Status) - attempting to start..."
Start-Service docker -ErrorAction SilentlyContinue
}
} else {
Write-Host "Docker service not found!"
}
$tries--
if ($tries -le 0) { throw "Docker daemon did not become ready" }
Start-Sleep -Seconds 2
}
docker info
-
name: Build base image
run: |
& docker build `
--build-arg WINDOWS_BASE_IMAGE `
--build-arg WINDOWS_BASE_IMAGE_TAG `
-t ${{ env.TEST_IMAGE_NAME }} `
-f Dockerfile.windows .
-
name: Build binaries
run: |
& docker run --name ${{ env.TEST_CTN_NAME }} -e "DOCKER_GITCOMMIT=${{ github.sha }}" `
${{ env.TEST_IMAGE_NAME }} hack\make.ps1 -Daemon -Client
-
name: Copy artifacts
run: |
New-Item -ItemType "directory" -Path "${{ env.BIN_OUT }}"
docker cp "${{ env.TEST_CTN_NAME }}`:c`:\usr\src\moby\bundles\docker.exe" ${{ env.BIN_OUT }}\
docker cp "${{ env.TEST_CTN_NAME }}`:c`:\usr\src\moby\bundles\dockerd.exe" ${{ env.BIN_OUT }}\
docker cp "${{ env.TEST_CTN_NAME }}`:c`:\usr\src\moby\bundles\docker-buildx.exe" ${{ env.BIN_OUT }}\
docker cp "${{ env.TEST_CTN_NAME }}`:c`:\gopath\bin\gotestsum.exe" ${{ env.BIN_OUT }}\
docker cp "${{ env.TEST_CTN_NAME }}`:c`:\containerd\bin\containerd.exe" ${{ env.BIN_OUT }}\
docker cp "${{ env.TEST_CTN_NAME }}`:c`:\containerd\bin\containerd-shim-runhcs-v1.exe" ${{ env.BIN_OUT }}\
Get-ChildItem -Path ${{ env.BIN_OUT }}
-
name: Upload artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: windows-integration-flaky-build
path: ${{ env.BIN_OUT }}/*
if-no-files-found: error
retention-days: 2
integration-flaky:
if: needs.detect-tests.outputs.has_tests == 'true'
needs:
- detect-tests
- build
runs-on: windows-2025
timeout-minutes: 120 # guardrails timeout for the whole job
continue-on-error: ${{ github.event_name != 'pull_request' }}
strategy:
fail-fast: false
matrix:
containerd:
- external
- embedded
env:
GOPATH: ${{ github.workspace }}\go
GOBIN: ${{ github.workspace }}\go\bin
BIN_OUT: ${{ github.workspace }}\out
INTEGRATION_TESTFLAGS: ${{ needs.detect-tests.outputs.test_flags }}
steps:
-
name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
-
name: Set up Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: ${{ env.GO_VERSION }}
cache: false
-
name: Set up OpenTelemetry Collector
id: setup-otel
run: |
New-Item -ItemType Directory -Force -Path bundles -ErrorAction Continue
Start-Process "msiexec" -ArgumentList "/i",
"https://github.com/open-telemetry/opentelemetry-collector-releases/releases/download/v$($Env:OTEL_COLLECTOR_VERSION)/otelcol_$($Env:OTEL_COLLECTOR_VERSION)_windows_x64.msi",
"/qn", "/l*v", "$(Join-Path (Get-Location) "bundles/otelcol-install.log")",
"COLLECTOR_SVC_ARGS=`"--config=`"`"file:$(Join-Path (Get-Location) "otelcol-ci-config.yml")`"`" --config=`"`"yaml:exporters::file::path: $(Join-Path (Get-Location) "bundles/otel-trace.jsonl")`"`"`"" `
-NoNewWindow -Wait
@("OTEL_EXPORTER_OTLP_ENDPOINT=http://127.0.0.1:4318", "OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf") | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf-8 -Append
shell: pwsh
env:
# Keep in sync with the version in .github/actions/setup-tracing/action.yml.
OTEL_COLLECTOR_VERSION: "0.144.0"
-
name: Env
run: |
Get-ChildItem Env: | Out-String
-
name: Init
run: |
New-Item -ItemType "directory" -Path "${{ github.workspace }}\go-build" -ErrorAction SilentlyContinue
New-Item -ItemType "directory" -Path "${{ github.workspace }}\go\pkg\mod" -ErrorAction SilentlyContinue
New-Item -ItemType "directory" -Path "bundles" -ErrorAction SilentlyContinue
New-Item -ItemType "directory" -Path "${env:ProgramData}\Docker" -ErrorAction SilentlyContinue
New-Item -ItemType "directory" -Path "${env:ProgramData}\Docker\cli-plugins" -ErrorAction SilentlyContinue
echo "WINDOWS_BASE_IMAGE_TAG=${{ env.WINDOWS_BASE_TAG_2025 }}" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf-8 -Append
Write-Output "${{ env.BIN_OUT }}" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
-
name: Download artifacts
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: windows-integration-flaky-build
path: ${{ env.BIN_OUT }}
-
name: Copy CLI plugin
run: |
Move-Item -Path "${{ env.BIN_OUT }}\docker-buildx.exe" -Destination "${env:ProgramData}\Docker\cli-plugins\docker-buildx.exe" -Force -ErrorAction Continue
-
name: Starting test daemon
id: start-daemon
uses: ./.github/actions/setup-windows-test-daemon
with:
bin_out: ${{ env.BIN_OUT }}
containerd: ${{ matrix.containerd }}
runtime: containerd
storage: snapshotter
-
name: Docker info
run: |
& "${{ env.BIN_OUT }}\docker" info
env:
DOCKER_HOST: npipe:////./pipe/docker_engine
-
name: Building contrib/busybox
run: |
$maxRetries = 5
for ($i = 1; $i -le $maxRetries; $i++) {
& "${{ env.BIN_OUT }}\docker" build -t busybox `
--build-arg WINDOWS_BASE_IMAGE `
--build-arg WINDOWS_BASE_IMAGE_TAG `
.\contrib\busybox\
if ($LASTEXITCODE -eq 0) {
break
}
if ($i -eq $maxRetries) {
Write-Error "Failed to build contrib/busybox after $maxRetries attempts"
exit 1
}
$delay = 15 * $i
Write-Warning "Build attempt $i failed (exit code: $LASTEXITCODE). Retrying in $delay seconds..."
Start-Sleep -Seconds $delay
}
env:
DOCKER_HOST: npipe:////./pipe/docker_engine
-
name: Test integration (flaky)
run: |
for ($i = 1; $i -le $Env:TEST_REPEAT; $i++) {
Write-Host "Running integration-test (iteration $i)"
.\hack\make.ps1 -TestIntegration
}
env:
DOCKER_HOST: npipe:////./pipe/docker_engine
TEST_CLIENT_BINARY: ${{ env.BIN_OUT }}\docker
-
name: Docker info
if: ${{ always() && steps.start-daemon.outcome != 'skipped' }}
run: |
& "${{ env.BIN_OUT }}\docker" info
env:
DOCKER_HOST: npipe:////./pipe/docker_engine
-
name: Stop daemon
if: always()
run: |
$ErrorActionPreference = "SilentlyContinue"
Stop-Service -Force -Name docker
$ErrorActionPreference = "Stop"
-
name: Daemon event logs
if: ${{ always() && steps.start-daemon.outcome != 'skipped' }}
run: |
New-Item -ItemType Directory -Force -Path ".\bundles" | Out-Null
Get-WinEvent -ea SilentlyContinue `
-FilterHashtable @{ProviderName= "docker"; LogName = "application"} |
Sort-Object @{Expression="TimeCreated";Descending=$false} |
ForEach-Object {"$($_.TimeCreated.ToUniversalTime().ToString("o")) [$($_.LevelDisplayName)] $($_.Message)"} |
Tee-Object -file ".\bundles\daemon.log"
-
name: Stop OpenTelemetry Collector
if: ${{ always() && steps.setup-otel.outcome != 'skipped' }}
run: |
$svc = Get-Service -DisplayName "OpenTelemetry Collector" -ErrorAction SilentlyContinue
if ($svc -and $svc.Status -ne "Stopped") {
($svc | Stop-Service -PassThru).WaitForStatus("Stopped", (New-TimeSpan -Seconds 30))
}
-
name: Upload reports
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: windows-integration-flaky-${{ matrix.containerd }}-reports
path: bundles/*
retention-days: 1