make.ps1 25 KB

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