Skip to content

fix(ci): install kind directly on Windows to avoid docker-desktop dep#261

Merged
skevetter merged 12 commits into
mainfrom
4896-ws-ci-kind-fix
May 8, 2026
Merged

fix(ci): install kind directly on Windows to avoid docker-desktop dep#261
skevetter merged 12 commits into
mainfrom
4896-ws-ci-kind-fix

Conversation

@skevetter

@skevetter skevetter commented May 7, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Replaces choco install kind with a direct binary download from kind.sigs.k8s.io on Windows CI runners
  • Chocolatey's kind package pulls docker-desktop as a dependency, which hangs on Windows runners since we only need podman (KIND_EXPERIMENTAL_PROVIDER: podman)
  • Keeps choco install podman-cli -y unchanged; only the kind installation method changes

Summary by CodeRabbit

  • Chores
    • Windows CI now installs Podman via a verified MSI, ensures WSL2 is enabled, and initializes a Podman machine.
    • Windows CI now downloads and verifies the kind binary, updates PATH, and creates kind clusters using generated identifiers.

Chocolatey's `kind` package pulls `docker-desktop` as a dependency,
which hangs on Windows CI runners. Since we use podman as the kind
provider, docker-desktop is not needed. Download the kind binary
directly from GitHub releases instead.
@coderabbitai

coderabbitai Bot commented May 7, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR updates the Windows CI workflow: Podman is installed from a pinned MSI with SHA256 verification, WSL2 is set and a rootful Podman machine initialized; the Windows kind step now downloads a pinned kind.exe, verifies its checksum, generates a cluster UUID inline, and creates the cluster using the pinned node image digest.

Changes

Windows Kubernetes Setup via Podman and kind

Layer / File(s) Summary
Podman MSI Installation
.github/workflows/pr-ci.yml
Downloads and verifies a pinned Podman MSI, performs a silent install with logging, validates podman.exe, adds install dir to GITHUB_PATH, sets WSL default to v2, and initializes/starts a rootful Podman machine.
Kind Cluster Setup
.github/workflows/pr-ci.yml
Downloads and checksum-verifies kind.exe, updates PATH/GITHUB_PATH, generates a cluster UUID during the step, and creates the kind cluster with the pinned node image digest.

Sequence Diagram(s)

sequenceDiagram
  participant GHA as GitHub Actions
  participant MSI as Podman MSI
  participant FS as FileSystem
  participant WSL as WSL2
  participant KindBin as kind.exe
  participant Podman as Podman
  participant Cluster as Kind Cluster

  GHA->>MSI: Download pinned Podman MSI
  GHA->>MSI: Verify MSI SHA256
  MSI->>FS: msiexec install (silent, log)
  GHA->>FS: Verify podman.exe exists (or dump log/search)
  GHA->>WSL: Set default version to 2
  GHA->>Podman: podman machine init --rootful && podman machine start

  GHA->>KindBin: Download pinned kind.exe and checksum
  GHA->>KindBin: Verify kind SHA256
  GHA->>GHA: Generate cluster UUID
  GHA->>KindBin: kind create cluster --name UUID --image pinned-digest
  KindBin->>Podman: Request node containers
  Podman->>Cluster: Start node containers
  Cluster->>GHA: Cluster ready
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix(ci): install kind directly on Windows to avoid docker-desktop dep' directly and clearly summarizes the main change: replacing Chocolatey-based kind installation with direct binary download on Windows CI to eliminate the unnecessary Docker Desktop dependency.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@netlify

netlify Bot commented May 7, 2026

Copy link
Copy Markdown

Deploy Preview for devsydev canceled.

Name Link
🔨 Latest commit 5b15df4
🔍 Latest deploy log https://app.netlify.com/projects/devsydev/deploys/69fd11c3aa4dcc00087c477b

Replace `choco install podman-cli` with a direct download of the podman
MSI installer from GitHub releases. This eliminates all Chocolatey
dependencies from the Windows CI steps, matching the direct-download
approach already used for kind.
@github-actions github-actions Bot added size/s and removed size/xs labels May 7, 2026
skevetter added 5 commits May 7, 2026 11:15
… URL

The kind download was failing because:
1. curl tried to write directly to C:\Program Files\RedHat\Podman\kind.exe
   before the MSI had created that directory
