ci(integration-cli): split test suites in a matrix
Split `DockerSuite` for `integration-cli` tests so we can create a matrix to reduce build time in our pipeline (windows atm). We could also use `tags` for this purpose. Let me know what sounds better to you. Keeping the working tree like this for visibility but will squash commits if it sgty.

Here is the overall build time for each of them after splitting (still windows):

```
- DockerApiSuite: ~12m06s
- DockerBenchmarkSuite: ~11s
- DockerCliAttachSuite: ~16s
- DockerCliBuildSuite: ~16m33s
- DockerCliCommitSuite: ~33s
- DockerCliCpSuite: ~54s
- DockerCliCreateSuite: ~45s
- DockerCliEventSuite: ~1m31s
- DockerCliExecSuite: ~26s
- DockerCliHealthSuite: ~8s
- DockerCliHistorySuite: ~32s
- DockerCliImagesSuite: ~27s
- DockerCliImportSuite: ~8s
- DockerCliInfoSuite: ~8s
- DockerCliInspectSuite: ~52s
- DockerCliLinksSuite: ~9s
- DockerCliLoginSuite: ~8s
- DockerCliLogsSuite: ~48s
- DockerCliNetmodeSuite: ~8s
- DockerCliNetworkSuite: ~8s
- DockerCliPluginLogDriverSuite: ~8s
- DockerCliPluginsSuite: ~10s
- DockerCliPortSuite: ~11s
- DockerCliProxySuite: ~8s
- DockerCliPruneSuite: ~9s
- DockerCliPsSuite: ~1m19s
- DockerCliPullSuite: ~9s
- DockerCliPushSuite: ~13s
- DockerCliRestartSuite: ~58s
- DockerCliRmiSuite: ~1m52s
- DockerCliRunSuite: ~4m07s
- DockerCliSaveLoadSuite: ~8s
- DockerCliSearchSuite: ~11s
- DockerCliSniSuite: ~10s
- DockerCliStartSuite: ~26s
- DockerCliStatsSuite: ~7s
- DockerCliTopSuite: ~16s
- DockerCliUpdateSuite: ~11s
- DockerNetworkSuite|DockerHubPullSuite|DockerRegistrySuite|DockerSchema1RegistrySuite|DockerRegistryAuthTokenSuite|DockerRegistryAuthHtpasswdSuite: ~11s
- DockerSwarmSuite: ~8s
- DockerDaemonSuite: ~8s
- DockerExternalVolumeSuite: ~7s
```

Before ~1h20m

After ~42m

