feat: checksums, toolkit versioning (v{major}.{rc}.{beta}.{alpha}.{build}), and downloadable release zips (#35)

* feat(zchecksums): SHA-256 manifest so a download can be verified before it's run

CHECKSUMS.txt lists a SHA-256 for every top-level .ps1 and .cmd - the files a
user actually executes. zchecksums verifies them; zchecksums -Update
regenerates after an intentional edit.

The manifest is sha256sum format, so 'sha256sum -c CHECKSUMS.txt' works on
Linux/macOS/WSL as well as the PowerShell path on Windows. Hashes are identical
on every platform because .gitattributes pins .ps1/.cmd to CRLF everywhere -
that pin is now load-bearing, so it is commented as such.

Beyond changed and missing files it also reports a script that is on disk but
NOT in the manifest, so something added outside a commit still gets noticed.
Exits non-zero on any of the three.

Honest about its limits, in the header and the README: the manifest lives in
the same repo as the code, so it is an integrity check rather than a signature.
It catches a truncated clone, a forgotten local edit, or an unlisted file - not
a compromised repo.

CHECKSUMS.txt is pinned to LF: sha256sum treats a trailing CR as part of the
filename and would report every entry as missing on Linux.

tests/Checksums.Tests.ps1 keeps it from rotting - a stale manifest is worse
than none, since it either cries wolf until people ignore it or quietly stops
covering a new script. The tests assert the format, LF endings, sort order,
full coverage of on-disk scripts, current hashes, and that zchecksums itself
exits 1 on a tampered file (proved by appending a byte and restoring it).

* 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).
This commit is contained in:
kellymichels 2026-07-28 13:47:25 -05:00 committed by GitHub
parent c20e82e209
commit 91b638ac31
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
50 changed files with 731 additions and 1 deletions

12
.gitattributes vendored
View File

