zscripts-token-savers/CHANGELOG.md
KellyMichels 502c0e8b29 feat(zversion, zrelease): toolkit versioning + downloadable release zips
Implements the versioning rule (SmartPlant's 5-segment scheme, now the global
standard; currently only sp and zscripts are on it at v1.x):

    v{major}.{rc}.{beta}.{alpha}.{build}

zversion: get / bump / bump-stage / set. A stage bump zeroes every lower
segment including build. 'bump' is one per PR and one per defect fix, not per
file. Any write rewrites three things together, because they are only useful
when they agree: build-version.json (source of truth), a '# Version:' line in
all 42 script headers (a lone copied script still says which release it came
from), and CHECKSUMS.txt (stamping changes every file).

zrelease: packages the current version as releases/zscripts-<version>.zip with
a sibling .sha256, for people who want the toolkit without cloning. One hash
verifies the download; the bundled CHECKSUMS.txt verifies the extracted
contents. Refuses to overwrite an existing version's zip (released = immutable;
bump instead), and refuses to package when zchecksums fails. tests/ excluded
from the zip; releases/ never packages itself.

First release included: releases/zscripts-v1.0.0.0.0.zip (42 scripts + 7
support files) and its .sha256.

.gitattributes: releases/*.sha256 pinned LF (sha256sum treats a trailing CR as
part of the filename), releases/*.zip marked binary.

Verified end-to-end as a downloader would experience it, in WSL: sha256sum -c
on the zip passes, unzip, sha256sum -c CHECKSUMS.txt inside gives 42 OK / 0
FAILED, and the extracted zdeploy.ps1 header and build-version.json both read
v1.0.0.0.0. Double-release guard and -Verify mode exercised. Full Pester suite
219/219 (the checksum tests absorb the new files automatically).
2026-07-28 13:27:50 -05:00

7.1 KiB

Changelog

Notable changes to the Evomedia.net Token Savers.

Unreleased

Fixed

  • zdeploy no longer deletes operator-managed files on deploy (#2) — the project-directory replacement preserved only ./.env, silently destroying every other server-side file (.env.db, staged signing keys, certs) on every deploy. All .env* files at the project root are now preserved by default, plus anything listed in the new deploy.preserve array (files or directories); the vite kind, which previously preserved nothing, gets the same protection. Found the hard way: a first production deploy of an auth service wiped its staged DB credentials and RSA signing keys.

Added

  • Versioned releases: zversion, zrelease, releases/ — the toolkit now carries one version in the SmartPlant 5-segment scheme, v{major}.{rc}.{beta}.{alpha}.{build}. zversion bump (one per PR / defect fix) and zversion bump-stage release|rc|beta|alpha (zeroes every lower segment) rewrite build-version.json, stamp # Version: into every script header — so a lone copied script still says which release it came from — and regenerate CHECKSUMS.txt in the same step. zrelease packages the current version as releases/zscripts-<version>.zip with a .sha256 beside it: one hash verifies the download, the bundled CHECKSUMS.txt verifies the extracted contents, so nobody needs to clone the repo to get a verifiable copy. Released zips are immutable — zrelease refuses to overwrite one.
  • zchecksums + CHECKSUMS.txt — a SHA-256 manifest covering every .ps1 and .cmd, so a download can be verified before anything is run. zchecksums checks them; zchecksums -Update regenerates after an intentional edit. The manifest is sha256sum format, so sha256sum -c CHECKSUMS.txt works on Linux/macOS/WSL too, and the hashes match on every platform because .gitattributes pins these files to CRLF everywhere. Flags changed files, missing files, and scripts present on disk but absent from the manifest. It's an integrity check, not a signature — the manifest sits in the same repo as the code, so it catches corruption and accidental drift, not a compromised repo. A Pester test fails if the manifest ever goes stale.
  • Test suite (Pester) — the toolkit now has automated coverage of its own pure logic: Get-ArchiveExcludes (including the deploy-vs-backup rule that keeps .env/uploads out of deploys but in backups), config and project lookups, remote.composeDir fallback, EC2 target composition, and build-label formatting. Run with Invoke-Pester .\tests (Pester 5+). Verified by mutation testing — reintroducing each historical bug turns the suite red.
  • ZCONFIG environment variable — overrides the path to zconfig.json, so a run can target an alternate config. Also gives the test suite a seam for injecting a fixture.
  • zec2_rotatekeys — safely rotate/reset server-side secrets — a new tool for when a secret leaks or a deploy overwrites a production .env with dev values. -Rotate KEY regenerates a key on the server (openssl rand -hex 32) so the new value never leaves the box; -Set KEY takes an operator-known value (e.g. DATABASE_URL, ADMIN_EMAIL) from a masked prompt and streams it over SSH stdin — never a command argument, never echoed. Backs the server .env up to a timestamped .bak first, updates the key atomically (matches or appends), auto-detects backend/.env from deploy.preserve, and with -Restart recreates the container (up -d --force-recreate, so the new values actually load — a plain restart keeps the old environment). -WhatIf previews the plan without touching anything.
  • zkill all — zkill now accepts all, stopping the dev server of every project that has a ports.dev (edge/docker stacks with no local dev server are skipped). Brings it in line with zdeploy all / zbackup all; the one-shot "stop everything I've got running locally".
  • zdeploy server-side health verification (verify block) — projects not published through the edge proxy can declare "verify": { "port": ..., "path": "/health", "expect": "..." } and the deploy is checked from the server itself (curl localhost:<port><path> over SSH) instead of hitting the public IP. Fixes a false PASS where the proxy's default vhost answered for apps that never started; projects with neither domain nor verify are now reported as NOT verified.
  • zdeploy optional deploy.gitPull — git pull --ff-only in the project root before zipping. zdeploy zips the working tree and doesn't otherwise pull, so a checkout left behind origin after a merged PR would deploy stale code while still bumping the build number — success that changes nothing. A failed pull aborts the deploy instead.
  • Per-project start config block — zstart honors optional pre-start steps from zconfig.json: "gitPull": true runs git pull --ff-only in the project root before starting (never boot a stale checkout), and "env": { ... } sets environment variables for the dev-server process. Example added to zconfig.example.json.
  • Switch-style argument tolerance — a leading dash on a project key is ignored everywhere (zdeploy -myapp == zdeploy myapp), for hands that grew up on per-project switches.

Changed

  • zbackup / zbackup_and_sync require an explicit target — running them bare now shows usage instead of quietly backing up every project; all does what bare invocation used to (matching zdeploy). The scheduled task created by setup_backup_schedule.ps1 passes all — re-run it if your task was registered before this change.
  • zbackup parses more DATABASE_URL styles — double/single-quoted values (Prisma convention), postgres:// and postgresql+driver:// schemes, and URLs without an explicit port (defaults to 5432) all work; previously these skipped the Postgres dump with "Could not parse DATABASE_URL".
  • zkill / port cleanup kills the whole process tree — listeners on a project's port are now terminated children-first. Auto-reloading servers (uvicorn/watchfiles, nodemon) spawn workers that inherit the listening socket; killing only the parent left orphans serving stale code.
  • zbackup finds DATABASE_URL in backend\.env too — projects with a frontend/backend split get their Postgres dump bundled without needing a root-level .env.

1.0.0

Initial public release: zstart / zkill / zrestart (local dev servers), zdeploy (zip → upload → compose build → live build-version verification, with handlers for python / vite / nextjs / edge / docker project kinds), zec2 / zec2online / zrepair (health checks and recovery), zbackup / zbackup_ec2 / zsync (local, server-side, and offsite backups), all driven by a single gitignored zconfig.json.