2. The kind.sigs.k8s.io redirect URL returned a 99-byte HTML page instead
   of following through to the binary

Fix by downloading to RUNNER_TEMP first (always exists) then moving, and
using the direct GitHub releases URL which doesn't have redirect issues.
…ndows

The podman MSI may not create the install directory synchronously before
the next shell command runs, causing `mv kind.exe` to fail with "No such
file or directory". Place kind.exe in RUNNER_TEMP instead and add it to
PATH independently. Also generate the cluster UUID inline since the
uuid step is skipped on Windows runners.
…or WSL test

The podman MSI install via bash was silently failing because
Start-Process didn't properly wait. Split the approach:
- provider test: use pre-installed Docker (no podman needed)
- up-docker-wsl test: install podman via PowerShell with proper
  wait/error handling, then start podman machine in a separate step
- Only set DOCKER_HOST to podman pipe for the up-docker-wsl test
Windows Docker is in Windows-container mode and cannot pull Linux
images like kindest/node. All Windows kind tests need podman for its
Linux VM (via WSL2). Replace the failing manual MSI install with the
redhat-actions/podman-install action which handles this reliably.
The redhat-actions/podman-install action has no v1 tag. Revert to MSI
approach with explicit INSTALLDIR parameter, verbose MSI logging for
diagnostics, and full path to podman.exe to avoid PATH race conditions.
@skevetter
skevetter marked this pull request as ready for review May 7, 2026 19:42

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/pr-ci.yml:
- Around line 401-403: The workflow downloads Podman (variables $msiUrl and
$msiPath) and kind without verifying integrity; update the steps that use
Invoke-WebRequest to also fetch the corresponding official SHA256 checksum files
for Podman and kind, compute the downloaded file's SHA256 (e.g., using
Get-FileHash) and compare against the published checksum before running msiexec
or executing the kind binary; if the hash verification fails, fail the job and
emit a clear error via Write-Error, otherwise proceed to installation. Include
the same verification for the other download steps referenced (the kind download
around lines 431-432) and ensure the checksum source uses the official release
asset URL.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 96c5e87b-0283-4985-b760-4d0f46686cc8

📥 Commits

Reviewing files that changed from the base of the PR and between a54d9ff and 0ae2e91.

📒 Files selected for processing (1)
  • .github/workflows/pr-ci.yml

Comment thread .github/workflows/pr-ci.yml
Verify integrity of downloaded binaries before execution to harden
against supply-chain attacks on Windows CI runners.
@github-actions github-actions Bot added size/m and removed size/s labels May 7, 2026
The Invoke-WebRequest of the shasums file returned binary content on
Windows PowerShell, causing the hash extraction regex to produce an
empty string. Pin the known hash directly instead.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
.github/workflows/pr-ci.yml (1)

437-452: ⚡ Quick win

Make the bash setup fail-fast and detect HTTP errors.

