github.com/moby/docker@v26.1.3+incompatible/hack/make.ps1 (about)

     1  <#
     2  .NOTES
     3      Author:  @jhowardmsft
     4  
     5      Summary: Windows native build script. This is similar to functionality provided
     6               by hack\make.sh, but uses native Windows PowerShell semantics. It does
     7               not support the full set of options provided by the Linux counterpart.
     8               For example:
     9  
    10               - You can't cross-build Linux docker binaries on Windows
    11               - Hashes aren't generated on binaries
    12               - 'Releasing' isn't supported.
    13               - Integration tests. This is because they currently cannot run inside a container,
    14                 and require significant external setup.
    15  
    16               It does however provided the minimum necessary to support parts of local Windows
    17               development and Windows to Windows CI.
    18  
    19               Usage Examples (run from repo root):
    20                  "hack\make.ps1 -Client" to build docker.exe client 64-bit binary (remote repo)
    21                  "hack\make.ps1 -TestUnit" to run unit tests
    22                  "hack\make.ps1 -Daemon -TestUnit" to build the daemon and run unit tests
    23                  "hack\make.ps1 -All" to run everything this script knows about that can run in a container
    24                  "hack\make.ps1" to build the daemon binary (same as -Daemon)
    25                  "hack\make.ps1 -Binary" shortcut to -Client and -Daemon
    26  
    27  .PARAMETER Client
    28       Builds the client binaries.
    29  
    30  .PARAMETER Daemon
    31       Builds the daemon binary.
    32  
    33  .PARAMETER Binary
    34       Builds the client and daemon binaries. A convenient shortcut to `make.ps1 -Client -Daemon`.
    35  
    36  .PARAMETER Race
    37       Use -race in go build and go test.
    38  
    39  .PARAMETER Noisy
    40       Use -v in go build.
    41  
    42  .PARAMETER ForceBuildAll
    43       Use -a in go build.
    44  
    45  .PARAMETER NoOpt
    46       Use -gcflags -N -l in go build to disable optimisation (can aide debugging).
    47  
    48  .PARAMETER CommitSuffix
    49       Adds a custom string to be appended to the commit ID (spaces are stripped).
    50  
    51  .PARAMETER DCO
    52       Runs the DCO (Developer Certificate Of Origin) test (must be run outside a container).
    53  
    54  .PARAMETER PkgImports
    55       Runs the pkg\ directory imports test (must be run outside a container).
    56  
    57  .PARAMETER GoFormat
    58       Runs the Go formatting test (must be run outside a container).
    59  
    60  .PARAMETER TestUnit
    61       Runs unit tests.
    62  
    63  .PARAMETER TestIntegration
    64       Runs integration tests.
    65  
    66  .PARAMETER TestIntegrationCli
    67       Runs integration-cli tests.
    68  
    69  .PARAMETER All
    70       Runs everything this script knows about that can run in a container.
    71  
    72  
    73  TODO
    74  - Unify the head commit
    75  - Add golint and other checks (swagger maybe?)
    76  
    77  #>
    78  
    79  
    80  param(
    81      [Parameter(Mandatory=$False)][switch]$Client,
    82      [Parameter(Mandatory=$False)][switch]$Daemon,
    83      [Parameter(Mandatory=$False)][switch]$Binary,
    84      [Parameter(Mandatory=$False)][switch]$Race,
    85      [Parameter(Mandatory=$False)][switch]$Noisy,
    86      [Parameter(Mandatory=$False)][switch]$ForceBuildAll,
    87      [Parameter(Mandatory=$False)][switch]$NoOpt,
    88      [Parameter(Mandatory=$False)][string]$CommitSuffix="",
    89      [Parameter(Mandatory=$False)][switch]$DCO,
    90      [Parameter(Mandatory=$False)][switch]$PkgImports,
    91      [Parameter(Mandatory=$False)][switch]$GoFormat,
    92      [Parameter(Mandatory=$False)][switch]$TestUnit,
    93      [Parameter(Mandatory=$False)][switch]$TestIntegration,
    94      [Parameter(Mandatory=$False)][switch]$TestIntegrationCli,
    95      [Parameter(Mandatory=$False)][switch]$All
    96  )
    97  
    98  $ErrorActionPreference = "Stop"
    99  $ProgressPreference = "SilentlyContinue"
   100  $pushed=$False  # To restore the directory if we have temporarily pushed to one.
   101  Set-Variable GOTESTSUM_LOCATION -option Constant -value "$env:GOPATH/bin/"
   102  
   103  # Utility function to get the commit ID of the repository
   104  Function Get-GitCommit() {
   105      if (-not (Test-Path ".\.git")) {
   106          # If we don't have a .git directory, but we do have the environment
   107          # variable DOCKER_GITCOMMIT set, that can override it.
   108          if ($env:DOCKER_GITCOMMIT.Length -eq 0) {
   109              Throw ".git directory missing and DOCKER_GITCOMMIT environment variable not specified."
   110          }
   111          Write-Host "INFO: Git commit ($env:DOCKER_GITCOMMIT) assumed from DOCKER_GITCOMMIT environment variable"
   112          return $env:DOCKER_GITCOMMIT
   113      }
   114      $gitCommit=$(git rev-parse --short HEAD)
   115      if ($(git status --porcelain --untracked-files=no).Length -ne 0) {
   116          $gitCommit="$gitCommit-unsupported"
   117          Write-Host ""
   118          Write-Warning "This version is unsupported because there are uncommitted file(s)."
   119          Write-Warning "Either commit these changes, or add them to .gitignore."
   120          git status --porcelain --untracked-files=no | Write-Warning
   121          Write-Host ""
   122      }
   123      return $gitCommit
   124  }
   125  
   126  # Utility function to determine if we are running in a container or not.
   127  # In Windows, we get this through an environment variable set in `Dockerfile.Windows`
   128  Function Check-InContainer() {
   129      if ($env:FROM_DOCKERFILE.Length -eq 0) {
   130          Write-Host ""
   131          Write-Warning "Not running in a container. The result might be an incorrect build."
   132          Write-Host ""
   133          return $False
   134      }
   135      return $True
   136  }
   137  
   138  # Utility function to warn if the version of go is correct. Used for local builds
   139  # outside of a container where it may be out of date with master.
   140  Function Verify-GoVersion() {
   141      Try {
   142          $goVersionDockerfile=(Select-String -Path ".\Dockerfile" -Pattern "^ARG[\s]+GO_VERSION=(.*)$").Matches.groups[1].Value -replace '\.0$',''
   143          $goVersionInstalled=(go version).ToString().Split(" ")[2].SubString(2)
   144      }
   145      Catch [Exception] {
   146          Throw "Failed to validate go version correctness: $_"
   147      }
   148      if (-not($goVersionInstalled -eq $goVersionDockerfile)) {
   149          Write-Host ""
   150          Write-Warning "Building with golang version $goVersionInstalled. You should update to $goVersionDockerfile"
   151          Write-Host ""
   152      }
   153  }
   154  
   155  # Utility function to get the commit for HEAD
   156  Function Get-HeadCommit() {
   157      $head = Invoke-Expression "git rev-parse --verify HEAD"
   158      if ($LASTEXITCODE -ne 0) { Throw "Failed getting HEAD commit" }
   159  
   160      return $head
   161  }
   162  
   163  # Utility function to get the commit for upstream
   164  Function Get-UpstreamCommit() {
   165      Invoke-Expression "git fetch -q https://github.com/docker/docker.git refs/heads/master"
   166      if ($LASTEXITCODE -ne 0) { Throw "Failed fetching" }
   167  
   168      $upstream = Invoke-Expression "git rev-parse --verify FETCH_HEAD"
   169      if ($LASTEXITCODE -ne 0) { Throw "Failed getting upstream commit" }
   170  
   171      return $upstream
   172  }
   173  
   174  # Build a binary (client or daemon)
   175  Function Execute-Build($type, $additionalBuildTags, $directory, $ldflags) {
   176      # Generate the build flags
   177      $buildTags = ""
   178      $ldflags = "-linkmode=internal " + $ldflags
   179      if ($Noisy)                     { $verboseParm=" -v" }
   180      if ($Race)                      { Write-Warning "Using race detector"; $raceParm=" -race"}
   181      if ($ForceBuildAll)             { $allParm=" -a" }
   182      if ($NoOpt)                     { $optParm=" -gcflags "+""""+"-N -l"+"""" }
   183      if ($additionalBuildTags -ne "") { $buildTags += $(" " + $additionalBuildTags) }
   184  
   185      # Do the go build in the appropriate directory
   186      # Note -linkmode=internal is required to be able to debug on Windows.
   187      # https://github.com/golang/go/issues/14319#issuecomment-189576638
   188      Write-Host "INFO: Building $type..."
   189      Push-Location $root\cmd\$directory; $global:pushed=$True
   190      $buildCommand = "go build" + `
   191                      $raceParm + `
   192                      $verboseParm + `
   193                      $allParm + `
   194                      $optParm + `
   195                      " -tags """ + $buildTags + """" + `
   196                      " -ldflags """ + $ldflags + """" + `
   197                      " -o $root\bundles\"+$directory+".exe"
   198      Invoke-Expression $buildCommand
   199      if ($LASTEXITCODE -ne 0) { Throw "Failed to compile $type" }
   200      Pop-Location; $global:pushed=$False
   201  }
   202  
   203  
   204  # Validates the DCO marker is present on each commit
   205  Function Validate-DCO($headCommit, $upstreamCommit) {
   206      Write-Host "INFO: Validating Developer Certificate of Origin..."
   207      # Username may only contain alphanumeric characters or dashes and cannot begin with a dash
   208      $usernameRegex='[a-zA-Z0-9][a-zA-Z0-9-]+'
   209  
   210      $dcoPrefix="Signed-off-by:"
   211      $dcoRegex="^(Docker-DCO-1.1-)?$dcoPrefix ([^<]+) <([^<>@]+@[^<>]+)>( \(github: ($usernameRegex)\))?$"
   212  
   213      $counts = Invoke-Expression "git diff --numstat $upstreamCommit...$headCommit"
   214      if ($LASTEXITCODE -ne 0) { Throw "Failed git diff --numstat" }
   215  
   216      # Counts of adds and deletes after removing multiple white spaces. AWK anyone? :(
   217      $adds=0; $dels=0; $($counts -replace '\s+', ' ') | %{ 
   218          $a=$_.Split(" "); 
   219          if ($a[0] -ne "-") { $adds+=[int]$a[0] }
   220          if ($a[1] -ne "-") { $dels+=[int]$a[1] }
   221      }
   222      if (($adds -eq 0) -and ($dels -eq 0)) { 
   223          Write-Warning "DCO validation - nothing to validate!"
   224          return
   225      }
   226  
   227      $commits = Invoke-Expression "git log  $upstreamCommit..$headCommit --format=format:%H%n"
   228      if ($LASTEXITCODE -ne 0) { Throw "Failed git log --format" }
   229      $commits = $($commits -split '\s+' -match '\S')
   230      $badCommits=@()
   231      $commits | ForEach-Object{
   232          # Skip commits with no content such as merge commits etc
   233          if ($(git log -1 --format=format: --name-status $_).Length -gt 0) {
   234              # Ignore exit code on next call - always process regardless
   235              $commitMessage = Invoke-Expression "git log -1 --format=format:%B --name-status $_"
   236              if (($commitMessage -match $dcoRegex).Length -eq 0) { $badCommits+=$_ }
   237          }
   238      }
   239      if ($badCommits.Length -eq 0) {
   240          Write-Host "Congratulations!  All commits are properly signed with the DCO!"
   241      } else {
   242          $e = "`nThese commits do not have a proper '$dcoPrefix' marker:`n"
   243          $badCommits | %{ $e+=" - $_`n"}
   244          $e += "`nPlease amend each commit to include a properly formatted DCO marker.`n`n"
   245          $e += "Visit the following URL for information about the Docker DCO:`n"
   246          $e += "https://github.com/docker/docker/blob/master/CONTRIBUTING.md#sign-your-work`n"
   247          Throw $e
   248      }
   249  }
   250  
   251  # Validates that .\pkg\... is safely isolated from internal code
   252  Function Validate-PkgImports($headCommit, $upstreamCommit) {
   253      Write-Host "INFO: Validating pkg import isolation..."
   254  
   255      # Get a list of go source-code files which have changed under pkg\. Ignore exit code on next call - always process regardless
   256      $files=@(); $files = Invoke-Expression "git diff $upstreamCommit...$headCommit --diff-filter=ACMR --name-only -- `'pkg\*.go`'"
   257      $badFiles=@(); $files | ForEach-Object{
   258          $file=$_
   259          # For the current changed file, get its list of dependencies, sorted and uniqued.
   260          $imports = Invoke-Expression "go list -e -f `'{{ .Deps }}`' $file"
   261          if ($LASTEXITCODE -ne 0) { Throw "Failed go list for dependencies on $file" }
   262          $imports = $imports -Replace "\[" -Replace "\]", "" -Split(" ") | Sort-Object | Get-Unique
   263          # Filter out what we are looking for
   264          $imports = @() + $imports -NotMatch "^github.com/docker/docker/pkg/" `
   265                                    -NotMatch "^github.com/docker/docker/vendor" `
   266                                    -NotMatch "^github.com/docker/docker/internal" `
   267                                    -Match "^github.com/docker/docker" `
   268                                    -Replace "`n", ""
   269          $imports | ForEach-Object{ $badFiles+="$file imports $_`n" }
   270      }
   271      if ($badFiles.Length -eq 0) {
   272          Write-Host 'Congratulations!  ".\pkg\*.go" is safely isolated from internal code.'
   273      } else {
   274          $e = "`nThese files import internal code: (either directly or indirectly)`n"
   275          $badFiles | ForEach-Object{ $e+=" - $_"}
   276          Throw $e
   277      }
   278  }
   279  
   280  # Validates that changed files are correctly go-formatted
   281  Function Validate-GoFormat($headCommit, $upstreamCommit) {
   282      Write-Host "INFO: Validating go formatting on changed files..."
   283  
   284      # Verify gofmt is installed
   285      if ($(Get-Command gofmt -ErrorAction SilentlyContinue) -eq $nil) { Throw "gofmt does not appear to be installed" }
   286  
   287      # Get a list of all go source-code files which have changed.  Ignore exit code on next call - always process regardless
   288      $files=@(); $files = Invoke-Expression "git diff $upstreamCommit...$headCommit --diff-filter=ACMR --name-only -- `'*.go`'"
   289      $files = $files | Select-String -NotMatch "^vendor/"
   290      $badFiles=@(); $files | %{
   291          # Deliberately ignore error on next line - treat as failed
   292          $content=Invoke-Expression "git show $headCommit`:$_"
   293  
   294          # Next set of hoops are to ensure we have LF not CRLF semantics as otherwise gofmt on Windows will not succeed.
   295          # Also note that gofmt on Windows does not appear to support stdin piping correctly. Hence go through a temporary file.
   296          $content=$content -join "`n"
   297          $content+="`n"
   298          $outputFile=[System.IO.Path]::GetTempFileName()
   299          if (Test-Path $outputFile) { Remove-Item $outputFile }
   300          [System.IO.File]::WriteAllText($outputFile, $content, (New-Object System.Text.UTF8Encoding($False)))
   301          $currentFile = $_ -Replace("/","\")
   302          Write-Host Checking $currentFile
   303          Invoke-Expression "gofmt -s -l $outputFile"
   304          if ($LASTEXITCODE -ne 0) { $badFiles+=$currentFile }
   305          if (Test-Path $outputFile) { Remove-Item $outputFile }
   306      }
   307      if ($badFiles.Length -eq 0) {
   308          Write-Host 'Congratulations!  All Go source files are properly formatted.'
   309      } else {
   310          $e = "`nThese files are not properly gofmt`'d:`n"
   311          $badFiles | ForEach-Object{ $e+=" - $_`n"}
   312          $e+= "`nPlease reformat the above files using `"gofmt -s -w`" and commit the result."
   313          Throw $e
   314      }
   315  }
   316  
   317  # Run the unit tests
   318  Function Run-UnitTests() {
   319      Write-Host "INFO: Running unit tests..."
   320      $testPath="./..."
   321      $goListCommand = "go list -e -f '{{if ne .Name """ + '\"github.com/docker/docker\"' + """}}{{.ImportPath}}{{end}}' $testPath"
   322      $pkgList = $(Invoke-Expression $goListCommand)
   323      if ($LASTEXITCODE -ne 0) { Throw "go list for unit tests failed" }
   324      $pkgList = $pkgList | Select-String -Pattern "github.com/docker/docker"
   325      $pkgList = $pkgList | Select-String -NotMatch "github.com/docker/docker/vendor"
   326      $pkgList = $pkgList | Select-String -NotMatch "github.com/docker/docker/man"
   327      $pkgList = $pkgList | Select-String -NotMatch "github.com/docker/docker/integration"
   328      $pkgList = $pkgList -replace "`r`n", " "
   329  
   330      $jsonFilePath = $bundlesDir + "\go-test-report-unit-tests.json"
   331      $xmlFilePath = $bundlesDir + "\junit-report-unit-tests.xml"
   332      $coverageFilePath = $bundlesDir + "\coverage-report-unit-tests.txt"
   333      $goTestArg = "--format=standard-verbose --jsonfile=$jsonFilePath --junitfile=$xmlFilePath -- " + $raceParm + " -coverprofile=$coverageFilePath -covermode=atomic -ldflags -w -a """ + "-test.timeout=10m" + """ $pkgList"
   334      Write-Host "INFO: Invoking unit tests run with $GOTESTSUM_LOCATION\gotestsum.exe $goTestArg"
   335      $pinfo = New-Object System.Diagnostics.ProcessStartInfo
   336      $pinfo.FileName = "$GOTESTSUM_LOCATION\gotestsum.exe"
   337      $pinfo.WorkingDirectory = "$($PWD.Path)"
   338      $pinfo.UseShellExecute = $false
   339      $pinfo.Arguments = $goTestArg
   340      $p = New-Object System.Diagnostics.Process
   341      $p.StartInfo = $pinfo
   342      $p.Start() | Out-Null
   343      $p.WaitForExit()
   344      if ($p.ExitCode -ne 0) { Throw "Unit tests failed" }
   345  }
   346  
   347  # Run the integration tests
   348  Function Run-IntegrationTests() {
   349      $escRoot = [Regex]::Escape($root)
   350      $env:DOCKER_INTEGRATION_DAEMON_DEST = $bundlesDir + "\tmp"
   351      $dirs = go list -test -f '{{- if ne .ForTest "" -}}{{- .Dir -}}{{- end -}}' .\integration\...
   352      ForEach($dir in $dirs) {
   353          # Normalize directory name for using in the test results files.
   354          $normDir = $dir.Trim()
   355          $normDir = $normDir -replace $escRoot, ""
   356          $normDir = $normDir -replace "\\", "-"
   357          $normDir = $normDir -replace "\/", "-"
   358          $normDir = $normDir -replace "\.", "-"
   359          if ($normDir.StartsWith("-"))
   360          {
   361              $normDir = $normDir.TrimStart("-")
   362          }
   363          if ($normDir.EndsWith("-"))
   364          {
   365              $normDir = $normDir.TrimEnd("-")
   366          }
   367          $jsonFilePath = $bundlesDir + "\go-test-report-int-tests-$normDir" + ".json"
   368          $xmlFilePath = $bundlesDir + "\junit-report-int-tests-$normDir" + ".xml"
   369          $coverageFilePath = $bundlesDir + "\coverage-report-int-tests-$normDir" + ".txt"
   370          Set-Location $dir
   371          Write-Host "Running $($PWD.Path)"
   372          $pinfo = New-Object System.Diagnostics.ProcessStartInfo
   373          $pinfo.FileName = "gotestsum.exe"
   374          $pinfo.WorkingDirectory = "$($PWD.Path)"
   375          $pinfo.UseShellExecute = $false
   376          $pinfo.Arguments = "--format=standard-verbose --jsonfile=$jsonFilePath --junitfile=$xmlFilePath -- -coverprofile=$coverageFilePath -covermode=atomic -test.timeout=60m $env:INTEGRATION_TESTFLAGS"
   377          $p = New-Object System.Diagnostics.Process
   378          $p.StartInfo = $pinfo
   379          $p.Start() | Out-Null
   380          $p.WaitForExit()
   381          if ($p.ExitCode -ne 0) { Throw "Integration tests failed" }
   382      }
   383  }
   384  
   385  # Run the integration-cli tests
   386  Function Run-IntegrationCliTests() {
   387      Write-Host "INFO: Running integration-cli tests..."
   388  
   389      $goTestRun = ""
   390      $reportSuffix = ""
   391      if ($env:INTEGRATION_TESTRUN.Length -ne 0)
   392      {
   393          $goTestRun = "-test.run=($env:INTEGRATION_TESTRUN)/"
   394          $reportSuffixStream = [IO.MemoryStream]::new([byte[]][char[]]$env:INTEGRATION_TESTRUN)
   395          $reportSuffix = "-" + (Get-FileHash -InputStream $reportSuffixStream -Algorithm SHA256).Hash
   396      }
   397  
   398      $jsonFilePath = $bundlesDir + "\go-test-report-int-cli-tests$reportSuffix.json"
   399      $xmlFilePath = $bundlesDir + "\junit-report-int-cli-tests$reportSuffix.xml"
   400      $coverageFilePath = $bundlesDir + "\coverage-report-int-cli-tests$reportSuffix.txt"
   401      $goTestArg = "--format=standard-verbose --packages=./integration-cli/... --jsonfile=$jsonFilePath --junitfile=$xmlFilePath -- -coverprofile=$coverageFilePath -covermode=atomic -tags=autogen -test.timeout=200m $goTestRun $env:INTEGRATION_TESTFLAGS"
   402      Write-Host "INFO: Invoking integration-cli tests run with gotestsum.exe $goTestArg"
   403      $pinfo = New-Object System.Diagnostics.ProcessStartInfo
   404      $pinfo.FileName = "gotestsum.exe"
   405      $pinfo.WorkingDirectory = "$($PWD.Path)"
   406      $pinfo.UseShellExecute = $false
   407      $pinfo.Arguments = $goTestArg
   408      $p = New-Object System.Diagnostics.Process
   409      $p.StartInfo = $pinfo
   410      $p.Start() | Out-Null
   411      $p.WaitForExit()
   412      if ($p.ExitCode -ne 0) { Throw "integration-cli tests failed" }
   413  }
   414  
   415  # Start of main code.
   416  Try {
   417      Write-Host -ForegroundColor Cyan "INFO: make.ps1 starting at $(Get-Date)"
   418  
   419      # Get to the root of the repo
   420      $root = $(Split-Path $MyInvocation.MyCommand.Definition -Parent | Split-Path -Parent)
   421      Push-Location $root
   422  
   423      # Ensure the bundles directory exists
   424      $bundlesDir = $root + "\bundles"
   425      Set-Variable bundlesDir -option ReadOnly
   426      New-Item -Force $bundlesDir -ItemType Directory | Out-Null
   427  
   428      # Handle the "-All" shortcut to turn on all things we can handle.
   429      # Note we expressly only include the items which can run in a container - the validations tests cannot
   430      # as they require the .git directory which is excluded from the image by .dockerignore
   431      if ($All) { $Client=$True; $Daemon=$True; $TestUnit=$True; }
   432  
   433      # Handle the "-Binary" shortcut to build both client and daemon.
   434      if ($Binary) { $Client = $True; $Daemon = $True }
   435  
   436      # Default to building the daemon if not asked for anything explicitly.
   437      if (-not($Client) -and -not($Daemon) -and -not($DCO) -and -not($PkgImports) -and -not($GoFormat) -and -not($TestUnit) -and -not($TestIntegration) -and -not($TestIntegrationCli)) { $Daemon=$True }
   438  
   439      # Verify git is installed
   440      if ($(Get-Command git -ErrorAction SilentlyContinue) -eq $nil) { Throw "Git does not appear to be installed" }
   441  
   442      # Verify go is installed
   443      if ($(Get-Command go -ErrorAction SilentlyContinue) -eq $nil) { Throw "GoLang does not appear to be installed" }
   444  
   445      # Get the git commit. This will also verify if we are in a repo or not. Then add a custom string if supplied.
   446      $gitCommit=Get-GitCommit
   447      if ($CommitSuffix -ne "") { $gitCommit += "-"+$CommitSuffix -Replace ' ', '' }
   448  
   449      # Get the version of docker (eg 17.04.0-dev)
   450      $dockerVersion="0.0.0-dev"
   451      # Overwrite dockerVersion if VERSION Environment variable is available
   452      if (Test-Path Env:\VERSION) { $dockerVersion=$env:VERSION }
   453  
   454      # Give a warning if we are not running in a container and are building binaries or running unit tests.
   455      # Not relevant for validation tests as these are fine to run outside of a container.
   456      if ($Client -or $Daemon -or $TestUnit) { $inContainer=Check-InContainer }
   457  
   458      # If we are not in a container, validate the version of GO that is installed.
   459      if (-not $inContainer) { Verify-GoVersion }
   460  
   461      # Verify GOPATH is set
   462      if ($env:GOPATH.Length -eq 0) { Throw "Missing GOPATH environment variable. See https://pkg.go.dev/cmd/go#hdr-GOPATH_environment_variable" }
   463  
   464      # Run autogen if building daemon.
   465      if ($Daemon) {
   466          Write-Host "INFO: Invoking autogen..."
   467          Try { .\hack\make\.go-autogen.ps1 -CommitString $gitCommit -DockerVersion $dockerVersion -Platform "$env:PLATFORM" -Product "$env:PRODUCT" -PackagerName "$env:PACKAGER_NAME" }
   468          Catch [Exception] { Throw $_ }
   469      }
   470  
   471      $ldflags = "-X 'github.com/docker/docker/dockerversion.Version="+$dockerVersion+"'"
   472      $ldflags += " -X 'github.com/docker/docker/dockerversion.GitCommit="+$gitCommit+"'"
   473      $ldflags += " -X 'github.com/docker/docker/dockerversion.BuildTime="+$env:BUILDTIME+"'"
   474      $ldflags += " -X 'github.com/docker/docker/dockerversion.PlatformName="+$env:PLATFORM+"'"
   475      $ldflags += " -X 'github.com/docker/docker/dockerversion.ProductName="+$env:PRODUCT+"'"
   476      $ldflags += " -X 'github.com/docker/docker/dockerversion.DefaultProductLicense="+$env:DEFAULT_PRODUCT_LICENSE+"'"
   477  
   478      # DCO, Package import and Go formatting tests.
   479      if ($DCO -or $PkgImports -or $GoFormat) {
   480          # We need the head and upstream commits for these
   481          $headCommit=Get-HeadCommit
   482          $upstreamCommit=Get-UpstreamCommit
   483  
   484          # Run DCO validation
   485          if ($DCO) { Validate-DCO $headCommit $upstreamCommit }
   486  
   487          # Run `gofmt` validation
   488          if ($GoFormat) { Validate-GoFormat $headCommit $upstreamCommit }
   489  
   490          # Run pkg isolation validation
   491          if ($PkgImports) { Validate-PkgImports $headCommit $upstreamCommit }
   492      }
   493  
   494      # Build the binaries
   495      if ($Client -or $Daemon) {
   496  
   497          # Perform the actual build
   498          if ($Daemon) { Execute-Build "daemon" "daemon" "dockerd" $ldflags }
   499          if ($Client) {
   500              # Get the Docker channel and version from the environment, or use the defaults.
   501              if (-not ($channel = $env:DOCKERCLI_CHANNEL)) { $channel = "stable" }
   502              if (-not ($version = $env:DOCKERCLI_VERSION)) { $version = "17.06.2-ce" }
   503  
   504              # Download the zip file and extract the client executable.
   505              Write-Host "INFO: Downloading docker/cli version $version from $channel..."
   506              $url = "https://download.docker.com/win/static/$channel/x86_64/docker-$version.zip"
   507              Invoke-WebRequest $url -OutFile "docker.zip"
   508              Try {
   509                  Add-Type -AssemblyName System.IO.Compression.FileSystem
   510                  $zip = [System.IO.Compression.ZipFile]::OpenRead("$PWD\docker.zip")
   511                  Try {
   512                      if (-not ($entry = $zip.Entries | Where-Object { $_.Name -eq "docker.exe" })) {
   513                          Throw "Cannot find docker.exe in $url"
   514                      }
   515                      [System.IO.Compression.ZipFileExtensions]::ExtractToFile($entry, "$PWD\bundles\docker.exe", $true)
   516                  }
   517                  Finally {
   518                      $zip.Dispose()
   519                  }
   520              }
   521              Finally {
   522                  Remove-Item -Force "docker.zip"
   523              }
   524          }
   525      }
   526  
   527      # Run unit tests
   528      if ($TestUnit) { Run-UnitTests }
   529  
   530      # Run integration tests
   531      if ($TestIntegration) { Run-IntegrationTests }
   532  
   533      # Run integration-cli tests
   534      if ($TestIntegrationCli) { Run-IntegrationCliTests }
   535  
   536      # Gratuitous ASCII art.
   537      if ($Daemon -or $Client) {
   538          Write-Host
   539          Write-Host -ForegroundColor Green " ________   ____  __."
   540          Write-Host -ForegroundColor Green " \_____  \ `|    `|/ _`|"
   541          Write-Host -ForegroundColor Green " /   `|   \`|      `<"
   542          Write-Host -ForegroundColor Green " /    `|    \    `|  \"
   543          Write-Host -ForegroundColor Green " \_______  /____`|__ \"
   544          Write-Host -ForegroundColor Green "         \/        \/"
   545          Write-Host
   546      }
   547  }
   548  Catch [Exception] {
   549      Write-Host -ForegroundColor Red ("`nERROR: make.ps1 failed:`n$_")
   550      Write-Host -ForegroundColor Red ($_.InvocationInfo.PositionMessage)
   551  
   552      # More gratuitous ASCII art.
   553      Write-Host
   554      Write-Host -ForegroundColor Red  "___________      .__.__             .___"
   555      Write-Host -ForegroundColor Red  "\_   _____/____  `|__`|  `|   ____   __`| _/"
   556      Write-Host -ForegroundColor Red  " `|    __) \__  \ `|  `|  `| _/ __ \ / __ `| "
   557      Write-Host -ForegroundColor Red  " `|     \   / __ \`|  `|  `|_\  ___// /_/ `| "
   558      Write-Host -ForegroundColor Red  " \___  /  (____  /__`|____/\___  `>____ `| "
   559      Write-Host -ForegroundColor Red  "     \/        \/             \/     \/ "
   560      Write-Host
   561  
   562      exit 1
   563  }
   564  Finally {
   565      Pop-Location # As we pushed to the root of the repo as the very first thing
   566      if ($global:pushed) { Pop-Location }
   567      Write-Host -ForegroundColor Cyan "INFO: make.ps1 ended at $(Get-Date)"
   568  }