Part of #26. The toolkit had no automated tests at all - including for the
functions that decide what goes into a deploy zip, which is where a dev .env
reached production (#23).
Phase 1 - the seam. Get-ZConfig read a hardcoded $PSScriptRoot\zconfig.json,
so nothing config-dependent could be tested without touching the real config.
Adds Get-ZConfigPath honoring $env:ZCONFIG (the bash port has always had this,
so it also closes a parity gap) and Reset-ZConfigCache to drop the memoised
config between fixtures. Deliberately did NOT convert the exit 1 paths to
throw: that changes observed CLI output, and the pure functions don't need it.
Phase 2 - 61 tests over the functions with no side effects: Get-ArchiveExcludes
(common/python/vite/nextjs lists, deploy.exclude merging, dedupe, array shape),
Get-ZConfig / Get-ZConfigPath / Get-ZProjectKeys / Get-ZProject (dash tolerance,
underscore-key filtering, memoisation), Get-ZEdgeProject, Get-RemoteComposeDir,
Get-Ec2Target / Get-Ec2Home, Get-LabelFromBuildJsonObj, Read-JsonBuildVersion.
The suite is verified by mutation testing rather than assumed useful - six
deliberate regressions were each introduced and confirmed to turn it red,
including reintroducing the exact #23 bug and its inverse (backups silently
dropping .env/uploads, which would produce restore points that cannot restore).
Runs off a fixture config injected via ZCONFIG, so it never reads a real
zconfig.json and passes on a machine that has never been configured.
* fix(ps): zbackup explicit target + robust DATABASE_URL parsing; ssh-stderr deploy fix
Restores parked, previously-uncommitted PowerShell improvements:
- zbackup / zbackup_and_sync require an explicit target: bare invocation
now prints usage instead of quietly backing up everything; 'all' does
what bare used to (matching zdeploy). setup_backup_schedule.ps1 passes
'all' to the scheduled task; both tolerate switch-style args.
- zbackup parses more DATABASE_URL styles: strips surrounding quotes
(Prisma convention), accepts postgres:// and postgresql+driver://
schemes, and treats the port as optional (defaults to 5432).
- Invoke-Ec2Step survives ssh stderr warnings: under ErrorActionPreference
'Stop', PS 5.1 turns any native stderr line (e.g. Docker's COMPOSE_BAKE
deprecation notice) into a terminating NativeCommandError, aborting a
deploy that actually succeeded. Drop to Continue locally and flatten
stderr so only the real exit code decides success.
* fix(ps): zbackup reports the real pg_dump failure, not "No DATABASE_URL"
Mirror of the bash fix. Invoke-LocalPgDump now owns all its messaging
(caller just captures success) and distinguishes the cases:
- no .env / no DATABASE_URL -> calm "No local DATABASE_URL".
- database not reachable (connection refused / could not connect / DNS /
timeout) -> calm "Local database not running at host:port" - a stopped
dev DB is a normal state.
- any other failure (version mismatch, auth, missing db) -> the loud,
full pg_dump error plus the host:port/db it tried, instead of a bare
"pg_dump failed (exit N)" followed by a misleading "No DATABASE_URL".
Captures pg_dump stderr (was 2>$null); drops ErrorActionPreference to
Continue locally so PS 5.1 doesn't turn that stderr into a terminating
NativeCommandError under the script's 'Stop' setting.
Only nextjs-kind excluded .env* from the deploy archive; python and vite
did not - so a project's local .env at its root got zipped and shipped to
the server on every deploy, planting local secrets over the server's own
(the operator-file restore only wins for files it preserved). Add
.env/.env.local/.env.production to the python and vite deploy excludes,
matching nextjs. Kept DEPLOY-only (like `uploads`): backups still capture
.env so a source backup stays complete. Bash + PowerShell.
Note: this covers a ROOT .env. A nested secret (e.g. DocketMail's
backend/.env) is handled separately via deploy.preserve in the project's
zconfig.
Config-driven PowerShell scripts to run infrastructure tasks (deploy, restart, backup, diagnostics) yourself instead of having an AI agent orchestrate them, to save agent tokens. Environment specifics live in zconfig.json (gitignored).