![image](https://user-images.githubusercontent.com/1951866/171687129-9ee7b1c2-ce0d-413c-a119-6b853f7fb06b.png)

.github/workflows/windows.yml
name: windows

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

on:
  workflow_dispatch:
  push:
    branches:
      - 'master'
      - '[0-9]+.[0-9]{2}'
    tags:
      - 'v*'
  pull_request:

env:
  GO_VERSION: 1.18.3
  WINDOWS_BASE_IMAGE: mcr.microsoft.com/windows/servercore
  WINDOWS_BASE_TAG_2019: ltsc2019
  WINDOWS_BASE_TAG_2022: ltsc2022
  TEST_IMAGE_NAME: moby:test
  TEST_CTN_NAME: moby
  DOCKER_BUILDKIT: 0

jobs:
  build:
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os:
          - windows-2019
          - windows-2022
    env:
      GOPATH: ${{ github.workspace }}\go
      GOBIN: ${{ github.workspace }}\go\bin
      BIN_OUT: ${{ github.workspace }}\out
    defaults:
      run:
        working-directory: ${{ env.GOPATH }}/src/github.com/docker/docker
    steps:
      -
        name: Checkout
        uses: actions/checkout@v3
        with:
          path: ${{ env.GOPATH }}/src/github.com/docker/docker
      -
        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"
          If ("${{ matrix.os }}" -eq "windows-2019") {
            echo "WINDOWS_BASE_IMAGE_TAG=${{ env.WINDOWS_BASE_TAG_2019 }}" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf-8 -Append
          } ElseIf ("${{ matrix.os }}" -eq "windows-2022") {
            echo "WINDOWS_BASE_IMAGE_TAG=${{ env.WINDOWS_BASE_TAG_2022 }}" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf-8 -Append
          }
      -
        name: Cache
        uses: actions/cache@v3
        with:
          path: |
            ~\AppData\Local\go-build
            ~\go\pkg\mod
            ${{ github.workspace }}\go-build
            ${{ env.GOPATH }}\pkg\mod
          key: ${{ matrix.os }}-${{ github.job }}-${{ hashFiles('**/vendor.sum') }}
          restore-keys: |
            ${{ matrix.os }}-${{ github.job }}-
      -
        name: Docker info
        run: |
          docker info
      -
        name: Build base image
        run: |
          docker pull ${{ env.WINDOWS_BASE_IMAGE }}:${{ env.WINDOWS_BASE_IMAGE_TAG }}
          docker tag ${{ env.WINDOWS_BASE_IMAGE }}:${{ env.WINDOWS_BASE_IMAGE_TAG }} microsoft/windowsservercore
          docker build --build-arg GO_VERSION -t ${{ env.TEST_IMAGE_NAME }} -f Dockerfile.windows .
      -
        name: Build binaries
        run: |
          & docker run --name ${{ env.TEST_CTN_NAME }} -e "DOCKER_GITCOMMIT=${{ github.sha }}" `
              -v "${{ github.workspace }}\go-build:C:\Users\ContainerAdministrator\AppData\Local\go-build" `
              -v "${{ github.workspace }}\go\pkg\mod:C:\gopath\pkg\mod" `
              ${{ 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`:\gopath\src\github.com\docker\docker\bundles\docker.exe" ${{ env.BIN_OUT }}\
          docker cp "${{ env.TEST_CTN_NAME }}`:c`:\gopath\src\github.com\docker\docker\bundles\dockerd.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 }}\
      -
        name: Upload artifacts
        uses: actions/upload-artifact@v3
        with:
          name: build-${{ matrix.os }}
          path: ${{ env.BIN_OUT }}/*
          if-no-files-found: error
          retention-days: 2

  unit-test:
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os:
          - windows-2019
          - windows-2022
    env:
      GOPATH: ${{ github.workspace }}\go
      GOBIN: ${{ github.workspace }}\go\bin
    defaults:
      run:
        working-directory: ${{ env.GOPATH }}/src/github.com/docker/docker
    steps:
      -
        name: Checkout
        uses: actions/checkout@v3
        with:
          path: ${{ env.GOPATH }}/src/github.com/docker/docker
      -
        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"
          New-Item -ItemType "directory" -Path "bundles"
          If ("${{ matrix.os }}" -eq "windows-2019") {
            echo "WINDOWS_BASE_IMAGE_TAG=${{ env.WINDOWS_BASE_TAG_2019 }}" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf-8 -Append
          } ElseIf ("${{ matrix.os }}" -eq "windows-2022") {
            echo "WINDOWS_BASE_IMAGE_TAG=${{ env.WINDOWS_BASE_TAG_2022 }}" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf-8 -Append
          }
      -
        name: Cache
        uses: actions/cache@v3
        with:
          path: |
            ~\AppData\Local\go-build
            ~\go\pkg\mod
            ${{ github.workspace }}\go-build
            ${{ env.GOPATH }}\pkg\mod
          key: ${{ matrix.os }}-${{ github.job }}-${{ hashFiles('**/vendor.sum') }}
          restore-keys: |
            ${{ matrix.os }}-${{ github.job }}-
      -
        name: Docker info
        run: |
          docker info
      -
        name: Build base image
        run: |
          docker pull ${{ env.WINDOWS_BASE_IMAGE }}:${{ env.WINDOWS_BASE_IMAGE_TAG }}
          docker tag ${{ env.WINDOWS_BASE_IMAGE }}:${{ env.WINDOWS_BASE_IMAGE_TAG }} microsoft/windowsservercore
          docker build --build-arg GO_VERSION -t ${{ env.TEST_IMAGE_NAME }} -f Dockerfile.windows .
      -
        name: Test
        run: |
          & docker run --name ${{ env.TEST_CTN_NAME }} -e "DOCKER_GITCOMMIT=${{ github.sha }}" `
            -v "${{ github.workspace }}\go-build:C:\Users\ContainerAdministrator\AppData\Local\go-build" `
            -v "${{ github.workspace }}\go\pkg\mod:C:\gopath\pkg\mod" `
            -v "${{ env.GOPATH }}\src\github.com\docker\docker\bundles:C:\gopath\src\github.com\docker\docker\bundles" `
            ${{ env.TEST_IMAGE_NAME }} hack\make.ps1 -TestUnit
      -
        name: Send to Codecov
        if: matrix.os == 'windows-2022'
        uses: codecov/codecov-action@v3
        with:
          working-directory: ${{ env.GOPATH }}\src\github.com\docker\docker
          directory: bundles
          env_vars: RUNNER_OS
          flags: unit
      -
        name: Upload reports
        if: always()
        uses: actions/upload-artifact@v3
        with:
          name: ${{ matrix.os }}-unit-reports
          path: ${{ env.GOPATH }}\src\github.com\docker\docker\bundles\*

  integration-test:
    runs-on: ${{ matrix.os }}
    needs:
      - build
    strategy:
      fail-fast: false
      matrix:
        os:
          - windows-2019
          - windows-2022
        runtime:
          - builtin
          - containerd
    env:
      GOPATH: ${{ github.workspace }}\go
      GOBIN: ${{ github.workspace }}\go\bin
      BIN_OUT: ${{ github.workspace }}\out
    defaults:
      run:
        working-directory: ${{ env.GOPATH }}/src/github.com/docker/docker
    steps:
      -
        name: Checkout
        uses: actions/checkout@v3
        with:
          path: ${{ env.GOPATH }}/src/github.com/docker/docker
      -
        name: Env
        run: |
          Get-ChildItem Env: | Out-String
      -
        name: Download artifacts
        uses: actions/download-artifact@v3
        with:
          name: build-${{ matrix.os }}
          path: ${{ env.BIN_OUT }}
      -
        name: Init
        run: |
          New-Item -ItemType "directory" -Path "bundles"
          If ("${{ matrix.os }}" -eq "windows-2019") {
            echo "WINDOWS_BASE_IMAGE_TAG=${{ env.WINDOWS_BASE_TAG_2019 }}" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf-8 -Append
          } ElseIf ("${{ matrix.os }}" -eq "windows-2022") {
            echo "WINDOWS_BASE_IMAGE_TAG=${{ env.WINDOWS_BASE_TAG_2022 }}" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf-8 -Append
          }
          Write-Output "${{ env.BIN_OUT }}" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
      -
        # removes docker service that is currently installed on the runner. we
        # could use Uninstall-Package but not yet available on Windows runners.
        # more info: https://github.com/actions/virtual-environments/blob/d3a5bad25f3b4326c5666bab0011ac7f1beec95e/images/win/scripts/Installers/Install-Docker.ps1#L11
        name: Removing current daemon
        run: |
          if (Get-Service docker -ErrorAction SilentlyContinue) {
            $dockerVersion = (docker version -f "{{.Server.Version}}")
            Write-Host "Current installed Docker version: $dockerVersion"
            # remove service
            Stop-Service -Force -Name docker
            Remove-Service -Name docker
            # removes event log entry. we could use "Remove-EventLog -LogName -Source docker"
            # but this cmd is only available since windows-2022
            $ErrorActionPreference = "SilentlyContinue"
            & reg delete "HKLM\SYSTEM\CurrentControlSet\Services\EventLog\Application\docker" /f 2>&1 | Out-Null
            $ErrorActionPreference = "Stop"
            Write-Host "Service removed"
          }
      -
        name: Starting containerd
        if: matrix.runtime == 'containerd'
        run: |
          Write-Host "Generating config"
          & "${{ env.BIN_OUT }}\containerd.exe" config default | Out-File "$env:TEMP\ctn.toml" -Encoding ascii
          Write-Host "Creating service"
          New-Item -ItemType Directory "$env:TEMP\ctn-root" -ErrorAction SilentlyContinue | Out-Null
          New-Item -ItemType Directory "$env:TEMP\ctn-state" -ErrorAction SilentlyContinue | Out-Null
          Start-Process -Wait "${{ env.BIN_OUT }}\containerd.exe" `
            -ArgumentList "--log-level=debug", `
              "--config=$env:TEMP\ctn.toml", `
              "--address=\\.\pipe\containerd-containerd", `
              "--root=$env:TEMP\ctn-root", `
              "--state=$env:TEMP\ctn-state", `
              "--log-file=$env:TEMP\ctn.log", `
              "--register-service"
          Write-Host "Starting service"
          Start-Service -Name containerd
          Start-Sleep -Seconds 5
          Write-Host "Service started successfully!"
      -
        name: Starting test daemon
        run: |
          Write-Host "Creating service"
          If ("${{ matrix.runtime }}" -eq "containerd") {
            $runtimeArg="--containerd=\\.\pipe\containerd-containerd"
            echo "DOCKER_WINDOWS_CONTAINERD_RUNTIME=1" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf-8 -Append
          }
          New-Item -ItemType Directory "$env:TEMP\moby-root" -ErrorAction SilentlyContinue | Out-Null
          New-Item -ItemType Directory "$env:TEMP\moby-exec" -ErrorAction SilentlyContinue | Out-Null
          Start-Process -Wait -NoNewWindow "${{ env.BIN_OUT }}\dockerd" `
            -ArgumentList $runtimeArg, "--debug", `
              "--host=npipe:////./pipe/docker_engine", `
              "--data-root=$env:TEMP\moby-root", `
              "--exec-root=$env:TEMP\moby-exec", `
              "--pidfile=$env:TEMP\docker.pid", `
              "--register-service"
          Write-Host "Starting service"
          Start-Service -Name docker
          Write-Host "Service started successfully!"
      -
        name: Waiting for test daemon to start
        run: |
          $tries=20
          Write-Host "Waiting for the test daemon to start..."
          While ($true) {
            $ErrorActionPreference = "SilentlyContinue"
            & "${{ env.BIN_OUT }}\docker" version
            $ErrorActionPreference = "Stop"
            If ($LastExitCode -eq 0) {
              break
            }
            $tries--
            If ($tries -le 0) {
              Throw "Failed to get a response from the daemon"
            }
            Write-Host -NoNewline "."
            Start-Sleep -Seconds 1
          }
          Write-Host "Test daemon started and replied!"
        env:
          DOCKER_HOST: npipe:////./pipe/docker_engine
      -
        name: Docker info
        run: |
          & "${{ env.BIN_OUT }}\docker" info
        env:
          DOCKER_HOST: npipe:////./pipe/docker_engine
      -
        name: Building contrib/busybox
        run: |
          & "${{ env.BIN_OUT }}\docker" build -t busybox `
            --build-arg WINDOWS_BASE_IMAGE `
            --build-arg WINDOWS_BASE_IMAGE_TAG `
            .\contrib\busybox\
        env:
          DOCKER_HOST: npipe:////./pipe/docker_engine
      -
        name: List images
        run: |
          & "${{ env.BIN_OUT }}\docker" images
        env:
          DOCKER_HOST: npipe:////./pipe/docker_engine
      -
        name: Set up Go
        uses: actions/setup-go@v3
        with:
          go-version: ${{ env.GO_VERSION }}
      -
        name: Test API
        run: |
          .\hack\make.ps1 -TestIntegration
        env:
          DOCKER_HOST: npipe:////./pipe/docker_engine
          GO111MODULE: "off"
          TEST_CLIENT_BINARY: ${{ env.BIN_OUT }}\docker
      -
        name: Test CLI
        run: |
          & gotestsum `
            --format=standard-verbose `
            --jsonfile="./bundles/go-test-report-int-cli-tests.json" `
            --junitfile="./bundles/junit-report-int-cli-tests.xml" `
            --packages="./integration-cli/..." `
            -- `
              "-coverprofile" "./bundles/coverage-report-int-cli-tests.txt" `
              "-covermode" "atomic" `
              "-tags" "autogen" `
              "-test.timeout" "200m"
        env:
          DOCKER_HOST: npipe:////./pipe/docker_engine
          GO111MODULE: "off"
          TEST_CLIENT_BINARY: ${{ env.BIN_OUT }}\docker
      -
        name: Send to Codecov
        if: matrix.os == 'windows-2022'
        uses: codecov/codecov-action@v3
        with:
          working-directory: ${{ env.GOPATH }}\src\github.com\docker\docker
          directory: bundles
          env_vars: RUNNER_OS
          flags: integration,${{ matrix.runtime }}
      -
        name: Docker info
        run: |
          & "${{ env.BIN_OUT }}\docker" info
        env:
          DOCKER_HOST: npipe:////./pipe/docker_engine
      -
        name: Stop containerd
        if: always() && matrix.runtime == 'containerd'
        run: |
          $ErrorActionPreference = "SilentlyContinue"
          Stop-Service -Force -Name containerd
          $ErrorActionPreference = "Stop"
      -
        name: Containerd logs
        if: always() && matrix.runtime == 'containerd'
        run: |
          Copy-Item "$env:TEMP\ctn.log" -Destination ".\bundles\containerd.log"
          Get-Content "$env:TEMP\ctn.log" | Out-Host
      -
        name: Stop daemon
        if: always()
        run: |
          $ErrorActionPreference = "SilentlyContinue"
          Stop-Service -Force -Name docker
          $ErrorActionPreference = "Stop"
      -
        # as the daemon is registered as a service we have to check the event
        # logs against the docker provider.
        name: Daemon event logs
        if: always()
        run: |
          Get-WinEvent -ea SilentlyContinue `
            -FilterHashtable @{ProviderName= "docker"; LogName = "application"} |
              Select-Object -Property TimeCreated, @{N='Detailed Message'; E={$_.Message}} |
              Sort-Object @{Expression="TimeCreated";Descending=$false} |
              Select-Object -ExpandProperty 'Detailed Message' | Tee-Object -file ".\bundles\daemon.log"
      -
        name: Upload reports
        if: always()
        uses: actions/upload-artifact@v3
        with:
          name: ${{ matrix.os }}-integration-reports-${{ matrix.runtime }}
          path: ${{ env.GOPATH }}\src\github.com\docker\docker\bundles\*

