diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml new file mode 100644 index 0000000000..48566106bc --- /dev/null +++ b/.github/workflows/windows.yml @@ -0,0 +1,411 @@ +name: windows + +on: + workflow_dispatch: + push: + branches: + - 'master' + - '[0-9]+.[0-9]{2}' + tags: + - 'v*' + pull_request: + +env: + GO_VERSION: 1.18.2 + 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: matrix.os == 'windows-2022' + uses: actions/upload-artifact@v3 + with: + name: 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: | + 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 --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: Upload reports + if: matrix.os == 'windows-2022' + uses: actions/upload-artifact@v3 + with: + name: integration-reports-${{ matrix.runtime }} + path: ${{ env.GOPATH }}\src\github.com\docker\docker\bundles\* + - + 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: | + 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' diff --git a/codecov.yml b/codecov.yml index 594265c6cf..ac8c6694c6 100644 --- a/codecov.yml +++ b/codecov.yml @@ -1,5 +1,8 @@ -comment: - layout: header, changes, diff, sunburst +comment: false + +github_checks: + annotations: false + coverage: status: patch: @@ -13,5 +16,6 @@ coverage: target: auto threshold: "15%" changes: false + ignore: - - "vendor/*" + - "vendor/**/*" diff --git a/hack/make.ps1 b/hack/make.ps1 index d7d3d581c0..8d1f7177a7 100644 --- a/hack/make.ps1 +++ b/hack/make.ps1 @@ -328,7 +328,10 @@ Function Run-UnitTests() { $pkgList = $pkgList | Select-String -NotMatch "github.com/docker/docker/integration" $pkgList = $pkgList -replace "`r`n", " " - $goTestArg = "--format=standard-verbose --jsonfile=bundles\go-test-report-unit-tests.json --junitfile=bundles\junit-report-unit-tests.xml -- " + $raceParm + " -cover -ldflags -w -a """ + "-test.timeout=10m" + """ $pkgList" + $jsonFilePath = $bundlesDir + "\go-test-report-unit-tests.json" + $xmlFilePath = $bundlesDir + "\junit-report-unit-tests.xml" + $coverageFilePath = $bundlesDir + "\coverage-report-unit-tests.txt" + $goTestArg = "--format=standard-verbose --jsonfile=$jsonFilePath --junitfile=$xmlFilePath -- " + $raceParm + " -coverprofile=$coverageFilePath -covermode=atomic -ldflags -w -a """ + "-test.timeout=10m" + """ $pkgList" Write-Host "INFO: Invoking unit tests run with $GOTESTSUM_LOCATION\gotestsum.exe $goTestArg" $pinfo = New-Object System.Diagnostics.ProcessStartInfo $pinfo.FileName = "$GOTESTSUM_LOCATION\gotestsum.exe" @@ -364,13 +367,14 @@ Function Run-IntegrationTests() { } $jsonFilePath = $bundlesDir + "\go-test-report-int-tests-$normDir" + ".json" $xmlFilePath = $bundlesDir + "\junit-report-int-tests-$normDir" + ".xml" + $coverageFilePath = $bundlesDir + "\coverage-report-int-tests-$normDir" + ".txt" Set-Location $dir Write-Host "Running $($PWD.Path)" $pinfo = New-Object System.Diagnostics.ProcessStartInfo $pinfo.FileName = "gotestsum.exe" $pinfo.WorkingDirectory = "$($PWD.Path)" $pinfo.UseShellExecute = $false - $pinfo.Arguments = "--format=standard-verbose --jsonfile=$jsonFilePath --junitfile=$xmlFilePath -- -test.timeout=60m $env:INTEGRATION_TESTFLAGS" + $pinfo.Arguments = "--format=standard-verbose --jsonfile=$jsonFilePath --junitfile=$xmlFilePath -- -coverprofile=$coverageFilePath -covermode=atomic -test.timeout=60m $env:INTEGRATION_TESTFLAGS" $p = New-Object System.Diagnostics.Process $p.StartInfo = $pinfo $p.Start() | Out-Null diff --git a/integration-cli/docker_cli_restart_test.go b/integration-cli/docker_cli_restart_test.go index 465afc6b27..a9c9d176d5 100644 --- a/integration-cli/docker_cli_restart_test.go +++ b/integration-cli/docker_cli_restart_test.go @@ -11,6 +11,7 @@ import ( "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" "gotest.tools/v3/poll" + "gotest.tools/v3/skip" ) func (s *DockerSuite) TestRestartStoppedContainer(c *testing.T) { @@ -171,6 +172,7 @@ func (s *DockerSuite) TestRestartContainerSuccess(c *testing.T) { // such that it assumes there is a host process to kill. In Hyper-V // containers, the process is inside the utility VM, not on the host. if DaemonIsWindows() { + skip.If(c, testEnv.GitHubActions()) testRequires(c, testEnv.DaemonInfo.Isolation.IsProcess) } @@ -247,6 +249,7 @@ func (s *DockerSuite) TestRestartPolicyAfterRestart(c *testing.T) { // such that it assumes there is a host process to kill. In Hyper-V // containers, the process is inside the utility VM, not on the host. if DaemonIsWindows() { + skip.If(c, testEnv.GitHubActions()) testRequires(c, testEnv.DaemonInfo.Isolation.IsProcess) } diff --git a/integration-cli/docker_cli_run_test.go b/integration-cli/docker_cli_run_test.go index 937fbb956b..ea80139eac 100644 --- a/integration-cli/docker_cli_run_test.go +++ b/integration-cli/docker_cli_run_test.go @@ -4151,6 +4151,9 @@ func (s *DockerSuite) TestRunEmptyEnv(c *testing.T) { // #28658 func (s *DockerSuite) TestSlowStdinClosing(c *testing.T) { + if DaemonIsWindows() { + skip.If(c, testEnv.GitHubActions()) + } const repeat = 3 // regression happened 50% of the time for i := 0; i < repeat; i++ { c.Run(strconv.Itoa(i), func(c *testing.T) { diff --git a/integration-cli/docker_cli_start_test.go b/integration-cli/docker_cli_start_test.go index 2ddc0563cc..45271911c7 100644 --- a/integration-cli/docker_cli_start_test.go +++ b/integration-cli/docker_cli_start_test.go @@ -186,14 +186,8 @@ func (s *DockerSuite) TestStartAttachWithRename(c *testing.T) { } func (s *DockerSuite) TestStartReturnCorrectExitCode(c *testing.T) { - dockerCmd(c, "create", "--restart=on-failure:2", "--name", "withRestart", "busybox", "sh", "-c", "exit 11") - dockerCmd(c, "create", "--rm", "--name", "withRm", "busybox", "sh", "-c", "exit 12") - - out, exitCode, err := dockerCmdWithError("start", "-a", "withRestart") - assert.ErrorContains(c, err, "") - assert.Equal(c, exitCode, 11, fmt.Sprintf("out: %s", out)) - - out, exitCode, err = dockerCmdWithError("start", "-a", "withRm") - assert.ErrorContains(c, err, "") - assert.Equal(c, exitCode, 12, fmt.Sprintf("out: %s", out)) + cli.DockerCmd(c, "create", "--restart=on-failure:2", "--name", "withRestart", "busybox", "sh", "-c", "exit 11") + cli.DockerCmd(c, "create", "--rm", "--name", "withRm", "busybox", "sh", "-c", "exit 12") + cli.Docker(cli.Args("start", "-a", "withRestart")).Assert(c, icmd.Expected{ExitCode: 11}) + cli.Docker(cli.Args("start", "-a", "withRm")).Assert(c, icmd.Expected{ExitCode: 12}) } diff --git a/testutil/environment/environment.go b/testutil/environment/environment.go index ea08d97181..88a9a7cf27 100644 --- a/testutil/environment/environment.go +++ b/testutil/environment/environment.go @@ -221,3 +221,8 @@ func EnsureFrozenImagesLinux(testEnv *Execution) error { } return nil } + +// GitHubActions is true if test is executed on a GitHub Runner. +func (e *Execution) GitHubActions() bool { + return os.Getenv("GITHUB_ACTIONS") == "true" +}