zscripts-token-savers/zversion.ps1
Kelly Michels 560a2064a2
chore(release): v1.0.0.0.22 (#67)
Build stamp catch-up for 1 merged PR(s) since v1.0.0.0.21:
  40fa250 refactor(tests): move the sanitization denylist to a data file both sides can read (#66)
2026-08-31 17:56:24 -05:00

167 lines
6.8 KiB
PowerShell

# Evomedia.net — https://github.com/evomedia-net/evo.zscripts
# Created by Kelly Michels · dev@evomedia.net
# Licensed under the MIT License. See LICENSE.
# Version: v1.0.0.0.22
# zversion.ps1 - manage the toolkit version.
#
# Usage:
# zversion print the current version
# zversion bump build + 1 (one bump per release)
# 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"
# Two blank lines after this script's output, matching every other z-script, so
# a run is visually separated from the next prompt. Local rather than from
# ZHelpers: this script is deliberately standalone, so it can run from an
# extracted release zip with nothing beside it.
function Write-ZTrailer { Write-Host ""; Write-Host "" }
$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
Write-ZTrailer
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))
Write-ZTrailer
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
Write-ZTrailer
exit 1
}
}
# Bumping a stage zeroes every lower segment, build included.
Update-Everything ("v{0}.{1}.{2}.{3}.0" -f $major, $rc, $beta, $alpha)
Write-ZTrailer
exit 0
}
"set" {
[void](Split-Version $Value)
Update-Everything $Value
Write-ZTrailer
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 release, not one per PR" -ForegroundColor Gray
Write-Host " bump-stage raise a stage; every lower segment resets to 0" -ForegroundColor Gray
Write-ZTrailer
exit 1
}
}