Files
PSProxmoxVE/tests/Dockerfile.test
T
goodolclint-claude[bot] fc073e7e2a ci: pin Pester by exact version everywhere it is installed or imported
Pester was installed with -MinimumVersion 5.0 and no ceiling in the CI job
image, both install steps in unit-tests.yml, and both Import-Module calls, plus
the suite's own import inside the container. The image is rebuilt on every CI
run and Pester is installed fresh on every unit-test run, so PSGallery chose the
version — a new major could reach the required PR checks with no commit here,
surfacing as unexplained test breakage on whichever PR ran next.

It had already happened. Steps named "Install Pester 5" were resolving 6.1.0 on
both legs, because Pester 6 declares PowerShellVersion 5.1 and so installs on
Windows PowerShell too. Nothing broke — the suite uses only constructs common to
5 and 6, and runs 1566/0 under 6.1.0 with no deprecation warnings — but nobody
chose it. The step names are corrected; they had been describing an install that
stopped happening some time ago.

Pinning the install alone is not enough, in two ways review found:

An unset variable does not fail. -RequiredVersion accepts an empty value and
degrades to "latest" for Install-Module and to "any" for Import-Module, both
exiting 0, so a renamed or dropped env key would silently restore the float this
commit removes. A guard step now fails the job instead.

The point of use was still floored. run-integration.sh imported the suite's
Pester with -MinimumVersion 5.0, so a second Pester reaching PSModulePath would
win regardless of what was installed. The Dockerfile now promotes the ARG to ENV
so the version is discoverable at runtime, and that import is pinned to it.

The pin lives in two files, so shell-selfchecks asserts they agree — split-brain
between the workflow and the image is precisely the unexplained breakage this is
meant to prevent. CONTRIBUTING.md and CLAUDE.md are updated too; the contributor
instructions were a third floating install site.

Recorded as an amendment to D017 — the same principle as the nested PVE package
pin, applied to the lane's own tooling.
2026-09-01 18:08:02 -05:00

76 lines
3.7 KiB
Docker

# PSProxmoxVE development and integration testing container
#
# Two targets:
# dev - .NET SDK + PowerShell + Pester (build & test, works on ARM/x86)
# dev-infra - Adds Terraform + PVE provisioning tools (x86 only)
#
# Usage:
# # For build + test (works on Mac M-series):
# docker compose -f tests/docker-compose.test.yml up -d
#
# # For full CI flow including provisioning (x86 only):
# docker compose -f tests/docker-compose.test.yml --profile infra up -d
# ── Base: .NET SDK + PowerShell + Pester ────────────────────────────
FROM mcr.microsoft.com/dotnet/sdk:10.0-noble AS dev
ENV DEBIAN_FRONTEND=noninteractive
# Install base packages
RUN apt-get update && apt-get install -y --no-install-recommends \
curl jq openssh-client ca-certificates apt-transport-https gnupg \
&& rm -rf /var/lib/apt/lists/*
# Install PowerShell: APT package on amd64, dotnet global tool on arm64.
# The Microsoft APT repo does not publish arm64 packages for PowerShell.
RUN if [ "$(dpkg --print-architecture)" = "amd64" ]; then \
curl -fsSL https://packages.microsoft.com/keys/microsoft.asc \
| gpg --dearmor -o /usr/share/keyrings/microsoft-archive-keyring.gpg \
&& echo "deb [arch=amd64 signed-by=/usr/share/keyrings/microsoft-archive-keyring.gpg] \
https://packages.microsoft.com/ubuntu/24.04/prod noble main" \
> /etc/apt/sources.list.d/microsoft-prod.list \
&& apt-get update && apt-get install -y --no-install-recommends powershell \
&& rm -rf /var/lib/apt/lists/*; \
else \
dotnet tool install --global PowerShell \
&& ln -s /root/.dotnet/tools/pwsh /usr/local/bin/pwsh; \
fi
# Install Pester and prepare module directory.
# Pinned, not floored: this image is rebuilt on every CI run, so a version range
# lets a new Pester major reach the gating lane with no commit to this repo.
# Bump deliberately, the way D017 treats the nested PVE package set.
ARG PESTER_VERSION=6.1.0
RUN pwsh -NoProfile -Command \
"Set-PSRepository -Name PSGallery -InstallationPolicy Trusted; \
Install-Module -Name Pester -RequiredVersion $PESTER_VERSION -Scope AllUsers -Force" \
&& pwsh -NoProfile -Command \
"if (-not (Get-Module -ListAvailable Pester | Where-Object Version -eq '$PESTER_VERSION')) { throw 'Pester $PESTER_VERSION not installed' }" \
&& mkdir -p /usr/local/share/powershell/Modules/PSProxmoxVE
# Promoted to ENV so the suite can pin its import too — the install pin alone
# does not bind the point of use if a second Pester ever reaches PSModulePath.
ENV PESTER_VERSION=$PESTER_VERSION
WORKDIR /repo
CMD ["pwsh", "-NoProfile"]
# ── Full: adds Terraform + PVE provisioning tools (x86 only) ───────
FROM dev AS dev-infra
RUN apt-get update && apt-get install -y --no-install-recommends \
dosfstools mtools sshpass python3 xorriso gnupg \
&& curl -fsSL https://apt.releases.hashicorp.com/gpg \
| gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg \
&& echo "deb [arch=amd64 signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] \
https://apt.releases.hashicorp.com noble main" \
> /etc/apt/sources.list.d/hashicorp.list \
&& curl -fsSL https://enterprise.proxmox.com/debian/proxmox-release-bookworm.gpg \
-o /usr/share/keyrings/proxmox-release-bookworm.gpg \
&& echo "deb [signed-by=/usr/share/keyrings/proxmox-release-bookworm.gpg] \
http://download.proxmox.com/debian/pve bookworm pve-no-subscription" \
> /etc/apt/sources.list.d/proxmox-pve.list \
&& apt-get update && apt-get install -y --no-install-recommends \
terraform proxmox-auto-install-assistant qemu-utils \
&& rm -rf /var/lib/apt/lists/*