mirror of
https://github.com/GoodOlClint/PSProxmoxVE.git
synced 2026-09-04 03:05:32 +00:00
08ee3ae249
The local dev environment had drifted badly from CI. Remove the parts that no longer describe anything real, and make the rest match how CI actually runs. Delete tests/dev.ps1. It wrapped run-integration.sh, which CI calls directly, and duplicated the module build that script already performs internally. As a second entry point it drifted: it still offered the PVE 8 leg retired in #88, mounted the Docker socket for storage containers replaced by the storage VM in #87, and pointed its remote-host examples at a runner decommissioned in the ARC migration. All four documents describing it used a positional syntax that bound the bare word to -Tests and then fell through to -Shell, so every documented command silently opened a container shell. Recorded as D019. Delete tests/infrastructure/runner/, a self-hosted-runner-in-Docker superseded by Actions Runner Controller. Make disk_storage and iso_storage required. Their defaults named a NAS that the lab replaced with Ceph, and CI overrides both from repository variables, so the defaults only ever misled local runs. require_env now fails at the top of a run rather than at terraform apply, and the descriptions point at tests/.env.test because cmd_provision deletes terraform.tfvars before applying. preflight-cleanup.sh no longer falls back to the literal "local" storage. An unset TF_VAR_iso_storage now skips only the ISO branch, leaving VM destroy and state cleanup intact, and emits a workflow annotation: force-cleanup is the only cleanup CI runs and it wipes Terraform state, so a silent skip strands the uploaded ISO with nothing left to reclaim it. Drop docker-ce-cli and the /var/run/docker.sock mount. Nothing in the container has called docker since #87 moved storage into a VM; the remaining docker calls run inside that VM over SSH. The CI job image is built from the same target, so this also removes a third-party apt repository from its supply chain. Rewrite tests/.env.test.example against what the code now requires, and fix the documented commands in CLAUDE.md, README.md, copilot-instructions.md and the integration README.
84 lines
3.4 KiB
Markdown
84 lines
3.4 KiB
Markdown
# PSProxmoxVE — Copilot Instructions
|
|
|
|
## Project Overview
|
|
|
|
C# binary PowerShell module for managing Proxmox VE (PVE) infrastructure. Two projects:
|
|
- `src/PSProxmoxVE/` — Cmdlets and module surface (targets `netstandard2.0`)
|
|
- `src/PSProxmoxVE.Core/` — Services, models, HTTP client (targets `netstandard2.0`)
|
|
|
|
Tests: xUnit (`tests/PSProxmoxVE.Core.Tests/`) and Pester 5 (`tests/PSProxmoxVE.Tests/`).
|
|
|
|
## Development Workflow
|
|
|
|
**All changes go through pull requests.** The `main` branch has branch protection enabled
|
|
(required build checks, required review, admin enforced). Never push directly to main.
|
|
|
|
Use [Conventional Commits](https://www.conventionalcommits.org/) for all commit messages
|
|
(e.g. `feat: add new cmdlet`, `fix: handle null node name`, `chore: update deps`).
|
|
|
|
### Build & test
|
|
|
|
```bash
|
|
# Build
|
|
dotnet build PSProxmoxVE.sln
|
|
|
|
# xUnit tests
|
|
dotnet test tests/PSProxmoxVE.Core.Tests/
|
|
|
|
# Pester tests (requires pwsh)
|
|
pwsh -Command "Invoke-Pester tests/PSProxmoxVE.Tests/ -Output Detailed"
|
|
```
|
|
|
|
The integration flow runs in the same container image CI uses. There is no wrapper
|
|
script — call `run-integration.sh` directly (x86 only):
|
|
|
|
```bash
|
|
pve() {
|
|
docker compose -f tests/docker-compose.test.yml --profile infra run --rm dev-infra \
|
|
bash tests/infrastructure/scripts/run-integration.sh "$@"
|
|
}
|
|
|
|
pve provision 9
|
|
pve test 9 Cluster,VMs # the area filter is optional
|
|
pve force-cleanup
|
|
```
|
|
|
|
## Key Coding Conventions
|
|
|
|
### Cmdlet rules
|
|
- All cmdlets use the `Pve` noun prefix (e.g. `Get-PveVm`, `New-PveSnapshot`).
|
|
- All cmdlet classes must be `sealed`.
|
|
- All cmdlets must have an `[OutputType(typeof(...))]` attribute.
|
|
- Destructive cmdlets (`Remove-*`, `Stop-*`, `Reset-*`, `Restart-*`, `Suspend-*`, restore ops) must set `ConfirmImpact = ConfirmImpact.High`.
|
|
- Use verb class constants — `VerbsCommon.Get`, not the string literal `"Get"`.
|
|
|
|
### Parameters
|
|
- `VmId` parameters: `[ValidateRange(100, 999999999)]`; use `int?` (nullable) when optional.
|
|
- Passwords must use `SecureString`, never plain `string`. Extract with `Marshal.SecureStringToGlobalAllocUnicode` inside a `try/finally` that calls `Marshal.ZeroFreeGlobalAllocUnicode`.
|
|
|
|
### URL paths
|
|
- All user-supplied or dynamic values interpolated into API URL paths must be wrapped in `Uri.EscapeDataString()`.
|
|
|
|
### Task polling
|
|
- Always use `TaskService.WaitForTask(upid, session, TimeoutSeconds, this)`.
|
|
- Never implement inline `while (true)` / `do/while` polling loops in cmdlet files.
|
|
|
|
### JSON serialization
|
|
- Use only `Newtonsoft.Json` (`[JsonProperty]`). Do **not** add `System.Text.Json` (`[JsonPropertyName]`) attributes.
|
|
|
|
### Error handling
|
|
- No bare `catch { }` or `catch (Exception) { }` blocks.
|
|
- Use a specific exception type (`catch (PveApiException ex)`) or a filtered catch with a `when` clause that excludes fatal exceptions.
|
|
|
|
### Framework targeting
|
|
- Publishable projects (`PSProxmoxVE`, `PSProxmoxVE.Core`): `netstandard2.0`.
|
|
- Test projects: `net10.0` + `net48`.
|
|
|
|
## Key Reference Files
|
|
|
|
Before writing new code, read these files to understand established patterns and open issues:
|
|
|
|
- [`DECISIONS.md`](../DECISIONS.md) — architectural decisions and anti-patterns that must not be reintroduced.
|
|
- [`docs/review/findings.json`](../docs/review/findings.json) — stable findings database (IDs F001… are permanent; resolved findings are marked, never deleted).
|
|
- [`docs/review/REVIEW_REPORT.md`](../docs/review/REVIEW_REPORT.md) — latest full review report.
|