Two robustness gaps in this step:

  • No set -euo pipefail: intermediate failures (curl, sha256sum, awk, python) won't abort the step, leading to confusing downstream errors (e.g., kind create cluster running with an empty CLUSTER_NAME).
  • curl -Lo does not check HTTP status. If the release URL ever 404s or is redirected to an error page, an HTML/error body is silently written to kind.exe (the SHA check would catch this, but --fail/-f produces a cleaner failure mode and ensures $RUNNER_TEMP/kind.sha256sum parsing isn't done on garbage).
♻️ Proposed change
         run: |
+          set -euo pipefail
-          curl -Lo "$RUNNER_TEMP/kind.exe" "https://github.com/kubernetes-sigs/kind/releases/download/v0.24.0/kind-windows-amd64"
-          curl -Lo "$RUNNER_TEMP/kind.sha256sum" "https://github.com/kubernetes-sigs/kind/releases/download/v0.24.0/kind-windows-amd64.sha256sum"
+          curl -fLo "$RUNNER_TEMP/kind.exe" "https://github.com/kubernetes-sigs/kind/releases/download/v0.24.0/kind-windows-amd64"
+          curl -fLo "$RUNNER_TEMP/kind.sha256sum" "https://github.com/kubernetes-sigs/kind/releases/download/v0.24.0/kind-windows-amd64.sha256sum"
           expected=$(awk '{print $1}' "$RUNNER_TEMP/kind.sha256sum")
           actual=$(sha256sum "$RUNNER_TEMP/kind.exe" | awk '{print $1}')
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/pr-ci.yml around lines 437 - 452, Add fail-fast and
HTTP-error detection to the bash run block: enable strict mode by adding set
-euo pipefail at the start of the script, change the curl invocations that
download "$RUNNER_TEMP/kind.exe" and "$RUNNER_TEMP/kind.sha256sum" to use the
--fail (or -f) flag so HTTP errors cause curl to exit non‑zero, and keep the
existing sha256sum verification and CLUSTER_NAME generation (python ... uuid)
before invoking kind create cluster --name "$CLUSTER_NAME"; reference the
RUNNER_TEMP, curl, sha256sum, CLUSTER_NAME and kind create cluster symbols when
making these edits.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/pr-ci.yml:
- Around line 414-430: The PowerShell step currently prints $proc.ExitCode and
relies on Test-Path to catch an MSI failure and does not abort on failures from
native commands (msiexec, wsl, podman), so change the step to check and fail on
non-zero exit codes: after the msiexec Start-Process block inspect
$proc.ExitCode and throw/exit if non-zero (instead of only logging), and after
each native invocation (wsl --set-default-version, & "$installDir\podman.exe"
machine init, set --rootful, start) check $LASTEXITCODE and fail immediately
with a clear message; optionally factor this into a small helper function (e.g.,
Assert-LastExitCode or Invoke-And-EnsureSuccess) to run the command and abort on
failure to keep the script DRY.
- Around line 429-430: The CI workflow sets DOCKER_HOST to the old
podman-machine named pipe; update the DOCKER_HOST variable in the workflow (the
DOCKER_HOST assignment) to point to Podman 5.x rootful Windows pipe
"npipe:////./pipe/docker_engine" instead of
"npipe:////./pipe/podman-machine-default" so Windows e2e tests connect to the
Podman daemon without Docker Desktop.

---

Nitpick comments:
In @.github/workflows/pr-ci.yml:
- Around line 437-452: Add fail-fast and HTTP-error detection to the bash run
block: enable strict mode by adding set -euo pipefail at the start of the
script, change the curl invocations that download "$RUNNER_TEMP/kind.exe" and
"$RUNNER_TEMP/kind.sha256sum" to use the --fail (or -f) flag so HTTP errors
cause curl to exit non‑zero, and keep the existing sha256sum verification and
CLUSTER_NAME generation (python ... uuid) before invoking kind create cluster
--name "$CLUSTER_NAME"; reference the RUNNER_TEMP, curl, sha256sum, CLUSTER_NAME
and kind create cluster symbols when making these edits.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: cb0b0f82-bab9-49eb-bdab-e6d5b8a5ffe0

📥 Commits

Reviewing files that changed from the base of the PR and between 0ae2e91 and 0b13136.

📒 Files selected for processing (1)
  • .github/workflows/pr-ci.yml

Comment on lines +414 to +430
$proc = Start-Process msiexec.exe -Wait -PassThru -ArgumentList "/i `"$msiPath`" /qn /norestart /l*v `"$logFile`" INSTALLDIR=`"$installDir`""
Write-Host "MSI exit code: $($proc.ExitCode)"

if (!(Test-Path "$installDir\podman.exe")) {
Write-Host "--- MSI install log (last 50 lines) ---"
Get-Content $logFile -Tail 50
Write-Host "--- Searching for podman.exe ---"
Get-ChildItem "C:\" -Filter "podman.exe" -Recurse -Depth 4 -ErrorAction SilentlyContinue | ForEach-Object { Write-Host $_.FullName }
throw "podman.exe not found at $installDir"
}

echo "$installDir" | Out-File -Append -FilePath $env:GITHUB_PATH -Encoding utf8

wsl --set-default-version 2
& "$installDir\podman.exe" machine init
& "$installDir\podman.exe" machine set --rootful
& "$installDir\podman.exe" machine start

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Native command failures don't fail this step in PowerShell.

By default, PowerShell does not propagate non-zero exit codes from native executables (msiexec, wsl, podman) into terminating errors, and $ErrorActionPreference = 'Stop' does not cover them either. As a result:

  • Line 414: $proc.ExitCode is only printed; an MSI failure (e.g., 1603/1618) is recovered only because Test-Path happens to catch missing podman.exe.
  • Lines 427–430: wsl --set-default-version 2, podman machine init, podman machine set --rootful, and podman machine start can all fail silently, leaving subsequent CI steps to fail with confusing downstream errors.

Check $LASTEXITCODE after each native invocation (or wrap in a small helper) so failures abort the job with a clear cause.

🛠️ Suggested hardening
           $proc = Start-Process msiexec.exe -Wait -PassThru -ArgumentList "/i `"$msiPath`" /qn /norestart /l*v `"$logFile`" INSTALLDIR=`"$installDir`""
           Write-Host "MSI exit code: $($proc.ExitCode)"
+          if ($proc.ExitCode -ne 0) {
+            Get-Content $logFile -Tail 100
+            throw "Podman MSI install failed with exit code $($proc.ExitCode)"
+          }

           if (!(Test-Path "$installDir\podman.exe")) {
             ...
           }

           echo "$installDir" | Out-File -Append -FilePath $env:GITHUB_PATH -Encoding utf8

-          wsl --set-default-version 2
-          & "$installDir\podman.exe" machine init
-          & "$installDir\podman.exe" machine set --rootful
-          & "$installDir\podman.exe" machine start
+          function Invoke-Native {
+            param([string]$Description, [scriptblock]$Cmd)
+            & $Cmd
+            if ($LASTEXITCODE -ne 0) { throw "$Description failed with exit code $LASTEXITCODE" }
+          }
+          Invoke-Native "wsl --set-default-version 2" { wsl --set-default-version 2 }
+          Invoke-Native "podman machine init"        { & "$installDir\podman.exe" machine init }
+          Invoke-Native "podman machine set --rootful" { & "$installDir\podman.exe" machine set --rootful }
+          Invoke-Native "podman machine start"       { & "$installDir\podman.exe" machine start }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/pr-ci.yml around lines 414 - 430, The PowerShell step
currently prints $proc.ExitCode and relies on Test-Path to catch an MSI failure
and does not abort on failures from native commands (msiexec, wsl, podman), so
change the step to check and fail on non-zero exit codes: after the msiexec
Start-Process block inspect $proc.ExitCode and throw/exit if non-zero (instead
of only logging), and after each native invocation (wsl --set-default-version, &
"$installDir\podman.exe" machine init, set --rootful, start) check $LASTEXITCODE
and fail immediately with a clear message; optionally factor this into a small
helper function (e.g., Assert-LastExitCode or Invoke-And-EnsureSuccess) to run
the command and abort on failure to keep the script DRY.

Comment thread .github/workflows/pr-ci.yml
skevetter added 3 commits May 7, 2026 16:32
Podman 5.x in rootful mode exposes the API on \\.\pipe\docker_engine,
not \\.\pipe\podman-machine-default. Update DOCKER_HOST in both the
kind setup step and the test runner step.
On Windows Git Bash, sha256sum outputs a leading backslash when the
file path contains backslashes. Strip it with awk gsub. Also pin the
kind hash directly and set DOCKER_HOST to the pipe podman actually uses.
The awk gsub approach didn't strip the backslash due to YAML escaping
complexity. Use sed with a character class to strip any non-hex prefix.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (2)
.github/workflows/pr-ci.yml (2)

414-415: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fail fast on native command errors in the Windows Podman setup step.

This block still allows msiexec, wsl, and podman machine failures to continue without an immediate hard fail, which can mask the root cause.

Suggested fix
           $proc = Start-Process msiexec.exe -Wait -PassThru -ArgumentList "/i `"$msiPath`" /qn /norestart /l*v `"$logFile`" INSTALLDIR=`"$installDir`""
           Write-Host "MSI exit code: $($proc.ExitCode)"
+          if ($proc.ExitCode -ne 0) {
+            Write-Host "--- MSI install log (last 50 lines) ---"
+            Get-Content $logFile -Tail 50
+            throw "Podman MSI install failed with exit code $($proc.ExitCode)"
+          }
+
+          function Assert-LastExitCode([string]$description) {
+            if ($LASTEXITCODE -ne 0) {
+              throw "$description failed with exit code $LASTEXITCODE"
+            }
+          }
...
-          wsl --set-default-version 2
-          & "$installDir\podman.exe" machine init
-          & "$installDir\podman.exe" machine set --rootful
-          & "$installDir\podman.exe" machine start
+          wsl --set-default-version 2
+          Assert-LastExitCode "wsl --set-default-version 2"
+          & "$installDir\podman.exe" machine init
+          Assert-LastExitCode "podman machine init"
+          & "$installDir\podman.exe" machine set --rootful
+          Assert-LastExitCode "podman machine set --rootful"
+          & "$installDir\podman.exe" machine start
+          Assert-LastExitCode "podman machine start"

Also applies to: 427-430

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/pr-ci.yml around lines 414 - 415, The PowerShell block
uses Start-Process msiexec.exe and then writes the exit code but doesn't fail
the job on non-zero exits; modify the msiexec invocation (Start-Process
msiexec.exe) to check $proc.ExitCode immediately after execution and if non-zero
call throw or exit with that code so the workflow fails fast; apply the same
pattern to the wsl and podman machine commands referenced in the nearby steps
(check their process exit codes and raise/exit on failure) so errors cannot be
silently ignored.

437-437: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Use the Podman 5.x rootful pipe for DOCKER_HOST on Windows.

podman-machine-default is inconsistent with the rootful setup in this workflow; both Windows DOCKER_HOST assignments should point to docker_engine.

Suggested fix
-          DOCKER_HOST: npipe:////./pipe/podman-machine-default
+          DOCKER_HOST: npipe:////./pipe/docker_engine
...
-              DOCKER_HOST="npipe:////./pipe/podman-machine-default" \
+              DOCKER_HOST="npipe:////./pipe/docker_engine" \

Also applies to: 506-506

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/pr-ci.yml at line 437, Update the Windows DOCKER_HOST
environment assignment to use the Podman 5.x rootful pipe name "docker_engine"
instead of "podman-machine-default"; replace the value
npipe:////./pipe/podman-machine-default with npipe:////./pipe/docker_engine for
the DOCKER_HOST entries so both Windows assignments consistently point to
docker_engine in the workflow YAML.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In @.github/workflows/pr-ci.yml:
- Around line 414-415: The PowerShell block uses Start-Process msiexec.exe and
then writes the exit code but doesn't fail the job on non-zero exits; modify the
msiexec invocation (Start-Process msiexec.exe) to check $proc.ExitCode
immediately after execution and if non-zero call throw or exit with that code so
the workflow fails fast; apply the same pattern to the wsl and podman machine
commands referenced in the nearby steps (check their process exit codes and
raise/exit on failure) so errors cannot be silently ignored.
- Line 437: Update the Windows DOCKER_HOST environment assignment to use the
Podman 5.x rootful pipe name "docker_engine" instead of
"podman-machine-default"; replace the value
npipe:////./pipe/podman-machine-default with npipe:////./pipe/docker_engine for
the DOCKER_HOST entries so both Windows assignments consistently point to
docker_engine in the workflow YAML.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 51a4c6cd-d63e-4c79-b747-210f07f92a90

📥 Commits

Reviewing files that changed from the base of the PR and between 0b13136 and 5b15df4.

📒 Files selected for processing (1)
  • .github/workflows/pr-ci.yml

@skevetter

Copy link
Copy Markdown
Contributor Author

CI Fixed ✓

All 44 jobs now passing. Three commits added on top of the checksum verification commit:

  1. 0b13136 — Pin podman MSI SHA256 hash directly instead of fetching the shasums file at runtime (PowerShell's Invoke-WebRequest returned the shasums as binary content, causing the hash regex to produce an empty string)

  2. b6317bd — Pin kind SHA256 hash directly, add DOCKER_HOST env to kind setup step, and attempt to strip leading backslash from sha256sum output via awk

  3. 5b15df4 — Use sed 's/^[^a-f0-9]*//' to reliably strip the leading \ that sha256sum on Windows Git Bash outputs when file paths contain backslashes

Also reverted the DOCKER_HOST pipe name back to podman-machine-default — the runner logs confirmed that's the pipe Podman actually listens on (Docker Desktop occupies docker_engine).

@skevetter
skevetter merged commit e06bcf5 into main May 8, 2026
54 checks passed
@skevetter
skevetter deleted the 4896-ws-ci-kind-fix branch May 8, 2026 02:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant