Add a new Windows installer supporting user scope

Fixes #22994 and #25968

Signed-off-by: Mario Loriedo <mario.loriedo@gmail.com>
This commit is contained in:
Mario Loriedo
2025-09-25 16:53:55 +02:00
parent d5b571056e
commit 9dbc33bb25
37 changed files with 2029 additions and 396 deletions

View File

@@ -188,10 +188,18 @@ jobs:
# functionality. We should avoid clobbering or re-building windows installers in most cases,
# For build-only, the .exe is saved in the workflow artifacts for a human
# to judge.
- name: Build
- name: Build the MSI
id: build
run: |
Push-Location contrib\win-installer
contrib\win-installer\build.ps1 `
-Version ${{steps.getversion.outputs.version}} `
-LocalReleaseDirPath ${{ github.workspace }}\release-artifacts `
-Architecture ${{ matrix.arch }}
Exit $LASTEXITCODE
- name: Build the bundle (legacy)
id: build-legacy
run: |
Push-Location contrib\win-installer-legacy
.\build.ps1 ${{steps.getversion.outputs.version}} prod ${{ github.workspace }}\release-artifacts
$code = $LASTEXITCODE
if ($code -eq 2) {
@@ -208,26 +216,40 @@ jobs:
Push-Location contrib\win-installer
Get-ChildItem
Pop-Location
- name: Rename the installer
Push-Location contrib\win-installer-legacy
Get-ChildItem
Pop-Location
- name: Rename the MSI
run: |
Push-Location contrib\win-installer
Copy-Item -Path podman-${{steps.getversion.outputs.version}}.msi -Destination podman-installer-windows-${{ matrix.arch }}.msi
Pop-Location
- name: Rename the bundle (legacy)
run: |
Push-Location contrib\win-installer-legacy
Copy-Item -Path podman-${{steps.getversion.outputs.version}}-setup.exe -Destination podman-installer-windows-${{ matrix.arch }}.exe
Pop-Location
- name: Upload the installer
- name: Upload the MSI
uses: actions/upload-artifact@v4
with:
name: win-msi-${{ matrix.arch }}
path: |
.\contrib\win-installer\podman-installer-windows-${{ matrix.arch }}.msi
- name: Upload the bundle (legacy)
uses: actions/upload-artifact@v4
with:
name: win-installer-${{ matrix.arch }}
path: |
.\contrib\win-installer\podman-installer-windows-${{ matrix.arch }}.exe
.\contrib\win-installer-legacy\podman-installer-windows-${{ matrix.arch }}.exe
# For backwards compatibility, we also upload the amd64 windows
# installer using the old name
- name: Upload the installer (legacy)
- name: Upload the bundle with the old name (legacy)
uses: actions/upload-artifact@v4
if: ${{ matrix.arch == 'amd64' }}
with:
name: win-installer
path: |
.\contrib\win-installer\podman-${{steps.getversion.outputs.version}}-setup.exe
.\contrib\win-installer-legacy\podman-${{steps.getversion.outputs.version}}-setup.exe
release:
name: Create Release
@@ -266,6 +288,8 @@ jobs:
mv mac-installers/* release-artifacts
mv win-installer-amd64/* release-artifacts
mv win-installer-arm64/* release-artifacts
mv win-msi-amd64/* release-artifacts
mv win-msi-arm64/* release-artifacts
pushd release-artifacts
sha256sum * > shasums
popd

View File

@@ -64,7 +64,7 @@ jobs:
- name: Check
id: check
run: |
Push-Location contrib\win-installer
Push-Location contrib\win-installer-legacy
.\check.ps1 ${{steps.getversion.outputs.version}}
$code = $LASTEXITCODE
if ($code -eq 2) {
@@ -108,7 +108,7 @@ jobs:
id: build
if: steps.check.outputs.already-exists != 'true' || steps.actual_dryrun.outputs.dryrun == 'true'
run: |
Push-Location contrib\win-installer
Push-Location contrib\win-installer-legacy
.\build.ps1 ${{steps.getversion.outputs.version}} prod
$code = $LASTEXITCODE
if ($code -eq 2) {
@@ -125,7 +125,7 @@ jobs:
name: installer
path: |
${{ steps.check.outputs.upload_asset_name }}
.\contrib\win-installer\shasums
.\contrib\win-installer-legacy\shasums
- name: Upload
if: >-
steps.actual_dryrun.outputs.dryrun == 'false' &&
@@ -134,7 +134,7 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
Push-Location contrib\win-installer
Push-Location contrib\win-installer-legacy
$version = "${{ steps.getversion.outputs.version }}"
if ($version[0] -ne "v") {
$version = "v$version"

View File

@@ -9,7 +9,7 @@ Windows.
- [Requirements](#requirements)
- [OS requirements](#os-requirements)
- [Git and go](#git-and-go)
- [Pandoc](#pandoc)
- [Pandoc (optional)](#pandoc-optional)
- [.NET SDK](#net-sdk)
- [Virtualization Provider](#virtualization-provider)
- [WSL](#wsl)
@@ -25,9 +25,10 @@ Windows.
- [Build and test the Podman Windows installer](#build-and-test-the-podman-windows-installer)
- [Build the Windows installer](#build-the-windows-installer)
- [Test the Windows installer](#test-the-windows-installer)
- [Build and test the standalone `podman.msi` file](#build-and-test-the-standalone-podmanmsi-file)
- [Verify the installation](#verify-the-installation)
- [Run the Windows installer automated tests](#run-the-windows-installer-automated-tests)
- [Verify the installation](#verify-the-installation)
- [Uninstall and clean-up](#uninstall-and-clean-up)
- [Retrieve Podman installed products](#retrieve-podman-installed-products)
- [Validate changes before submitting a PR](#validate-changes-before-submitting-a-pr)
- [winmake lint](#winmake-lint)
- [winmake validatepr](#winmake-validatepr)
@@ -86,9 +87,15 @@ winget install -e Microsoft.DotNet.SDK.8
used too and can be installed using `dotnet install`:
```pwsh
dotnet tool install --global wix
dotnet tool install --global wix --version 5.0.2
```
:information_source: Because WiX Toolset has changed its licensing model when v6
was released, [Podman still uses the WiX Toolset
v5.0.2](https://github.com/containers/podman/issues/27042)
and we recommend using it as well for local development (although it's not
strictly required).
### Virtualization Provider
Running Podman on Windows requires a virtualization provider. The supported
@@ -125,7 +132,7 @@ Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All
After running this command, a restart of the Windows machine is required.
:information_source: Configure the VM provider used by podman (Hyper-V or WSL)
in the file `%PROGRAMDATA%/containers/containers.conf`.
in the file `%APPDATA%/containers/containers.conf`.
[More on that later](#create-a-configuration-file-optional).
## Get the source code
@@ -242,9 +249,9 @@ To test some particular configurations of Podman, create a `containers.conf`
file:
```
New-Item -ItemType Directory $env:PROGRAMDATA\containers\
New-Item -ItemType File $env:PROGRAMDATA\containers\containers.conf
notepad $env:PROGRAMDATA\containers\containers.conf
New-Item -ItemType Directory $env:APPDATA\containers\
New-Item -ItemType File $env:APPDATA\containers\containers.conf
notepad $env:APPDATA\containers\containers.conf
```
For example, to test with Hyper-V as the virtualization provider, use the
@@ -288,15 +295,15 @@ To learn how to use the Podman client, refer to its
## Build and test the Podman Windows installer
The Podman Windows installer (e.g., `podman-5.1.0-dev-setup.exe`) is a bundle
that includes an msi package (`podman.msi`). It's built using the
[WiX Toolset](https://wixtoolset.org/) and the
[PanelSwWixExtension](https://github.com/nirbar/PanelSwWixExtension/tree/master5)
WiX extension. The source code is in the folder `contrib\win-installer`.
The Podman Windows installer (e.g., `podman-5.7.0.msi`) is an MSI package
built using the [WiX Toolset](https://wixtoolset.org/) v5. The installer
supports installation at both user scope (per-user) and machine scope
(per-machine/administrator). The source code is in the folder
`contrib\win-installer`.
### Build the Windows installer
To build the installation bundle, run the following command:
To build the MSI installer, run the following command:
```pwsh
.\winmake.ps1 installer
@@ -306,14 +313,15 @@ To build the installation bundle, run the following command:
required before running this command.
Locate the installer in the `contrib\win-installer` folder (relative to checkout
root) with a name like `podman-5.2.0-dev-setup.exe`.
root) with a name like `podman-5.7.0.msi`, where `5.7.0` is the version of
Podman on the local branch.
The `installer` target of `winmake.ps1` runs the script
`contrib\win-installer\build.ps1` that, in turns, executes:
- `dotnet build podman.wixproj`: builds `podman.msi` from the WiX source files `podman.wxs`,
`pages.wxs`, `podman-ui.wxs` and `welcome-install-dlg.wxs`.
- `dotnet build podman-setup.wixproj`: builds `podman-setup.exe` file from
[WiX Burn bundle](https://wixtoolset.org/docs/tools/burn/) `burn.wxs`.
`contrib\win-installer\build.ps1` that, in turn, executes:
- `dotnet build podman.wixproj`: builds `podman.msi` from the WiX source files
`wix\podman-main.wxs`, `wix\podman-ui-main.wxs`, and
`wix\podman-ui-welcome-dlg.wxs`.
### Test the Windows installer
@@ -321,37 +329,54 @@ Double-click on the Windows installer to run it. To get the installation logs
with debug information, running it via the command line is recommended:
```pwsh
contrib\win-installer\podman-5.1.0-dev-setup.exe /install /log podman-setup.log
msiexec /package contrib\win-installer\podman-5.7.0.msi /l*v podman-msi.log
```
It generates the files `podman-setup.log` and `podman-setup_000_Setup.log`,
which include detailed installation information, in the current directory.
It generates the file `podman-msi.log`, which includes detailed installation
information, in the current directory.
Run it in `quiet` mode to automate the installation and avoid interacting with
the GUI. Open the terminal **as an administrator**, add the `/quiet` option, and
set the bundle variable `MachineProvider` (`wsl` or `hyperv`):
The MSI installer supports both user-scope and machine-scope installations:
- **User scope (per-user)**: No administrator privileges required. Files are
installed in the user's profile directory, and the PATH is updated only for
the current user. This is the default scope.
- **Machine scope (per-machine)**: Requires administrator privileges. Files are
installed in `Program Files`, and the PATH is updated for all users.
To run an automated installation in quiet, non-interactive mode and set the
machine provider (`wsl` or `hyperv`), use the following command:
**User scope installation** (no administrator required):
```pwsh
contrib\win-installer\podman-5.1.0-dev-setup.exe /install `
/log podman-setup.log /quiet `
MachineProvider=wsl
msiexec /package contrib\win-installer\podman-5.7.0.msi /l*v podman-msi.log `
/quiet MSIINSTALLPERUSER=1 MACHINE_PROVIDER=wsl
```
**Machine scope installation** (requires administrator terminal):
```pwsh
msiexec /package contrib\win-installer\podman-5.7.0.msi /l*v podman-msi.log `
/quiet ALLUSERS=1 MACHINE_PROVIDER=wsl
```
:information_source: If uninstallation fails, the installer may end up in an
inconsistent state. Podman results as uninstalled, but some install packages are
still tracked in the Windows registry and will affect further tentative to
re-install Podman. When this is the case, trying to re-install Podman results in
the installer returning zero (success) but no action is executed. The trailing
packages `GID` can be found in installation logs:
inconsistent state. Podman results as uninstalled, but the MSI package is still
tracked in the Windows registry and will affect further attempts to reinstall
Podman. When this is the case, trying to reinstall Podman results in the
installer returning zero (success) but no action is executed. The package
`GUID` can be found in the installation logs:
```
Detected related package: {<GID>}
```log
Product: Podman CLI -- Installation completed successfully.
ProductCode: {<GUID>}
```
To fix this problem remove the related packages:
To fix this problem, remove the tracked package:
```pwsh
msiexec /x "{<GID>}"
msiexec /x "{<GUID>}"
```
#### Run the Windows installer automated tests
@@ -363,66 +388,46 @@ it requires an administrator terminal.
.\winmake.ps1 installertest [wsl|hyperv]
```
### Build and test the standalone `podman.msi` file
#### Verify the installation
Building and testing the standalone `podman.msi` package during development may
be useful. Even if this package is not published as a standalone file when
Podman is released (it's included in the `podman-setup.exe` bundle), it can be
faster to build and test that rather than the full bundle during the development
phase.
Run the command `dotnet build` to build the standalone `podman.msi` file:
```pwsh
Push-Location .\contrib\win-installer\
dotnet build podman.wixproj /property:DefineConstants="VERSION=9.9.9" -o .
Pop-Location
```
It creates the file `.\contrib\win-installer\en-US\podman.msi`. Test it using the
[Microsoft Standard Installer](https://learn.microsoft.com/en-us/windows/win32/msi/standard-installer-command-line-options)
command line tool:
```pwsh
msiexec /package contrib\win-installer\en-US\podman.msi /l*v podman-msi.log
```
To run it in quiet, non-interactive mode, open the terminal **as an
administrator**, add the `/quiet` option, and set the MSI property
`MACHINE_PROVIDER` (`wsl` or `hyperv`):
```pwsh
msiexec /package contrib\win-installer\en-US\podman.msi /l*v podman-msi.log /quiet MACHINE_PROVIDER=wsl
```
:information_source: `podman.msi` GUI dialogs, defined in the file
`contrib\win-installer\welcome-install-dlg.wxs`, are distinct from the installation bundle
`podman-setup.exe` GUI dialogs, defined in
`contrib\win-installer\podman-theme.xml`.
### Verify the installation
Inspect the msi installation log `podman-msi.log` (or
`podman-setup_000_Setup.log` if testing with the bundle) to verify that the
Inspect the MSI installation log `podman-msi.log` to verify that the
installation was successful:
```pwsh
Select-String -Path "podman-msi.log" -Pattern "Installation success or error status: 0"
```
These commands too are helpful to check the installation:
The following commands are helpful to check the installation:
**For machine scope (per-machine) installations:**
```pwsh
# Check the copy of the podman client in the Podman folder
Test-Path -Path "$ENV:PROGRAMFILES\RedHat\Podman\podman.exe"
Test-Path -Path "$ENV:PROGRAMFILES\Podman\podman.exe"
# Check the generation of the podman configuration file
Test-Path -Path "$ENV:PROGRAMDATA\containers\containers.conf.d\99-podman-machine-provider.conf"
# Check that the installer configured the right provider
Get-Content "$ENV:PROGRAMDATA\containers\containers.conf.d\99-podman-machine-provider.conf" | Select -Skip 1 | ConvertFrom-StringData | % { $_.provider }
# Check the creation of the registry key
Test-Path -Path "HKLM:\SOFTWARE\Red Hat\Podman"
Get-ItemProperty "HKLM:\SOFTWARE\Red Hat\Podman" InstallDir
# Check the podman.exe is in the $PATH
Test-Path -Path "HKLM:\SOFTWARE\Podman"
Get-ItemProperty "HKLM:\SOFTWARE\Podman" InstallDir
# Check that podman.exe is in the $PATH
$env:PATH | Select-String -Pattern "Podman"
```
**For user scope (per-user) installations:**
```pwsh
# Check the copy of the podman client in the Podman folder
Test-Path -Path "$ENV:LOCALAPPDATA\Programs\Podman\podman.exe"
# Check the generation of the podman configuration file
Test-Path -Path "$ENV:APPDATA\containers\containers.conf.d\99-podman-machine-provider.conf"
# Check that the installer configured the right provider
Get-Content "$ENV:APPDATA\containers\containers.conf.d\99-podman-machine-provider.conf" | Select -Skip 1 | ConvertFrom-StringData | % { $_.provider }
# Check the creation of the registry key
Test-Path -Path "HKCU:\SOFTWARE\Podman"
Get-ItemProperty "HKCU:\SOFTWARE\Podman" InstallDir
# Check that podman.exe is in the $PATH
$env:PATH | Select-String -Pattern "Podman"
```
@@ -437,44 +442,125 @@ $ENV:CONTAINERS_MACHINE_PROVIDER='hyperv'; .\contrib\cirrus\win-installer-main.p
### Uninstall and clean-up
Podman can be uninstalled from the Windows Control Panel or running the
following command from a terminal **as an administrator**:
Podman can be uninstalled from the Windows Control Panel or using the MSI
uninstall command. Administrator privileges will be required if Podman was
installed for the machine, rather than for a user:
```pwsh
contrib\win-installer\podman-5.1.0-dev-setup.exe /uninstall /quiet /log podman-setup-uninstall.log
msiexec /x contrib\win-installer\podman-5.7.0.msi /quiet /l*v podman-msi-uninstall.log
```
The uninstaller does not delete some folders. Clean them up manually:
**For machine scope installations:**
```pwsh
$extraFolders = @(
"$ENV:PROGRAMDATA\containers\"
"$ENV:LOCALAPPDATA\containers\"
"$env:USERPROFILE.config\containers\"
"$env:USERPROFILE.local\share\containers\"
)
$extraFolders | ForEach-Object {Remove-Item -Recurse -Force $PSItem}
"$env:USERPROFILE\.config\containers\"
"$env:USERPROFILE\.local\share\containers\"
)
$extraFolders | ForEach-Object {Remove-Item -Recurse -Force $PSItem -ErrorAction SilentlyContinue}
```
**For user scope installations:**
```pwsh
$extraFolders = @(
"$ENV:APPDATA\containers\"
"$ENV:LOCALAPPDATA\containers\"
"$env:USERPROFILE\.config\containers\"
"$env:USERPROFILE\.local\share\containers\"
)
$extraFolders | ForEach-Object {Remove-Item -Recurse -Force $PSItem -ErrorAction SilentlyContinue}
```
The following commands are helpful to verify that the uninstallation was
successful:
**For machine scope installations:**
```pwsh
# Inspect the uninstallation log for a success message
Select-String -Path "podman-setup-uninstall_000_Setup.log" -Pattern "Removal success or error status: 0"
Select-String -Path "podman-msi-uninstall.log" -Pattern "Removal success or error status: 0"
# Check that the uninstaller removed Podman resources
$foldersToCheck = @(
"$ENV:PROGRAMFILES\RedHat\Podman\podman.exe"
"HKLM:\SOFTWARE\Red Hat\Podman"
"$ENV:PROGRAMFILES\Podman\podman.exe"
"HKLM:\SOFTWARE\Podman"
"$ENV:PROGRAMDATA\containers\"
"$env:USERPROFILE.config\containers\"
"$env:USERPROFILE.local\share\containers\"
"$ENV:LOCALAPPDATA\containers\"
"$env:USERPROFILE\.config\containers\"
"$env:USERPROFILE\.local\share\containers\"
"$ENV:APPDATA\containers\"
"$ENV:PROGRAMDATA\containers\containers.conf.d\99-podman-machine-provider.conf"
)
$foldersToCheck | ForEach-Object {Test-Path -Path $PSItem}
```
**For user scope installations:**
```pwsh
# Inspect the uninstallation log for a success message
Select-String -Path "podman-msi-uninstall.log" -Pattern "Removal success or error status: 0"
# Check that the uninstaller removed Podman resources
$foldersToCheck = @(
"$ENV:PROGRAMFILES\Podman\podman.exe"
"HKCU:\SOFTWARE\Podman"
"$ENV:APPDATA\containers\"
"$env:USERPROFILE\.config\containers\"
"$env:USERPROFILE\.local\share\containers\"
"$ENV:LOCALAPPDATA\containers\"
"$ENV:APPDATA\containers\containers.conf.d\99-podman-machine-provider.conf"
)
$foldersToCheck | ForEach-Object {Test-Path -Path $PSItem}
```
#### Retrieve Podman installed products
MSI uninstallations can leave the package tracked in the Windows registry. This
can cause issues when trying to reinstall Podman. The following command can be
used to retrieve the package information:
```pwsh
$Installer = New-Object -ComObject WindowsInstaller.Installer
$InstallerProducts = $Installer.ProductsEx("", "", 7)
$InstalledProducts = ForEach($Product in $InstallerProducts){
try {
$ProductCode = $Product.ProductCode()
$LocalPackage = try { $Product.InstallProperty("LocalPackage") } catch { "Unknown" }
$VersionString = try { $Product.InstallProperty("VersionString") } catch { "Unknown" }
$ProductName = $Product.InstallProperty("ProductName")
[PSCustomObject]@{
ProductCode = $ProductCode
LocalPackage = $LocalPackage
VersionString = $VersionString
ProductName = $ProductName
}
}
catch {
Write-Warning "Failed to process product: $($_.Exception.Message)"
# Skip this product and continue
continue
}
}
$InstalledProducts | Where-Object {$_.ProductName -match "podman"}
```
This command returns a list of installed Podman products:
```log
ProductCode LocalPackage VersionString ProductName
----------- ------------ ------------- -----------
{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} Unknown Unknown Podman
```
The product code can be used to uninstall the Podman package:
```pwsh
msiexec /x "{<product-code>}"
```
## Validate changes before submitting a PR
The script `winmake.ps1` has a couple of targets to check the source code
@@ -499,7 +585,6 @@ tools:
pip install pre-commit
```
### winmake validatepr
Target `validatepr` performs a more exhaustive validation but takes

View File

@@ -3,41 +3,71 @@
. $PSScriptRoot\win-lib.ps1
. $PSScriptRoot\..\win-installer\utils.ps1
if ($Env:CI -eq "true") {
if ($Env:CIRRUS_CI -eq "true") {
$WIN_INST_FOLDER = "$ENV:CIRRUS_WORKING_DIR\repo\contrib\win-installer"
$RELEASE_DIR = "$ENV:CIRRUS_WORKING_DIR\repo"
} else {
$WIN_INST_FOLDER = "$PSScriptRoot\..\win-installer"
$ENV:WIN_INST_VER = "9.9.9"
$RELEASE_DIR = "$PSScriptRoot\..\..\contrib\win-installer\current"
$RELEASE_DIR = Resolve-Path -Path "$PSScriptRoot\..\..\contrib\win-installer\current"
if ($null -eq $ENV:CONTAINERS_MACHINE_PROVIDER) { $ENV:CONTAINERS_MACHINE_PROVIDER = 'wsl' }
}
$ENV:LATEST_GH_RELEASE_ID = "199677288" # v5.4.0
Push-Location $WIN_INST_FOLDER
$ENV:PODMAN_ARCH = Get-Current-Architecture # on Cirrus CI this should always be amd64
# Build and test the windows installer
# To get the a GitHub release ID run the following command:
# curl -s -H "Accept: application/vnd.github+json" \
# https://api.github.com/repos/containers/podman/releases/tags/v5.6.2 | jq '.id'
$ENV:LATEST_GH_RELEASE_ID = "251232431" # v5.6.2
$NEXT_WIN_INST_VER="9.9.10"
# Download the previous installer to test a major update
if (!$env:PREV_SETUP_EXE_PATH) {
$env:PREV_SETUP_EXE_PATH = Get-Podman-Setup-From-GitHub $ENV:LATEST_GH_RELEASE_ID
}
#########################################################
# Build and test the new windows installer msi package
#########################################################
$installer_folder = Resolve-Path -Path "$WIN_INST_FOLDER"
# Note: consumes podman-remote-release-windows_amd64.zip from repo.tar.zst
Run-Command "${installer_folder}\build.ps1 -Version `"$Env:WIN_INST_VER`" -Architecture `"$ENV:PODMAN_ARCH`" -LocalReleaseDirPath `"$RELEASE_DIR`""
# Build a v9.9.10 installer to test an update from current to next version
Run-Command "${installer_folder}\build.ps1 -Version `"$NEXT_WIN_INST_VER`" -Architecture `"$ENV:PODMAN_ARCH`" -LocalReleaseDirPath `"$RELEASE_DIR`""
# Run the installer silently and WSL/HyperV install options disabled (prevent reboots)
$command = "${installer_folder}\test.ps1 "
$command += "-scenario all "
$command += "-provider $ENV:CONTAINERS_MACHINE_PROVIDER "
$command += "-msiPath `"${installer_folder}\podman-$ENV:WIN_INST_VER.msi`" "
$command += "-nextMsiPath `"${installer_folder}\podman-$NEXT_WIN_INST_VER.msi`" "
$command += "-previousSetupExePath `"$env:PREV_SETUP_EXE_PATH`""
Run-Command "${command}"
#########################################################
# Build and test the legacy windows installer setup bundle
#########################################################
$installer_folder = Resolve-Path -Path "$WIN_INST_FOLDER-legacy"
Push-Location "${installer_folder}"
# Note: consumes podman-remote-release-windows_amd64.zip from repo.tar.zst
Run-Command ".\build.ps1 $Env:WIN_INST_VER dev `"$RELEASE_DIR`""
# Build a v9.9.10 installer to test an update from current to next version
$NEXT_WIN_INST_VER="9.9.10"
Run-Command ".\build.ps1 `"$NEXT_WIN_INST_VER`" dev `"$RELEASE_DIR`""
Pop-Location
# Run the installer silently and WSL/HyperV install options disabled (prevent reboots)
$command = "$WIN_INST_FOLDER\test-installer.ps1 "
$command = "${installer_folder}\test-installer.ps1 "
$command += "-scenario all "
$command += "-provider $ENV:CONTAINERS_MACHINE_PROVIDER "
$command += "-setupExePath `"$WIN_INST_FOLDER\podman-$ENV:WIN_INST_VER-dev-setup.exe`""
$command += "-previousSetupExePath `"$env:PREV_SETUP_EXE_PATH`""
$command += "-nextSetupExePath `"$WIN_INST_FOLDER\podman-$NEXT_WIN_INST_VER-dev-setup.exe`""
$command += "-setupExePath `"${installer_folder}\podman-$ENV:WIN_INST_VER-dev-setup.exe`" "
$command += "-previousSetupExePath `"$env:PREV_SETUP_EXE_PATH`" "
$command += "-nextSetupExePath `"${installer_folder}\podman-$NEXT_WIN_INST_VER-dev-setup.exe`" "
Run-Command "${command}"

13
contrib/win-installer-legacy/.gitignore vendored Normal file
View File

@@ -0,0 +1,13 @@
artifacts/
current/
docs/
en-US/
fetch/
podman-*setup.exe
engine.exe
obj/
shasums
*.wixobj
*.wixpdb
*.log
*.msi

View File

@@ -49,15 +49,28 @@ contrib\win-installer\podman-9.9.9-dev-setup.exe /x /log contrib\win-installer\p
## retrieve installed podman msi package information
```pwsh
$Installer = New-Object -ComObject WindowsInstaller.Installer;
$InstallerProducts = $Installer.ProductsEx("", "", 7);
$Installer = New-Object -ComObject WindowsInstaller.Installer
$InstallerProducts = $Installer.ProductsEx("", "", 7)
$InstalledProducts = ForEach($Product in $InstallerProducts){
[PSCustomObject]@{ProductCode = $Product.ProductCode();
LocalPackage = $Product.InstallProperty("LocalPackage");
VersionString = $Product.InstallProperty("VersionString");
ProductName = $Product.InstallProperty("ProductName")
}
};
try {
$ProductCode = $Product.ProductCode()
$LocalPackage = try { $Product.InstallProperty("LocalPackage") } catch { "Unknown" }
$VersionString = try { $Product.InstallProperty("VersionString") } catch { "Unknown" }
$ProductName = $Product.InstallProperty("ProductName")
[PSCustomObject]@{
ProductCode = $ProductCode
LocalPackage = $LocalPackage
VersionString = $VersionString
ProductName = $ProductName
}
}
catch {
Write-Warning "Failed to process product: $($_.Exception.Message)"
# Skip this product and continue
continue
}
}
$InstalledProducts | Where-Object {$_.ProductName -match "podman"}
```

View File

@@ -0,0 +1,156 @@
function ExitOnError() {
if ($LASTEXITCODE -ne 0) {
Exit 1
}
}
function SignItem() {
param(
[Parameter(Mandatory)]
[string[]]$fileNames
)
foreach ($val in $ENV:APP_ID, $ENV:TENANT_ID, $ENV:CLIENT_SECRET, $ENV:CERT_NAME) {
if (!$val) {
Write-Host "Skipping signing (no config)"
Return
}
}
CheckCommand AzureSignTool.exe "AzureSignTool"
AzureSignTool.exe sign -du "https://github.com/containers/podman" `
-kvu "https://$ENV:VAULT_ID.vault.azure.net" `
-kvi $ENV:APP_ID `
-kvt $ENV:TENANT_ID `
-kvs $ENV:CLIENT_SECRET `
-kvc $ENV:CERT_NAME `
-tr http://timestamp.digicert.com $fileNames
ExitOnError
}
function CheckCommand() {
param(
[Parameter(Mandatory)]
[string] $cmd,
[Parameter(Mandatory)]
[string] $description
)
if (! (Get-Command $cmd -errorAction SilentlyContinue)) {
Write-Host "Required dep `"$description`" is not installed"
Exit 1
}
}
function CheckRequirements() {
CheckCommand "wix" "WiX Toolset"
CheckCommand "go" "Golang"
}
if ($args.Count -lt 1 -or $args[0].Length -lt 1) {
Write-Host "Usage: " $MyInvocation.MyCommand.Name "<version> [dev|prod] [release_dir]"
Write-Host
Write-Host 'Uses Env Vars: '
Write-Host ' $ENV:FETCH_BASE_URL - GitHub Repo Address to locate release on'
Write-Host ' $ENV:V531_SETUP_EXE_PATH - Path to v5.3.1 setup.exe used to build the patch'
Write-Host ' $ENV:PODMAN_ARCH - Installer target platform (x64 or arm64)'
Write-Host 'Env Settings for signing (optional)'
Write-Host ' $ENV:VAULT_ID'
Write-Host ' $ENV:APP_ID'
Write-Host ' $ENV:TENANT_ID'
Write-Host ' $ENV:CLIENT_SECRET'
Write-Host ' $ENV:CERT_NAME'
Write-Host
Write-Host "Example: Download and build from the official Github release (dev output): "
Write-Host " .\build.ps1 4.2.0"
Write-Host
Write-Host "Example: Build a dev build from a pre-download release "
Write-Host " .\build.ps1 4.2.0 dev fetchdir"
Write-Host
Exit 1
}
# Pre-set to standard locations in-case build env does not refresh paths
$Env:Path="$Env:Path;C:\Users\micro\mingw64\bin;C:\ProgramData\chocolatey\lib\mingw\tools\install\mingw64\bin;;C:\Program Files\Go\bin;C:\Program Files\dotnet"
CheckRequirements
$version = $args[0]
if ($version[0] -eq "v") {
$version = $version.Substring(1)
}
$suffix = "-dev"
if ($args.Count -gt 1 -and $args[1] -eq "prod") {
$suffix = ""
}
$releaseDir = ""
if ($args.Count -gt 2) {
$releaseDir = $args[2]
}
Push-Location $PSScriptRoot
.\process-release.ps1 $version $releaseDir
if ($LASTEXITCODE -eq 2) {
Write-Host "Skip signaled, relaying skip"
Exit 2
}
if ($ENV:INSTVER -eq "") {
Write-Host "process-release did not define an install version!"
Exit 1
}
$installerPlatform = ""
if ($null -eq $ENV:PODMAN_ARCH -or "" -eq $ENV:PODMAN_ARCH -or "amd64" -eq $ENV:PODMAN_ARCH) {
$installerPlatform = "x64"
} elseif ($ENV:PODMAN_ARCH -eq "arm64") {
$installerPlatform = "arm64"
} else {
Write-Host "Unknown architecture $ENV:PODMAN_ARCH. Valid options are amd64 or arm64."
Exit 1
}
SignItem @("artifacts/win-sshproxy.exe",
"artifacts/podman.exe")
$gvExists = Test-Path "artifacts/gvproxy.exe"
if ($gvExists) {
SignItem @("artifacts/gvproxy.exe")
Remove-Item Env:\UseGVProxy -ErrorAction SilentlyContinue
} else {
$env:UseGVProxy = "Skip"
}
# Retaining for possible future additions
# $pExists = Test-Path "artifacts/policy.json"
# if ($pExists) {
# Remove-Item Env:\IncludePolicyJSON -ErrorAction SilentlyContinue
# } else {
# $env:IncludePolicyJSON = "Skip"
# }
if (Test-Path ./obj) {
Remove-Item ./obj -Recurse -Force -Confirm:$false
}
dotnet build podman.wixproj /property:DefineConstants="VERSION=$ENV:INSTVER" /property:InstallerPlatform="$installerPlatform" -o .; ExitOnError
SignItem @("en-US\podman.msi")
dotnet build podman-setup.wixproj /property:DefineConstants="VERSION=$ENV:INSTVER" /property:InstallerPlatform="$installerPlatform" -o .; ExitOnError
wix burn detach podman-setup.exe -engine engine.exe; ExitOnError
SignItem @("engine.exe")
$file = "podman-$version$suffix-setup.exe"
wix burn reattach -engine engine.exe podman-setup.exe -o $file; ExitOnError
SignItem @("$file")
if (Test-Path -Path shasums) {
$hash = (Get-FileHash -Algorithm SHA256 $file).Hash.ToLower()
Write-Output "$hash $file" | Out-File -Append -FilePath shasums
}
Write-Host "Complete"
Get-ChildItem "podman-$version$suffix-setup.exe"
Pop-Location

View File

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -35,7 +35,7 @@ param (
[switch]$skipConfigFileCreation=$false
)
. $PSScriptRoot\utils.ps1
. $PSScriptRoot\..\win-installer\utils.ps1
$MachineConfPath = "$env:ProgramData\containers\containers.conf.d\99-podman-machine-provider.conf"
$PodmanFolderPath = "$env:ProgramFiles\RedHat\Podman"

13
contrib/win-installer/.gitignore vendored Normal file
View File

@@ -0,0 +1,13 @@
artifacts/
current/
docs/
en-US/
fetch/
podman-*setup.exe
engine.exe
obj/
shasums
*.wixobj
*.wixpdb
*.log
*.msi

View File

@@ -1,154 +1,226 @@
function ExitOnError() {
if ($LASTEXITCODE -ne 0) {
Exit 1
}
#!/usr/bin/env pwsh
<#
.SYNOPSIS
Build Podman Windows MSI installer
.DESCRIPTION
This script builds a Podman MSI installer for Windows using WiX Toolset.
The release artifacts (podman.exe, gvproxy.exe, win-sshproxy.exe and
docs) are either downloaded from GitHub or copied from a local directory,
extracted, signed (if signing credentials are available), and packaged
into an MSI installer.
.PARAMETER Version
Podman version to build (e.g., "5.6.2" or "v5.6.2"). This will be the
version of the MSI installer to be built.
.PARAMETER Architecture
Target architecture for the installer. Valid values: 'amd64', 'arm64'.
Default: 'amd64'
.PARAMETER LocalReleaseDirPath
Optional path to a local directory containing the release zip file
(podman-remote-release-windows_<arch>.zip). If not specified, the
release will be downloaded from GitHub.
.PARAMETER RemoteReleaseRepoUrl
URL of the Podman release repository to download from. Default is the
official Podman GitHub repository. This parameter is primarily used by
the Podman release scripts.
.EXAMPLE
.\build.ps1 -Version 5.6.2
Download and build amd64 MSI from the official GitHub release
.EXAMPLE
.\build.ps1 -Version 5.6.2 -Architecture arm64
Download and build arm64 MSI from the official GitHub release
.EXAMPLE
.\build.ps1 -Version 5.6.2 -LocalReleaseDirPath .\current
Build an MSI from a pre-downloaded release in the current directory
.EXAMPLE
.\build.ps1 -Version 5.6.2 -Architecture arm64 `
-LocalReleaseDirPath .\current
Build an arm64 MSI from a local release directory
.NOTES
Requirements:
- .NET SDK (https://dotnet.microsoft.com/download)
- WiX Toolset (install: dotnet tool install --global wix)
Environment Variables for signing (optional):
$ENV:VAULT_ID $ENV:APP_ID $ENV:TENANT_ID
$ENV:CLIENT_SECRET $ENV:CERT_NAME
#>
param(
[Parameter(
Mandatory = $true,
ParameterSetName = 'LocalReleaseDirPath',
Position = 0,
HelpMessage = 'Podman version to build (MSI installer version)'
)]
[ValidateNotNullOrEmpty()]
[ValidatePattern('^v?([0-9]+\.[0-9]+\.[0-9]+)(-.*)?$')]
[string]$Version,
[Parameter(
Mandatory = $false,
Position = 1,
HelpMessage = 'Target Architecture'
)]
[ValidateSet('amd64', 'arm64')]
[string]$Architecture = 'amd64',
[Parameter(
Mandatory = $false,
Position = 2,
HelpMessage = 'Path to pre-downloaded release zip file'
)]
[ValidateScript({ Test-Path $_ -PathType Container })]
[string]$LocalReleaseDirPath = '',
[Parameter(
Mandatory = $false,
Position = 3,
HelpMessage = 'URL of the Podman release repository'
)]
[string]$RemoteReleaseRepoUrl = 'https://github.com/containers/podman'
)
. $PSScriptRoot\utils.ps1
# Strip leading 'v' from version if present
$Version = $Version.TrimStart('v')
################################################################################
# REQUIREMENTS CHECK
################################################################################
Write-Host 'Checking requirements (dotnet and wix)'
# Check if .NET SDK is installed
if (! (Get-Command 'dotnet' -errorAction SilentlyContinue)) {
Write-Error "Required dep `".NET SDK`" is not installed. " `
+ 'Please install it from https://dotnet.microsoft.com/download'
Exit 1
}
function SignItem() {
param(
[Parameter(Mandatory)]
[string[]]$fileNames
)
# Check if WiX Toolset is installed
Invoke-Expression 'dotnet tool list --global wix' `
-ErrorAction SilentlyContinue | Out-Null
if ($LASTEXITCODE -ne 0) {
Write-Error "Required dep `"Wix Toolset`" is not installed. " `
+ 'Please install it with the command ' `
+ "`"dotnet tool install --global wix`""
Exit 1
}
foreach ($val in $ENV:APP_ID, $ENV:TENANT_ID, $ENV:CLIENT_SECRET, $ENV:CERT_NAME) {
if (!$val) {
Write-Host "Skipping signing (no config)"
Return
}
}
################################################################################
# COPY OR DOWNLOAD RELEASE ARTIFACTS AND SIGN THEM
################################################################################
Write-Host 'Deleting old directories if they exist (''docs'', ''artifacts'' ' `
'and ''fetch'')'
foreach ($dir in 'docs', 'artifacts', 'fetch') {
Remove-Item -Force -Recurse -Path $PSScriptRoot\$dir `
-ErrorAction SilentlyContinue | Out-Null
}
CheckCommand AzureSignTool.exe "AzureSignTool"
Write-Host 'Creating empty ''fetch'' and ''artifacts'' directories'
foreach ($dir in 'fetch', 'artifacts') {
New-Item $PSScriptRoot\$dir -ItemType Directory | Out-Null
}
AzureSignTool.exe sign -du "https://github.com/containers/podman" `
-kvu "https://$ENV:VAULT_ID.vault.azure.net" `
-kvi $ENV:APP_ID `
-kvt $ENV:TENANT_ID `
-kvs $ENV:CLIENT_SECRET `
-kvc $ENV:CERT_NAME `
-tr http://timestamp.digicert.com $fileNames
$ProgressPreference = 'SilentlyContinue';
if (!$LocalReleaseDirPath) {
$releaseZipUrl = "$RemoteReleaseRepoUrl/releases/download/" `
+ "v$Version/podman-remote-release-windows_$Architecture.zip"
Write-Host "Downloading $releaseZipUrl"
DownloadReleaseFile -url $releaseZipUrl `
-outputFile "$PSScriptRoot\fetch\release.zip" `
-failOnError
DownloadReleaseFile `
-url "$RemoteReleaseRepoUrl/releases/download/v$Version/shasums" `
-outputFile "$PSScriptRoot\shasums"
}
else {
$sourceZip = "$LocalReleaseDirPath\" `
+ "podman-remote-release-windows_$Architecture.zip"
Write-Host "Copying $sourceZip to $PSScriptRoot\fetch\release.zip"
Copy-Item -Path $sourceZip `
-Destination "$PSScriptRoot\fetch\release.zip" `
-ErrorAction Stop
}
Write-Host "Expanding the podman release zip file to $PSScriptRoot\fetch"
Expand-Archive -Path $PSScriptRoot\fetch\release.zip `
-DestinationPath $PSScriptRoot\fetch `
-ErrorAction Stop
ExitOnError
Write-Host -NoNewline 'Copying artifacts: '
Foreach ($fileName in 'podman.exe', 'win-sshproxy.exe', 'gvproxy.exe') {
Write-Host -NoNewline "$fileName, "
Get-ChildItem -Path "$PSScriptRoot\fetch\" `
-Filter "$fileName" `
-Recurse | `
Copy-Item -Container:$false `
-Destination "$PSScriptRoot\artifacts\" `
-ErrorAction Stop
ExitOnError
}
function CheckCommand() {
param(
[Parameter(Mandatory)]
[string] $cmd,
[Parameter(Mandatory)]
[string] $description
)
Write-Host 'docs'
Get-ChildItem -Path $PSScriptRoot\fetch\ -Filter 'docs' -Recurse | `
Copy-Item -Recurse `
-Container:$false `
-Destination "$PSScriptRoot\docs" `
-ErrorAction Stop
ExitOnError
if (! (Get-Command $cmd -errorAction SilentlyContinue)) {
Write-Host "Required dep `"$description`" is not installed"
Exit 1
}
Write-Host 'Deleting the ''fetch'' folder'
Remove-Item -Force -Recurse -Path $PSScriptRoot\fetch `
-ErrorAction SilentlyContinue | Out-Null
SignItem @("$PSScriptRoot\artifacts\win-sshproxy.exe",
"$PSScriptRoot\artifacts\podman.exe",
"$PSScriptRoot\artifacts\gvproxy.exe")
ExitOnError
################################################################################
# BUILD THE MSI
################################################################################
dotnet clean $PSScriptRoot\wix\podman.wixproj
Remove-Item $PSScriptRoot\wix\obj -Recurse -Force -Confirm:$false `
-ErrorAction 'Ignore'
$archMap = @{
'amd64' = 'x64'
'arm64' = 'arm64'
}
$installerPlatform = $archMap[$Architecture]
Write-Host 'Building the MSI...'
dotnet build $PSScriptRoot\wix\podman.wixproj `
/property:DefineConstants="VERSION=$Version" `
/property:InstallerPlatform="$installerPlatform" `
/property:OutputName="podman-$Version" `
-o $PSScriptRoot
ExitOnError
$msiName = "podman-$Version.msi"
SignItem @("$PSScriptRoot\$msiName")
if (Test-Path -Path $PSScriptRoot\shasums) {
$hash = (Get-FileHash -Algorithm SHA256 `
$PSScriptRoot\$msiName).Hash.ToLower()
Write-Output "$hash $msiName" | `
Out-File -Append -FilePath $PSScriptRoot\shasums
}
function CheckRequirements() {
CheckCommand "wix" "WiX Toolset"
CheckCommand "go" "Golang"
}
if ($args.Count -lt 1 -or $args[0].Length -lt 1) {
Write-Host "Usage: " $MyInvocation.MyCommand.Name "<version> [dev|prod] [release_dir]"
Write-Host
Write-Host 'Uses Env Vars: '
Write-Host ' $ENV:FETCH_BASE_URL - GitHub Repo Address to locate release on'
Write-Host ' $ENV:V531_SETUP_EXE_PATH - Path to v5.3.1 setup.exe used to build the patch'
Write-Host ' $ENV:PODMAN_ARCH - Installer target platform (x64 or arm64)'
Write-Host 'Env Settings for signing (optional)'
Write-Host ' $ENV:VAULT_ID'
Write-Host ' $ENV:APP_ID'
Write-Host ' $ENV:TENANT_ID'
Write-Host ' $ENV:CLIENT_SECRET'
Write-Host ' $ENV:CERT_NAME'
Write-Host
Write-Host "Example: Download and build from the official Github release (dev output): "
Write-Host " .\build.ps1 4.2.0"
Write-Host
Write-Host "Example: Build a dev build from a pre-download release "
Write-Host " .\build.ps1 4.2.0 dev fetchdir"
Write-Host
Exit 1
}
# Pre-set to standard locations in-case build env does not refresh paths
$Env:Path="$Env:Path;C:\Users\micro\mingw64\bin;C:\ProgramData\chocolatey\lib\mingw\tools\install\mingw64\bin;;C:\Program Files\Go\bin;C:\Program Files\dotnet"
CheckRequirements
$version = $args[0]
if ($version[0] -eq "v") {
$version = $version.Substring(1)
}
$suffix = "-dev"
if ($args.Count -gt 1 -and $args[1] -eq "prod") {
$suffix = ""
}
$releaseDir = ""
if ($args.Count -gt 2) {
$releaseDir = $args[2]
}
.\process-release.ps1 $version $releaseDir
if ($LASTEXITCODE -eq 2) {
Write-Host "Skip signaled, relaying skip"
Exit 2
}
if ($ENV:INSTVER -eq "") {
Write-Host "process-release did not define an install version!"
Exit 1
}
$installerPlatform = ""
if ($null -eq $ENV:PODMAN_ARCH -or "" -eq $ENV:PODMAN_ARCH -or "amd64" -eq $ENV:PODMAN_ARCH) {
$installerPlatform = "x64"
} elseif ($ENV:PODMAN_ARCH -eq "arm64") {
$installerPlatform = "arm64"
} else {
Write-Host "Unknown architecture $ENV:PODMAN_ARCH. Valid options are amd64 or arm64."
Exit 1
}
SignItem @("artifacts/win-sshproxy.exe",
"artifacts/podman.exe")
$gvExists = Test-Path "artifacts/gvproxy.exe"
if ($gvExists) {
SignItem @("artifacts/gvproxy.exe")
Remove-Item Env:\UseGVProxy -ErrorAction SilentlyContinue
} else {
$env:UseGVProxy = "Skip"
}
# Retaining for possible future additions
# $pExists = Test-Path "artifacts/policy.json"
# if ($pExists) {
# Remove-Item Env:\IncludePolicyJSON -ErrorAction SilentlyContinue
# } else {
# $env:IncludePolicyJSON = "Skip"
# }
if (Test-Path ./obj) {
Remove-Item ./obj -Recurse -Force -Confirm:$false
}
dotnet build podman.wixproj /property:DefineConstants="VERSION=$ENV:INSTVER" /property:InstallerPlatform="$installerPlatform" -o .; ExitOnError
SignItem @("en-US\podman.msi")
dotnet build podman-setup.wixproj /property:DefineConstants="VERSION=$ENV:INSTVER" /property:InstallerPlatform="$installerPlatform" -o .; ExitOnError
wix burn detach podman-setup.exe -engine engine.exe; ExitOnError
SignItem @("engine.exe")
$file = "podman-$version$suffix-setup.exe"
wix burn reattach -engine engine.exe podman-setup.exe -o $file; ExitOnError
SignItem @("$file")
if (Test-Path -Path shasums) {
$hash = (Get-FileHash -Algorithm SHA256 $file).Hash.ToLower()
Write-Output "$hash $file" | Out-File -Append -FilePath shasums
}
Write-Host "Complete"
Get-ChildItem "podman-$version$suffix-setup.exe"
Write-Host 'Complete'
Get-ChildItem "$PSScriptRoot\$msiName"

View File

@@ -0,0 +1,783 @@
#!/usr/bin/env pwsh
<#
.SYNOPSIS
Automated test script for the Podman Windows MSI installer.
.DESCRIPTION
This script provides automated end-to-end tests for the Podman Windows MSI
installer. It supports testing installation, update, and configuration
scenarios for both user and machine scopes, as well as for different
virtualization providers (WSL and Hyper-V).
The script validates the presence and correctness of installed files,
registry keys, and configuration files.
.PARAMETER scenario
The test scenario to execute. Supported values:
- test-objects-exist
- test-objects-exist-not
- installation-green-field
- installation-skip-config-creation-flag
- installation-with-pre-existing-podman-exe
- update-from-current-to-next
- update-from-current-to-next-with-modified-config
- update-from-current-to-next-with-removed-config
- update-from-legacy-to-current
- all
.PARAMETER msiPath
Path to the current Podman MSI installer to test.
.PARAMETER nextMsiPath
Path to the next version Podman MSI installer (for update scenarios).
.PARAMETER previousSetupExePath
Path to the legacy Podman setup EXE installer (for legacy update scenarios).
.PARAMETER provider
The virtualization provider to test with. Supported values: 'wsl', 'hyperv'. Default: 'wsl'.
.PARAMETER skipConfigFileCreation
Switch to skip creation of the configuration file during installation.
.PARAMETER scope
Installation scope. Supported values: 'user', 'machine'. Default: 'user'.
.EXAMPLE
.\test.ps1 -scenario all -msiPath "C:\path\to\podman.msi" -nextMsiPath "C:\path\to\next\podman.msi" -scope user
.NOTES
- When using '-scope machine', this script must be run as Administrator.
- This script is intended for use by Podman developers and CI pipelines to validate installer behavior.
- See build_windows.md for more information and usage examples.
#>
param (
[Parameter(Mandatory)]
[ValidateSet('test-objects-exist', 'test-objects-exist-not', 'installation-green-field', 'installation-skip-config-creation-flag', 'installation-with-pre-existing-podman-exe',
#"update-from-prev-to-current", "update-from-prev-to-current-with-modified-config", "update-from-prev-to-current-with-removed-config",
'update-from-current-to-next', 'update-from-current-to-next-with-modified-config', 'update-from-current-to-next-with-removed-config',
'update-from-legacy-to-current',
'all')]
[string]$scenario,
[ValidateScript({ Test-Path $_ -PathType Leaf })]
[string]$msiPath,
# [ValidateScript({Test-Path $_ -PathType Leaf})]
# [string]$previousMsiPath,
[ValidateScript({ Test-Path $_ -PathType Leaf })]
[string]$nextMsiPath,
[ValidateScript({ Test-Path $_ -PathType Leaf })]
[string]$previousSetupExePath,
[ValidateSet('wsl', 'hyperv')]
[string]$provider = 'wsl',
[switch]$skipConfigFileCreation = $false,
[ValidateSet('machine', 'user')]
[string]$scope = 'user'
)
. $PSScriptRoot\utils.ps1
# Check if running as administrator when testing machine scope installation
if ($scope -eq 'machine') {
$currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
$isAdmin = $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
if (-not $isAdmin) {
throw 'The -scope machine parameter requires the script to be run as Administrator. Please run PowerShell as Administrator and try again.'
}
}
# Get the architecture of the current OS
$osArch = [System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture
$arch = switch ($osArch) {
'X64' { 'amd64' }
'Arm64' { 'arm64' }
default { throw "Unsupported architecture: $osArch" }
}
# 99-podman-machine-provider.conf file path
$MachineConfPathPerMachine = "$env:ProgramData\containers\containers.conf.d\99-podman-machine-provider.conf"
$MachineConfPathPerMachineLegacy = $MachineConfPathPerMachine
$MachineConfPathPerUser = "$env:AppData\containers\containers.conf.d\99-podman-machine-provider.conf"
# Podman application folder path
$PodmanFolderPathPerMachine = "$env:ProgramFiles\Podman"
$PodmanFolderPathPerMachineLegacy = "$env:ProgramFiles\RedHat\Podman"
$PodmanFolderPathPerUser = "$env:LocalAppData\Programs\Podman"
# Podman.executable file path
$PodmanExePathPerMachine = "$PodmanFolderPathPerMachine\podman.exe"
$PodmanExePathPerMachineLegacy = "$PodmanFolderPathPerMachineLegacy\podman.exe"
$PodmanExePathPerUser = "$PodmanFolderPathPerUser\podman.exe"
$WindowsPathsToTestPerMachine = @($PodmanExePathPerMachine,
"$PodmanFolderPathPerMachine\win-sshproxy.exe",
'HKLM:\SOFTWARE\Podman')
$WindowsPathsToTestLegacy = @($PodmanExePathPerMachineLegacy,
"$PodmanFolderPathPerMachineLegacy\win-sshproxy.exe",
'HKLM:\SOFTWARE\Red Hat\Podman')
$WindowsPathsToTestPerUser = @($PodmanExePathPerUser,
"$PodmanFolderPathPerUser\win-sshproxy.exe",
'HKCU:\SOFTWARE\Podman')
function Install-Podman-Bundle {
param (
[ValidateScript({ Test-Path $_ -PathType Leaf })]
[string]$setupExePath = $script:previousSetupExePath
)
if ($script:skipConfigFileCreation) { $skipConfigFileCreationVar = '1' } else { $skipConfigFileCreationVar = '0' }
Write-Host "Running the installer ($setupExePath)..."
Write-Host "(provider=`"$script:provider`", SkipConfigFileCreation=`"$skipConfigFileCreationVar`")"
$ret = Start-Process -Wait `
-PassThru "$setupExePath" `
-ArgumentList "/install /quiet `
MachineProvider=${script:provider} `
SkipConfigFileCreation=${skipConfigFileCreationVar} `
/log $PSScriptRoot\podman-setup.log"
if ($ret.ExitCode -ne 0) {
Write-Host 'Install failed, dumping log'
Get-Content $PSScriptRoot\podman-setup.log
throw "Exit code is $($ret.ExitCode)"
}
Write-Host "Installation completed successfully!`n"
}
function Install-Podman-Package {
param (
[Parameter(Mandatory)]
[ValidateScript({ Test-Path $_ -PathType Leaf })]
[string]$msiPath,
[string]$msiProperties,
[switch]$shouldFail = $false
)
Write-Host "Running the installer ($msiPath)..."
if ($msiProperties) {
Write-Host "MSI Properties: $msiProperties"
}
else {
Write-Host 'MSI Properties: none'
}
$msiExecArgs = "/package $msiPath /quiet /l*v $PSScriptRoot\podman-msi.log $msiProperties"
Write-Host "msiexec $msiExecArgs"
$ret = Start-Process -Wait `
-PassThru 'msiexec' `
-ArgumentList $msiExecArgs
if ($ret.ExitCode -ne 0 -and -not $shouldFail) {
Write-Host 'Install failed, dumping log'
Get-Content $PSScriptRoot\podman-msi.log
throw "Exit code is $($ret.ExitCode)"
}
if ($ret.ExitCode -eq 0 -and $shouldFail) {
Write-Host 'Install completed successfully but a failure was expected, dumping log'
Get-Content $PSScriptRoot\podman-msi.log
throw "Exit code is $($ret.ExitCode) but a failure was expected"
}
if ($shouldFail) {
Write-Host "Installation failed as expected!`n"
}
else {
Write-Host "Installation completed successfully!`n"
}
}
function Install-Podman-Package-with-Explicit-Properties {
param (
[ValidateScript({ Test-Path $_ -PathType Leaf })]
[string]$msiPath = $script:msiPath,
[ValidateSet('machine', 'user')]
[string]$scope = $script:scope,
[switch]$skipConfigFileCreation = $script:skipConfigFileCreation
)
# MACHINE_PROVIDER
$MACHINE_PROVIDER_PROP = "MACHINE_PROVIDER=$script:provider"
# SKIP_CONFIG_FILE_CREATION
if ($skipConfigFileCreation) {
$SKIP_CONFIG_FILE_CREATION_PROP = 'SKIP_CONFIG_FILE_CREATION=1'
}
else {
$SKIP_CONFIG_FILE_CREATION_PROP = 'SKIP_CONFIG_FILE_CREATION=0'
}
# ALLUSERS or MSIINSTALLPERUSER
if ($scope -eq 'machine') {
$ALLUSERS_OR_MSIINSTALLPERUSER_PROP = 'ALLUSERS=1'
}
else {
$ALLUSERS_OR_MSIINSTALLPERUSER_PROP = 'MSIINSTALLPERUSER=1'
}
Install-Podman-Package -msiPath $msiPath -msiProperties "${MACHINE_PROVIDER_PROP} ${ALLUSERS_OR_MSIINSTALLPERUSER_PROP} ${SKIP_CONFIG_FILE_CREATION_PROP}"
}
function Update-Podman-Package {
param (
[ValidateSet('From-Previous', 'To-Next', 'From-Previous-Legacy', 'To-Next-Scope-Switch')]
[string]$mode = 'From-Previous',
[ValidateSet('none', 'switch-provider', 'delete-config-file')]
[string]$configurationUpdate = 'none'
)
# Step 1: Install the initial version
switch ($mode) {
# There is no "previous package" yet so this scenario cannot be tested.
# This block, and those in STEP 3 and 5, should be commented out after the
# release of dual scope MSI.
# 'From-Previous' {
# Install-Podman-Package-with-Explicit-Properties -msiPath $msiPreviousPath
# Test-Installation -scope $script:scope
# }
'To-Next' {
Install-Podman-Package-with-Explicit-Properties
Test-Installation
}
'From-Previous-Legacy' {
Install-Podman-Bundle
Test-Installation -scope 'machine-legacy'
}
'To-Next-Scope-Switch' {
if ($script:scope -eq 'machine') {
$newScope = 'user'
}
else {
$newScope = 'machine'
}
Install-Podman-Package-with-Explicit-Properties -scope $newScope
Test-Installation -scope $newScope
}
}
# Step 2: Make some changes to the configration file if requested
$newProvider = $script:provider
$configFileRemoved = $false
switch ($configurationUpdate) {
'switch-provider' {
$newProvider = Switch-Podman-Machine-Conf-Content -scope $script:scope
}
'delete-config-file' {
Remove-Podman-Machine-Conf -scope $script:scope
$configFileRemoved = $true
}
}
# Step 3: Install the next version
$msiProperties = ''
if ($script:scope -eq 'machine') {
$msiProperties = 'ALLUSERS=1'
}
switch ($mode) {
# 'From-Previous' {
# Install-Podman-Package -msiPath $script:msiPath
# Test-Installation -scope $script:scope -expectedConfiguredProvider $newProvider -configFileExistNot:$configFileRemoved
# }
'To-Next' {
Install-Podman-Package -msiPath $script:nextMsiPath -msiProperties $msiProperties
Test-Installation -scope $script:scope -expectedConfiguredProvider $newProvider -configFileExistNot:$configFileRemoved
}
'From-Previous-Legacy' {
Install-Podman-Package -shouldFail -msiPath $script:msiPath -msiProperties $msiProperties
}
'To-Next-Scope-Switch' {
Install-Podman-Package -shouldFail -msiPath $script:nextMsiPath -msiProperties $msiProperties
}
}
# Step 4: Check that the changes to the configuration file are persisted
switch ($configurationUpdate) {
'switch-provider' {
Test-Podman-Machine-Conf-Content -expected $newProvider -scope $script:scope
}
'delete-config-file' {
Test-Podman-Machine-Conf-Exist-Not -scope $script:scope -configFileRemoved:$configFileRemoved
}
}
# Step 5: Uninstall
switch ($mode) {
# 'From-Previous' {
# Uninstall-Podman-Package -msiPath $msiPreviousPath -scope $script:scope
# Test-Uninstallation -scope $script:scope
# }
'To-Next' {
Uninstall-Podman-Package -msiPath $script:nextMsiPath
Test-Uninstallation -scope $script:scope
}
'From-Previous-Legacy' {
Uninstall-Podman-Bundle -setupExePath $script:previousSetupExePath
Test-Uninstallation -scope 'machine-legacy'
}
'To-Next-Scope-Switch' {
if ($script:scope -eq 'machine') {
$newScope = 'user'
}
else {
$newScope = 'machine'
}
Uninstall-Podman-Package -msiPath $script:msiPath
Test-Uninstallation -scope $newScope
}
}
}
function Test-Podman-Objects-Exist {
param (
[ValidateSet('machine-legacy', 'machine', 'user')]
[string]$scope = $script:scope
)
Write-Host "Verifying that podman files, folders and registry entries exist...(scope=$scope)"
if ($scope -eq 'machine') {
$WindowsPathsToTest = $WindowsPathsToTestPerMachine
}
elseif ($scope -eq 'machine-legacy') {
$WindowsPathsToTest = $WindowsPathsToTestLegacy
}
else {
$WindowsPathsToTest = $WindowsPathsToTestPerUser
}
$WindowsPathsToTest | ForEach-Object {
if (! (Test-Path -Path $_) ) {
throw "Expected $_ but doesn't exist"
}
}
Write-Host "Verification was successful!`n"
}
function Test-Podman-Machine-Conf-Exist {
param (
[ValidateSet('machine-legacy', 'machine', 'user')]
[string]$scope = $script:scope
)
if ($scope -eq 'machine') {
$MachineConfPath = $MachineConfPathPerMachine
}
elseif ($scope -eq 'machine-legacy') {
$MachineConfPath = $MachineConfPathPerMachineLegacy
}
else {
$MachineConfPath = $MachineConfPathPerUser
}
Write-Host "Verifying that $MachineConfPath exist...(scope=$scope)"
if (! (Test-Path -Path $MachineConfPath) ) {
throw "Expected $MachineConfPath but doesn't exist"
}
Write-Host "Verification was successful!`n"
}
function Test-Podman-Machine-Conf-Content {
[CmdletBinding(PositionalBinding = $false)]
param (
[ValidateSet('wsl', 'hyperv')]
[string]$expected = $script:provider,
[ValidateSet('machine-legacy', 'machine', 'user')]
[string]$scope = $script:scope
)
Write-Host "Verifying that the machine provider configuration is correct...(scope=$scope)"
if ($scope -eq 'machine') {
$MachineConfPath = $MachineConfPathPerMachine
}
elseif ($scope -eq 'machine-legacy') {
$MachineConfPath = $MachineConfPathPerMachineLegacy
}
else {
$MachineConfPath = $MachineConfPathPerUser
}
$machineProvider = Get-Content $MachineConfPath | Select-Object -Skip 1 | ConvertFrom-StringData | ForEach-Object { $_.provider }
if ( $machineProvider -ne "`"$expected`"" ) {
throw "Expected `"$expected`" as default machine provider but got $machineProvider"
}
Write-Host "Verification was successful!`n"
}
function Uninstall-Podman-Bundle {
param (
# [Parameter(Mandatory)]
[ValidateScript({ Test-Path $_ -PathType Leaf })]
[string]$setupExePath
)
Write-Host "Running the uninstaller ($setupExePath)..."
$ret = Start-Process -Wait `
-PassThru "$setupExePath" `
-ArgumentList "/uninstall `
/quiet /log $PSScriptRoot\podman-setup-uninstall.log"
if ($ret.ExitCode -ne 0) {
Write-Host 'Uninstall failed, dumping log'
Get-Content $PSScriptRoot\podman-setup-uninstall.log
throw "Exit code is $($ret.ExitCode)"
}
Write-Host "The uninstallation completed successfully!`n"
}
function Uninstall-Podman-Package {
param (
[Parameter(Mandatory)]
[ValidateScript({ Test-Path $_ -PathType Leaf })]
[string]$msiPath
)
Write-Host "Running the uninstaller ($msiPath)..."
$ret = Start-Process -Wait `
-PassThru 'msiexec' `
-ArgumentList "/uninstall $msiPath /quiet /l*v $PSScriptRoot\podman-msi-uninstall.log"
if ($ret.ExitCode -ne 0) {
Write-Host 'Uninstall failed, dumping log'
Get-Content $PSScriptRoot\podman-msi-uninstall.log
throw "Exit code is $($ret.ExitCode)"
}
Write-Host "The uninstallation completed successfully!`n"
}
function Test-Podman-Objects-Exist-Not {
param (
[ValidateSet('machine-legacy', 'machine', 'user')]
[string]$scope = $script:scope
)
Write-Host "Verifying that podman files, folders and registry entries don't exist...(scope=$scope)"
if ($scope -eq 'machine') {
$WindowsPathsToTest = $WindowsPathsToTestPerMachine
}
elseif ($scope -eq 'machine-legacy') {
$WindowsPathsToTest = $WindowsPathsToTestLegacy
}
else {
$WindowsPathsToTest = $WindowsPathsToTestPerUser
}
$WindowsPathsToTest | ForEach-Object {
if ( Test-Path -Path $_ ) {
throw "Path $_ is present"
}
}
Write-Host "Verification was successful!`n"
}
function Test-Podman-Machine-Conf-Exist-Not {
param (
[ValidateSet('machine-legacy', 'machine', 'user')]
[string]$scope = $script:scope
)
if ($scope -eq 'machine') {
$MachineConfPath = $MachineConfPathPerMachine
}
elseif ($scope -eq 'machine-legacy') {
$MachineConfPath = $MachineConfPathPerMachineLegacy
}
else {
$MachineConfPath = $MachineConfPathPerUser
}
Write-Host "Verifying that $MachineConfPath doesn't exist...(scope=$scope)"
if ( Test-Path -Path $MachineConfPath ) {
throw "Path $MachineConfPath is present"
}
Write-Host "Verification was successful!`n"
}
function New-Fake-Podman-Exe {
param (
[ValidateSet('machine-legacy', 'machine', 'user')]
[string]$scope = $script:scope
)
if ($scope -eq 'machine') {
$PodmanFolderPath = $PodmanFolderPathPerMachine
$PodmanExePath = $PodmanExePathPerMachine
}
elseif ($scope -eq 'machine-legacy') {
$PodmanFolderPath = $PodmanFolderPathPerMachineLegacy
$PodmanExePath = $PodmanExePathPerMachineLegacy
}
else {
$PodmanFolderPath = $PodmanFolderPathPerUser
$PodmanExePath = $PodmanExePathPerUser
}
Write-Host "Creating a fake $PodmanExePath...(scope=$scope)"
New-Item -ItemType Directory -Path $PodmanFolderPath -Force -ErrorAction Stop | out-null
New-Item -ItemType File -Path $PodmanExePath -ErrorAction Stop | out-null
Write-Host "Creation successful!`n"
}
function Switch-Podman-Machine-Conf-Content {
param (
[ValidateSet('machine-legacy', 'machine', 'user')]
[string]$scope = $script:scope
)
$currentProvider = $script:provider
if ( $currentProvider -eq 'wsl' ) { $newProvider = 'hyperv' } else { $newProvider = 'wsl' }
if ($scope -eq 'machine') {
$MachineConfPath = $MachineConfPathPerMachine
}
elseif ($scope -eq 'machine-legacy') {
$MachineConfPath = $MachineConfPathPerMachineLegacy
}
else {
$MachineConfPath = $MachineConfPathPerUser
}
Write-Host "Editing $MachineConfPath content (was $currentProvider, will be $newProvider)..."
"[machine]`nprovider=`"$newProvider`"" | Out-File -FilePath $MachineConfPath -ErrorAction Stop
Write-Host "Edit successful!`n"
return $newProvider
}
function Remove-Podman-Machine-Conf {
param (
[ValidateSet('machine-legacy', 'machine', 'user')]
[string]$scope = $script:scope
)
if ($scope -eq 'machine') {
$MachineConfPath = $MachineConfPathPerMachine
}
elseif ($scope -eq 'machine-legacy') {
$MachineConfPath = $MachineConfPathPerMachineLegacy
}
else {
$MachineConfPath = $MachineConfPathPerUser
}
Write-Host "Deleting $MachineConfPath..."
Remove-Item -Path $MachineConfPath -ErrorAction Stop | out-null
Write-Host "Deletion successful!`n"
}
function Test-Installation {
[CmdletBinding(PositionalBinding = $false)]
param (
[ValidateSet('wsl', 'hyperv')]
[string]$expectedConfiguredProvider,
[ValidateSet('machine-legacy', 'machine', 'user')]
[string]$scope = $script:scope,
[switch]$configFileExistNot = $false
)
Test-Podman-Objects-Exist -scope $scope
if ($configFileExistNot) {
Test-Podman-Machine-Conf-Exist-Not -scope $scope
}
else {
Test-Podman-Machine-Conf-Exist -scope $scope
if ($expectedConfiguredProvider) {
Test-Podman-Machine-Conf-Content -expected $expectedConfiguredProvider -scope $scope
}
else {
Test-Podman-Machine-Conf-Content -scope $scope
}
}
}
function Test-Installation-No-Config {
param (
[ValidateSet('machine-legacy', 'machine', 'user')]
[string]$scope = $script:scope
)
Test-Podman-Objects-Exist -scope $scope
Test-Podman-Machine-Conf-Exist-Not -scope $scope
}
function Test-Uninstallation {
param (
[ValidateSet('machine-legacy', 'machine', 'user')]
[string]$scope = $script:scope
)
Test-Podman-Objects-Exist-Not -scope $scope
Test-Podman-Machine-Conf-Exist-Not -scope $scope
}
# SCENARIOS
function Start-Scenario-Installation-Green-Field {
Write-Host "`n==========================================="
Write-Host ' Running scenario: Installation-Green-Field'
Write-Host '==========================================='
Install-Podman-Package-with-Explicit-Properties -msiPath $script:msiPath -scope $script:scope
Test-Installation
Uninstall-Podman-Package -msiPath $script:msiPath
Test-Uninstallation
}
function Start-Scenario-Installation-Skip-Config-Creation-Flag {
Write-Host "`n========================================================="
Write-Host ' Running scenario: Installation-Skip-Config-Creation-Flag'
Write-Host '========================================================='
Install-Podman-Package-with-Explicit-Properties -msiPath $script:msiPath -scope $script:scope -skipConfigFileCreation:$true
Test-Installation-No-Config
Uninstall-Podman-Package -msiPath $script:msiPath
Test-Uninstallation
}
function Start-Scenario-Installation-With-Pre-Existing-Podman-Exe {
Write-Host "`n============================================================"
Write-Host ' Running scenario: Installation-With-Pre-Existing-Podman-Exe'
Write-Host '============================================================'
New-Fake-Podman-Exe
Install-Podman-Package-with-Explicit-Properties -msiPath $script:msiPath -scope $script:scope
Test-Installation-No-Config
Uninstall-Podman-Package -msiPath $script:msiPath
Test-Uninstallation
# remove the Podman folder created by `New-Fake-Podman-Exe` that
# otherwise would remain after the uninstallation
if ($script:scope -eq 'machine') {
Remove-Item -Path $PodmanFolderPathPerMachine -Recurse -Force
}
elseif ($script:scope -eq 'machine-legacy') {
Remove-Item -Path $PodmanFolderPathPerMachineLegacy -Recurse -Force
}
else {
Remove-Item -Path $PodmanFolderPathPerUser -Recurse -Force
}
}
# function Start-Scenario-Update-From-Prev-To-Current {
# Write-Host "`n======================================================"
# Write-Host " Running scenario: Update-From-Prev-To-Current"
# Write-Host "======================================================"
# Update-Podman-Package -mode "From-Previous" -configurationUpdate "none"
# }
# function Start-Scenario-Update-From-Prev-To-Current-With-Modified-Config {
# Write-Host "`n=============================================================="
# Write-Host " Running scenario: Update-From-Prev-To-Current-With-Modified-Config"
# Write-Host "=============================================================="
# Update-Podman-Package -mode "From-Previous" -configurationUpdate "switch-provider"
# }
# function Start-Scenario-Update-From-Prev-To-Current-With-Removed-Config {
# Write-Host "`n=============================================================="
# Write-Host " Running scenario: Update-From-Prev-To-Current-With-Removed-Config"
# Write-Host "=============================================================="
# Update-Podman-Package -mode "From-Previous" -configurationUpdate "delete-config-file"
# }
function Start-Scenario-Update-From-Current-To-Next {
Write-Host "`n======================================================"
Write-Host ' Running scenario: Update-From-Current-To-Next'
Write-Host '======================================================'
Update-Podman-Package -mode 'To-Next' -configurationUpdate 'none'
}
function Start-Scenario-Update-From-Current-To-Next-With-Modified-Config {
Write-Host "`n=============================================================="
Write-Host ' Running scenario: Update-From-Current-To-Next-With-Modified-Config'
Write-Host '=============================================================='
Update-Podman-Package -mode 'To-Next' -configurationUpdate 'switch-provider'
}
function Start-Scenario-Update-From-Current-To-Next-With-Removed-Config {
Write-Host "`n=============================================================="
Write-Host ' Running scenario: Update-From-Current-To-Next-With-Removed-Config'
Write-Host '=============================================================='
Update-Podman-Package -mode 'To-Next' -configurationUpdate 'delete-config-file'
}
function Start-Scenario-Update-From-Legacy-To-Current {
Write-Host "`n======================================================"
Write-Host ' Running scenario: Update-From-Legacy-To-Current'
Write-Host '======================================================'
Update-Podman-Package -mode 'From-Previous-Legacy' -configurationUpdate 'none'
}
switch ($script:scenario) {
'test-objects-exist' {
Test-Podman-Objects-Exist
}
'test-objects-exist-not' {
Test-Podman-Objects-Exist-Not
}
'installation-green-field' {
if (!$script:msiPath) {
throw "Current installer path is not defined. Use '-msiPath <msi-path>' to define it."
}
Start-Scenario-Installation-Green-Field
}
'installation-skip-config-creation-flag' {
if (!$script:msiPath) {
throw "Current installer path is not defined. Use '-msiPath <msi-path>' to define it."
}
Start-Scenario-Installation-Skip-Config-Creation-Flag
}
'installation-with-pre-existing-podman-exe' {
if (!$script:msiPath) {
throw "Current installer path is not defined. Use '-msiPath <msi-path>' to define it."
}
Start-Scenario-Installation-With-Pre-Existing-Podman-Exe
}
# 'update-from-prev-to-current' {
# if (!$script:msiPath) {
# throw "Current installer path is not defined. Use '-msiPath <msi-path>' to define it."
# }
# if (!$script:previousMsiPath) {
# $script:previousMsiPath = Get-Latest-Podman-MSI-From-GitHub -arch $script:arch
# }
# Start-Scenario-Update-From-Prev-To-Current
# }
# 'update-from-prev-to-current-with-modified-config' {
# if (!$script:msiPath) {
# throw "Current installer path is not defined. Use '-msiPath <msi-path>' to define it."
# }
# if (!$script:previousMsiPath) {
# $script:previousMsiPath = Get-Latest-Podman-MSI-From-GitHub -arch $script:arch
# }
# Start-Scenario-Update-From-Prev-To-Current-With-Modified-Config
# }
# 'update-from-prev-to-current-with-removed-config' {
# if (!$script:msiPath) {
# throw "Current installer path is not defined. Use '-msiPath <msi-path>' to define it."
# }
# if (!$script:previousMsiPath) {
# $script:previousMsiPath = Get-Latest-Podman-MSI-From-GitHub -arch $script:arch
# }
# Start-Scenario-Update-From-Prev-To-Current-With-Removed-Config
# }
'update-from-current-to-next' {
if (!$script:msiPath) {
throw "Current installer path is not defined. Use '-msiPath <msi-path>' to define it."
}
if (!$script:nextMsiPath) {
throw "Next version installer path is not defined. Use '-nextMsiPath <msi-path>' to define it."
}
Start-Scenario-Update-From-Current-To-Next
}
'update-from-current-to-next-with-modified-config' {
if (!$script:msiPath) {
throw "Current installer path is not defined. Use '-msiPath <msi-path>' to define it."
}
if (!$script:nextMsiPath) {
throw "Next version installer path is not defined. Use '-nextMsiPath <msi-path>' to define it."
}
Start-Scenario-Update-From-Current-To-Next-With-Modified-Config
}
'update-from-current-to-next-with-removed-config' {
if (!$script:msiPath) {
throw "Current installer path is not defined. Use '-msiPath <msi-path>' to define it."
}
if (!$script:nextMsiPath) {
throw "Next version installer path is not defined. Use '-nextMsiPath <msi-path>' to define it."
}
Start-Scenario-Update-From-Current-To-Next-With-Removed-Config
}
'update-from-legacy-to-current' {
if (!$script:msiPath) {
throw "Current installer path is not defined. Use '-msiPath <msi-path>' to define it."
}
if (!$script:previousSetupExePath) {
$script:previousSetupExePath = Get-Latest-Podman-Setup-From-GitHub -arch $script:arch
}
Start-Scenario-Update-From-Legacy-To-Current
}
'all' {
if (!$script:msiPath) {
throw "Current installer path is not defined. Use '-msiPath <msi-path>' to define it."
}
if (!$script:nextMsiPath) {
throw "Next version installer path is not defined. Use '-nextMsiPath <msi-path>' to define it."
}
# if (!$script:previousMsiPath) {
# $script:previousMsiPath = Get-Latest-Podman-MSI-From-GitHub -arch $script:arch
# }
if (!$script:previousSetupExePath) {
$script:previousSetupExePath = Get-Latest-Podman-Setup-From-GitHub -arch $script:arch
}
Start-Scenario-Installation-Green-Field
Start-Scenario-Installation-Skip-Config-Creation-Flag
Start-Scenario-Installation-With-Pre-Existing-Podman-Exe
# Start-Scenario-Update-From-Prev-To-Current
# Start-Scenario-Update-From-Prev-To-Current-With-Modified-Config
# Start-Scenario-Update-From-Prev-To-Current-With-Removed-Config
Start-Scenario-Update-From-Current-To-Next
Start-Scenario-Update-From-Current-To-Next-With-Modified-Config
Start-Scenario-Update-From-Current-To-Next-With-Removed-Config
Start-Scenario-Update-From-Legacy-To-Current
}
}

View File

@@ -1,23 +1,113 @@
#!/usr/bin/env pwsh
function Get-Latest-Podman-Setup-From-GitHub {
return Get-Podman-Setup-From-GitHub "latest"
param(
[ValidateSet("amd64", "arm64")]
[string] $arch = "amd64"
)
return Get-Podman-Setup-From-GitHub "latest" $arch
}
function Get-Podman-Setup-From-GitHub {
param(
[Parameter(Mandatory)]
[string] $version
[string] $version,
[ValidateSet("amd64", "arm64")]
[string] $arch = "amd64"
)
Write-Host "Downloading the $version Podman windows setup from GitHub..."
Write-Host "Downloading the $arch $version Podman windows setup from GitHub..."
$apiUrl = "https://api.github.com/repos/containers/podman/releases/$version"
$response = Invoke-RestMethod -Uri $apiUrl -Headers @{"User-Agent"="PowerShell"} -ErrorAction Stop
$downloadUrl = $response.assets[0].browser_download_url
Write-Host "Downloading URL: $downloadUrl"
$latestTag = $response.tag_name
$destinationPath = "$PSScriptRoot\podman-$latestTag-setup.exe"
Write-Host "Looking for an asset named ""podman-installer-windows-$arch.exe"""
$downloadAsset = $response.assets | Where-Object { $_.name -eq "podman-installer-windows-$arch.exe" } | Select-Object -First 1
if (-not $downloadAsset) {
# remove the first char from $latestTag if it is a "v"
if ($latestTag[0] -eq "v") {
$newLatestTag = $latestTag.Substring(1)
}
Write-Host "Not found. Looking for an asset named ""podman-$newLatestTag-setup.exe"""
$downloadAsset = $response.assets | Where-Object { $_.name -eq "podman-$newLatestTag-setup.exe" } | Select-Object -First 1
}
$downloadUrl = $downloadAsset.browser_download_url
Write-Host "Downloading URL: $downloadUrl"
$destinationPath = "$PSScriptRoot\podman-${latestTag}-setup.exe"
Write-Host "Destination Path: $destinationPath"
Invoke-WebRequest -Uri $downloadUrl -OutFile $destinationPath
Write-Host "Command completed successfully!`n"
return $destinationPath
}
function DownloadReleaseFile {
param(
[Parameter(Mandatory)]
[string]$url,
[Parameter(Mandatory)]
[string]$outputFile,
[Parameter(Mandatory=$false, Position=3, HelpMessage="Fail if `Invoke-WebRequest` fails, silently continue if not specified")]
[switch]$failOnError = $false
)
$ProgressPreference = 'SilentlyContinue';
try {
Invoke-WebRequest -UseBasicParsing -ErrorAction Stop -Uri $url -OutFile $outputFile
} Catch {
if ($FailOnError) {
if ($_.Exception.Response.StatusCode -eq 404) {
Write-Error "URL not available $url"
Exit 2
}
throw $_.Exception
}
}
}
function ExitOnError() {
if ($LASTEXITCODE -ne 0) {
Exit 1
}
}
function SignItem() {
param(
[Parameter(Mandatory)]
[string[]]$fileNames
)
foreach ($val in $ENV:APP_ID, $ENV:TENANT_ID, $ENV:CLIENT_SECRET, $ENV:CERT_NAME) {
if (!$val) {
Write-Host 'Skipping signing (no config)'
Return
}
}
CheckCommand AzureSignTool.exe 'AzureSignTool'
AzureSignTool.exe sign -du 'https://github.com/containers/podman' `
-kvu "https://$ENV:VAULT_ID.vault.azure.net" `
-kvi $ENV:APP_ID `
-kvt $ENV:TENANT_ID `
-kvs $ENV:CLIENT_SECRET `
-kvc $ENV:CERT_NAME `
-tr http://timestamp.digicert.com $fileNames
ExitOnError
}
function Get-Current-Architecture {
$arch = [System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture
if ($arch -eq 'X64') {
return 'amd64'
} elseif ($arch -eq 'Arm64') {
return 'arm64'
} else {
throw "Unsupported architecture: $arch"
}
}
# Pre-set to standard locations in-case build env does not refresh paths
$Env:Path = "$Env:Path;" + `
'C:\Users\micro\mingw64\bin;' + `
'C:\ProgramData\chocolatey\lib\mingw\tools\install\mingw64\bin;' + `
';C:\Program Files\Go\bin;' + `
'C:\Program Files\dotnet'

View File

@@ -0,0 +1,180 @@
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:PanelSW="http://schemas.panel-sw.co.il/wix/WixExtension" xmlns:util="http://wixtoolset.org/schemas/v4/wxs/util">
<?ifndef VERSION?>
<?error VERSION must be defined via command line argument?>
<?endif?>
<?ifdef env.UseGVProxy?>
<?define UseGVProxy = "$(env.UseGVProxy)"?>
<?else?>
<?define UseGVProxy = ""?>
<?endif?>
<Package Name="Podman CLI" Manufacturer="Podman" Version="$(VERSION)" UpgradeCode="a6a9dd9c-0732-44ba-9279-ffe22ea50671" Scope="perUserOrMachine">
<Media Id="1" Cabinet="Podman.cab" EmbedCab="yes" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." Schedule="afterInstallExecute" />
<Property Id="WINDOWSBUILDNUMBER" Secure="yes">
<RegistrySearch Id="BuildNumberSearch" Root="HKLM" Key="SOFTWARE\Microsoft\Windows NT\CurrentVersion" Name="CurrentBuildNumber" Type="raw" />
</Property>
<Launch Condition="Installed OR (WINDOWSBUILDNUMBER &gt;= 19041)"
Message="Windows 10 (19041) or later is required to run this application." />
<!--
The installer fails during installation if the legacy Podman
registry key is found. Otherwise the user would end up with two
installations of Podman. This is because it's not possible to
do an update from a machine scope bundle (the legacy installer) to a
dual scope package (this MSI).
-->
<Property Id="LEGACY_PODMAN_REGISTRY_KEY_FOUND">
<RegistrySearch Id="LegacyPodmanRegistryKeySearch"
Root="HKLM"
Key="SOFTWARE\Red Hat\Podman"
Name="InstallDir"
Type="raw" />
</Property>
<Launch Condition="Installed OR (NOT LEGACY_PODMAN_REGISTRY_KEY_FOUND)"
Message="Found an older version of Podman that is not compatible with
this installer.&#13;&#10;&#13;&#10;Uninstall it using 'Add or Remove
Programs' and retry. During uninstallation, all containers, images, machines,
and other data will be preserved." />
<util:QueryNativeMachine />
<Launch Condition='"$(sys.BUILDARCH)" ~= "x64" IMP WIX_NATIVE_MACHINE = 34404'
Message="This version of the [ProductName] installer can only run on $(sys.BUILDARCH) machines." />
<Property Id="DiskPrompt" Value="Podman $(VERSION) Installation" />
<Property Id="MACHINE_PROVIDER" Value="wsl" />
<Property Id="MACHINE_PROVIDER_CONFIG_FILE_PATH">
<DirectorySearch Id="CONFDIRFolderSearch" Path="[CONFDIR]">
<FileSearch Name="99-podman-machine-provider.conf" />
</DirectorySearch>
</Property>
<!--
ProgramFiles6432Folder corresponds to %ProgramFiles% when the scope
is machine and to %LocalAppData%\Programs when the scope is user.
https://learn.microsoft.com/en-us/windows/win32/msi/single-package-authoring
-->
<Property Id="MAIN_EXECUTABLE_FILE_PATH">
<DirectorySearch Id="ProgramFiles64FolderSearch" Path="[ProgramFiles64Folder]">
<DirectorySearch Id="PodmanFolderSearch" Path="Podman">
<FileSearch Name="podman.exe" />
</DirectorySearch>
</DirectorySearch>
</Property>
<SetProperty Id="CONFDIR"
Action="SetCONFDIR_User"
Value="[AppDataFolder]containers\containers.conf.d"
Before="AppSearch"
Condition="MSIINSTALLPERUSER=1 AND NOT IS_UPGRADE"
Sequence="first" />
<SetProperty Id="CONFDIR"
Action="SetCONFDIR_Machine"
Value="[CommonAppDataFolder]containers\containers.conf.d"
Before="AppSearch"
Condition="ALLUSERS=1 AND NOT MSIINSTALLPERUSER=1 AND NOT IS_UPGRADE"
Sequence="first" />
<!--
Property CREATE_MACHINE_PROVIDER_CONFIG_FILE is set at runtime and used as the condition to run the `MachineProviderConfigFile` Component:
The machine provider config file is created (or is not deleted if it already exist) if these conditions are met:
- The user hasn't set property `SKIP_CONFIG_FILE_CREATION` to 1
- The main executable file (<PFILESDIR>/Podman/podman.exe) doesn't exist or, if it exists, the machine provider config file exists
-->
<SetProperty Id="CREATE_MACHINE_PROVIDER_CONFIG_FILE"
After="AppSearch"
Value="1"
Sequence="first"
Condition="(NOT (SKIP_CONFIG_FILE_CREATION = 1)) AND ((NOT MAIN_EXECUTABLE_FILE_PATH) OR (MACHINE_PROVIDER_CONFIG_FILE_PATH))" />
<!--
Property HIDE_PROVIDER_CHOICE is set at runtime and used as the condition to hide the Machine Provider
choice from the MSI GUI (the Radio Button Group and other related controls):
The machine provider choice isn't shown to the user if one of these conditions are met:
- The user has set the property `SKIP_CONFIG_FILE_CREATION` to 1
- The machine provider config file (<CONFDIR>/containers/containers.conf.d/99-podman-machine-provider.conf) exists
- The main executable file (<PFILESDIR>/Podman/podman.exe) exists
-->
<SetProperty Id="HIDE_PROVIDER_CHOICE"
After="AppSearch"
Value="1"
Sequence="first"
Condition="(SKIP_CONFIG_FILE_CREATION = 1) OR (MACHINE_PROVIDER_CONFIG_FILE_PATH) OR (MAIN_EXECUTABLE_FILE_PATH)" />
<CustomAction Id="OpenGuide" DllEntry="WixShellExec" Impersonate="yes" BinaryRef="Wix4UtilCA_$(sys.BUILDARCHSHORT)" />
<util:BroadcastEnvironmentChange />
<Feature Id="Complete" Level="1">
<ComponentRef Id="INSTALLDIR_Component" />
<ComponentRef Id="EnvEntriesComponent" />
<ComponentRef Id="MainExecutable" />
<ComponentRef Id="WinSshProxyExecutable" />
<?if $(var.UseGVProxy) != Skip?>
<ComponentRef Id="GvProxyExecutable" />
<?endif?>
<ComponentRef Id="GuideHTMLComponent" />
<ComponentGroupRef Id="ManFiles" />
</Feature>
<Feature Id="MachineProviderConfig" Level="1">
<ComponentRef Id="MachineProviderConfigFile" />
</Feature>
<Icon Id="podman.ico" SourceFile="resources/podman-logo.ico" />
<Property Id="ARPPRODUCTICON" Value="podman.ico" />
<Property Id="WixShellExecTarget" Value="[#GuideHTMLFile]" />
<Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOXTEXT" Value="Show Getting Started Guide" />
<Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOX" Value="1" />
<WixVariable Id="WixUIBannerBmp" Value="resources\podman-banner.png" />
<WixVariable Id="WixUIDialogBmp" Value="resources\podman-dialog.png" />
<UIRef Id="PodmanUI" />
<UI>
<Publish Dialog="ExitDialog" Control="Finish" Event="DoAction" Value="OpenGuide" Condition="(WIXUI_EXITDIALOGOPTIONALCHECKBOX = 1) AND (NOT Installed) AND (NOT UpdateStarted)" />
</UI>
<!--
ProgramFiles6432Folder corresponds to %ProgramFiles% when the scope
is machine and to %LocalAppData%\Programs when the scope is user.
https://learn.microsoft.com/en-us/windows/win32/msi/single-package-authoring
-->
<StandardDirectory Id="ProgramFiles6432Folder">
<Directory Id="INSTALLDIR" Name="Podman">
<Component Id="INSTALLDIR_Component" Guid="14B310C4-9B5D-4DA5-ADF9-B9D008E4CD82" Bitness="always64">
<CreateFolder />
<RegistryKey Root="HKMU" Key="SOFTWARE\Podman">
<RegistryValue Name="InstallDir" Value="[INSTALLDIR]" Type="string" />
</RegistryKey>
</Component>
<Component Id="MainExecutable" Guid="73752F94-6589-4C7B-ABED-39D655A19714" Bitness="always64">
<File Id="MainExecutableFile" Name="podman.exe" Source="..\artifacts\podman.exe" KeyPath="yes" />
</Component>
<Component Id="WinSshProxyExecutable" Guid="0DA730AB-2F97-40E8-A8FC-356E88EAA4D2" Bitness="always64">
<File Id="WinSshProxyExecutableFile" Name="win-sshproxy.exe" Source="..\artifacts\win-sshproxy.exe" KeyPath="yes" />
</Component>
<?if $(var.UseGVProxy) != Skip?>
<Component Id="GvProxyExecutable" Guid="1A4A2975-AD2D-44AA-974B-9B343C098333" Bitness="always64">
<File Id="GvProxyExecutableFile" Name="gvproxy.exe" Source="..\artifacts\gvproxy.exe" KeyPath="yes" />
</Component>
<?endif?>
<Component Id="GuideHTMLComponent" Guid="8B23C76B-F7D4-4030-8C46-1B5729E616B5" Bitness="always64">
<File Id="GuideHTMLFile" Name="welcome-podman.html" Source="..\docs\podman-for-windows.html" KeyPath="yes" />
</Component>
</Directory>
</StandardDirectory>
<!--
The following code creates the `<CONFDIR>/containers/containers.conf.d` directory
CONFDIR is the logical target directory whose path will be set by the CONFDIR property.
-->
<Directory Id="CONFDIR">
<Component Id="MachineProviderConfigFile" Guid="C32C0040-D9AF-4155-AC7E-465B63B6BE3B" Condition="CREATE_MACHINE_PROVIDER_CONFIG_FILE" Transitive="true">
<CreateFolder />
<IniFile Id="MachineProviderConfigFile" Action="createLine" Directory="CONFDIR" Section="machine" Name="99-podman-machine-provider.conf" Key="provider" Value="&quot;[MACHINE_PROVIDER]&quot;"/>
</Component>
</Directory>
<Directory Id="EnvEntries">
<Component Id="EnvEntriesComponent" Guid="b662ec43-0e0e-4018-8bf3-061904bb8f5b" Bitness="always64">
<CreateFolder />
<Environment Id="UpdatePath" Name="PATH" Action="set" Permanent="no" Part="last" Value="[INSTALLDIR]" />
</Component>
</Directory>
</Package>
</Wix>

View File

@@ -0,0 +1,48 @@
<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. -->
<!--
First-time install dialog sequence:
- WixUI_WelcomeEulaDlg
Maintenance dialog sequence:
WixUI_MaintenanceWelcomeDlg
- WixUI_MaintenanceTypeDlg
- WixUI_VerifyReadyDlg
Patch dialog sequence:
- WixUI_WelcomeDlg
- WixUI_VerifyReadyDlg
-->
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
<Fragment>
<UI Id="PodmanUI">
<TextStyle Id="WixUI_Font_Normal" FaceName="Tahoma" Size="8" />
<TextStyle Id="WixUI_Font_Bigger" FaceName="Tahoma" Size="12" />
<TextStyle Id="WixUI_Font_Title" FaceName="Tahoma" Size="9" Bold="yes" />
<Property Id="DefaultUIFont" Value="WixUI_Font_Normal" />
<Property Id="WixUI_Mode" Value="Minimal" />
<DialogRef Id="ErrorDlg" />
<DialogRef Id="FatalError" />
<DialogRef Id="FilesInUse" />
<DialogRef Id="MsiRMFilesInUse" />
<DialogRef Id="PrepareDlg" />
<DialogRef Id="ProgressDlg" />
<DialogRef Id="ResumeDlg" />
<DialogRef Id="UserExit" />
<DialogRef Id="WelcomeInstallDlg" />
<Publish Dialog="ExitDialog" Control="Finish" Event="EndDialog" Value="Return" Order="999" />
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="MaintenanceTypeDlg" />
<Publish Dialog="MaintenanceWelcomeDlg" Control="Next" Event="NewDialog" Value="MaintenanceTypeDlg" />
<Publish Dialog="MaintenanceTypeDlg" Control="RepairButton" Event="NewDialog" Value="VerifyReadyDlg" />
<Publish Dialog="MaintenanceTypeDlg" Control="RemoveButton" Event="NewDialog" Value="VerifyReadyDlg" />
<Publish Dialog="MaintenanceTypeDlg" Control="Back" Event="NewDialog" Value="MaintenanceWelcomeDlg" />
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="WelcomeInstallDlg" Order="2" Condition="Installed AND PATCH" />
<InstallUISequence>
<Show Dialog="WelcomeInstallDlg" Before="ProgressDlg" Condition="(NOT Installed) AND NOT AFTERREBOOT" />
</InstallUISequence>
<Property Id="ARPNOMODIFY" Value="1" />
</UI>
<UIRef Id="WixUI_Common" />
</Fragment>
</Wix>

View File

@@ -0,0 +1,33 @@
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
<Fragment>
<UI>
<Dialog Id="WelcomeInstallDlg" Width="370" Height="270" Title="!(loc.WelcomeDlg_Title)">
<Control Id="Bitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="234" TabSkip="no" Text="!(loc.WelcomeDlgBitmap)" />
<Control Id="Title" Type="Text" X="135" Y="20" Width="220" Height="60" Transparent="yes" NoPrefix="yes" Text="!(loc.WelcomeDlgTitle)" />
<Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
<Control Id="DescriptionInstall" Type="Text" X="135" Y="50" Width="220" Height="60" Transparent="yes" NoPrefix="yes" Text="!(loc.WelcomeDlgDescription)" HideCondition="WIX_UPGRADE_DETECTED" />
<Control Id="DescriptionUpdate" Type="Text" X="135" Y="50" Width="220" Height="60" Transparent="yes" NoPrefix="yes" Text="!(loc.WelcomeUpdateDlgDescriptionUpdate)" HideCondition="NOT WIX_UPGRADE_DETECTED" />
<Control Id="ProviderChoice" Type="Text" X="135" Y="115" Width="220" Height="18" Transparent="yes" NoPrefix="yes" Text="Select the Virtualization Provider for the Podman machine:" HideCondition="HIDE_PROVIDER_CHOICE" />
<Control Type="RadioButtonGroup" Property="MACHINE_PROVIDER" Id="MachineProviderRadioButtonGroup" Width="226" Height="30" X="135" Y="135" HideCondition="HIDE_PROVIDER_CHOICE">
<RadioButtonGroup Property="MACHINE_PROVIDER">
<RadioButton Text="Windows Linux Subsystem (WSLv2)" Height="15" Value="wsl" Width="226" X="10" Y="0" />
<RadioButton Text="Windows Hyper-V" Height="15" Value="hyperv" Width="226" X="10" Y="15" />
</RadioButtonGroup>
</Control>
<Control Id="Back" Type="PushButton" X="156" Y="243" Width="56" Height="17" Disabled="yes" Text="!(loc.WixUIBack)" />
<Control Id="Install" Type="PushButton" ElevationShield="no" X="212" Y="243" Width="80" Height="17" Default="yes" Text="!(loc.WixUINext)">
<Publish Event="SpawnWaitDialog" Value="WaitForCostingDlg" Condition="!(wix.WixUICostingPopupOptOut) OR CostingComplete = 1" />
<Publish Event="EndDialog" Value="Return" Condition="OutOfDiskSpace &lt;&gt; 1" />
<Publish Event="SpawnDialog" Value="OutOfRbDiskDlg" Condition="OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND (PROMPTROLLBACKCOST=&quot;P&quot; OR NOT PROMPTROLLBACKCOST)" />
<Publish Event="EndDialog" Value="Return" Condition="OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND PROMPTROLLBACKCOST=&quot;D&quot;" />
<Publish Event="EnableRollback" Value="False" Condition="OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND PROMPTROLLBACKCOST=&quot;D&quot;" />
<Publish Event="SpawnDialog" Value="OutOfDiskDlg" Condition="(OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 1) OR (OutOfDiskSpace = 1 AND PROMPTROLLBACKCOST=&quot;F&quot;)" />
</Control>
<Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="!(loc.WixUICancel)">
<Publish Event="SpawnDialog" Value="CancelDlg" />
</Control>
</Dialog>
</UI>
</Fragment>
</Wix>

View File

@@ -0,0 +1,20 @@
<Project Sdk="WixToolset.Sdk/5.0.2">
<PropertyGroup>
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
</PropertyGroup>
<ItemGroup>
<HarvestDirectory Include="..\docs">
<ComponentGroupName>ManFiles</ComponentGroupName>
<DirectoryRefId>INSTALLDIR</DirectoryRefId>
<SuppressRootDirectory>true</SuppressRootDirectory>
</HarvestDirectory>
<BindPath Include="..\docs" />
<Compile Include="podman-main.wxs;podman-ui-main.wxs;podman-ui-welcome-dlg.wxs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="PanelSwWixExtension4" Version="5.4.5.422" />
<PackageReference Include="WixToolset.Heat" Version="5.0.2" />
<PackageReference Include="WixToolset.UI.wixext" Version="5.0.2" />
<PackageReference Include="WixToolset.Util.wixext" Version="5.0.2" />
</ItemGroup>
</Project>

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -1,16 +1,16 @@
#!/usr/bin/env powershell
[CmdletBinding(PositionalBinding=$false)]
[CmdletBinding(PositionalBinding = $false)]
param (
[ValidateSet("amd64", "arm64")]
[Alias("arch")]
[ValidateSet('amd64', 'arm64')]
[Alias('arch')]
[string]$architecture = $(
$defaultArchitecture = "amd64"
$arch = try {& go env GOARCH} catch {
$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")) {
if ($arch -cnotin @('arm64', 'amd64')) {
Write-Warning "Unsupported architecture $arch. Using default ($defaultArchitecture)."
return $defaultArchitecture
}
@@ -22,8 +22,8 @@ param (
. ./contrib/cirrus/win-lib.ps1
# Targets
function Podman-Remote{
New-Item -ItemType Directory -Force -Path "./bin/windows"
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 "
@@ -34,8 +34,8 @@ function Podman-Remote{
Run-Command "go build --ldflags `"$commit $buildInfo `" --tags `"$remotetags`" --o ./bin/windows/podman.exe ./cmd/podman/."
}
function Make-Clean{
$paths= @(
function Make-Clean {
$paths = @(
# Files generated by the `podman` target
"$PSScriptRoot\bin\windows"
# Files generated by the `installer` target
@@ -43,12 +43,22 @@ function Make-Clean{
"$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\wix\obj"
"$PSScriptRoot\contrib\win-installer\*.log"
"$PSScriptRoot\contrib\win-installer\*.exe"
"$PSScriptRoot\contrib\win-installer\*.msi"
"$PSScriptRoot\contrib\win-installer\*.wixpdb"
"$PSScriptRoot\contrib\win-installer\shasums"
# Files generated by the `installer-legacy` target
"$PSScriptRoot\contrib\win-installer-legacy\artifacts"
"$PSScriptRoot\contrib\win-installer-legacy\current"
"$PSScriptRoot\contrib\win-installer-legacy\docs"
"$PSScriptRoot\contrib\win-installer-legacy\en-us"
"$PSScriptRoot\contrib\win-installer-legacy\fetch"
"$PSScriptRoot\contrib\win-installer-legacy\obj"
"$PSScriptRoot\contrib\win-installer-legacy\*.log"
"$PSScriptRoot\contrib\win-installer-legacy\*.exe"
"$PSScriptRoot\contrib\win-installer-legacy\*.wixpdb"
# Files generated by the Documentation target
"$PSScriptRoot\docs\build\remote\podman-*.html"
"$PSScriptRoot\docs\build\remote\podman-for-windows.html"
@@ -57,7 +67,8 @@ function Make-Clean{
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) {
}
elseif (Test-Path -Path $path -PathType Leaf) {
Remove-Item $path -Force -Confirm:$false
}
}
@@ -65,22 +76,23 @@ function Make-Clean{
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"
$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'
if ($null -eq $ENV:GINKGOTIMEOUT) { $ENV:GINKGOTIMEOUT = '--timeout=15m' }
Run-Command "./bin/ginkgo.exe -vv -r --tags `"$remotetags`" ${ENV:GINKGOTIMEOUT} --trace --no-color --skip-package `"$skippackages`""
}
function Local-Machine {
param (
[string]$files
[string]$files
);
Build-Ginkgo
if ($files) {
$files = "--focus-file ""$files"""
} elseif ($FOCUS_FILE) {
$files = "--focus-file ""$files"""
}
elseif ($FOCUS_FILE) {
$files = "--focus-file ""$FOCUS_FILE"" --silence-skips"
}
if ($FOCUS) {
@@ -97,25 +109,27 @@ function Win-SSHProxy {
[string]$Version
);
New-Item -ItemType Directory -Force -Path "./bin/windows"
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\.]+)"
$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"
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{
function Installer {
param (
[string]$version,
[string]$suffix = "dev"
[string]$suffix = 'dev',
[string]$installerPath = "$PSScriptRoot\contrib\win-installer"
);
Write-Host "Building the windows installer for $architecture"
@@ -130,15 +144,15 @@ function Installer{
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"
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"
$zipFileDest = "$installerPath\current"
Build-Distribution-Zip-File -destinationPath $zipFileDest
if (-Not $version) {
@@ -146,20 +160,21 @@ function Installer{
$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
# Run build.ps1
if ($installerPath -eq "$PSScriptRoot\contrib\win-installer-legacy") {
$ENV:PODMAN_ARCH = $architecture # This is used by the "build.ps1" script
Run-Command "$installerPath\build.ps1 $version $suffix `"$zipFileDest`""
}
else {
Run-Command "$installerPath\build.ps1 -Version $version -Architecture $architecture -LocalReleaseDirPath `"$zipFileDest`""
}
}
function Test-Installer{
function Test-Installer {
param (
[string]$version,
[ValidateSet("dev", "prod")]
[string]$flavor = "dev",
[ValidateSet("wsl", "hyperv")]
[string]$provider = "wsl"
[ValidateSet('wsl', 'hyperv')]
[string]$provider = 'wsl'
);
if (-Not $version) {
@@ -167,42 +182,82 @@ function Test-Installer{
$version = Get-Podman-Version
}
if ($flavor -eq "prod") {
$suffix = ""
} else {
$suffix = "-dev"
$msiPath = "$PSScriptRoot\contrib\win-installer\podman-${version}.msi"
if (!(Test-Path -Path $msiPath -PathType Leaf)) {
Write-Host "MSI executable not found in path $msiPath."
Write-Host "Make 'installer' before making the installer test:"
Write-Host ' .\winmake.ps1 installer'
Exit 1
}
$setupExePath = "$PSScriptRoot\contrib\win-installer\podman-${version}${suffix}-setup.exe"
$nextMsiPath = "$PSScriptRoot\contrib\win-installer\podman-9.9.9.msi"
if (!(Test-Path -Path $nextMsiPath -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.ps1"
$command += ' -scenario all'
$command += " -provider $provider"
$command += " -msiPath $msiPath"
$command += " -nextMsiPath $nextMsiPath"
Run-Command "${command}"
}
function Test-Installer-Legacy {
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-legacy\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"
Write-Host ' .\winmake.ps1 installer-legacy'
Exit 1
}
$nextSetupExePath = "$PSScriptRoot\contrib\win-installer\podman-9.9.9-dev-setup.exe"
$nextSetupExePath = "$PSScriptRoot\contrib\win-installer-legacy\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."
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-legacy 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 = "$PSScriptRoot\contrib\win-installer-legacy\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"
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."
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
}
@@ -222,8 +277,8 @@ function Documentation{
# 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"
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)) {
@@ -238,29 +293,29 @@ function DocumentationUsingPodman{
}
# 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."
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"
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"
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"
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"
$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"
$validateImage = 'quay.io/libpod/validatepr:latest'
$validateCommand = 'make .validatepr'
# Check that podman is installed
if (!(Get-Command -Name $podmanExecutable -ErrorAction SilentlyContinue)) {
@@ -277,59 +332,59 @@ function Validate{
# 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."
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{
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."
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."
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 'pre-commit run --all-files'
Run-Command "golangci-lint run --timeout=10m --build-tags=`"$remotetags`" $PSScriptRoot\cmd\podman"
}
# Helpers
function Build-Ginkgo{
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"
Write-Host 'Building Ginkgo'
Run-Command 'go build -o ./bin/ginkgo.exe ./vendor/github.com/onsi/ginkgo/v2/ginkgo'
}
function Git-Commit{
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(!$?){
Get-Command git -ErrorAction SilentlyContinue | out-null
if (!$?) {
return
}
$commit = git rev-parse HEAD
$dirty = git status --porcelain --untracked-files=no
if ($dirty){
if ($dirty) {
$commit = "$commit-dirty"
}
return $commit
}
function Build-Distribution-Zip-File{
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"
@@ -355,23 +410,23 @@ function Build-Distribution-Zip-File{
Remove-Item -Recurse -Force -Path "$tempFolder"
}
function Get-Podman-Version{
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 "-.*", ""
$version = $version -replace '-.*', ''
return $version
}
# Init script
$target = $params[0]
$remotetags = "remote exclude_graphdriver_btrfs containers_image_openpgp"
$remotetags = 'remote exclude_graphdriver_btrfs containers_image_openpgp'
switch ($target) {
{$_ -in '', 'podman-remote', 'podman'} {
{ $_ -in '', 'podman-remote', 'podman' } {
Podman-Remote
}
'localunit' {
@@ -386,7 +441,7 @@ switch ($target) {
'clean' {
Make-Clean
}
{$_ -in 'win-sshproxy', 'win-gvproxy'} {
{ $_ -in 'win-sshproxy', 'win-gvproxy' } {
if ($params.Count -gt 1) {
$ref = $params[1]
}
@@ -395,17 +450,35 @@ switch ($target) {
'installer' {
if ($params.Count -gt 1) {
Installer -version $params[1]
} else {
}
else {
Installer
}
}
'installertest' {
if ($params.Count -gt 1) {
Test-Installer -provider $params[1]
} else {
}
else {
Test-Installer
}
}
'installer-legacy' {
if ($params.Count -gt 1) {
Installer -version $params[1] -installerPath $PSScriptRoot\contrib\win-installer-legacy
}
else {
Installer -installerPath $PSScriptRoot\contrib\win-installer-legacy
}
}
'installertest-legacy' {
if ($params.Count -gt 1) {
Test-Installer-Legacy -provider $params[1]
}
else {
Test-Installer-Legacy
}
}
'docs' {
Documentation
}
@@ -419,39 +492,39 @@ switch ($target) {
Lint
}
default {
Write-Host "Usage: " $MyInvocation.MyCommand.Name "<target> [options] [<-architecture|-arch>=<amd64|arm64>]"
Write-Host 'Usage: ' $MyInvocation.MyCommand.Name '<target> [options] [<-architecture|-arch>=<amd64|arm64>]'
Write-Host
Write-Host "Example: Build podman-remote "
Write-Host " .\winmake podman-remote"
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 'Example: Run all unit tests '
Write-Host ' .\winmake localunit'
Write-Host
Write-Host "Example: Run all machine tests "
Write-Host " .\winmake localmachine"
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 '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 '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 '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 '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 '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 '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 'Example: Validate code changes before submitting a PR'
Write-Host ' .\winmake validatepr'
Write-Host
Write-Host "Example: Run linters"
Write-Host " .\winmake lint"
Write-Host 'Example: Run linters'
Write-Host ' .\winmake lint'
}
}