@ -1,3 +1,13 @@
# PowerShell/cmd are happiest with CRLF on Windows. # PowerShell/cmd are happiest with CRLF on Windows. The pin matters beyond
# convenience: it makes these files byte-identical on every platform, which is
# what lets CHECKSUMS.txt hold one hash per file rather than one per OS.
*.ps1 text eol=crlf *.ps1 text eol=crlf
*.cmd text eol=crlf *.cmd text eol=crlf
# The checksum manifest must stay LF: `sha256sum -c` treats a trailing CR as
# part of the filename and reports every entry as missing.
CHECKSUMS.txt text eol=lf
releases/*.sha256 text eol=lf
# Release zips are binary and immutable.
releases/*.zip binary

View File

@ -22,6 +22,27 @@ Notable changes to the Evomedia.net Token Savers.
credentials and RSA signing keys. credentials and RSA signing keys.
### Added ### 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 - **Test suite (Pester)** — the toolkit now has automated coverage of its own
pure logic: `Get-ArchiveExcludes` (including the deploy-vs-backup rule that pure logic: `Get-ArchiveExcludes` (including the deploy-vs-backup rule that
keeps `.env`/`uploads` out of deploys but *in* backups), config and project keeps `.env`/`uploads` out of deploys but *in* backups), config and project

42
CHECKSUMS.txt Normal file
View File

@ -0,0 +1,42 @@
90e4105107d27a44ee7199e459f86941013d5e29d2a7a53882d48347e05b1530 setup_backup_schedule.ps1
00ea2054ca36dd84133aaaa381437d39374407b1fcd33caecbdea09b4967247f token-count.ps1
4903f0194fe749269bb61ffacace6e957ce44503522d625560dcc882b69f91b4 zbackup.cmd
7d8446fc5f04ec1d0f695b6390db5bbfb86f410f6d8aac14720fd3aa4bfa3525 zbackup.ps1
8b375c8a759e37b812293ae168dcf19ae1ca0c136c9d3f2d7ae90a84c1e26f3f zbackup_and_sync.ps1
c336a61cb8563736bd6550671d7dc90b14702a43f25a97b1ac15ffd64605fbf6 zbackup_ec2.cmd
47ccde67ba8502997105c995e509c1ed1016ffac264df60c6ac539a5b99eda08 zbackup_ec2.ps1
20e6282901a919aa32ea717c739ba2dc9657426dff860f0e5fce201edefd99da zchecksums.cmd
692b7b0ff9e51e5d9b880358b33c54d2db4f967297a5350e154df1ce6f06ebc6 zchecksums.ps1
b56085112e7c573926a70a58872163b71416d58ce91ea7114b1f5de5fc96c982 zdeploy.cmd
8f52b2114c8d84e397b7a4f4e1f45ea7201c59fe3e1b4147fa08ad26d0325035 zdeploy.ps1
fa817d3bd7bba98b03b411d3c5a82b210d3cca316ac0c9785afa5b4ac5fe0766 zec2.cmd
5f70432af23df3459a98d9ad6a0da723783f2269dd5f5ab8ecdd6366ebc84942 zec2.ps1
4df94eda29b6f5b2cb6bfa63e0add4d90ea24d936305f36a69988e8dd5d69154 zec2_rotatekeys.cmd
cc980bec4a9205a774c05ee1a7e0473e604adf5370b548015a5cb47412dd5853 zec2_rotatekeys.ps1
fae88c3d77efaef1a60d8d74bd0ca880ca67f85a2ab302fd182dfeb33e9465ce zec2online.cmd
daf58f09cf118128c69282d51bbcece71cdeb1ce423737f6583ed00be460d98f zec2online.ps1
2cb21bc7c18ab18e05403b10ca6316b334215ecf359796d53e1b3fe295ac88f2 ZHelpers.ps1
bace82f5efc0cf63f260ccd5e134032029b70fe633900d3a6345f7eb079c121e zkill.cmd
443af456a5ababda04d882abf28f18079473708a90249c7294d03f8120db60f6 zkill.ps1
0e95bebabe8e56894c19519b38f57544bfb6903a3fe2f093fb7bf592c68b86da ZKiller.ps1
957784b0261010baec0966319fddf887171b7835770cd0d4f55fb0c58ee70db2 ZKillOnly.ps1
70330253df23a140ca4c87a10107eb6dde86fa66292de6a56cda300889b8f329 zrelease.cmd
e29782135c4ca25eeff9655751a80fecda6c8fa8031a478a263ececb29a14937 zrelease.ps1
8031864bc4ad92e1fc23a6f9ff1886e2b54bde5cda48658f3e4b60b90846937e zrepair.cmd
51ca23196efefa8482a8be88f66239830dbce9e1dcabb98e7c5edf493dc30a2e zrepair.ps1
b45c4ce12cb0d907cb2bb53a6fb1b4a0e0cfd61d8cc54f14a1badc73a953befb zrestart.cmd
2cb349166a8cc93353fec4b59bbe4b3d9acb10597a06ae6f7317ebd5287a17b1 zrestart.ps1
7e760b07cbcc0599afc7cbf2a45a05818300e6c1a96c1df7ce835f6d502e080e zrestartd.cmd
f4808922ba1529a50d0f6b69fa1b73c02edbeeba48bd4bb2ada7790d220413d6 zsetup.cmd
f669146bd46a3bebeb66b1cde8ed451557e7528282e4d7f5a04563a23572179f zsetup.ps1
634a9376513846ba2ee3635afdf515d68626e0144e731d045cbfd7ea60018923 zsetup_mail.ps1
85f3301616f7409720e4eeb3f3f4e367f0bb1d336fe13123b9ce6674361a6251 zstart.cmd
2e353bee9e7bf78d39c32b98b3375eebff89d5b9c2313fa05b3ff3161e836b91 zstart.ps1
f6107ca1d887ef1b3f94f51a40772a59d01fa1a582420a74766a2acc68bbe01f zstart_docker.cmd
5f15a05f5972dd8a3d33efa224db2d2640f3562436ec1bc2efb7354fc9b4653f zstart_docker.ps1
92bd61afa382b1c38bbd33cf19661084ba64cdb8b2ca6690d44c9ea1ee85a6af zstartd.cmd
ecd3bad1348fcd31c15b7365a9bb48742066cf98f0b1dd0aace4c4ce7a384242 zstop.ps1
8f75cd61112cec34a504073cd6086c18ad5c1c368cd62f9603c04bcd50156189 zsync.cmd
10e22effc5425d29ef3dc6eec9d69709dd02754a3baa5276ffdb1bbfe03a4dde zsync.ps1
2746c4e003c744f860cec2356844409304c2e9d577bbe6f895f39bc3140ca7d7 zversion.cmd
529d4b2ae72603d2591475d65969bccd3f629522234315051ac95a88f6290a51 zversion.ps1

View File

@ -131,6 +131,9 @@ The `.cmd` wrappers are the everyday interface. Every command takes one or more
| `zbackup_ec2 [<key> ...]` | Pull DB dumps + server-side data files down from the server | | `zbackup_ec2 [<key> ...]` | Pull DB dumps + server-side data files down from the server |
| `zsync [<key>]` | Copy new backups offsite (or build + mirror a vite dist) | | `zsync [<key>]` | Copy new backups offsite (or build + mirror a vite dist) |
| `zstart_docker` | Run a local docker compose stack from `scriptsRoot\docker\` | | `zstart_docker` | Run a local docker compose stack from `scriptsRoot\docker\` |
| `zchecksums [-Update]` | Verify every script against `CHECKSUMS.txt` (SHA-256) |
| `zversion [bump \| bump-stage <s> \| set <v>]` | Show or advance the toolkit version (stamps every header) |
| `zrelease [-Verify]` | Package the current version as `releases/zscripts-<version>.zip` + `.sha256` |
### Local development ### Local development
@ -385,6 +388,44 @@ Give the project a `verify` block instead, and `zdeploy` checks the app **from t
2. That's it: `zstart`, `zkill`, `zrestart`, `zbackup`, `zdeploy`, `zec2`, `zec2online`, `zrepair`, `zstop` all accept the new key immediately. 2. That's it: `zstart`, `zkill`, `zrestart`, `zbackup`, `zdeploy`, `zec2`, `zec2online`, `zrepair`, `zstop` all accept the new key immediately.
3. A project whose deploy doesn't fit the python/vite/nextjs/edge/docker patterns needs its own `Invoke-<Kind>Deploy` function in `zdeploy.ps1` — copy an existing handler; they're all variations on zip → upload → compose up → verify. 3. A project whose deploy doesn't fit the python/vite/nextjs/edge/docker patterns needs its own `Invoke-<Kind>Deploy` function in `zdeploy.ps1` — copy an existing handler; they're all variations on zip → upload → compose up → verify.
## Downloading without cloning
Each release is packaged as a zip in [`releases/`](releases/) — grab the latest `zscripts-v*.zip`, check it, unzip, done:
```bash
sha256sum -c zscripts-v1.0.0.0.0.zip.sha256 # verify the download
unzip zscripts-v1.0.0.0.0.zip -d zscripts # extract
cd zscripts && sha256sum -c CHECKSUMS.txt # verify the contents
```
The zip contains every command, `CHECKSUMS.txt`, `zconfig.example.json`, and the docs. Versions follow `v{major}.{rc}.{beta}.{alpha}.{build}`; every script header carries the release version it shipped in, so even a single copied file can be traced to its release.
## Verifying what you downloaded
`CHECKSUMS.txt` holds a SHA-256 for every `.ps1` and `.cmd` in the repo. Check them before running anything:
```powershell
zchecksums
```
Or with the standard tool on Linux/macOS/WSL — the manifest is `sha256sum` format:
```bash
sha256sum -c CHECKSUMS.txt
```
The hashes are identical on every platform: `.gitattributes` pins `.ps1`/`.cmd` to CRLF everywhere, so a file is byte-for-byte the same whether you cloned on Windows or Linux.
`zchecksums` flags three things — a file whose contents changed, a listed file that's gone, and a script on disk that **isn't** in the manifest (so something added quietly still gets noticed). It exits non-zero on any of them.
If you edit a script yourself, regenerate and commit the manifest with it:
```powershell
zchecksums -Update
```
**What this does and doesn't prove.** `CHECKSUMS.txt` lives in the same repo as the scripts, so anyone who could alter a script could alter the manifest too. It's an integrity check, not a signature: it reliably catches a truncated clone, a local edit you forgot about, or a file added outside a commit. It does *not* prove the code came from this project — for that you'd need a signature or a hash published outside this repo.
## Tests ## Tests
The toolkit has its own [Pester](https://pester.dev) suite covering the pure logic — the exclude lists, config lookups, and version-label formatting that the deploy and backup paths depend on: The toolkit has its own [Pester](https://pester.dev) suite covering the pure logic — the exclude lists, config lookups, and version-label formatting that the deploy and backup paths depend on:

View File

@ -1,6 +1,7 @@
# Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers # Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers
# Created by Kelly Michels · dev@evomedia.net # Created by Kelly Michels · dev@evomedia.net
# Licensed under the MIT License. See LICENSE. # Licensed under the MIT License. See LICENSE.
# Version: v1.0.0.0.0
# ZHelpers.ps1 — shared library dot-sourced by every z script. Not run directly. # ZHelpers.ps1 — shared library dot-sourced by every z script. Not run directly.

View File

@ -1,6 +1,7 @@
# Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers # Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers
# Created by Kelly Michels · dev@evomedia.net # Created by Kelly Michels · dev@evomedia.net
# Licensed under the MIT License. See LICENSE. # Licensed under the MIT License. See LICENSE.
# Version: v1.0.0.0.0
# ZKillOnly.ps1 — stop local dev server listeners for any project in zconfig.json. # ZKillOnly.ps1 — stop local dev server listeners for any project in zconfig.json.
# #

View File

@ -1,6 +1,7 @@
# Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers # Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers
# Created by Kelly Michels · dev@evomedia.net # Created by Kelly Michels · dev@evomedia.net
# Licensed under the MIT License. See LICENSE. # Licensed under the MIT License. See LICENSE.
# Version: v1.0.0.0.0
# ZKiller.ps1 — kill then restart dev servers for any project in zconfig.json. # ZKiller.ps1 — kill then restart dev servers for any project in zconfig.json.
# #

3
build-version.json Normal file
View File

@ -0,0 +1,3 @@
{
"version": "v1.0.0.0.0"
}

Binary file not shown.

View File

@ -0,0 +1 @@
17202e39be7b4a5f46418b9f2d1bbfc58c356f591abf416a1c9348b85241f006 zscripts-v1.0.0.0.0.zip

View File

@ -1,6 +1,7 @@
# Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers # Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers
# Created by Kelly Michels · dev@evomedia.net # Created by Kelly Michels · dev@evomedia.net
# Licensed under the MIT License. See LICENSE. # Licensed under the MIT License. See LICENSE.
# Version: v1.0.0.0.0
# setup_backup_schedule.ps1 — create a scheduled task for daily backups + OneDrive sync # setup_backup_schedule.ps1 — create a scheduled task for daily backups + OneDrive sync
# #

111
tests/Checksums.Tests.ps1 Normal file
View File

@ -0,0 +1,111 @@
# Evomedia.net Token Savers - https://github.com/kellymichels/zscripts-token-savers
# Created by Kelly Michels - dev@evomedia.net
# Licensed under the MIT License. See LICENSE.
# Checksums.Tests.ps1 - keeps CHECKSUMS.txt honest.
#
# Invoke-Pester .\tests
#
# A checksum manifest is worse than useless once it drifts: it either cries wolf
# on every run until people stop reading it, or it quietly stops covering a new
# script. These tests fail the moment the manifest and the scripts disagree, so
# "forgot to run zchecksums -Update" surfaces here rather than in a user's
# verification run.
BeforeAll {
$script:RepoRoot = Split-Path -Parent $PSScriptRoot
$script:Manifest = Join-Path $script:RepoRoot "CHECKSUMS.txt"
# Same set zchecksums.ps1 covers: top-level executables.
$script:Covered = @(
Get-ChildItem -LiteralPath $script:RepoRoot -File |
Where-Object { $_.Extension -in @('.ps1', '.cmd') } |
Sort-Object Name
)
$script:Listed = [ordered]@{}
if (Test-Path -LiteralPath $script:Manifest) {
foreach ($line in [IO.File]::ReadAllLines($script:Manifest)) {
if ($line -match '^([0-9a-fA-F]{64})\s+(.+)$') {
$script:Listed[$Matches[2].Trim()] = $Matches[1].ToLowerInvariant()
}
}
}
}
Describe "CHECKSUMS.txt" {
It "exists" {
Test-Path -LiteralPath $script:Manifest | Should -BeTrue
}
# NOTE: no angle brackets in It names - Pester treats them as -ForEach data
# placeholders and tries to evaluate the contents as an expression.
It "is sha256sum-compatible: 64 hex chars, two spaces, then the filename" {
# Anything else and `sha256sum -c CHECKSUMS.txt` warns or bails, which
# is half the point of publishing it.
foreach ($line in [IO.File]::ReadAllLines($script:Manifest)) {
if (-not $line.Trim()) { continue }
$line | Should -Match '^[0-9a-f]{64} \S.*$'
}
}
It "uses LF line endings" {
# A trailing CR becomes part of the filename for sha256sum, so every
# entry would report as missing on Linux/macOS.
([IO.File]::ReadAllText($script:Manifest)) | Should -Not -Match "`r"
}
It "is sorted by filename" {
$names = @($script:Listed.Keys)
($names -join ',') | Should -Be (($names | Sort-Object) -join ',')
}
}
Describe "manifest matches what is on disk" {
It "lists every top-level .ps1 / .cmd (nothing silently uncovered)" {
$missingFromManifest = @($script:Covered.Name | Where-Object { -not $script:Listed.Contains($_) })
$missingFromManifest -join ', ' | Should -BeNullOrEmpty -Because "these scripts are not in CHECKSUMS.txt - run 'zchecksums -Update'"
}
It "lists nothing that no longer exists" {
$onDisk = @($script:Covered.Name)
$stale = @($script:Listed.Keys | Where-Object { $onDisk -notcontains $_ })
$stale -join ', ' | Should -BeNullOrEmpty -Because "these entries point at files that are gone - run 'zchecksums -Update'"
}
It "records the current hash of <_>" -ForEach @(
(Get-ChildItem -LiteralPath (Split-Path -Parent $PSScriptRoot) -File |
Where-Object { $_.Extension -in @('.ps1', '.cmd') } |
Sort-Object Name | Select-Object -ExpandProperty Name)
) {
$name = $_
$script:Listed.Contains($name) | Should -BeTrue -Because "$name is missing from CHECKSUMS.txt"
$actual = (Get-FileHash -LiteralPath (Join-Path $script:RepoRoot $name) -Algorithm SHA256).Hash.ToLowerInvariant()
$actual | Should -Be $script:Listed[$name] -Because "$name changed since CHECKSUMS.txt was written - run 'zchecksums -Update'"
}
}
Describe "zchecksums.ps1" {
It "verifies clean and exits 0 against the committed manifest" {
$out = & powershell -NoProfile -ExecutionPolicy Bypass -File (Join-Path $script:RepoRoot "zchecksums.ps1") -Quiet 2>&1
$LASTEXITCODE | Should -Be 0 -Because ($out -join "`n")
}
It "exits non-zero when a covered file has been tampered with" {
# Proves the check actually detects a modified script rather than always
# passing. Appends a byte to a real script, verifies, then restores it.
$victim = Join-Path $script:RepoRoot "zchecksums.cmd"
$original = [IO.File]::ReadAllBytes($victim)
try {
[IO.File]::AppendAllText($victim, "REM tampered`r`n")
& powershell -NoProfile -ExecutionPolicy Bypass -File (Join-Path $script:RepoRoot "zchecksums.ps1") -Quiet *> $null
$LASTEXITCODE | Should -Be 1
}
finally {
[IO.File]::WriteAllBytes($victim, $original)
}
# Restored, so a normal verify passes again.
& powershell -NoProfile -ExecutionPolicy Bypass -File (Join-Path $script:RepoRoot "zchecksums.ps1") -Quiet *> $null
$LASTEXITCODE | Should -Be 0
}
}

View File

@ -1,6 +1,7 @@
# Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers # Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers
# Created by Kelly Michels · dev@evomedia.net # Created by Kelly Michels · dev@evomedia.net
# Licensed under the MIT License. See LICENSE. # Licensed under the MIT License. See LICENSE.
# Version: v1.0.0.0.0
# token-count.ps1 — measure script output volume to estimate AI agent token costs. # token-count.ps1 — measure script output volume to estimate AI agent token costs.
# #

View File

@ -1,6 +1,7 @@
REM Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers REM Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers
REM Created by Kelly Michels · dev@evomedia.net REM Created by Kelly Michels · dev@evomedia.net
REM Licensed under the MIT License. See LICENSE. REM Licensed under the MIT License. See LICENSE.
REM Version: v1.0.0.0.0
@echo off @echo off
powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0zbackup.ps1" %* powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0zbackup.ps1" %*

View File

@ -1,6 +1,7 @@
# Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers # Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers
# Created by Kelly Michels · dev@evomedia.net # Created by Kelly Michels · dev@evomedia.net
# Licensed under the MIT License. See LICENSE. # Licensed under the MIT License. See LICENSE.
# Version: v1.0.0.0.0
# zbackup.ps1 — local backups: zip project sources (plus a Postgres dump when the # zbackup.ps1 — local backups: zip project sources (plus a Postgres dump when the
# project's .env has a DATABASE_URL) into the backups folder. # project's .env has a DATABASE_URL) into the backups folder.

View File

@ -1,6 +1,7 @@
# Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers # Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers
# Created by Kelly Michels · dev@evomedia.net # Created by Kelly Michels · dev@evomedia.net
# Licensed under the MIT License. See LICENSE. # Licensed under the MIT License. See LICENSE.
# Version: v1.0.0.0.0
# zbackup_and_sync.ps1 — run backups, then sync the backups folder offsite. # zbackup_and_sync.ps1 — run backups, then sync the backups folder offsite.
# #

View File

@ -1,6 +1,7 @@
REM Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers REM Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers
REM Created by Kelly Michels · dev@evomedia.net REM Created by Kelly Michels · dev@evomedia.net
REM Licensed under the MIT License. See LICENSE. REM Licensed under the MIT License. See LICENSE.
REM Version: v1.0.0.0.0
@echo off @echo off
powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0zbackup_ec2.ps1" %* powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0zbackup_ec2.ps1" %*

View File

@ -1,6 +1,7 @@
# Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers # Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers
# Created by Kelly Michels · dev@evomedia.net # Created by Kelly Michels · dev@evomedia.net
# Licensed under the MIT License. See LICENSE. # Licensed under the MIT License. See LICENSE.
# Version: v1.0.0.0.0
# zbackup_ec2.ps1 — pull backups down from the server: a Postgres dump for projects # zbackup_ec2.ps1 — pull backups down from the server: a Postgres dump for projects
# with a "db" config block, plus a zip of server-side data dirs (uploads/archive/dist). # with a "db" config block, plus a zip of server-side data dirs (uploads/archive/dist).

7
zchecksums.cmd Normal file
View File

@ -0,0 +1,7 @@
REM Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers
REM Created by Kelly Michels · dev@evomedia.net
REM Licensed under the MIT License. See LICENSE.
REM Version: v1.0.0.0.0
@echo off
powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0zchecksums.ps1" %*

144
zchecksums.ps1 Normal file
View File

@ -0,0 +1,144 @@
# Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers
# Created by Kelly Michels · dev@evomedia.net
# Licensed under the MIT License. See LICENSE.
# Version: v1.0.0.0.0
# zchecksums.ps1 - verify (or regenerate) SHA-256 checksums for the scripts.
#
# Usage:
# zchecksums verify every script against CHECKSUMS.txt
# zchecksums -Update regenerate CHECKSUMS.txt after changing a script
# zchecksums -Quiet verify, print only the summary line
#
# Exit codes: 0 = everything matches, 1 = a mismatch, missing or unlisted file.
#
# WHAT THIS DOES AND DOES NOT PROTECT AGAINST
# -------------------------------------------
# CHECKSUMS.txt lives in the same repo as the scripts, so anyone able to modify
# a script can also modify the manifest. This is an integrity check, not a
# signature. It reliably catches:
#
# * a truncated or corrupted download / clone
# * a file edited locally that you forgot about
# * a script added or removed without going through a commit
#
# It does NOT prove the code came from this project - only a signature (GPG,
# Sigstore) or a hash published somewhere outside this repo can do that. Compare
# against the copy on GitHub if you need that assurance.
#
# Only *.ps1 and *.cmd are covered: they are what you actually execute, and
# .gitattributes pins them to CRLF on every platform, so their hashes are
# identical on Windows, Linux and macOS. Files without that pin would hash
# differently per platform and are deliberately left out.
#
# RUN -Update ON A CLEAN CHECKOUT
# ------------------------------
# Hash whatever is on disk. That is only the same as what a user clones if the
# working copy matches git's normalised form. An editor that writes LF leaves a
# file git still considers unchanged (it normalises to LF in the index either
# way), so the file sits there with LF while every clone gets CRLF - and the
# manifest generated from it fails for everyone else. If in doubt:
#
# git status --short # must be clean
# git rm -r --cached . ; git reset --hard # or delete the scripts and
# # `git checkout -- .`
#
# then re-run -Update. The surest check is to clone the repo somewhere else and
# run `sha256sum -c CHECKSUMS.txt` there.
[CmdletBinding()]
param(
[switch]$Update,
[switch]$Quiet
)
$ErrorActionPreference = "Stop"
$ManifestName = "CHECKSUMS.txt"
$Manifest = Join-Path $PSScriptRoot $ManifestName
# The covered set: executable scripts, top level only. Sorted for a stable file.
function Get-CoveredFiles {
Get-ChildItem -LiteralPath $PSScriptRoot -File |
Where-Object { $_.Extension -in @('.ps1', '.cmd') } |
Sort-Object Name
}
function Get-Sha256([string]$Path) {
return (Get-FileHash -LiteralPath $Path -Algorithm SHA256).Hash.ToLowerInvariant()
}
# sha256sum-compatible: "<hash> <name>", LF endings, so `sha256sum -c` works on
# Linux/macOS as well as this script on Windows.
function Write-Manifest($Files) {
$lines = foreach ($f in $Files) { "{0} {1}" -f (Get-Sha256 $f.FullName), $f.Name }
$text = ($lines -join "`n") + "`n"
[IO.File]::WriteAllText($Manifest, $text, (New-Object Text.UTF8Encoding($false)))
}
function Read-Manifest {
if (-not (Test-Path -LiteralPath $Manifest)) { return $null }
$map = [ordered]@{}
foreach ($line in [IO.File]::ReadAllLines($Manifest)) {
$t = $line.Trim()
if (-not $t -or $t.StartsWith('#')) { continue }
# "<64 hex> <name>" - two spaces is the sha256sum convention, but accept
# any run of whitespace so a hand-edited file still parses.
if ($t -match '^([0-9a-fA-F]{64})\s+(.+)$') {
$map[$Matches[2].Trim()] = $Matches[1].ToLowerInvariant()
}
}
return $map
}
$files = @(Get-CoveredFiles)
if ($Update) {
Write-Manifest $files
Write-Host ""
Write-Host "=== zchecksums (updated) ===" -ForegroundColor Cyan
Write-Host (" Wrote {0} with {1} entries." -f $ManifestName, $files.Count) -ForegroundColor Green
Write-Host " Commit it alongside the script change, or verification will fail." -ForegroundColor DarkGray
Write-Host ""
exit 0
}
$expected = Read-Manifest
if ($null -eq $expected) {
Write-Host "ERROR: $ManifestName not found. Run 'zchecksums -Update' to create it." -ForegroundColor Red
exit 1
}
$ok = 0
$changed = @()
$missing = @()
$unlisted = @()
foreach ($f in $files) {
if (-not $expected.Contains($f.Name)) { $unlisted += $f.Name; continue }
if ((Get-Sha256 $f.FullName) -eq $expected[$f.Name]) { $ok++ } else { $changed += $f.Name }
}
foreach ($name in $expected.Keys) {
if (-not (Test-Path -LiteralPath (Join-Path $PSScriptRoot $name))) { $missing += $name }
}
$bad = $changed.Count + $missing.Count + $unlisted.Count
if (-not $Quiet) {
Write-Host ""
Write-Host "=== zchecksums ===" -ForegroundColor Cyan
foreach ($n in $changed) { Write-Host " CHANGED $n" -ForegroundColor Red }
foreach ($n in $missing) { Write-Host " MISSING $n (listed but not on disk)" -ForegroundColor Red }
foreach ($n in $unlisted) { Write-Host " UNLISTED $n (on disk but not in $ManifestName)" -ForegroundColor Yellow }
}
if ($bad -eq 0) {
Write-Host (" OK - {0} file(s) match {1}." -f $ok, $ManifestName) -ForegroundColor Green
Write-Host ""
exit 0
}
Write-Host (" FAILED - {0} ok, {1} changed, {2} missing, {3} unlisted." -f $ok, $changed.Count, $missing.Count, $unlisted.Count) -ForegroundColor Red
Write-Host " If you changed a script on purpose, run: zchecksums -Update" -ForegroundColor DarkGray
Write-Host ""
exit 1

View File

@ -1,6 +1,7 @@
REM Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers REM Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers
REM Created by Kelly Michels · dev@evomedia.net REM Created by Kelly Michels · dev@evomedia.net
REM Licensed under the MIT License. See LICENSE. REM Licensed under the MIT License. See LICENSE.
REM Version: v1.0.0.0.0
@echo off @echo off
powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0zdeploy.ps1" %* powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0zdeploy.ps1" %*

View File

@ -1,6 +1,7 @@
# Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers # Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers
# Created by Kelly Michels · dev@evomedia.net # Created by Kelly Michels · dev@evomedia.net
# Licensed under the MIT License. See LICENSE. # Licensed under the MIT License. See LICENSE.
# Version: v1.0.0.0.0
# zdeploy.ps1 — deploy any project defined in zconfig.json to the server. # zdeploy.ps1 — deploy any project defined in zconfig.json to the server.
# Each project runs its own docker compose stack; the handler is picked by the # Each project runs its own docker compose stack; the handler is picked by the

View File

@ -1,6 +1,7 @@
REM Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers REM Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers
REM Created by Kelly Michels · dev@evomedia.net REM Created by Kelly Michels · dev@evomedia.net
REM Licensed under the MIT License. See LICENSE. REM Licensed under the MIT License. See LICENSE.
REM Version: v1.0.0.0.0
@echo off @echo off
powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0zec2.ps1" %* powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0zec2.ps1" %*

View File

@ -1,6 +1,7 @@
# Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers # Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers
# Created by Kelly Michels · dev@evomedia.net # Created by Kelly Michels · dev@evomedia.net
# Licensed under the MIT License. See LICENSE. # Licensed under the MIT License. See LICENSE.
# Version: v1.0.0.0.0
# zec2.ps1 — quick reachability check (TCP + HTTP + live build version) for deployed projects. # zec2.ps1 — quick reachability check (TCP + HTTP + live build version) for deployed projects.
# #

View File

@ -1,6 +1,7 @@
REM Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers REM Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers
REM Created by Kelly Michels · dev@evomedia.net REM Created by Kelly Michels · dev@evomedia.net
REM Licensed under the MIT License. See LICENSE. REM Licensed under the MIT License. See LICENSE.
REM Version: v1.0.0.0.0
@echo off @echo off
powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0zec2_rotatekeys.ps1" %* powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0zec2_rotatekeys.ps1" %*

View File

@ -1,6 +1,7 @@
# Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers # Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers
# Created by Kelly Michels · dev@evomedia.net # Created by Kelly Michels · dev@evomedia.net
# Licensed under the MIT License. See LICENSE. # Licensed under the MIT License. See LICENSE.
# Version: v1.0.0.0.0
# zec2_rotatekeys.ps1 - rotate / reset secret keys in a project's SERVER-SIDE # zec2_rotatekeys.ps1 - rotate / reset secret keys in a project's SERVER-SIDE
# .env, in place, without the values ever passing through this machine's shell # .env, in place, without the values ever passing through this machine's shell

View File

@ -1,6 +1,7 @@
REM Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers REM Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers
REM Created by Kelly Michels · dev@evomedia.net REM Created by Kelly Michels · dev@evomedia.net
REM Licensed under the MIT License. See LICENSE. REM Licensed under the MIT License. See LICENSE.
REM Version: v1.0.0.0.0
@echo off @echo off
powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0zec2online.ps1" %* powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0zec2online.ps1" %*

View File

@ -1,6 +1,7 @@
# Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers # Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers
# Created by Kelly Michels · dev@evomedia.net # Created by Kelly Michels · dev@evomedia.net
# Licensed under the MIT License. See LICENSE. # Licensed under the MIT License. See LICENSE.
# Version: v1.0.0.0.0
# zec2online.ps1 — deep health check: verify apps are live AND running the expected # zec2online.ps1 — deep health check: verify apps are live AND running the expected
# build; auto-start downed stacks via docker compose and stream diagnostics. # build; auto-start downed stacks via docker compose and stream diagnostics.

View File

@ -1,6 +1,7 @@
REM Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers REM Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers
REM Created by Kelly Michels · dev@evomedia.net REM Created by Kelly Michels · dev@evomedia.net
REM Licensed under the MIT License. See LICENSE. REM Licensed under the MIT License. See LICENSE.
REM Version: v1.0.0.0.0
@echo off @echo off
powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0ZKillOnly.ps1" %* powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0ZKillOnly.ps1" %*

View File

@ -1,6 +1,7 @@
# Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers # Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers
# Created by Kelly Michels · dev@evomedia.net # Created by Kelly Michels · dev@evomedia.net
# Licensed under the MIT License. See LICENSE. # Licensed under the MIT License. See LICENSE.
# Version: v1.0.0.0.0
# zkill.ps1 — alias for ZKillOnly.ps1 (kept so both names work). All args pass through. # zkill.ps1 — alias for ZKillOnly.ps1 (kept so both names work). All args pass through.
& (Join-Path $PSScriptRoot "ZKillOnly.ps1") @args & (Join-Path $PSScriptRoot "ZKillOnly.ps1") @args

7
zrelease.cmd Normal file
View File

@ -0,0 +1,7 @@
REM Evomedia.net — https://github.com/kellymichels/zscripts-token-savers
REM Created by Kelly Michels · dev@evomedia.net
REM Licensed under the MIT License. See LICENSE.
REM Version: v1.0.0.0.0
@echo off
powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0zrelease.ps1" %*

146
zrelease.ps1 Normal file
View File

@ -0,0 +1,146 @@
# Evomedia.net — https://github.com/kellymichels/zscripts-token-savers
# Created by Kelly Michels · dev@evomedia.net
# Licensed under the MIT License. See LICENSE.
# Version: v1.0.0.0.0
# zrelease.ps1 - package the current version as a downloadable zip.
#
# Usage:
# zrelease build releases/zscripts-<version>.zip
# zrelease -Force overwrite an existing zip for this version
# zrelease -Verify re-check the zip already on disk for this version
#
# For people who want the toolkit without cloning: one zip, one hash to check.
#
# WHAT GOES IN
# ------------
# every *.ps1 / *.cmd the commands themselves
# CHECKSUMS.txt per-file manifest, so the contents can be
# re-verified after unzipping
# zconfig.example.json you need it to configure anything
# README.md, CHANGELOG.md, LICENSE, TOKEN_SAVINGS.md
# build-version.json which release this is
#
# Left out: tests/ (a user does not need the suite to run the commands) and
# releases/ (never package the packages).
#
# WHAT COMES OUT
# releases/zscripts-v1.0.0.0.1.zip
# releases/zscripts-v1.0.0.0.1.zip.sha256 <- sha256sum format, one line
#
# Two layers on purpose: the .sha256 verifies you downloaded the zip intact,
# and CHECKSUMS.txt inside verifies the individual scripts after extraction.
# Both are integrity checks, not signatures - see the note in zchecksums.ps1.
[CmdletBinding()]
param(
[switch]$Force,
[switch]$Verify
)
$ErrorActionPreference = "Stop"
$ReleasesDir = Join-Path $PSScriptRoot "releases"
$VersionFile = Join-Path $PSScriptRoot "build-version.json"
if (-not (Test-Path -LiteralPath $VersionFile)) {
Write-Host "ERROR: build-version.json not found. Run 'zversion set v1.0.0.0.0' first." -ForegroundColor Red
exit 1
}
$version = (Get-Content -LiteralPath $VersionFile -Raw -Encoding UTF8 | ConvertFrom-Json).version
if ($version -notmatch '^v\d+\.\d+\.\d+\.\d+\.\d+$') {
Write-Host "ERROR: build-version.json holds an invalid version '$version'." -ForegroundColor Red
exit 1
}
$zipName = "zscripts-$version.zip"
$zipPath = Join-Path $ReleasesDir $zipName
$shaPath = "$zipPath.sha256"
function Get-Sha256([string]$Path) {
return (Get-FileHash -LiteralPath $Path -Algorithm SHA256).Hash.ToLowerInvariant()
}
# ---- verify mode -------------------------------------------------------------
if ($Verify) {
if (-not (Test-Path -LiteralPath $zipPath)) {
Write-Host "ERROR: $zipName not found in releases/." -ForegroundColor Red
exit 1
}
if (-not (Test-Path -LiteralPath $shaPath)) {
Write-Host "ERROR: $zipName.sha256 not found." -ForegroundColor Red
exit 1
}
$expected = ((Get-Content -LiteralPath $shaPath -Raw) -split '\s+')[0].ToLowerInvariant()
$actual = Get-Sha256 $zipPath
Write-Host ""
Write-Host "=== zrelease (verify) ===" -ForegroundColor Cyan
if ($actual -eq $expected) {
Write-Host " OK - $zipName matches its .sha256." -ForegroundColor Green
Write-Host ""
exit 0
}
Write-Host " FAILED - $zipName does not match its .sha256." -ForegroundColor Red
Write-Host ""
exit 1
}
# ---- build mode --------------------------------------------------------------
if ((Test-Path -LiteralPath $zipPath) -and -not $Force) {
Write-Host ""
Write-Host "ERROR: releases/$zipName already exists." -ForegroundColor Red
Write-Host " A released version is immutable - bump instead: zversion bump" -ForegroundColor DarkGray
Write-Host " (or pass -Force if you are rebuilding one that was never published)" -ForegroundColor DarkGray
Write-Host ""
exit 1
}
# Refuse to package scripts that disagree with the manifest.
& (Join-Path $PSScriptRoot "zchecksums.ps1") -Quiet | Out-Null
if ($LASTEXITCODE -ne 0) {
Write-Host ""
Write-Host "ERROR: checksum verification failed - refusing to package." -ForegroundColor Red
Write-Host " Run 'zchecksums' to see what differs, then 'zversion bump' to restamp." -ForegroundColor DarkGray
Write-Host ""
exit 1
}
New-Item -ItemType Directory -Force -Path $ReleasesDir | Out-Null
$staging = Join-Path ([IO.Path]::GetTempPath()) ("zrel-" + [guid]::NewGuid().ToString("N"))
New-Item -ItemType Directory -Path $staging -Force | Out-Null
try {
$scripts = @(Get-ChildItem -LiteralPath $PSScriptRoot -File | Where-Object { $_.Extension -in @('.ps1', '.cmd') })
foreach ($f in $scripts) { Copy-Item -LiteralPath $f.FullName -Destination $staging }
$extras = @('CHECKSUMS.txt', 'zconfig.example.json', 'README.md', 'CHANGELOG.md', 'LICENSE', 'TOKEN_SAVINGS.md', 'build-version.json')
$included = @()
foreach ($name in $extras) {
$p = Join-Path $PSScriptRoot $name
if (Test-Path -LiteralPath $p) { Copy-Item -LiteralPath $p -Destination $staging; $included += $name }
}
if (Test-Path -LiteralPath $zipPath) { Remove-Item -LiteralPath $zipPath -Force }
Add-Type -AssemblyName System.IO.Compression.FileSystem -ErrorAction SilentlyContinue
[IO.Compression.ZipFile]::CreateFromDirectory($staging, $zipPath, [IO.Compression.CompressionLevel]::Optimal, $false)
}
finally {
Remove-Item -LiteralPath $staging -Recurse -Force -ErrorAction SilentlyContinue
}
$hash = Get-Sha256 $zipPath
# sha256sum format, LF ending, so `sha256sum -c` works on Linux/macOS.
[IO.File]::WriteAllText($shaPath, "$hash $zipName`n", (New-Object Text.UTF8Encoding($false)))
$sizeKb = [math]::Round((Get-Item -LiteralPath $zipPath).Length / 1KB, 1)
Write-Host ""
Write-Host "=== zrelease ===" -ForegroundColor Cyan
Write-Host " Version: $version" -ForegroundColor Green
Write-Host " Zip: releases/$zipName ($sizeKb KB, $($scripts.Count) scripts + $($included.Count) support file(s))" -ForegroundColor Gray
Write-Host " SHA-256: $hash" -ForegroundColor Gray
Write-Host " Digest: releases/$zipName.sha256" -ForegroundColor Gray
Write-Host ""
Write-Host " Commit both files - a release lives in the repo under releases/." -ForegroundColor DarkGray
Write-Host ""
exit 0

View File

@ -1,6 +1,7 @@
REM Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers REM Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers
REM Created by Kelly Michels · dev@evomedia.net REM Created by Kelly Michels · dev@evomedia.net
REM Licensed under the MIT License. See LICENSE. REM Licensed under the MIT License. See LICENSE.
REM Version: v1.0.0.0.0
@echo off @echo off
powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0zrepair.ps1" %* powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0zrepair.ps1" %*

View File

@ -1,6 +1,7 @@
# Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers # Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers
# Created by Kelly Michels · dev@evomedia.net # Created by Kelly Michels · dev@evomedia.net
# Licensed under the MIT License. See LICENSE. # Licensed under the MIT License. See LICENSE.
# Version: v1.0.0.0.0
# zrepair.ps1 — audit and repair container/proxy routing on the server, then smoke test. # zrepair.ps1 — audit and repair container/proxy routing on the server, then smoke test.
# #

View File

@ -1,6 +1,7 @@
REM Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers REM Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers
REM Created by Kelly Michels · dev@evomedia.net REM Created by Kelly Michels · dev@evomedia.net
REM Licensed under the MIT License. See LICENSE. REM Licensed under the MIT License. See LICENSE.
REM Version: v1.0.0.0.0
@echo off @echo off
powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0ZKiller.ps1" %* powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0ZKiller.ps1" %*

View File

@ -1,6 +1,7 @@
# Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers # Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers
# Created by Kelly Michels · dev@evomedia.net # Created by Kelly Michels · dev@evomedia.net
# Licensed under the MIT License. See LICENSE. # Licensed under the MIT License. See LICENSE.
# Version: v1.0.0.0.0
# zrestart.ps1 — alias for ZKiller.ps1 (kept so both names work). All args pass through. # zrestart.ps1 — alias for ZKiller.ps1 (kept so both names work). All args pass through.
& (Join-Path $PSScriptRoot "ZKiller.ps1") @args & (Join-Path $PSScriptRoot "ZKiller.ps1") @args

View File

@ -1,6 +1,7 @@
REM Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers REM Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers
REM Created by Kelly Michels · dev@evomedia.net REM Created by Kelly Michels · dev@evomedia.net
REM Licensed under the MIT License. See LICENSE. REM Licensed under the MIT License. See LICENSE.
REM Version: v1.0.0.0.0
@echo off @echo off
powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0ZKiller.ps1" -Detached %* powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0ZKiller.ps1" -Detached %*

View File

@ -1,6 +1,7 @@
REM Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers REM Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers
REM Created by Kelly Michels · dev@evomedia.net REM Created by Kelly Michels · dev@evomedia.net
REM Licensed under the MIT License. See LICENSE. REM Licensed under the MIT License. See LICENSE.
REM Version: v1.0.0.0.0
@echo off @echo off
powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0zsetup.ps1" %* powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0zsetup.ps1" %*

View File

@ -1,6 +1,7 @@
# Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers # Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers
# Created by Kelly Michels · dev@evomedia.net # Created by Kelly Michels · dev@evomedia.net
# Licensed under the MIT License. See LICENSE. # Licensed under the MIT License. See LICENSE.
# Version: v1.0.0.0.0
# zsetup.ps1 — prepare a project for local dev: create its Python venv and install # zsetup.ps1 — prepare a project for local dev: create its Python venv and install
# dependencies (python kind), or run `npm install` (vite/nextjs). Idempotent - # dependencies (python kind), or run `npm install` (vite/nextjs). Idempotent -

View File

@ -1,6 +1,7 @@
# Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers # Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers
# Created by Kelly Michels · dev@evomedia.net # Created by Kelly Michels · dev@evomedia.net
# Licensed under the MIT License. See LICENSE. # Licensed under the MIT License. See LICENSE.
# Version: v1.0.0.0.0
# zsetup_mail.ps1 — create admin@ and noreply@ mailboxes in a docker-mailserver # zsetup_mail.ps1 — create admin@ and noreply@ mailboxes in a docker-mailserver
# container on the server, and print the DNS records + SMTP/IMAP settings to use. # container on the server, and print the DNS records + SMTP/IMAP settings to use.

View File

@ -1,6 +1,7 @@
REM Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers REM Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers
REM Created by Kelly Michels · dev@evomedia.net REM Created by Kelly Michels · dev@evomedia.net
REM Licensed under the MIT License. See LICENSE. REM Licensed under the MIT License. See LICENSE.
REM Version: v1.0.0.0.0
@echo off @echo off
powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0ZStart.ps1" %* powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0ZStart.ps1" %*

View File

@ -1,6 +1,7 @@
# Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers # Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers
# Created by Kelly Michels · dev@evomedia.net # Created by Kelly Michels · dev@evomedia.net
# Licensed under the MIT License. See LICENSE. # Licensed under the MIT License. See LICENSE.
# Version: v1.0.0.0.0
# zstart.ps1 — start local dev servers for any project defined in zconfig.json. # zstart.ps1 — start local dev servers for any project defined in zconfig.json.
# #

View File

@ -1,6 +1,7 @@
REM Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers REM Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers
REM Created by Kelly Michels · dev@evomedia.net REM Created by Kelly Michels · dev@evomedia.net
REM Licensed under the MIT License. See LICENSE. REM Licensed under the MIT License. See LICENSE.
REM Version: v1.0.0.0.0
@echo off @echo off
powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0zstart_docker.ps1" %* powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0zstart_docker.ps1" %*

View File

@ -1,6 +1,7 @@
# Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers # Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers
# Created by Kelly Michels · dev@evomedia.net # Created by Kelly Michels · dev@evomedia.net
# Licensed under the MIT License. See LICENSE. # Licensed under the MIT License. See LICENSE.
# Version: v1.0.0.0.0
# zstart_docker.ps1 — bring up a local docker compose stack from <scriptsRoot>\docker\. # zstart_docker.ps1 — bring up a local docker compose stack from <scriptsRoot>\docker\.
# #

View File

@ -1,6 +1,7 @@
REM Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers REM Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers
REM Created by Kelly Michels · dev@evomedia.net REM Created by Kelly Michels · dev@evomedia.net
REM Licensed under the MIT License. See LICENSE. REM Licensed under the MIT License. See LICENSE.
REM Version: v1.0.0.0.0
@echo off @echo off
powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0ZStart.ps1" -Detached %* powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0ZStart.ps1" -Detached %*

View File

@ -1,6 +1,7 @@
# Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers # Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers
# Created by Kelly Michels · dev@evomedia.net # Created by Kelly Michels · dev@evomedia.net
# Licensed under the MIT License. See LICENSE. # Licensed under the MIT License. See LICENSE.
# Version: v1.0.0.0.0
# zstop.ps1 — stop docker compose stacks on the server without removing data or files. # zstop.ps1 — stop docker compose stacks on the server without removing data or files.
# #

View File

@ -1,6 +1,7 @@
REM Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers REM Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers
REM Created by Kelly Michels · dev@evomedia.net REM Created by Kelly Michels · dev@evomedia.net
REM Licensed under the MIT License. See LICENSE. REM Licensed under the MIT License. See LICENSE.
REM Version: v1.0.0.0.0
@echo off @echo off
powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0zsync.ps1" %* powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0zsync.ps1" %*

View File

@ -1,6 +1,7 @@
# Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers # Evomedia.net Token Savers — https://github.com/kellymichels/zscripts-token-savers
# Created by Kelly Michels · dev@evomedia.net # Created by Kelly Michels · dev@evomedia.net
# Licensed under the MIT License. See LICENSE. # Licensed under the MIT License. See LICENSE.
# Version: v1.0.0.0.0
# zsync.ps1 — copy new backup files offsite; or build + mirror a vite project's dist. # zsync.ps1 — copy new backup files offsite; or build + mirror a vite project's dist.
# #

7
zversion.cmd Normal file
View File

@ -0,0 +1,7 @@
REM Evomedia.net — https://github.com/kellymichels/zscripts-token-savers
REM Created by Kelly Michels · dev@evomedia.net
REM Licensed under the MIT License. See LICENSE.
REM Version: v1.0.0.0.0
@echo off
powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0zversion.ps1" %*

154
zversion.ps1 Normal file
View File

@ -0,0 +1,154 @@
# Evomedia.net — https://github.com/kellymichels/zscripts-token-savers
# Created by Kelly Michels · dev@evomedia.net
# Licensed under the MIT License. See LICENSE.
# Version: v1.0.0.0.0
# zversion.ps1 - manage the toolkit version.
#
# Usage:
# zversion print the current version
# zversion bump build + 1 (one bump per PR / per defect fix)
# zversion bump-stage alpha alpha + 1, build -> 0
# zversion bump-stage beta beta + 1, alpha/build -> 0
# zversion bump-stage rc rc + 1, beta/alpha/build -> 0
# zversion bump-stage release major + 1, everything below -> 0
# zversion set v1.2.0.0.5 set an exact version
#
# THE SCHEME
# ----------
# v{major}.{rc}.{beta}.{alpha}.{build}
#
# Priority runs left to right, and bumping any stage zeroes every lower segment
# including build. One version for the whole toolkit, not per script.
#
# WHAT A BUMP TOUCHES
# -------------------
# Anything other than a plain read rewrites three things together, because they
# are only useful if they agree:
# 1. build-version.json - the source of truth
# 2. the "# Version:" line in every .ps1 / .cmd header, so a script that has
# been copied out of the repo still says which release it came from
# 3. CHECKSUMS.txt - stamping changes every file, so the manifest must
# be regenerated or verification fails immediately
#
# Run this on a clean checkout: it hashes files as they sit on disk, and an
# editor that writes LF leaves a file git still considers unchanged. See the
# note in zchecksums.ps1.
[CmdletBinding()]
param(
[Parameter(Position = 0)][string]$Command = "get",
[Parameter(Position = 1)][string]$Value
)
$ErrorActionPreference = "Stop"
$VersionFile = Join-Path $PSScriptRoot "build-version.json"
$VersionRe = '^v(\d+)\.(\d+)\.(\d+)\.(\d+)\.(\d+)$'
$DefaultVersion = "v1.0.0.0.0"
function Read-Version {
if (-not (Test-Path -LiteralPath $VersionFile)) { return $DefaultVersion }
try {
$v = (Get-Content -LiteralPath $VersionFile -Raw -Encoding UTF8 | ConvertFrom-Json).version
if ($v -match $VersionRe) { return $v }
} catch { }
return $DefaultVersion
}
function Write-Version([string]$Version) {
$json = [ordered]@{ version = $Version } | ConvertTo-Json
[IO.File]::WriteAllText($VersionFile, $json + "`n", (New-Object Text.UTF8Encoding($false)))
}
function Split-Version([string]$Version) {
if ($Version -notmatch $VersionRe) {
throw "Invalid version '$Version'. Expected v{major}.{rc}.{beta}.{alpha}.{build}, e.g. v1.0.0.0.3."
}
return [int[]]@($Matches[1], $Matches[2], $Matches[3], $Matches[4], $Matches[5])
}
# Rewrite (or insert) the "# Version:" header line in every covered script.
function Set-ScriptVersionHeaders([string]$Version) {
$stamped = 0
foreach ($f in Get-ChildItem -LiteralPath $PSScriptRoot -File | Where-Object { $_.Extension -in @('.ps1', '.cmd') }) {
$text = [IO.File]::ReadAllText($f.FullName)
# Keep each file's own comment marker: # for PowerShell, REM for cmd.
$marker = if ($f.Extension -eq '.cmd') { 'REM' } else { '#' }
$line = "$marker Version: $Version"
if ($text -match "(?m)^(#|REM) Version: v[\d\.]+\r?$") {
$new = [regex]::Replace($text, "(?m)^(#|REM) Version: v[\d\.]+\r?$", [System.Text.RegularExpressions.MatchEvaluator] { param($m) $line })
} else {
# Insert directly after the licence line, which every header carries.
$pattern = "(?m)^((#|REM) Licensed under the MIT License\. See LICENSE\.)\r?$"
if ($text -notmatch $pattern) { continue }
$new = [regex]::Replace($text, $pattern, [System.Text.RegularExpressions.MatchEvaluator] { param($m) $m.Groups[1].Value + "`r`n" + $line }, 1)
}
if ($new -ne $text) {
# .ps1/.cmd are pinned to CRLF by .gitattributes - write them that
# way or every stamped file shows up as changed on the next clone.
$new = ($new -replace "`r`n", "`n") -replace "`n", "`r`n"
[IO.File]::WriteAllText($f.FullName, $new, (New-Object Text.UTF8Encoding($false)))
$stamped++
}
}
return $stamped
}
function Update-Everything([string]$Version) {
Write-Version $Version
$n = Set-ScriptVersionHeaders $Version
& (Join-Path $PSScriptRoot "zchecksums.ps1") -Update | Out-Null
Write-Host ""
Write-Host "=== zversion ===" -ForegroundColor Cyan
Write-Host " Version: $Version" -ForegroundColor Green
Write-Host " Stamped: $n script header(s)" -ForegroundColor Gray
Write-Host " Refreshed: CHECKSUMS.txt" -ForegroundColor Gray
Write-Host " Commit build-version.json, the stamped scripts and CHECKSUMS.txt together." -ForegroundColor DarkGray
Write-Host ""
}
$current = Read-Version
switch ($Command.ToLowerInvariant().TrimStart('-')) {
"get" {
Write-Host $current
exit 0
}
"bump" {
$p = Split-Version $current
Update-Everything ("v{0}.{1}.{2}.{3}.{4}" -f $p[0], $p[1], $p[2], $p[3], ($p[4] + 1))
exit 0
}
"bump-stage" {
$p = Split-Version $current
$major, $rc, $beta, $alpha = $p[0], $p[1], $p[2], $p[3]
switch (("$Value").ToLowerInvariant()) {
"release" { $major++; $rc = 0; $beta = 0; $alpha = 0 }
"rc" { $rc++; $beta = 0; $alpha = 0 }
"beta" { $beta++; $alpha = 0 }
"alpha" { $alpha++ }
default {
Write-Host "ERROR: stage must be one of: release, rc, beta, alpha" -ForegroundColor Red
exit 1
}
}
# Bumping a stage zeroes every lower segment, build included.
Update-Everything ("v{0}.{1}.{2}.{3}.0" -f $major, $rc, $beta, $alpha)
exit 0
}
"set" {
[void](Split-Version $Value)
Update-Everything $Value
exit 0
}
default {
Write-Host ""
Write-Host "Usage: zversion [get | bump | bump-stage <release|rc|beta|alpha> | set <version>]" -ForegroundColor Yellow
Write-Host " Scheme: v{major}.{rc}.{beta}.{alpha}.{build} (current: $current)" -ForegroundColor Gray
Write-Host " bump build + 1 - one per PR, one per defect fix" -ForegroundColor Gray
Write-Host " bump-stage raise a stage; every lower segment resets to 0" -ForegroundColor Gray
Write-Host ""
exit 1
}
}