Update verify_changelog.sh

This commit is contained in:
2025-12-18 16:58:32 -06:00
parent 785312d4a7
commit b83c6f4791

View File

@@ -1,71 +1,66 @@
<?php #!/usr/bin/env bash
/** #
* verify_changelog.php # Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
* #
* Verifies that CHANGELOG.md is compliant with basic release governance rules. # This file is part of a Moko Consulting project.
* #
* Enforced rules # SPDX-License-Identifier: GPL-3.0-or-later
* - CHANGELOG.md must exist at repository root. #
* - File must not contain unresolved placeholders such as "UNRELEASED" or "TBD". # FILE INFORMATION
* - Headings must follow semantic version format: ## [NN.NN.NN] # DEFGROUP: MokoStandards
* - The highest version must appear first. # INGROUP: Tooling.Changelog
* # FILE: verify_changelog.sh
* Intended usage # BRIEF: Validate CHANGELOG.md governance rules for CI enforcement
* - CI validation step (read-only). #
* - Does not modify files. # PURPOSE:
* # Validate that CHANGELOG.md contains only released, properly ordered entries and complies with MokoStandards governance rules.
* Exit codes
* - 0: Changelog is valid
* - 1: Validation failure
*/
$changelog = 'CHANGELOG.md'; set -euo pipefail
if (!file_exists($changelog)) { CHANGELOG="CHANGELOG.md"
fwrite(STDERR, "ERROR: CHANGELOG.md not found at repository root\n");
exit(1);
}
$content = file_get_contents($changelog); if [ ! -f "$CHANGELOG" ]; then
if ($content === false) { echo "ERROR: CHANGELOG.md not found at repository root" >&2
fwrite(STDERR, "ERROR: Unable to read CHANGELOG.md\n"); exit 1
exit(1); fi
}
$errors = []; CONTENT="$(cat "$CHANGELOG")"
// Rule: no unresolved placeholders if echo "$CONTENT" | grep -Eiq '^##[[:space:]]*\[?TODO\]?'; then
$placeholders = ['UNRELEASED', 'TBD', 'TO DO', 'TODO']; echo "ERROR: TODO section detected in CHANGELOG.md." >&2
foreach ($placeholders as $token) { echo "CHANGELOG.md must contain released versions only." >&2
if (stripos($content, $token) !== false) { echo "Move all TODO items to TODO.md and remove the section from CHANGELOG.md." >&2
$errors[] = "Unresolved placeholder detected: {$token}"; exit 1
} fi
}
// Rule: extract version headings if echo "$CONTENT" | grep -Eiq 'UNRELEASED'; then
preg_match_all('/^## \[([0-9]+\.[0-9]+\.[0-9]+)\]/m', $content, $matches); echo "ERROR: UNRELEASED placeholder detected in CHANGELOG.md." >&2
$versions = $matches[1] ?? []; exit 1
fi
if (empty($versions)) { for token in "TBD" "TO BE DETERMINED" "PLACEHOLDER"; do
$errors[] = 'No version headings found (expected format: ## [NN.NN.NN])'; if echo "$CONTENT" | grep -Eiq "$token"; then
} else { echo "ERROR: Unresolved placeholder detected: $token" >&2
// Rule: highest version first exit 1
$sorted = $versions; fi
usort($sorted, 'version_compare'); done
$sorted = array_reverse($sorted);
if ($versions !== $sorted) { mapfile -t versions < <(
$errors[] = 'Versions are not ordered from newest to oldest'; grep -E '^## \[[0-9]+\.[0-9]+\.[0-9]+\] [0-9]{4}-[0-9]{2}-[0-9]{2}$' "$CHANGELOG" \
} | sed -E 's/^## \[([0-9]+\.[0-9]+\.[0-9]+)\].*/\1/'
} )
if (!empty($errors)) { if [ "${#versions[@]}" -eq 0 ]; then
fwrite(STDERR, "CHANGELOG.md validation failed:\n"); echo "ERROR: No valid version headings found in CHANGELOG.md" >&2
foreach ($errors as $err) { exit 1
fwrite(STDERR, " - {$err}\n"); fi
}
exit(1);
}
echo "CHANGELOG.md validation passed\n"; sorted_versions="$(printf '%s\n' "${versions[@]}" | sort -Vr)"
exit(0);
if [ "$(printf '%s\n' "${versions[@]}")" != "$sorted_versions" ]; then
echo "ERROR: Versions are not ordered from newest to oldest" >&2
exit 1
fi
echo "CHANGELOG.md validation passed"
exit 0