ci: Setup otel tracing for windows integration tests
Related to:

- https://github.com/moby/moby/pull/45652

**- What I did**

* Set up Jaeger before running integration tests on Windows builds
* Download traces and put them in build artifacts

Note that for both Linux and Windows builds, the trace file can't be fully imported in Jaeger due to its size. In addition, big trace files also tend to create many many DOM nodes, leading to unresponsive browser tab. One have to tweak the CI config on a given PR to limit how much integration tests are run to get a usable trace file.

**- A picture of a cute animal (not mandatory but encouraged)**

![](https://www.thesprucepets.com/thmb/bKgaPD0oT0AjK6-QdbbxpnX-3xM=/1280x0/filters:no_upscale():strip_icc()/step_6-clownfish-596f711ac4124400102014c2.jpg)
.github/workflows/.windows.yml
# reusable workflow
name: .windows

# TODO: hide reusable workflow from the UI. Tracked in https://github.com/community/community/discussions/12025

on:
  workflow_call:
    inputs:
      os:
        required: true
        type: string
      storage:
        required: true
        type: string
        default: "graphdriver"
      send_coverage:
        required: false
        type: boolean
        default: false

env:
  GO_VERSION: "1.21.3"
  GOTESTLIST_VERSION: v0.3.1
  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
  ITG_CLI_MATRIX_SIZE: 6

jobs:
  build:
    runs-on: ${{ inputs.os }}
    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 ("${{ inputs.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 ("${{ inputs.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: ${{ inputs.os }}-${{ github.job }}-${{ hashFiles('**/vendor.sum') }}
          restore-keys: |
            ${{ inputs.os }}-${{ github.job }}-
      -
        name: Docker info
        run: |
          docker info
      -
        name: Build base image
        run: |
          & docker build `
            --build-arg WINDOWS_BASE_IMAGE `
            --build-arg WINDOWS_BASE_IMAGE_TAG `
            --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-${{ inputs.storage }}-${{ inputs.os }}
          path: ${{ env.BIN_OUT }}/*
          if-no-files-found: error
          retention-days: 2

  unit-test:
    runs-on: ${{ inputs.os }}
    timeout-minutes: 120
    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 ("${{ inputs.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 ("${{ inputs.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: ${{ inputs.os }}-${{ github.job }}-${{ hashFiles('**/vendor.sum') }}
          restore-keys: |
            ${{ inputs.os }}-${{ github.job }}-
      -
        name: Docker info
        run: |
          docker info
      -
        name: Build base image
        run: |
          & docker build `
            --build-arg WINDOWS_BASE_IMAGE `
            --build-arg WINDOWS_BASE_IMAGE_TAG `
            --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: inputs.send_coverage
        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: ${{ inputs.os }}-${{ inputs.storage }}-unit-reports
          path: ${{ env.GOPATH }}\src\github.com\docker\docker\bundles\*

  unit-test-report:
    runs-on: ubuntu-latest
    if: always()
    needs:
      - unit-test
    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: ${{ inputs.os }}-${{ inputs.storage }}-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: |
          # This step creates a matrix for integration-cli tests. Tests suites
          # are distributed in integration-test job through a matrix. There is
          # also an override being added to the matrix like "./..." to run
          # "Test integration" step exclusively.
          matrix="$(gotestlist -d ${{ env.ITG_CLI_MATRIX_SIZE }} -o "./..." ./...)"
          echo "matrix=$matrix" >> $GITHUB_OUTPUT
      -
        name: Show matrix
        run: |
          echo ${{ steps.tests.outputs.matrix }}

  integration-test:
    runs-on: ${{ inputs.os }}
    continue-on-error: ${{ inputs.storage == 'snapshotter' && github.event_name != 'pull_request' }}
    timeout-minutes: 120
    needs:
      - build
      - integration-test-prepare
    strategy:
      fail-fast: false
      matrix:
        storage:
          - ${{ inputs.storage }}
        runtime:
          - builtin
          - containerd
        test: ${{ fromJson(needs.integration-test-prepare.outputs.matrix) }}
        exclude:
          - storage: snapshotter
            runtime: builtin
    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-${{ inputs.storage }}-${{ inputs.os }}
          path: ${{ env.BIN_OUT }}
      -
        name: Init
        run: |
          New-Item -ItemType "directory" -Path "bundles"
          If ("${{ inputs.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 ("${{ inputs.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 not available atm
            $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"
          If ("${{ inputs.storage }}" -eq "snapshotter") {
            # Make the env-var visible to the service-managed dockerd, as there's no CLI flag for this option.
            & reg add "HKLM\SYSTEM\CurrentControlSet\Services\docker" /v Environment /t REG_MULTI_SZ /s '@' /d TEST_INTEGRATION_USE_SNAPSHOTTER=1 
            echo "TEST_INTEGRATION_USE_SNAPSHOTTER=1" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf-8 -Append
          }
          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: inputs.send_coverage
        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"} |
              Sort-Object @{Expression="TimeCreated";Descending=$false} |
              ForEach-Object {"$($_.TimeCreated.ToUniversalTime().ToString("o")) [$($_.LevelDisplayName)] $($_.Message)"} |
              Tee-Object -file ".\bundles\daemon.log"
      -
        name: Upload reports
        if: always()
        uses: actions/upload-artifact@v3
        with:
          name: ${{ inputs.os }}-${{ inputs.storage }}-integration-reports-${{ matrix.runtime }}
          path: ${{ env.GOPATH }}\src\github.com\docker\docker\bundles\*

  integration-test-report:
    runs-on: ubuntu-latest
    continue-on-error: ${{ inputs.storage == 'snapshotter' && github.event_name != 'pull_request' }}
    if: always()
    needs:
      - integration-test
    strategy:
      fail-fast: false
      matrix:
        storage:
          - ${{ inputs.storage }}
        runtime:
          - builtin
          - containerd
        exclude:
          - storage: snapshotter
            runtime: builtin
    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: ${{ inputs.os }}-${{ inputs.storage }}-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

# reusable workflow
name: .windows

# TODO: hide reusable workflow from the UI. Tracked in https://github.com/community/community/discussions/12025

on:
  workflow_call:
    inputs:
      os:
        required: true
        type: string
      storage:
        required: true
        type: string
        default: "graphdriver"
      send_coverage:
        required: false
        type: boolean
        default: false

env:
  GO_VERSION: "1.21.3"
  GOTESTLIST_VERSION: v0.3.1
  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
  ITG_CLI_MATRIX_SIZE: 6

jobs:
  build:
    runs-on: ${{ inputs.os }}
    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 ("${{ inputs.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 ("${{ inputs.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: ${{ inputs.os }}-${{ github.job }}-${{ hashFiles('**/vendor.sum') }}
          restore-keys: |
            ${{ inputs.os }}-${{ github.job }}-
      -
        name: Docker info
        run: |
          docker info
      -
        name: Build base image
        run: |
          & docker build `
            --build-arg WINDOWS_BASE_IMAGE `
            --build-arg WINDOWS_BASE_IMAGE_TAG `
            --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-${{ inputs.storage }}-${{ inputs.os }}
          path: ${{ env.BIN_OUT }}/*
          if-no-files-found: error
          retention-days: 2

  unit-test:
    runs-on: ${{ inputs.os }}
    timeout-minutes: 120
    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 ("${{ inputs.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 ("${{ inputs.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: ${{ inputs.os }}-${{ github.job }}-${{ hashFiles('**/vendor.sum') }}
          restore-keys: |
            ${{ inputs.os }}-${{ github.job }}-
      -
        name: Docker info
        run: |
          docker info
      -
        name: Build base image
        run: |
          & docker build `
            --build-arg WINDOWS_BASE_IMAGE `
            --build-arg WINDOWS_BASE_IMAGE_TAG `
            --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: inputs.send_coverage
        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: ${{ inputs.os }}-${{ inputs.storage }}-unit-reports
          path: ${{ env.GOPATH }}\src\github.com\docker\docker\bundles\*

  unit-test-report:
    runs-on: ubuntu-latest
    if: always()
    needs:
      - unit-test
    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: ${{ inputs.os }}-${{ inputs.storage }}-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: |
          # This step creates a matrix for integration-cli tests. Tests suites
          # are distributed in integration-test job through a matrix. There is
          # also an override being added to the matrix like "./..." to run
          # "Test integration" step exclusively.
          matrix="$(gotestlist -d ${{ env.ITG_CLI_MATRIX_SIZE }} -o "./..." ./...)"
          echo "matrix=$matrix" >> $GITHUB_OUTPUT
      -
        name: Show matrix
        run: |
          echo ${{ steps.tests.outputs.matrix }}

  integration-test:
    runs-on: ${{ inputs.os }}
    continue-on-error: ${{ inputs.storage == 'snapshotter' && github.event_name != 'pull_request' }}
    timeout-minutes: 120
    needs:
      - build
      - integration-test-prepare
    strategy:
      fail-fast: false
      matrix:
        storage:
          - ${{ inputs.storage }}
        runtime:
          - builtin
          - containerd
        test: ${{ fromJson(needs.integration-test-prepare.outputs.matrix) }}
        exclude:
          - storage: snapshotter
            runtime: builtin
    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
      -
        run: |
          # Jaeger is set up on Linux through the setup-tracing action. If you update Jaeger here, don't forget to
          # update the version set in .github/actions/setup-tracing/action.yml.
          Invoke-WebRequest -Uri "https://github.com/jaegertracing/jaeger/releases/download/v1.46.0/jaeger-1.46.0-windows-amd64.tar.gz" -OutFile ".\jaeger-1.46.0-windows-amd64.tar.gz"
          tar -zxvf ".\jaeger-1.46.0-windows-amd64.tar.gz"
          Start-Process '.\jaeger-1.46.0-windows-amd64\jaeger-all-in-one.exe'
          echo "OTEL_EXPORTER_OTLP_ENDPOINT=http://127.0.0.1:4318" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf-8 -Append
        shell: pwsh
      -
        name: Env
        run: |
          Get-ChildItem Env: | Out-String
      -
        name: Download artifacts
        uses: actions/download-artifact@v3
        with:
          name: build-${{ inputs.storage }}-${{ inputs.os }}
          path: ${{ env.BIN_OUT }}
      -
        name: Init
        run: |
          New-Item -ItemType "directory" -Path "bundles"
          If ("${{ inputs.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 ("${{ inputs.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 not available atm
            $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"
          If ("${{ inputs.storage }}" -eq "snapshotter") {
            # Make the env-var visible to the service-managed dockerd, as there's no CLI flag for this option.
            & reg add "HKLM\SYSTEM\CurrentControlSet\Services\docker" /v Environment /t REG_MULTI_SZ /s '@' /d TEST_INTEGRATION_USE_SNAPSHOTTER=1 
            echo "TEST_INTEGRATION_USE_SNAPSHOTTER=1" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf-8 -Append
          }
          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: inputs.send_coverage
        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"} |
              Sort-Object @{Expression="TimeCreated";Descending=$false} |
              ForEach-Object {"$($_.TimeCreated.ToUniversalTime().ToString("o")) [$($_.LevelDisplayName)] $($_.Message)"} |
              Tee-Object -file ".\bundles\daemon.log"
      -
        name: Download Jaeger traces
        if: always()
        run: |
          Invoke-WebRequest `
            -Uri "http://127.0.0.1:16686/api/traces?service=integration-test-client" `
            -OutFile ".\bundles\jaeger-trace.json"
      -
        name: Upload reports
        if: always()
        uses: actions/upload-artifact@v3
        with:
          name: ${{ inputs.os }}-${{ inputs.storage }}-integration-reports-${{ matrix.runtime }}
          path: ${{ env.GOPATH }}\src\github.com\docker\docker\bundles\*

  integration-test-report:
    runs-on: ubuntu-latest
    continue-on-error: ${{ inputs.storage == 'snapshotter' && github.event_name != 'pull_request' }}
    if: always()
    needs:
      - integration-test
    strategy:
      fail-fast: false
      matrix:
        storage:
          - ${{ inputs.storage }}
        runtime:
          - builtin
          - containerd
        exclude:
          - storage: snapshotter
            runtime: builtin
    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: ${{ inputs.os }}-${{ inputs.storage }}-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 tried both suggestions but that doesn't work; see [here](https://github.com/moby/moby/actions/runs/6559848202) and [here](https://github.com/moby/moby/actions/runs/6561595001).

I'll try with the absolute path hardcoded to see what happens.