diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7e75e4f6ea..936b0b14d0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,13 +4,15 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks.git rev: v3.4.0 hooks: - # buildah-tests.diff is generated by 'git format-patch' and includes + # `buildah-tests.diff` is generated by 'git format-patch' and includes # trailing whitespace as part of its format. We can work around that, # but unfortunately the buildah repo has some files with tabs, which # git-diff formats as '[+/-]', which these hooks choke on. - # Just disable checks on this diff file as a special case. + # `contrib/systemd/user` is a symlink but for some reason, on windows, + # pre-commit consider it as a regular file and tries to fix it. + # Just disable checks on these files as a special case. - id: end-of-file-fixer - exclude: test/buildah-bud/buildah-tests.diff + exclude: test/buildah-bud/buildah-tests.diff|contrib/systemd/user - id: trailing-whitespace exclude: test/buildah-bud/buildah-tests.diff|test/e2e/quadlet/remap-keep-id2.container|test/e2e/quadlet/line-continuation-whitespace.container - id: mixed-line-ending diff --git a/build_windows.md b/build_windows.md index 3640be8ca0..5a93faca7b 100644 --- a/build_windows.md +++ b/build_windows.md @@ -1,115 +1,219 @@ # Building the Podman client and client installer on Windows -The following describes the process for building the Podman client on Windows. +The following describes the process for building and testing the Podman Windows +client (`podman.exe`) and the Podman Windows installer (`podman-setup.exe`) on +Windows. + +## Topics + +- [Requirements](#requirements) + - [OS requirements](#os-requirements) + - [Git and go](#git-and-go) + - [Pandoc](#pandoc) + - [WiX Toolset v3](#wix-toolset-v3) + - [Virtualization Provider](#virtualization-provider) + - [WSL](#wsl) + - [Hyper-V](#hyper-v) +- [Get the source code](#get-the-source-code) + - [Allow local PowerShell scripts execution](#allow-local-powershell-scripts-execution) +- [Build and test the Podman client for Windows](#build-and-test-the-podman-client-for-windows) + - [Build the Podman client](#build-the-podman-client) + - [Download gvproxy.exe and win-sshproxy.exe](#download-gvproxyexe-and-win-sshproxyexe) + - [Create a configuration file (optional)](#create-a-configuration-file-optional) + - [Create and start a podman machine](#create-and-start-a-podman-machine) + - [Run a container using podman](#run-a-container-using-podman) +- [Build and test the Podman Windows installer](#build-and-test-the-podman-windows-installer) + - [Build the installer](#build-the-installer) + - [Test the installer](#test-the-installer) + - [Build and test the standalone `podman.msi` file](#build-and-test-the-standalone-podmanmsi-file) + - [Verify the installation](#verify-the-installation) + - [Uninstall and clean-up](#uninstall-and-clean-up) +- [Validate changes before submitting a PR](#validate-changes-before-submitting-a-pr) + - [winmake lint](#winmake-lint) + - [winmake validatepr](#winmake-validatepr) + +## Requirements + +### OS requirements + +This documentation assumes one uses a Windows 10 or 11 development machine and a +PowerShell terminal. + +### Git and go + +To build Podman, the [git](https://gitforwindows.org/) and [go](https://go.dev) +tools are required. In case they are not yet installed, open a Windows +PowerShell terminal and run the following command (it assumes that +[winget](https://learn.microsoft.com/en-us/windows/package-manager/winget/) is +installed): + +```pwsh +winget install -e GoLang.Go Git.Git +``` + +:information_source: A terminal restart is advised for the `PATH` to be +reloaded. This can also be manually changed by configuring the `PATH`: -## OS requirements +```pwsh +$env:Path += ";C:\Program Files\Go\bin\;C:\Program Files\Git\cmd\" +``` -Windows OS can behave very differently depending on how it was configured. This documentation assumes that one is using -a [Windows 11 development machine](https://developer.microsoft.com/en-us/windows/downloads/virtual-machines/) or a -configuration close to this one. The Podman Windows client installer bundles several tools, which are unnecessary for Podman builds, but this -set of packages is well aligned with GitHub's `windows-latest` offerings. Some of the tools will still be missing from -this distribution and will have to be manually added after this installation completes. +### Pandoc -## Install Pandoc +[Pandoc](https://pandoc.org/) is used to generate Podman documentation. It is +required for building the documentation and the +[bundle installer](#build-the-installer). It can be avoided when building and +testing the +[Podman client for Windows](#build-and-test-the-podman-client-for-windows) or +[the standalone `podman.msi` installer](#build-and-test-the-standalone-podmanmsi-file). +Pandoc can be installed from https://pandoc.org/installing.html. When performing +the Pandoc installation one, has to choose the option "Install for all users" +(to put the binaries into "Program Files" directory). -Pandoc could be installed from https://pandoc.org/installing.html When performing the Pandoc installation one, has to choose the option -"Install for all users" (to put the binaries into "Program Files" directory). +### WiX Toolset v3 -## Install WiX Toolset v3 (is preinstalled in GitHub runner) -The latest release of the WiX Toolset can be obtained from https://wixtoolset.org/docs/wix3/. Installing it into a clean VM might require +[WiX Toolset](https://wixtoolset.org) **v3** is used to develop and build the +Podman Windows installer. It's not required for the Podman Windows client. +Version 3 of the WiX Toolset can be obtained from +https://wixtoolset.org/docs/wix3/. Installing it into a clean VM might require an additional installation of .NET Framework 3.5 in advance ([instructions for adding .NET Framework 3.5 via enabling the Windows feature](https://learn.microsoft.com/en-us/dotnet/framework/install/dotnet-35-windows#enable-the-net-framework-35-in-control-panel)) -## Building and running +### Virtualization Provider -### Install git and go +Running Podman on Windows requires a virtualization provider. The supported +providers are the +[Windows Subsystem for Linux (WSL)](https://learn.microsoft.com/en-us/windows/wsl/) +and +[Hyper-V](https://learn.microsoft.com/en-us/virtualization/hyper-v-on-windows/quick-start/enable-hyper-v). +At least one of those two is required to test podman on a local Windows machine. -To build Podman, the [git](https://gitforwindows.org/) and [go](https://go.dev) tools are required. In case they are not yet installed, -open a Windows Terminal and run the following command (it assumes that [winget](https://learn.microsoft.com/en-us/windows/package-manager/winget/) is installed): +#### WSL -``` -winget install -e GoLang.Go Git.Git -``` - -:information_source: A terminal restart is advised for the `PATH` to be reloaded. This can also be manually changed by configuring the `PATH`: +WSL can be installed on Windows 10 and Windows 11, including Windows Home, with +the following command, from a PowerShell or Windows Command Prompt terminal in +**administrator mode**: -``` -$env:Path += ";C:\Program Files\Go\bin\;C:\Program Files\Git\cmd\" +```pwsh +wsl --install ``` -### Enable Hyper-V (optional) +For more information refer to +[the official documentation](https://learn.microsoft.com/en-us/windows/wsl/). -Podman on Windows can run on the [Windows Subsystem for Linux (WSL)](https://learn.microsoft.com/en-us/windows/wsl/) or -on [Hyper-V](https://learn.microsoft.com/en-us/virtualization/hyper-v-on-windows/quick-start/enable-hyper-v). +#### Hyper-V -Hyper-V is built into Windows Enterprise, Pro, or Education (not Home) as an optional feature. It is available on Windows 10 and 11 only -and [has some particular requirements in terms of CPU and memory](https://learn.microsoft.com/en-us/virtualization/hyper-v-on-windows/quick-start/enable-hyper-v#check-requirements). +Hyper-V is an optional feature of Windows Enterprise, Pro, or Education (not +Home). It is available on Windows 10 and 11 only and +[has some particular requirements in terms of CPU and memory](https://learn.microsoft.com/en-us/virtualization/hyper-v-on-windows/quick-start/enable-hyper-v#check-requirements). To enable it on a supported system, enter the following command: -``` +```pwsh Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All ``` -After running this command a restart of the Windows machine is required. +After running this command, a restart of the Windows machine is required. -:information_source: The VM provider used by podman (Hyper-V or WSL) can be configured in the file -`%APPDATA%/containers/containers.conf`. [More on that later](#configure-podman). +:information_source: Configure the VM provider used by podman (Hyper-V or WSL) +in the file `%PROGRAMDATA%/containers/containers.conf`. +[More on that later](#create-a-configuration-file-optional). -### Get the source code +## Get the source code Open a Windows Terminal and run the following command: -``` +```pwsh git config --global core.autocrlf false ``` -This configures git so that it does **not** automatically convert LF to CRLF. Files are expected to use the Unix LF rather -Windows CRLF in the Podman git repository. +It configures git so that it does **not** automatically convert LF to CRLF. In +the Podman git repository, files are expected to use Unix LF rather than Windows +CRLF. Then run the command to clone the Podman git repository: -``` +```pwsh git clone https://github.com/containers/podman ``` -This will create the folder `podman` in the current directory and clone the Podman git repository into it. +It creates the folder `podman` in the current directory and clones the Podman +git repository into it. -### Build the podman client for windows +### Allow local PowerShell scripts execution -The Podman client for Windows can be built with the PowerShell script [winmake.ps1](https://github.com/containers/podman/blob/main/winmake.ps1). +A developer can build the Podman client for Windows and the Windows installer +with the PowerShell script +[winmake.ps1](https://github.com/containers/podman/blob/main/winmake.ps1). -The ExecutionPolicy is set to `Restricted` on Windows computers by default: running scripts is not allowed. -The ExecutionPolicy on the machine can be determined with this command: +Windows sets the ExecutionPolicy to `Restricted` by default; running scripts is +prohibited. Determine the ExecutionPolicy on the machine with this command: -``` +```pwsh Get-ExecutionPolicy ``` -If the command returns `Restricted`, the ExecutionPolicy should be changed to `RemoteSigned`: +If the command returns `Restricted`, the ExecutionPolicy should be changed to +`RemoteSigned`: -``` +```pwsh Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser ``` -This policy allows the execution of local PowerShell scripts, such as `winmake.ps1`, for the current user: +This policy allows the execution of local PowerShell scripts, such as +`winmake.ps1`, for the current user. + +## Build and test the Podman client for Windows + +The following steps describe how to build the `podman.exe` binary from sources +and test it. + +### Build the Podman client +Open a PowerShell terminal and move to Podman local git repository directory: + +```pwsh +Set-Location .\podman ``` -# Get in the podman git repository directory -cd podman -# Build podman.exe +Build `podman.exe` + +``` .\winmake.ps1 podman-remote +``` -# Download gvproxy.exe and win-sshproxy.exe -# that are needed to execute the podman client -.\winmake.ps1 win-gvproxy +:information_source: Verify build's success by checking the content of the +`.\bin\windows` folder. Upon successful completion, the executable `podman.exe` +should be there: + +```pwsh +Get-ChildItem .\bin\windows\ + + + Directory: C:\Users\mario\Git\podman\bin\windows + + +Mode LastWriteTime Length Name +---- ------------- ------ ---- +-a---- 2/27/2024 11:59 AM 45408256 podman.exe ``` -:information_source: To verify that the build was completed successfully, check the content of the .\bin\windows` folder. -Upon successful completion three executables should be shown: +### Download gvproxy.exe and win-sshproxy.exe +[gvisor-tap-vsock](https://github.com/containers/gvisor-tap-vsock/) binaries +(`gvproxy-windowsgui.exe` and `win-sshproxy.exe`) are required to run the Podman +client on Windows. The executables are expected to be in the same folder as +`podman.exe`. The following command downloads the latest version in the +`.\bin\windows\` folder: + +```pwsh +.\winmake.ps1 win-gvproxy ``` -ls .\bin\windows\ + +:information_source: To verify that the binaries have been downloaded +successfully, check the content of the .\bin\windows` folder. + +```pwsh +Get-ChildItem .\bin\windows\ Directory: C:\Users\mario\Git\podman\bin\windows @@ -122,161 +226,249 @@ Mode LastWriteTime Length Name -a---- 2/29/2024 12:10 PM 4089856 win-sshproxy.exe ``` -### Configure podman +### Create a configuration file (optional) -Create a containers.conf file: +To test some particular configurations of Podman, create a `containers.conf` +file: ``` -mkdir $env:APPDATA\containers\ -New-Item -ItemType File $env:APPDATA\containers\containers.conf -notepad $env:APPDATA\containers\containers.conf +New-Item -ItemType Directory $env:PROGRAMDATA\containers\ +New-Item -ItemType File $env:PROGRAMDATA\containers\containers.conf +notepad $env:PROGRAMDATA\containers\containers.conf ``` -and add the following lines in it: +For example, to test with Hyper-V as the virtualization provider, use the +following content: ```toml [machine] -# Specify the provider -# Values can be "hyperv" or "wsl" provider="hyperv" -[engine] -# Specify the path of the helper binaries. -# NOTE: path should use slashes instead of anti-slashes -helper_binaries_dir=["C:/Users/mario/git/podman/bin/windows"] ``` -Create a policy.json file: - -``` -New-Item -ItemType File $env:APPDATA\containers\policy.json -notepad $env:APPDATA\containers\policy.json -```` - -and add the following lines in it: - -```json -{ - "default": [ - { - "type": "insecureAcceptAnything" - } - ], - "transports": { - "docker-daemon": { - "": [{ "type": "insecureAcceptAnything" }] - } - } -} -``` +Find the complete list of configuration options in the +[documentation](https://github.com/containers/common/blob/main/docs/containers.conf.5.md). ### Create and start a podman machine -Run a terminal **as an administrator** and execute the following commands to create a Podman machine: +Execute the following commands in a terminal to create a Podman machine: -``` +```pwsh .\bin\windows\podman.exe machine init ``` -When `machine init` completes run `machine start`: +When `machine init` completes, run `machine start`: -``` +```pwsh .\bin\windows\podman.exe machine start ``` +:information_source: If the virtualization provider is Hyperv-V, execute the +above commands in an administrator terminal. + ### Run a container using podman -The locally built Podman client for Windows can now be used to run containers: +Use the locally built Podman client for Windows to run containers: -``` +```pwsh .\bin\windows\podman.exe run hello-world ``` -:information_source: Unlike the previous machine commands, this one doesn't require administrative privileges. - -## Building the Podman client and installer with MSYS2 +To learn how to use the Podman client, refer to its +[tutorial](https://github.com/containers/podman/blob/main/docs/tutorials/remote_client.md). -### Install msys2 +## Build and test the Podman Windows installer -Podman requires brew -- a collection of Unix like build tools and libraries adapted for Windows. More details and -installation instructions are available from their [home page](https://www.msys2.org/). There are also premade GitHub -actions for this tool that are available. +The Podman Windows installer (e.g., `podman-5.1.0-dev-setup.exe`) is a bundle +that includes an msi package (`podman.msi`) and installs the WSL kernel +(`podman-wslkerninst.exe`). It's built using the +[WiX Toolset](https://wixtoolset.org/) and the +[PanelSwWixExtension](https://github.com/nirbar/PanelSwWixExtension/tree/wix3-v3.11.1.353) +WiX extension. The source code is in the folder `contrib\win-installer`. -### Install build dependencies +### Build the Windows installer -Podman requires some software from msys2 to be able to build. This can be done using msys2 shell. One can start it -from the Start menu. This documentation covers only usage of MSYS2 UCRT64 shell (msys2 shells come preconfigured for -different [environments](https://www.msys2.org/docs/environments/)). +To build the installation bundle, run the following command: -``` -$ pacman -S git make zip mingw-w64-ucrt-x86_64-gcc mingw-w64-ucrt-x86_64-go mingw-w64-ucrt-x86_64-python +```pwsh +.\winmake.ps1 installer ``` -The Pandoc tool installed in a prior step is specific, that is the installer doesn't add the tool to any PATH environment -variable known to msys2, so, it has to be linked explicitly to work. +:information_source: making `podman-remote`, `win-gvproxy`, and `docs` is +required before running this command. -``` -$ mkdir -p /usr/local/bin -$ ln -sf "/c/Program Files/Pandoc/pandoc.exe" "/usr/local/bin/pandoc.exe" -``` +Locate the installer in the `contrib\win-installer` folder (relative to checkout +root) with a name like `podman-5.2.0-dev-setup.exe`. -### Restart shell (important) +The `installer` target of `winmake.ps1` runs the script +`contrib\win-installer\build.ps1` that, in turns, executes: -One needs to restart the [msys2](https://www.msys2.org/) shell after dependency installation before proceeding with the build. +- `build-hooks.bat`: builds `podman-wslkerninst.exe` (WSL kernel installer) and + `podman-msihooks.dll` (helper that checks if WSL and Hyper-V are installed). +- `build-msi.bat`: builds `podman.msi` from the WiX source files `podman.wxs`, + `pages.wxs`, `podman-ui.wxs` and `welcome-install-dlg.wxs`. +- `build-burn.bat`: builds `podman-setup.exe` file from + [WiX Burn bundle](https://wixtoolset.org/docs/tools/burn/) `burn.wxs`. -### Obtain Podman source code +### Test the Windows installer -One can obtain the latest source code for Podman from its [GitHub](https://github.com/containers/podman) repository. +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 ``` -$ git clone https://github.com/containers/podman.git go/src/github.com/containers/podman + +It generates the files `podman-setup.log` and `podman-setup_000_Setup.log`, +which include 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 variables `MachineProvider` (`wsl` or `hyperv`), `WSLCheckbox` +(`1` to install WSL as part of the installation, `0` otherwise), and +`HyperVCheckbox` (`1` to install Hyper-V as part of the installation, `0` +otherwise): + +```pwsh +contrib\win-installer\podman-5.1.0-dev-setup.exe /install /log podman-setup.log /quiet MachineProvider=wsl WSLCheckbox=0 HyperVCheckbox=0 ``` -### Build client +### Build and test the standalone `podman.msi` file + +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 script `contrib\win-installer\build-msi.bat` to build the standalone +`podman.msi` file: -After completing the preparatory steps of obtaining the Podman source code and installing its dependencies, the client -can now be built. +```pwsh +Push-Location .\contrib\win-installer\ +.\build-msi.bat 9.9.9 +Pop-Location +``` + +It creates the file `.\contrib\win-installer\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\podman.msi /l*v podman-msi.log ``` -$ cd go/src/github.com/containers/podman -$ make clean podman-remote-release-windows_amd64.zip + +To run it in quiet, non-interactive mode, open the terminal **as an +administrator**, add the `/quiet` option, and set the MSI properties +`MACHINE_PROVIDER` (`wsl` or `hyperv`), `WITH_WSL` (`1` to install WSL as part +of the installation, `0` otherwise) and `WITH_HYPERV` (`1` to install Hyper-V as +part of the installation, `0` otherwise): + +```pwsh +msiexec /package contrib\win-installer\podman.msi /l*v podman-msi.log /quiet MACHINE_PROVIDER=wsl WITH_WSL=0 WITH_HYPERV=0 ``` -The complete distribution will be packaged to the `podman-remote-release-windows_amd64.zip` file. It is possible to -unzip it and replace files in the default Podman installation with the built ones to use the custom build. +:information_source: `podman.msi` GUI dialogs, defined in the file +`contrib\win-installer\podman-ui.wxs`, are distinct from the installation bundle +`podman-setup.exe` GUI dialogs, defined in +`contrib\win-installer\welcome-install-dlg.wxs`. -#### Build client only (for faster feedback loop) +### Verify the installation -Building Podman by following this documentation can take a fair amount of time and effort. Packaging the installer adds even more overhead. If -the only needed artifact is the Podman binary itself, it is possible to build only it with this command: +Inspect the msi installation log `podman-msi.log` (or +`podman-setup_000_Setup.log` if testing with the bundle) to verify that the +installation was successful: +```pwsh +Select-String -Path "podman-msi.log" -Pattern "Installation success or error status: 0" ``` -$ make podman-remote + +These commands too are helpful to check the installation: + +```pwsh +# Check the copy of the podman client in the Podman folder +Test-Path -Path "$ENV:PROGRAMFILES\RedHat\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 +$env:PATH | Select-String -Pattern "$ENV:PROGRAMFILES\RedHat\Podman" ``` -The binary will be located in `bin/windows/`. It could be used as drop in replacement for the installed version of -Podman. +:information_source: Podman CI uses script +`contrib\cirrus\win-installer-main.ps1`. Use it locally, too, to build and test +the installer. + +### Uninstall and clean-up -It is also possible to cross-build for other platforms by providing GOOS and GOARCH environment variables. +Podman can be uninstalled from the Windows Control Panel or running the +following command from a terminal **as an administrator**: -### Build client installer +```pwsh +contrib\win-installer\podman-5.1.0-dev-setup.exe /uninstall /quiet /log podman-setup-uninstall.log +``` -As Windows requires more effort in comparison to Unix systems for installation procedures, it is sometimes -easier to pack the changes into a ready-to-use installer. To create the installer, the full client distribution in ZIP -format has to be built beforehand. +The uninstaller does not delete some folders. Clean them up manually: +```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} ``` -$ export BUILD_PODMAN_VERSION=$(test/version/version | sed 's/-.*//') -$ mkdir -p contrib/win-installer/current -$ cp podman-remote-release-windows_amd64.zip contrib/win-installer/current/ -$ cd contrib/win-installer -$ powershell -ExecutionPolicy Bypass -File build.ps1 $BUILD_PODMAN_VERSION dev current + +The following commands are helpful to verify that the uninstallation was +successful: + +```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" +# Check that the uninstaller removed Podman resources +$foldersToCheck = @( + "$ENV:PROGRAMFILES\RedHat\Podman\podman.exe" + "HKLM:\SOFTWARE\Red Hat\Podman" + "$ENV:PROGRAMDATA\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} ``` -The installer will be located in the `contrib/win-installer` folder (relative to checkout root) and will have a name -like `podman-4.5.0-dev-setup.exe`. This could be installed in a similar manner as the official Podman for Windows installers -(when installing unsigned binaries is allowed on the host). +## Validate changes before submitting a PR -## Using the client +The script `winmake.ps1` has a couple of targets to check the source code +statically. GitHub Pull request checks execute the same statical analysis. It is +highly recommended that you run them locally before submitting a PR. -To learn how to use the Podman client, refer to its -[tutorial](https://github.com/containers/podman/blob/main/docs/tutorials/remote_client.md). +### winmake lint + +The `lint` target provides a fast validation target. It runs the following +tools: + +- `golangci-lint`: runs go-specific linters configured in + [`.golangci.yml`](.golangci.yml) +- `pre-commit`: runs more linters configured in + [`.pre-commit-config.yaml`](.pre-commit-config.yaml) + +:information_source: Install [golangci-lint](https://golangci-lint.run) and +[pre-commit](https://pre-commit.com) to run `winmake.ps1 lint`. + +### winmake validatepr + +Target `validatepr` performs a more exhaustive validation but takes +significantly more time to complete. It uses `podman` to run the target +`.validatepr` of the [Linux `Makefile`](Makefile). It builds Podman for Linux, +MacOS and Windows and then performs the same checks as the `lint` target plus +many more. + +:information_source: Create and start a Podman machine before running +`winmake.ps1 lint`. Configure the Podman machine with at least 4GB of memory: +`podman machine init -m 4096`. diff --git a/docs/make.bat b/docs/make.bat deleted file mode 100644 index 6247f7e231..0000000000 --- a/docs/make.bat +++ /dev/null @@ -1,35 +0,0 @@ -@ECHO OFF - -pushd %~dp0 - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build -) -set SOURCEDIR=source -set BUILDDIR=build - -if "%1" == "" goto help - -%SPHINXBUILD% >NUL 2>NUL -if errorlevel 9009 ( - echo. - echo.The 'sphinx-build' command was not found. Make sure you have Sphinx - echo.installed, then set the SPHINXBUILD environment variable to point - echo.to the full path of the 'sphinx-build' executable. Alternatively you - echo.may add the Sphinx directory to PATH. - echo. - echo.If you don't have Sphinx installed, grab it from - echo.http://sphinx-doc.org/ - exit /b 1 -) - -%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% -goto end - -:help -%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% - -:end -popd diff --git a/docs/make.ps1 b/docs/make.ps1 new file mode 100644 index 0000000000..27289aae7f --- /dev/null +++ b/docs/make.ps1 @@ -0,0 +1,147 @@ +function Get-Podman-Commands-List{ + param ( + [string]$podmanClient, + [string]$command + ); + if(!$podmanClient) { + $podmanClient="$PSScriptRoot\..\bin\windows\podman.exe" + } + if($command) { + $podmanHelpCommand="help $command" + Write-Host "Retrieving the list of ""podman $command"" subcommands." + } else { + $podmanHelpCommand="help" + Write-Host "Retrieving the list of ""podman"" commands." + } + + # Retrieve the list of subcommands of $command + # e.g. "podman help machine" returns the list of + # "podman machine" subcommands: info, init, etc... + $subCommands = @() + $subCommands = Invoke-Expression "$podmanClient $podmanHelpCommand" | + Select-String -Pattern "^\s*Available Commands:" -Context 0, 1000 | Out-String -Stream | + Select-String -Pattern "^\s+$" -Context 1000, 0 | Out-String -Stream | + Select-String -Pattern ">\s*Available Commands:|^>\s*$|^\s*$" -NotMatch | Out-String -Stream | + ForEach-Object { $_ -replace '^\s*(\w+)\s+.*$', '$1' } | Where-Object { $_ -ne "" } + + if ($command) { + $subCommands = $subCommands | ForEach-Object { "$command $_" } + } + + # Recursively get the list of sub-subcommands for each subcommand + foreach ($subCommand in $subCommands) { + + $subSubCommands = @() + $subSubCommands = Get-Podman-Commands-List -podmanClient "$podmanClient" -command "${subCommand}" + + if ($subSubCommands) { + $subCommands += $subSubCommands + } + } + + return $subCommands +} + +function Build-Podman-For-Windows-HTML-Page{ + $srcFolder = "$PSScriptRoot\tutorials" + $srcFile = "$srcFolder\podman-for-windows.md" + $destFolder = "$PSScriptRoot\build\remote" + $destFile = "$destFolder\podman-for-windows.html" + $cssFile = "$PSScriptRoot\standalone-styling.css" + $pandocOptions = "--ascii --from markdown-smart -c $cssFile --standalone " + + "--embed-resources --metadata title=""Podman for Windows"" " + + "-V title=" + + Write-Host -NoNewline "Generating $destFile from $srcFile..." + Push-Location $srcFolder + New-Item -ItemType Directory -Force -Path $destFolder | Out-Null + Invoke-Expression "pandoc $pandocOptions $srcFile > $destFile" + Pop-Location + Write-Host "done." +} + +function Build-Podman-Remote-HTML-Page{ + $markdownFolder = "$PSScriptRoot\source\markdown" + # Look for all podman-remote*.md files in the markdown folder + Get-ChildItem -Path "$markdownFolder" -Filter "podman-remote*.md" | ForEach-Object { + # Extract the command name from the file name + $command = $_.Name -replace '^podman-(.*).1.md$','$1' + # Generate the documentation HTML page + Build-Podman-Command-HTML-Page -command $command + } +} + +function Find-Podman-Command-Markdown-File{ + param ( + [string]$command + ); + # A podman command documentation can be in one of the following files + $markdownFolder = "$PSScriptRoot\source\markdown" + $srcFileMdIn = "$markdownFolder\podman-$command.1.md.in" + $srcFileMd = "$markdownFolder\podman-$command.1.md" + $linkFile = "$markdownFolder\links\podman-$command.1" + + if (Test-Path -Path $srcFileMdIn -PathType Leaf) { + return $srcFileMdIn + } elseif (Test-Path -Path $srcFileMd -PathType Leaf) { + return $srcFileMd + } elseif (Test-Path -Path $linkFile -PathType Leaf) { + # In $linkFile there is a link to a markdown file + $srcFile = Get-Content -Path $linkFile + # $srcFile is something like ".so man1/podman-attach.1" + # and the markdown file is "podman-attach.1.md" + $srcFile = $srcFile -replace ".so man1/", "" + $srcFileMdIn = "$markdownFolder\$srcFile.md.in" + $srcFileMd = "$markdownFolder\$srcFile.md" + if (Test-Path -Path "$srcFileMdIn" -PathType Leaf) { + return "$srcFileMdIn" + } elseif (Test-Path -Path $srcFileMd -PathType Leaf) { + return "$srcFileMd" + } + } + return $null +} + +function Build-Podman-Command-HTML-Page{ + param ( + [string]$command + ); + + $destFile = "$PSScriptRoot\build\remote\podman-$command.html" + $srcFile = Find-Podman-Command-Markdown-File -command $command + + if (!$srcFile) { + Write-Host "Couldn't find the documentation source file for $command. Skipping." + continue + } + + $pandocOptions = "--ascii --standalone --from markdown-smart " + + "--lua-filter=$PSScriptRoot\links-to-html.lua " + + "--lua-filter=$PSScriptRoot\use-pagetitle.lua" + + Write-Host -NoNewline "Generating $command documentation..." + Invoke-Expression "pandoc $pandocOptions -o $destFile $srcFile" | Out-Null + Write-Host "done." +} + +# Generate podman-for-windows.html +Build-Podman-For-Windows-HTML-Page + +# Generate podman-remote*.html +Build-Podman-Remote-HTML-Page + +# Get the list of podman commands on Windows +if ($args[1]) { + $commands = Get-Podman-Commands-List "-podmanClient $args[1]" +} +else { + $commands = Get-Podman-Commands-List +} + +# Generate podman commands documentation +foreach ($command in $commands) { + # Replace spaces with hyphens in the command name + # e.g. machine os apply becomes machine-os-apply + $command = $command -replace ' ', '-' + Build-Podman-Command-HTML-Page -command $command +} diff --git a/winmake.ps1 b/winmake.ps1 index 33d7306e3f..d1a61b8425 100644 --- a/winmake.ps1 +++ b/winmake.ps1 @@ -1,4 +1,6 @@ +#!/usr/bin/env powershell + . ./contrib/cirrus/win-lib.ps1 # Targets @@ -43,6 +45,114 @@ function Win-SSHProxy { curl.exe -sSL -o "./bin/windows/win-sshproxy.exe" --retry 5 "https://github.com/containers/gvisor-tap-vsock/releases/download/$Version/win-sshproxy.exe" } +function Installer{ + param ( + [string]$version, + [string]$suffix = "dev" + ); + Write-Host "Building the windows installer" + + # Check for the files to include in the installer + $requiredArtifacts = @( + "$PSScriptRoot\bin\windows\podman.exe" + "$PSScriptRoot\bin\windows\gvproxy.exe" + "$PSScriptRoot\bin\windows\win-sshproxy.exe" + "$PSScriptRoot\docs\build\remote\podman-for-windows.html" + ) + $requiredArtifacts | ForEach-Object { + if (!(Test-Path -Path $PSItem -PathType Leaf)) { + Write-Host "$PSItem not found." + Write-Host "Make 'podman', 'win-gvproxy' and 'docs' before making the installer:" + Write-Host " .\winmake.ps1 podman-remote" + Write-Host " .\winmake.ps1 win-gvproxy" + Write-Host " .\winmake.ps1 docs" + Exit 1 + } + } + + # Create the ZIP file with the full client distribution + $zipFileDest = "$PSScriptRoot\contrib\win-installer\current" + Build-Distribution-Zip-File -destinationPath $zipFileDest + + if (-Not $version) { + # Get Podman version from local source code + $version = Get-Podman-Version + } + + # Run \contrib\win-installer\build.ps1 + Push-Location $PSScriptRoot\contrib\win-installer + Run-Command ".\build.ps1 $version $suffix `"$zipFileDest`"" + Pop-Location +} + +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." + Exit 1 + } + # Check that the podman client is built + $podmanClient = "$PSScriptRoot\bin\windows\podman.exe" + if (!(Test-Path -Path $podmanClient -PathType Leaf)) { + Write-Host "$podmanClient not found. Make 'podman-remote' before 'documentation'." + Exit 1 + } + Run-Command "$PSScriptRoot\docs\make.ps1 $podmanClient" +} + +function Validate{ + $podmanExecutable = "podman" + $podmanSrcVolumeMount = "${PSScriptRoot}:/go/src/github.com/containers/podman" + # All files bind mounted from a Windows host are marked as executable. + # That makes the pre-commit hook "check-executables-have-shebangs" fail. + # Setting the environment variable "SKIP=check-executables-have-shebangs" + # allow to skip that pre-commit hook. + $podmanEnvVariable = "-e SKIP=check-executables-have-shebangs" + $podmanRunArgs = "--rm -v $podmanSrcVolumeMount --security-opt label=disable -t -w /go/src/github.com/containers/podman $podmanEnvVariable" + $validateImage = "quay.io/libpod/validatepr:latest" + $validateCommand = "make .validatepr" + + # Check that podman is installed + if (!(Get-Command -Name $podmanExecutable -ErrorAction SilentlyContinue)) { + Write-Host "$podmanExecutable not found. $podmanExecutable is required to run the validate script." + Exit 1 + } + + # Check that a podman machine exist + $currentMachine = (podman machine info -f json | ConvertFrom-Json).Host.CurrentMachine + if (!$currentMachine) { + Write-Host "Podman machine doesn't exist. Initialize and start one before running the validate script." + Exit 1 + } + + # Check that the podman machine is running + $state = (podman machine info -f json | ConvertFrom-Json).Host.MachineState + if ($state -ne "Running") { + Write-Host "Podman machine is not running. Start the machine before running the validate script." + Exit 1 + } + + Run-Command "$podmanExecutable run $podmanRunArgs $validateImage $validateCommand" +} + +function Lint{ + # Check that golangci-lint is installed + if (!(Get-Command -Name "golangci-lint" -ErrorAction SilentlyContinue)) { + Write-Host "The tool ""golangci-lint"" not found. Install https://golangci-lint.run/ before running the lint script." + Exit 1 + } + + # Check that pre-commit is installed + if (!(Get-Command -Name "pre-commit" -ErrorAction SilentlyContinue)) { + Write-Host "The tool ""pre-commit"" not found. Install https://pre-commit.com/ before running the lint script." + Exit 1 + } + + Run-Command "golangci-lint run --timeout=10m --build-tags=`"$remotetags`" $PSScriptRoot\cmd\podman" + Run-Command "pre-commit run --all-files" +} + # Helpers function Build-Ginkgo{ if (Test-Path -Path ./test/tools/build/ginkgo.exe -PathType Leaf) { @@ -69,6 +179,49 @@ function Git-Commit{ return $commit } +function Build-Distribution-Zip-File{ + param ( + [string]$destinationPath + ); + $binariesFolder = "$PSScriptRoot\bin\windows" + $documentationFolder = "$PSScriptRoot\docs\build\remote\" + $zipFile = "$destinationPath\podman-remote-release-windows_amd64.zip" + + # Create a temporary folder to store the distribution files + $tempFolder = New-Item -ItemType Directory -Force -Path "$env:TEMP\podman-windows" + + # Copy bin\windows\ content to the temporary folder + Copy-Item -Recurse -Force -Path "$binariesFolder\*" -Destination "$tempFolder\" + + # Copy docs\build\remote to the temporary folder + Copy-Item -Recurse -Force -Path "$documentationFolder" -Destination "$tempFolder\docs\" + + # If $destination path doesn't exist, create it + if (-Not (Test-Path -Path $destinationPath -PathType Container)) { + New-Item -ItemType Directory -Force -Path $destinationPath + } + + # Create the ZIP file with the full client distribution + Compress-Archive -Path "$tempFolder\*" -DestinationPath $zipFile -Force + + # Delete the temporary folder + Remove-Item -Recurse -Force -Path "$tempFolder" +} + +function Get-Podman-Version{ + $versionSrc = "$PSScriptRoot\test\version\" + $versionBin = "$PSScriptRoot\test\version\version.exe" + + # If version.exe doesn't exist, build it + if (-Not (Test-Path -Path "$versionBin" -PathType Leaf)) { + Run-Command "go build --o `"$versionBin`" `"$versionSrc`"" + } + $version = Invoke-Expression "$versionBin" + # Remove the '-dev' suffix from the version + $version = $version -replace "-.*", "" + return $version +} + # Init script $target = $args[0] @@ -93,6 +246,18 @@ switch ($target) { } Win-SSHProxy -Ref $ref } + 'installer' { + Installer + } + 'docs' { + Documentation + } + 'validatepr' { + Validate + } + 'lint' { + Lint + } default { Write-Host "Usage: " $MyInvocation.MyCommand.Name " [options]" Write-Host @@ -107,5 +272,17 @@ switch ($target) { Write-Host Write-Host "Example: Download win-gvproxy and win-sshproxy helpers" Write-Host " .\winmake win-gvproxy" + Write-Host + Write-Host "Example: Build the windows installer" + Write-Host " .\winmake installer" + Write-Host + Write-Host "Example: Generate the documetation artifacts" + Write-Host " .\winmake docs" + Write-Host + Write-Host "Example: Validate code changes before submitting a PR" + Write-Host " .\winmake validatepr" + Write-Host + Write-Host "Example: Run linters" + Write-Host " .\winmake lint" } }