name: windows

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

on:
  workflow_dispatch:
  push:
    branches:
      - 'master'
      - '[0-9]+.[0-9]{2}'
    tags:
      - 'v*'
  pull_request:

env:
  GO_VERSION: 1.18.3
  GOTESTLIST_VERSION: v0.2.0
  TESTSTAT_VERSION: v0.1.3
  WINDOWS_BASE_IMAGE: mcr.microsoft.com/windows/servercore
  WINDOWS_BASE_TAG_2019: ltsc2019
  WINDOWS_BASE_TAG_2022: ltsc2022
  TEST_IMAGE_NAME: moby:test
  TEST_CTN_NAME: moby
  DOCKER_BUILDKIT: 0

jobs:
  build:
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os:
          - windows-2019
          - windows-2022
    env:
      GOPATH: ${{ github.workspace }}\go
      GOBIN: ${{ github.workspace }}\go\bin
      BIN_OUT: ${{ github.workspace }}\out
    defaults:
      run:
        working-directory: ${{ env.GOPATH }}/src/github.com/docker/docker
    steps:
      -
        name: Checkout
        uses: actions/checkout@v3
        with:
          path: ${{ env.GOPATH }}/src/github.com/docker/docker
      -
        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"
          If ("${{ matrix.os }}" -eq "windows-2019") {
            echo "WINDOWS_BASE_IMAGE_TAG=${{ env.WINDOWS_BASE_TAG_2019 }}" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf-8 -Append
          } ElseIf ("${{ matrix.os }}" -eq "windows-2022") {
            echo "WINDOWS_BASE_IMAGE_TAG=${{ env.WINDOWS_BASE_TAG_2022 }}" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf-8 -Append
          }
      -
        name: Cache
        uses: actions/cache@v3
        with:
          path: |
            ~\AppData\Local\go-build
            ~\go\pkg\mod
            ${{ github.workspace }}\go-build
            ${{ env.GOPATH }}\pkg\mod
          key: ${{ matrix.os }}-${{ github.job }}-${{ hashFiles('**/vendor.sum') }}
          restore-keys: |
            ${{ matrix.os }}-${{ github.job }}-
      -
        name: Docker info
        run: |
          docker info
      -
        name: Build base image
        run: |
          docker pull ${{ env.WINDOWS_BASE_IMAGE }}:${{ env.WINDOWS_BASE_IMAGE_TAG }}
          docker tag ${{ env.WINDOWS_BASE_IMAGE }}:${{ env.WINDOWS_BASE_IMAGE_TAG }} microsoft/windowsservercore
          docker build --build-arg GO_VERSION -t ${{ env.TEST_IMAGE_NAME }} -f Dockerfile.windows .
      -
        name: Build binaries
        run: |
          & docker run --name ${{ env.TEST_CTN_NAME }} -e "DOCKER_GITCOMMIT=${{ github.sha }}" `
              -v "${{ github.workspace }}\go-build:C:\Users\ContainerAdministrator\AppData\Local\go-build" `
              -v "${{ github.workspace }}\go\pkg\mod:C:\gopath\pkg\mod" `
              ${{ 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`:\gopath\src\github.com\docker\docker\bundles\docker.exe" ${{ env.BIN_OUT }}\
          docker cp "${{ env.TEST_CTN_NAME }}`:c`:\gopath\src\github.com\docker\docker\bundles\dockerd.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 }}\
      -
        name: Upload artifacts
        uses: actions/upload-artifact@v3
        with:
          name: build-${{ matrix.os }}
          path: ${{ env.BIN_OUT }}/*
          if-no-files-found: error
          retention-days: 2

  unit-test:
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os:
          - windows-2019
          - windows-2022
    env:
      GOPATH: ${{ github.workspace }}\go
      GOBIN: ${{ github.workspace }}\go\bin
    defaults:
      run:
        working-directory: ${{ env.GOPATH }}/src/github.com/docker/docker
    steps:
      -
        name: Checkout
        uses: actions/checkout@v3
        with:
          path: ${{ env.GOPATH }}/src/github.com/docker/docker
      -
        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"
          New-Item -ItemType "directory" -Path "bundles"
          If ("${{ matrix.os }}" -eq "windows-2019") {
            echo "WINDOWS_BASE_IMAGE_TAG=${{ env.WINDOWS_BASE_TAG_2019 }}" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf-8 -Append
          } ElseIf ("${{ matrix.os }}" -eq "windows-2022") {
            echo "WINDOWS_BASE_IMAGE_TAG=${{ env.WINDOWS_BASE_TAG_2022 }}" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf-8 -Append
          }
      -
        name: Cache
        uses: actions/cache@v3
        with:
          path: |
            ~\AppData\Local\go-build
            ~\go\pkg\mod
            ${{ github.workspace }}\go-build
            ${{ env.GOPATH }}\pkg\mod
          key: ${{ matrix.os }}-${{ github.job }}-${{ hashFiles('**/vendor.sum') }}
          restore-keys: |
            ${{ matrix.os }}-${{ github.job }}-
      -
        name: Docker info
        run: |
          docker info
      -
        name: Build base image
        run: |
          docker pull ${{ env.WINDOWS_BASE_IMAGE }}:${{ env.WINDOWS_BASE_IMAGE_TAG }}
          docker tag ${{ env.WINDOWS_BASE_IMAGE }}:${{ env.WINDOWS_BASE_IMAGE_TAG }} microsoft/windowsservercore
          docker build --build-arg GO_VERSION -t ${{ env.TEST_IMAGE_NAME }} -f Dockerfile.windows .
      -
        name: Test
        run: |
          & docker run --name ${{ env.TEST_CTN_NAME }} -e "DOCKER_GITCOMMIT=${{ github.sha }}" `
            -v "${{ github.workspace }}\go-build:C:\Users\ContainerAdministrator\AppData\Local\go-build" `
            -v "${{ github.workspace }}\go\pkg\mod:C:\gopath\pkg\mod" `
            -v "${{ env.GOPATH }}\src\github.com\docker\docker\bundles:C:\gopath\src\github.com\docker\docker\bundles" `
            ${{ env.TEST_IMAGE_NAME }} hack\make.ps1 -TestUnit
      -
        name: Send to Codecov
        if: matrix.os == 'windows-2022'
        uses: codecov/codecov-action@v3
        with:
          working-directory: ${{ env.GOPATH }}\src\github.com\docker\docker
          directory: bundles
          env_vars: RUNNER_OS
          flags: unit
      -
        name: Upload reports
        if: always()
        uses: actions/upload-artifact@v3
        with:
          name: ${{ matrix.os }}-unit-reports
          path: ${{ env.GOPATH }}\src\github.com\docker\docker\bundles\*

  unit-test-report:
    runs-on: ubuntu-latest
    if: always()
    needs:
      - unit-test
    strategy:
      fail-fast: false
      matrix:
        os:
          - windows-2019
          - windows-2022
    steps:
      -
        name: Set up Go
        uses: actions/setup-go@v3
        with:
          go-version: ${{ env.GO_VERSION }}
      -
        name: Download artifacts
        uses: actions/download-artifact@v3
        with:
          name: ${{ matrix.os }}-unit-reports
          path: /tmp/artifacts
      -
        name: Install teststat
        run: |
          go install github.com/vearutop/teststat@${{ env.TESTSTAT_VERSION }}
      -
        name: Create summary
        run: |
          teststat -markdown $(find /tmp/artifacts -type f -name '*.json' -print0 | xargs -0) >> $GITHUB_STEP_SUMMARY

  integration-test-prepare:
    runs-on: ubuntu-latest
    outputs:
      matrix: ${{ steps.tests.outputs.matrix }}
    steps:
      -
        name: Checkout
        uses: actions/checkout@v3
      -
        name: Set up Go
        uses: actions/setup-go@v3
        with:
          go-version: ${{ env.GO_VERSION }}
      -
        name: Install gotestlist
        run:
          go install github.com/crazy-max/gotestlist/cmd/gotestlist@${{ env.GOTESTLIST_VERSION }}
      -
        name: Create matrix
        id: tests
        working-directory: ./integration-cli
        run: |
          # Distribute integration-cli tests for the matrix in integration-test job.
          # Also prepend ./... to the matrix. This is a special case to run "Test integration" step exclusively.
          matrix="$(gotestlist -d 4 ./...)"
          matrix="$(echo "$matrix" | jq -c '. |= ["./..."] + .')"
          echo "::set-output name=matrix::$matrix"
      -
        name: Show matrix
        run: |
          echo ${{ steps.tests.outputs.matrix }}

  integration-test:
    runs-on: ${{ matrix.os }}
    needs:
      - build
      - integration-test-prepare
    strategy:
      fail-fast: false
      matrix:
        os:
          - windows-2019
          - windows-2022
        runtime:
          - builtin
          - containerd
        test: ${{ fromJson(needs.integration-test-prepare.outputs.matrix) }}
    env:
      GOPATH: ${{ github.workspace }}\go
      GOBIN: ${{ github.workspace }}\go\bin
      BIN_OUT: ${{ github.workspace }}\out
    defaults:
      run:
        working-directory: ${{ env.GOPATH }}/src/github.com/docker/docker
    steps:
      -
        name: Checkout
        uses: actions/checkout@v3
        with:
          path: ${{ env.GOPATH }}/src/github.com/docker/docker
      -
        name: Env
        run: |
          Get-ChildItem Env: | Out-String
      -
        name: Download artifacts
        uses: actions/download-artifact@v3
        with:
          name: build-${{ matrix.os }}
          path: ${{ env.BIN_OUT }}
      -
        name: Init
        run: |
          New-Item -ItemType "directory" -Path "bundles"
          If ("${{ matrix.os }}" -eq "windows-2019") {
            echo "WINDOWS_BASE_IMAGE_TAG=${{ env.WINDOWS_BASE_TAG_2019 }}" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf-8 -Append
          } ElseIf ("${{ matrix.os }}" -eq "windows-2022") {
            echo "WINDOWS_BASE_IMAGE_TAG=${{ env.WINDOWS_BASE_TAG_2022 }}" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf-8 -Append
          }
          Write-Output "${{ env.BIN_OUT }}" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
      -
        # removes docker service that is currently installed on the runner. we
        # could use Uninstall-Package but not yet available on Windows runners.
        # more info: https://github.com/actions/virtual-environments/blob/d3a5bad25f3b4326c5666bab0011ac7f1beec95e/images/win/scripts/Installers/Install-Docker.ps1#L11
        name: Removing current daemon
        run: |
          if (Get-Service docker -ErrorAction SilentlyContinue) {
            $dockerVersion = (docker version -f "{{.Server.Version}}")
            Write-Host "Current installed Docker version: $dockerVersion"
            # remove service
            Stop-Service -Force -Name docker
            Remove-Service -Name docker
            # removes event log entry. we could use "Remove-EventLog -LogName -Source docker"
            # but this cmd is only available since windows-2022
            $ErrorActionPreference = "SilentlyContinue"
            & reg delete "HKLM\SYSTEM\CurrentControlSet\Services\EventLog\Application\docker" /f 2>&1 | Out-Null
            $ErrorActionPreference = "Stop"
            Write-Host "Service removed"
          }
      -
        name: Starting containerd
        if: matrix.runtime == 'containerd'
        run: |
          Write-Host "Generating config"
          & "${{ env.BIN_OUT }}\containerd.exe" config default | Out-File "$env:TEMP\ctn.toml" -Encoding ascii
          Write-Host "Creating service"
          New-Item -ItemType Directory "$env:TEMP\ctn-root" -ErrorAction SilentlyContinue | Out-Null
          New-Item -ItemType Directory "$env:TEMP\ctn-state" -ErrorAction SilentlyContinue | Out-Null
          Start-Process -Wait "${{ env.BIN_OUT }}\containerd.exe" `
            -ArgumentList "--log-level=debug", `
              "--config=$env:TEMP\ctn.toml", `
              "--address=\\.\pipe\containerd-containerd", `
              "--root=$env:TEMP\ctn-root", `
              "--state=$env:TEMP\ctn-state", `
              "--log-file=$env:TEMP\ctn.log", `
              "--register-service"
          Write-Host "Starting service"
          Start-Service -Name containerd
          Start-Sleep -Seconds 5
          Write-Host "Service started successfully!"
      -
        name: Starting test daemon
        run: |
          Write-Host "Creating service"
          If ("${{ matrix.runtime }}" -eq "containerd") {
            $runtimeArg="--containerd=\\.\pipe\containerd-containerd"
            echo "DOCKER_WINDOWS_CONTAINERD_RUNTIME=1" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf-8 -Append
          }
          New-Item -ItemType Directory "$env:TEMP\moby-root" -ErrorAction SilentlyContinue | Out-Null
          New-Item -ItemType Directory "$env:TEMP\moby-exec" -ErrorAction SilentlyContinue | Out-Null
          Start-Process -Wait -NoNewWindow "${{ env.BIN_OUT }}\dockerd" `
            -ArgumentList $runtimeArg, "--debug", `
              "--host=npipe:////./pipe/docker_engine", `
              "--data-root=$env:TEMP\moby-root", `
              "--exec-root=$env:TEMP\moby-exec", `
              "--pidfile=$env:TEMP\docker.pid", `
              "--register-service"
          Write-Host "Starting service"
          Start-Service -Name docker
          Write-Host "Service started successfully!"
      -
        name: Waiting for test daemon to start
        run: |
          $tries=20
          Write-Host "Waiting for the test daemon to start..."
          While ($true) {
            $ErrorActionPreference = "SilentlyContinue"
            & "${{ env.BIN_OUT }}\docker" version
            $ErrorActionPreference = "Stop"
            If ($LastExitCode -eq 0) {
              break
            }
            $tries--
            If ($tries -le 0) {
              Throw "Failed to get a response from the daemon"
            }
            Write-Host -NoNewline "."
            Start-Sleep -Seconds 1
          }
          Write-Host "Test daemon started and replied!"
        env:
          DOCKER_HOST: npipe:////./pipe/docker_engine
      -
        name: Docker info
        run: |
          & "${{ env.BIN_OUT }}\docker" info
        env:
          DOCKER_HOST: npipe:////./pipe/docker_engine
      -
        name: Building contrib/busybox
        run: |
          & "${{ env.BIN_OUT }}\docker" build -t busybox `
            --build-arg WINDOWS_BASE_IMAGE `
            --build-arg WINDOWS_BASE_IMAGE_TAG `
            .\contrib\busybox\
        env:
          DOCKER_HOST: npipe:////./pipe/docker_engine
      -
        name: List images
        run: |
          & "${{ env.BIN_OUT }}\docker" images
        env:
          DOCKER_HOST: npipe:////./pipe/docker_engine
      -
        name: Set up Go
        uses: actions/setup-go@v3
        with:
          go-version: ${{ env.GO_VERSION }}
      -
        name: Test integration
        if: matrix.test == './...'
        run: |
          .\hack\make.ps1 -TestIntegration
        env:
          DOCKER_HOST: npipe:////./pipe/docker_engine
          GO111MODULE: "off"
          TEST_CLIENT_BINARY: ${{ env.BIN_OUT }}\docker
      -
        name: Test integration-cli
        if: matrix.test != './...'
        run: |
          .\hack\make.ps1 -TestIntegrationCli
        env:
          DOCKER_HOST: npipe:////./pipe/docker_engine
          GO111MODULE: "off"
          TEST_CLIENT_BINARY: ${{ env.BIN_OUT }}\docker
          INTEGRATION_TESTRUN: ${{ matrix.test }}
      -
        name: Send to Codecov
        if: matrix.os == 'windows-2022'
        uses: codecov/codecov-action@v3
        with:
          working-directory: ${{ env.GOPATH }}\src\github.com\docker\docker
          directory: bundles
          env_vars: RUNNER_OS
          flags: integration,${{ matrix.runtime }}
      -
        name: Docker info
        run: |
          & "${{ env.BIN_OUT }}\docker" info
        env:
          DOCKER_HOST: npipe:////./pipe/docker_engine
      -
        name: Stop containerd
        if: always() && matrix.runtime == 'containerd'
        run: |
          $ErrorActionPreference = "SilentlyContinue"
          Stop-Service -Force -Name containerd
          $ErrorActionPreference = "Stop"
      -
        name: Containerd logs
        if: always() && matrix.runtime == 'containerd'
        run: |
          Copy-Item "$env:TEMP\ctn.log" -Destination ".\bundles\containerd.log"
          Get-Content "$env:TEMP\ctn.log" | Out-Host
      -
        name: Stop daemon
        if: always()
        run: |
          $ErrorActionPreference = "SilentlyContinue"
          Stop-Service -Force -Name docker
          $ErrorActionPreference = "Stop"
      -
        # as the daemon is registered as a service we have to check the event
        # logs against the docker provider.
        name: Daemon event logs
        if: always()
        run: |
          Get-WinEvent -ea SilentlyContinue `
            -FilterHashtable @{ProviderName= "docker"; LogName = "application"} |
              Select-Object -Property TimeCreated, @{N='Detailed Message'; E={$_.Message}} |
              Sort-Object @{Expression="TimeCreated";Descending=$false} |
              Select-Object -ExpandProperty 'Detailed Message' | Tee-Object -file ".\bundles\daemon.log"
      -
        name: Upload reports
        if: always()
        uses: actions/upload-artifact@v3
        with:
          name: ${{ matrix.os }}-integration-reports-${{ matrix.runtime }}
          path: ${{ env.GOPATH }}\src\github.com\docker\docker\bundles\*

  integration-test-report:
    runs-on: ubuntu-latest
    if: always()
    needs:
      - integration-test
    strategy:
      fail-fast: false
      matrix:
        os:
          - windows-2019
          - windows-2022
        runtime:
          - builtin
          - containerd
    steps:
      -
        name: Set up Go
        uses: actions/setup-go@v3
        with:
          go-version: ${{ env.GO_VERSION }}
      -
        name: Download artifacts
        uses: actions/download-artifact@v3
        with:
          name: ${{ matrix.os }}-integration-reports-${{ matrix.runtime }}
          path: /tmp/artifacts
      -
        name: Install teststat
        run: |
          go install github.com/vearutop/teststat@${{ env.TESTSTAT_VERSION }}
      -
        name: Create summary
        run: |
          teststat -markdown $(find /tmp/artifacts -type f -name '*.json' -print0 | xargs -0) >> $GITHUB_STEP_SUMMARY

I would suggest splitting this so that if `gotestlist` fails for any reason, we get an explicit failure instead of just an empty matrix:

```suggestion
          matrix="$(gotestlist -d 4 ./...)"
          matrix="$(echo "$matrix" | jq -c '. |= ["./..."] + .')"
          echo "::set-output name=matrix::$matrix"
```

(due to `set -e` quirks :see_no_evil:)