#!/usr/bin/env powershell [CmdletBinding(PositionalBinding=$false)] param ( [ValidateSet("amd64", "arm64")] [Alias("arch")] [string]$architecture = $( $defaultArchitecture = "amd64" $arch = try {& go env GOARCH} catch { Write-Warning "Failed retriving the host architecture, using default ($defaultArchitecture). Is Go installed?" return $defaultArchitecture } if ($arch -cnotin @("arm64", "amd64")) { Write-Warning "Unsupported architecture $arch. Using default ($defaultArchitecture)." return $defaultArchitecture } return $arch ), [parameter(ValueFromRemainingArguments)][object[]]$params = @() ) . ./contrib/cirrus/win-lib.ps1 # Targets function Podman-Remote{ New-Item -ItemType Directory -Force -Path "./bin/windows" $buildInfo = Get-Date -UFormat %s -Millisecond 0 $buildInfo = "-X github.com/containers/podman/v5/libpod/define.buildInfo=$buildInfo " $commit = Git-Commit $commit = "-X github.com/containers/podman/v5/libpod/define.gitCommit=$commit " $ENV:GOARCH = $architecture Run-Command "go build --ldflags `"$commit $buildInfo `" --tags `"$remotetags`" --o ./bin/windows/podman.exe ./cmd/podman/." } function Make-Clean{ $paths= @( # Files generated by the `podman` target "$PSScriptRoot\bin\windows" # Files generated by the `installer` target "$PSScriptRoot\test\version\version.exe" "$PSScriptRoot\contrib\win-installer\artifacts" "$PSScriptRoot\contrib\win-installer\current" "$PSScriptRoot\contrib\win-installer\docs" "$PSScriptRoot\contrib\win-installer\en-us" "$PSScriptRoot\contrib\win-installer\fetch" "$PSScriptRoot\contrib\win-installer\obj" "$PSScriptRoot\contrib\win-installer\*.log" "$PSScriptRoot\contrib\win-installer\*.exe" "$PSScriptRoot\contrib\win-installer\*.wixpdb" # Files generated by the Documentation target "$PSScriptRoot\docs\build\remote\podman-*.html" "$PSScriptRoot\docs\build\remote\podman-for-windows.html" ) foreach ($path in $paths) { if (Test-Path -Path $path -PathType Container) { Remove-Item $path -Recurse -Force -Confirm:$false } elseif (Test-Path -Path $path -PathType Leaf) { Remove-Item $path -Force -Confirm:$false } } } function Local-Unit { Build-Ginkgo $skippackages="hack,internal\domain\infra\abi,internal\domain\infra\tunnel,libpod\lock\shm,pkg\api\handlers\libpod,pkg\api\handlers\utils,pkg\bindings," $skippackages+="pkg\domain\infra\abi,pkg\emulation,pkg\machine\apple,pkg\machine\applehv,pkg\machine\e2e,pkg\machine\libkrun," $skippackages+="pkg\machine\provider,pkg\machine\proxyenv,pkg\machine\qemu,pkg\specgen\generate,pkg\systemd,test\e2e,test\utils,cmd\rootlessport," $skippackages+="pkg\pidhandle" Run-Command "./bin/ginkgo.exe -vv -r --tags `"$remotetags`" --timeout=15m --trace --no-color --skip-package `"$skippackages`"" } function Local-Machine { param ( [string]$files ); Build-Ginkgo if ($files) { $files = " --focus-file $files " } Run-Command "./bin/ginkgo.exe -vv --tags `"$remotetags`" --timeout=90m --trace --no-color $files pkg/machine/e2e/." } # Expect starting directory to be /podman function Win-SSHProxy { param ( [string]$Version ); New-Item -ItemType Directory -Force -Path "./bin/windows" if (-Not $Version) { $match = Select-String -Path "$PSScriptRoot\go.mod" -Pattern "github.com/containers/gvisor-tap-vsock\s+(v[\d\.]+)" $Version = $match.Matches.Groups[1].Value } Write-Host "Downloading gvproxy version $version" if ($architecture -eq "amd64") { curl.exe -sSL -o "./bin/windows/gvproxy.exe" --retry 5 "https://github.com/containers/gvisor-tap-vsock/releases/download/$Version/gvproxy-windowsgui.exe" curl.exe -sSL -o "./bin/windows/win-sshproxy.exe" --retry 5 "https://github.com/containers/gvisor-tap-vsock/releases/download/$Version/win-sshproxy.exe" } else { curl.exe -sSL -o "./bin/windows/gvproxy.exe" --retry 5 "https://github.com/containers/gvisor-tap-vsock/releases/download/$Version/gvproxy-windows-arm64.exe" curl.exe -sSL -o "./bin/windows/win-sshproxy.exe" --retry 5 "https://github.com/containers/gvisor-tap-vsock/releases/download/$Version/win-sshproxy-arm64.exe" } } function Installer{ param ( [string]$version, [string]$suffix = "dev" ); Write-Host "Building the windows installer for $architecture" # Check for the files to include in the installer $requiredArtifacts = @( "$PSScriptRoot\bin\windows\podman.exe" "$PSScriptRoot\bin\windows\gvproxy.exe" "$PSScriptRoot\bin\windows\win-sshproxy.exe" "$PSScriptRoot\docs\build\remote\podman-for-windows.html" ) $requiredArtifacts | ForEach-Object { if (!(Test-Path -Path $PSItem -PathType Leaf)) { Write-Host "$PSItem not found." Write-Host "Make 'podman', 'win-gvproxy' and 'docs' (or 'docs-using-podman') before making the installer:" Write-Host " .\winmake.ps1 podman-remote" Write-Host " .\winmake.ps1 win-gvproxy" Write-Host " .\winmake.ps1 docs or .\winmake.ps1 docs-using-podman" Exit 1 } } # Create the ZIP file with the full client distribution $zipFileDest = "$PSScriptRoot\contrib\win-installer\current" Build-Distribution-Zip-File -destinationPath $zipFileDest if (-Not $version) { # Get Podman version from local source code $version = Get-Podman-Version } # Run \contrib\win-installer\build.ps1 Push-Location $PSScriptRoot\contrib\win-installer $ENV:PODMAN_ARCH = $architecture # This is used by the "build.ps1" script Run-Command ".\build.ps1 $version $suffix `"$zipFileDest`"" Pop-Location } function Test-Installer{ param ( [string]$version, [ValidateSet("dev", "prod")] [string]$flavor = "dev", [ValidateSet("wsl", "hyperv")] [string]$provider = "wsl" ); if (-Not $version) { # Get Podman version from local source code $version = Get-Podman-Version } if ($flavor -eq "prod") { $suffix = "" } else { $suffix = "-dev" } $setupExePath = "$PSScriptRoot\contrib\win-installer\podman-${version}${suffix}-setup.exe" if (!(Test-Path -Path $setupExePath -PathType Leaf)) { Write-Host "Setup executable not found in path $setupExePath." Write-Host "Make 'installer' before making the installer test:" Write-Host " .\winmake.ps1 installer" Exit 1 } $nextSetupExePath = "$PSScriptRoot\contrib\win-installer\podman-9.9.9-dev-setup.exe" if (!(Test-Path -Path $nextSetupExePath -PathType Leaf)) { Write-Host "The automated tests include testing the upgrade from current version to a future version." Write-Host "That requires a version 9.9.9 of the installer:" Write-Host " .\winmake.ps1 installer 9.9.9" Write-Host "Build it and retry running installertest." Exit 1 } $command = "$PSScriptRoot\contrib\win-installer\test-installer.ps1" $command += " -scenario all" $command += " -provider $provider" $command += " -setupExePath $setupExePath" $command += " -nextSetupExePath $nextSetupExePath" Run-Command "${command}" } function Documentation{ Write-Host "Generating the documentation artifacts" # Check that pandoc is installed if (!(Get-Command -Name "pandoc" -ErrorAction SilentlyContinue)) { Write-Host "Pandoc not found. Pandoc is required to convert the documentation Markdown files into HTML files." Write-Host "Alternatively, use '.\winmake docs-using-podman' to use a container to run pandoc and generate the documentation." Exit 1 } # Check that the podman client is built $podmanClient = "$PSScriptRoot\bin\windows\podman.exe" if (!(Test-Path -Path $podmanClient -PathType Leaf)) { Write-Host "$podmanClient not found. Make 'podman-remote' before 'documentation'." Exit 1 } Run-Command "$PSScriptRoot\docs\make.ps1 $podmanClient" } # DocumentationUsingPodman generates documentation with pandoc running in a container. # This is usefult on Windows arm64 where pandoc is not available. # It's also useful to generate documentation identical to CI. # It requires the podman client to be built and a podman machine running. # The whole podman git repository is bind mounted in the container at /podman. # The documentation is generated by running the command `make podman-remote-windows-docs`. # The generated documentation is stored in the directory docs/build/remote. function DocumentationUsingPodman{ Write-Host "Generating documentation artifacts" # Check that podman has been built $podmanClient = "${PSScriptRoot}\bin\windows\podman.exe" if (!(Test-Path -Path $podmanClient -PathType Leaf)) { Write-Host "$podmanClient not found. Make 'podman-remote' before 'documentation'." Exit 1 } # Check that a podman machine exist $currentMachine = (& ${podmanClient} machine info -f json | ConvertFrom-Json).Host.CurrentMachine if (!$currentMachine) { Write-Host "Podman machine doesn't exist. Initialize and start one before running the validate script." Exit 1 } # Check that the podman machine is running $state = (& ${podmanClient} machine info -f json | ConvertFrom-Json).Host.MachineState if ($state -ne "Running") { Write-Host "Podman machine is not running. Start the machine before running the validate script." Exit 1 } Write-Host "Building the image to generate the documentation" Run-Command "${podmanClient} build --build-arg TARGET_OS=windows -t podman-docs-generator ${PSScriptRoot}/docs" Write-Host "Starting the container to run the documentation build" Run-Command "${podmanClient} run -t --rm -v ${PSScriptRoot}:/podman podman-docs-generator" } function Validate{ $podmanExecutable = "podman" $podmanSrcVolumeMount = "${PSScriptRoot}:/go/src/github.com/containers/podman" # All files bind mounted from a Windows host are marked as executable. # That makes the pre-commit hook "check-executables-have-shebangs" fail. # Setting the environment variable "SKIP=check-executables-have-shebangs" # allow to skip that pre-commit hook. $podmanEnvVariable = "-e SKIP=check-executables-have-shebangs" $podmanRunArgs = "--rm -v $podmanSrcVolumeMount --security-opt label=disable -t -w /go/src/github.com/containers/podman $podmanEnvVariable" $validateImage = "quay.io/libpod/validatepr:latest" $validateCommand = "make .validatepr" # Check that podman is installed if (!(Get-Command -Name $podmanExecutable -ErrorAction SilentlyContinue)) { Write-Host "$podmanExecutable not found. $podmanExecutable is required to run the validate script." Exit 1 } # Check that a podman machine exist $currentMachine = (podman machine info -f json | ConvertFrom-Json).Host.CurrentMachine if (!$currentMachine) { Write-Host "Podman machine doesn't exist. Initialize and start one before running the validate script." Exit 1 } # Check that the podman machine is running $state = (podman machine info -f json | ConvertFrom-Json).Host.MachineState if ($state -ne "Running") { Write-Host "Podman machine is not running. Start the machine before running the validate script." Exit 1 } Run-Command "$podmanExecutable run $podmanRunArgs $validateImage $validateCommand" } function Lint{ # Check that golangci-lint is installed if (!(Get-Command -Name "golangci-lint" -ErrorAction SilentlyContinue)) { Write-Host "The tool ""golangci-lint"" not found. Install https://golangci-lint.run/ before running the lint script." Exit 1 } # Check that pre-commit is installed if (!(Get-Command -Name "pre-commit" -ErrorAction SilentlyContinue)) { Write-Host "The tool ""pre-commit"" not found. Install https://pre-commit.com/ before running the lint script." Exit 1 } Run-Command "pre-commit run --all-files" Run-Command "golangci-lint run --timeout=10m --build-tags=`"$remotetags`" $PSScriptRoot\cmd\podman" } # Helpers function Build-Ginkgo{ if (Test-Path -Path ./bin/ginkgo.exe -PathType Leaf) { return } Write-Host "Building Ginkgo" Run-Command "go build -o ./bin/ginkgo.exe ./vendor/github.com/onsi/ginkgo/v2/ginkgo" } function Git-Commit{ # git is not installed by default on windows, # so if we can't get the commit, we don't include this info Get-Command git -ErrorAction SilentlyContinue | out-null if(!$?){ return } $commit = git rev-parse HEAD $dirty = git status --porcelain --untracked-files=no if ($dirty){ $commit = "$commit-dirty" } return $commit } function Build-Distribution-Zip-File{ param ( [string]$destinationPath ); $binariesFolder = "$PSScriptRoot\bin\windows" $documentationFolder = "$PSScriptRoot\docs\build\remote\" $zipFile = "$destinationPath\podman-remote-release-windows_$architecture.zip" # Create a temporary folder to store the distribution files $tempFolder = New-Item -ItemType Directory -Force -Path "$env:TEMP\podman-windows" # Copy bin\windows\ content to the temporary folder Copy-Item -Recurse -Force -Path "$binariesFolder\*" -Destination "$tempFolder\" # Copy docs\build\remote to the temporary folder Copy-Item -Recurse -Force -Path "$documentationFolder" -Destination "$tempFolder\docs\" # If $destination path doesn't exist, create it if (-Not (Test-Path -Path $destinationPath -PathType Container)) { New-Item -ItemType Directory -Force -Path $destinationPath } # Create the ZIP file with the full client distribution Compress-Archive -Path "$tempFolder\*" -DestinationPath $zipFile -Force # Delete the temporary folder Remove-Item -Recurse -Force -Path "$tempFolder" } function Get-Podman-Version{ $versionSrc = "$PSScriptRoot\test\version\" $versionBin = "$PSScriptRoot\test\version\version.exe" Run-Command "go build --o `"$versionBin`" `"$versionSrc`"" $version = Invoke-Expression "$versionBin" # Remove the '-dev' suffix from the version $version = $version -replace "-.*", "" return $version } # Init script $target = $params[0] $remotetags = "remote exclude_graphdriver_btrfs containers_image_openpgp" switch ($target) { {$_ -in '', 'podman-remote', 'podman'} { Podman-Remote } 'localunit' { Local-Unit } 'localmachine' { if ($params.Count -gt 1) { $files = $params[1] } Local-Machine -files $files } 'clean' { Make-Clean } {$_ -in 'win-sshproxy', 'win-gvproxy'} { if ($params.Count -gt 1) { $ref = $params[1] } Win-SSHProxy($ref) } 'installer' { if ($params.Count -gt 1) { Installer -version $params[1] } else { Installer } } 'installertest' { if ($params.Count -gt 1) { Test-Installer -provider $params[1] } else { Test-Installer } } 'docs' { Documentation } 'docs-using-podman' { DocumentationUsingPodman } 'validatepr' { Validate } 'lint' { Lint } default { Write-Host "Usage: " $MyInvocation.MyCommand.Name " [options] [<-architecture|-arch>=]" Write-Host Write-Host "Example: Build podman-remote " Write-Host " .\winmake podman-remote" Write-Host Write-Host "Example: Run all unit tests " Write-Host " .\winmake localunit" Write-Host Write-Host "Example: Run all machine tests " Write-Host " .\winmake localmachine" Write-Host Write-Host "Example: Run specfic machine tests " Write-Host " .\winmake localmachine "basic_test.go"" Write-Host Write-Host "Example: Download win-gvproxy and win-sshproxy helpers" Write-Host " .\winmake win-gvproxy" Write-Host Write-Host "Example: Build the windows installer" Write-Host " .\winmake installer" Write-Host Write-Host "Example: Run windows installer tests" Write-Host " .\winmake installertest hyperv" Write-Host Write-Host "Example: Generate the documentation artifacts" Write-Host " .\winmake docs" Write-Host Write-Host "Example: Generate the documentation artifacts by running pandoc in a container" Write-Host " .\winmake docs-using-podman" Write-Host Write-Host "Example: Validate code changes before submitting a PR" Write-Host " .\winmake validatepr" Write-Host Write-Host "Example: Run linters" Write-Host " .\winmake lint" } }