- Fix storage_ip derivation to use default route first, not Swarm RemoteManagers
- Make iSCSI container entrypoint idempotent (check before create for target/LUN/bind)
- Pin erichough/nfs-server from 'latest' to '2.2.1' for reproducibility
- Replace curl|sh Docker install with apt repo in Dockerfile.test
- Add docker.sock security warnings in docker-compose.test.yml and CI workflow
- Update stale 'storage VM' references in comments and .env.test.example"
Co-authored-by: GoodOlClint <151449+GoodOlClint@users.noreply.github.com>
Agent-Logs-Url: https://github.com/GoodOlClint/PSProxmoxVE/sessions/534c0a63-2988-496c-b0ae-e291fcfa050b
Provision two PVE nodes per version (a/b) for future cluster testing,
plus Docker-based iSCSI target and NFS server for shared storage tests.
Multi-node changes:
- Each PVE version gets two nodes: 9a/9b and 8a/8b (4 VMs total)
- Parameterized answer.toml FQDN for unique hostnames per node
- Per-node auto-install ISOs with unique answer files
- Node name discovered from FQDN and included in test config
- API token creation handles pre-existing tokens (delete + recreate)
- New test env vars: PVETEST_HOST_B, PVETEST_APITOKEN_B
- Removed preflight cleanup from provision (use explicit cleanup instead)
Docker storage services:
- New docker-compose.storage.yml with iSCSI (tgt) and NFS containers
- Host networking so PVE nodes can reach storage services
- Docker socket mounted into dev-infra container for host Docker access
- Docker CLI added to dev-infra Dockerfile stage
- New test env vars: PVETEST_STORAGE_VM_IP, PVETEST_ISCSI_IQN, PVETEST_NFS_EXPORT
Other fixes:
- first-boot.sh installs open-iscsi on PVE nodes
- preflight-cleanup.sh handles empty ISO filename gracefully
- TMPDIR set to work dir to avoid /tmp overflow during ISO uploads
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The Dockerfile.test stages only install packages (no COPY), but the
build context changed from tests/infrastructure/ to repo root. Without
a .dockerignore, Docker sends the entire repo (250MB) to the daemon
before building, causing CI to hang.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace tests/infrastructure/Dockerfile with tests/Dockerfile.test
(single multi-stage Dockerfile for both CI and local dev)
- CI container-image job now builds from Dockerfile.test target dev-infra
- Add ARM support: PowerShell installed via dotnet tool on arm64,
APT package on amd64
- Replace tests/dev.sh (bash) with tests/dev.ps1 (PowerShell) for
cross-platform support (Windows, macOS, Linux)
- Add -DockerHost parameter for running x86 containers on a remote
Docker host from ARM Macs (rsyncs repo, uses SSH Docker transport)
- Add -NoCleanup switch to keep nested PVE VMs after integration tests
- integration command now provisions nested PVE VMs instead of testing
against a pre-existing PVE directly
- Share /opt/pve-isos host path between CI and local dev (was separate
Docker named volume)
- Delete tools/Invoke-Tests.ps1 (unused, overlapped with run-integration.sh)
- Add .gitignore entries for Terraform state/artifacts
- Update all documentation references
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The node name "pve" was being masked in all CI logs because GitHub
Actions auto-masks secret values. Since the node name is not sensitive,
use vars.PVE_TARGET_NODE instead of secrets.PVE_TARGET_NODE.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All changes now go through pull requests. Branch protection is enabled
on main (required build checks, required review, admin enforced).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Dockerfile.test: multi-stage build with dev (ARM+x86) and dev-infra
(x86 only, adds Terraform + PVE provisioning tools) targets
- docker-compose.test.yml: services for both targets, .env.test support
- dev.sh: helper script wrapping container lifecycle and run-integration.sh
- .env.test.example: template for integration test configuration
- .gitignore: exclude .env.test, whitelist .env.*.example
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Provision, test, and cleanup jobs now call run-integration.sh instead
of inlining ~170 lines of shell. Logic changes only need to be made
in one place, shared between CI and local dev.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Single source of truth for the provision → test → cleanup lifecycle,
callable from both CI workflows and local dev containers.
Subcommands: provision, test [8|9|all], cleanup, all
Detects CI vs local via $GITHUB_ACTIONS and adjusts output accordingly.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- generate-help.ps1: rewritten to use Update-MarkdownHelp (merge) by
default, preserving hand-written descriptions and examples. Only
New-MarkdownHelp on genuinely new cmdlets. -Force flag for full regen.
- docs/cmdlets: parameter metadata updated via platyPS merge, CRLF
normalized to LF
- Removed stale Send-PveIso.md (cmdlet renamed to Send-PveFile)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- CI workflow: PVE_PASSWORD now reads from secrets.PVE_TEST_PASSWORD
- variables.tf: removed default password, requires TF_VAR env var
- Integration README: examples use <your-test-password> placeholder
- create-api-token.sh: example IP changed to pve.example.com
- .gitignore: added .env/.env.* exclusion
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Runner VM now has 2 runner instances registered, so both test matrix
entries can execute simultaneously against their respective pre-
provisioned nested PVE VMs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
GitHub Actions redacts any value that matches a secret or masked string
in job outputs, making them empty in downstream jobs. This affected
host IPs, tokens, and even port 8006 (substring of PVE_ENDPOINT).
The provision job now writes connection details to
/opt/pve-isos/test-config.json on the shared volume. Test jobs read
this file directly with jq — no job outputs needed for sensitive values.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
::add-mask:: on the VM IP addresses caused GitHub Actions to redact
them in job outputs, making needs.provision.outputs.pve*_host empty
in the test jobs. The IPs are internal lab addresses, not sensitive.
Token masking is retained.
Also removes terraform debug output from prior commit.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
${{ runner.temp }} may resolve differently inside containers. Use
${RUNNER_TEMP} shell variable with unquoted heredoc instead. Added
debug output to diagnose ISO path issues.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Restructures the integration test workflow from a monolithic sequential
job into separate provision → test → cleanup stages:
- provision: creates ALL nested PVE VMs in a single terraform apply
(parallel), waits for APIs, creates tokens, passes outputs to tests
- test: matrix [pve9, pve8] consumes provision outputs, no provisioning
- cleanup: always runs, API-only teardown for all VMs
Terraform refactored to for_each with pve_instances map variable,
enabling parallel ISO upload and VM creation.
New caching scripts reduce redundant downloads:
- ensure-base-iso.sh: downloads PVE ISOs to /opt/pve-isos if missing
- ensure-cloud-images.sh: caches cloud image + OVA with 7-day TTL
- prepare-auto-iso.sh: --cache-dir flag with hash-based skip
Runner no longer needs manual ISO provisioning (zero-touch setup).
cleanup-images bumped to min-versions-to-keep: 3 to survive overlapping
runs. All jobs gated against dependabot.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
SharpCompress 0.47.3 renamed ReaderFactory.Open() to OpenReader() and
now requires an explicit ReaderOptions parameter. The synchronous API
is still available — no async conversion needed.
Closes#12
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The dependabot actor check was only on the build job. The container-image
and cleanup-images jobs still ran — cleanup-images with if: always()
deleted GHCR container images while the main branch integration run was
still using them, causing PVE 8 tests to fail with "image not found".
Now all four integration jobs (build, container-image, integration,
cleanup-images) are gated with github.actor != 'dependabot[bot]'.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Suspend-PveContainer and Restart-PveContainer gained ConfirmImpact.High
in F062/F063 fixes. The "Should throw when no session is active" Pester
tests invoke these cmdlets without -Confirm:$false, causing the
confirmation prompt to fire before the session check — failing in
non-interactive CI on all platforms.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
unit-tests.yml: The publishable project targets netstandard2.0 only
(D009/F047), so the net48 build matrix entry fails. PS 5.1 loads
netstandard2.0 assemblies on .NET Framework 4.8, so the PS 5.1 Pester
tests now use the netstandard2.0 artifact.
integration-tests.yml: Skip entire workflow for dependabot PRs since
integration tests on the self-hosted runner are expensive and dependency
bumps don't warrant full end-to-end testing. Also updates dotnet SDK
from 9.0.x to 10.0.x for consistency.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Restart-PveContainer gained ConfirmImpact.High in the F062 fix, which
correctly prompts for confirmation on destructive operations. The
integration test was missing -Confirm:$false, causing a
NullReferenceException in non-interactive CI. The cascading failure also
broke the Copy-PveContainer test (F081).
Also updates CONTRIBUTING.md to reference .NET SDK 10.0+ (was 9.0+) to
match all CI workflows and test project TFM (F083).
Includes scan-6 review report and findings database update (F001-F083).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
F058 (critical): Replace while(true) infinite-loop task polling with
TaskService.WaitForTask in 5 container snapshot and storage cmdlets.
F073+F047 (high): Migrate net9.0 → net10.0 across both source .csproj
files, build.yml, publish.yml, and test helper.
F071 (medium): Add Uri.EscapeDataString() to all inline URL path
segments in ~16 cmdlets that bypass service classes (D003).
F062+F063 (medium): Add ConfirmImpact.High to Restart-PveContainer
and Suspend-PveContainer (D006).
F075 (medium): Generate markdown help docs for 89 cmdlets that were
missing documentation (170 total, up from 81).
F072 (low): Remove unused System.Text.Json dependency from Core.csproj.
F074 (low): Raise publish smoke-test threshold from 60 to 150.
F065 (low): Add .github/ISSUE_TEMPLATE/config.yml.
F066 (low): Add CODEOWNERS.
Also fix _TestHelper.ps1 net9.0 → net10.0 framework reference.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>