fix(ci): guard migration SQL files against exceeding the manifest version
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Has been skipped
Generic: Project CI / Lint & Validate (pull_request) Has been cancelled
Universal: PR Check / Branch Policy (pull_request) Has been cancelled
Universal: PR Check / Secret Scan (pull_request) Has been cancelled
Universal: PR Check / Validate PR (pull_request) Has been cancelled
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Has been cancelled
Generic: Repo Health / Access control (pull_request) Has been cancelled
Generic: Repo Health / Site Health (pull_request) Has been cancelled
Branch Cleanup / Delete merged branch (pull_request) Has been cancelled
RC Revert / Rename rc/ back to dev/ (pull_request) Has been cancelled
Universal: Workflow Sync Trigger / Sync workflows to live repos (pull_request) Has been cancelled
Generic: Project CI / Tests (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled

Rework the SQL-schema check so each component is validated against ITS OWN
manifest version instead of a single package-level version applied to every
sql/updates/mysql dir (which mis-flagged independently-versioned sub-extensions).

Add check #11: fail if any update file version exceeds its component manifest
version. This catches migration files drifting onto a different numbering lane
and getting ahead of the release version (e.g. 01.14.00.sql while the manifest
is 01.01.40) at PR time instead of surfacing as a runtime schema mismatch.

Authored-by: Moko Consulting
Claude-Session: https://claude.ai/code/session_01VXrBk7psPzJPHVuBDJwt2x
This commit is contained in:
2026-07-12 21:37:03 +00:00
parent 585e40245c
commit 8c579a2841
+47 -21
View File
@@ -502,28 +502,54 @@ jobs:
done <<< "$INSTALL_FILES"
fi
# 10. Current manifest version should have an update SQL file
MANIFEST=""
for XML_FILE in $(find . -maxdepth 2 -name "*.xml" -not -path "./.git/*" -not -path "./vendor/*"); do
if grep -q "<extension" "$XML_FILE" 2>/dev/null; then
MANIFEST="$XML_FILE"
break
fi
done
if [ -n "$MANIFEST" ]; then
MANIFEST_VERSION=$(grep -oP '<version>\K[^<]+' "$MANIFEST" 2>/dev/null | head -1)
if [ -n "$MANIFEST_VERSION" ]; then
UPDATE_DIRS=$(find . -path "*/sql/updates/mysql" -type d -not -path "./.git/*" 2>/dev/null)
if [ -n "$UPDATE_DIRS" ]; then
while IFS= read -r UPDATE_DIR; do
if [ ! -f "${UPDATE_DIR}/${MANIFEST_VERSION}.sql" ]; then
echo "::error file=${MANIFEST}::No update SQL file for current version ${MANIFEST_VERSION}"
echo "- **Missing \`${UPDATE_DIR}/${MANIFEST_VERSION}.sql\`** — update file must exist for manifest version" >> $GITHUB_STEP_SUMMARY
ERRORS=$((ERRORS + 1))
fi
done <<< "$UPDATE_DIRS"
# 10 & 11. Per-component schema/version consistency. Each component
# versions independently, so resolve every sql/updates/mysql dir
# against ITS OWN manifest (not one package-level version):
# (10) the component's manifest version must have a matching update file
# (11) no update file may exceed the component's manifest version
# (this is the guard that catches migration files drifting onto
# a different numbering lane and getting ahead of the release)
UPDATE_DIRS=$(find . -path "*/sql/updates/mysql" -type d -not -path "./.git/*" 2>/dev/null)
if [ -n "$UPDATE_DIRS" ]; then
while IFS= read -r UPDATE_DIR; do
# Component root is three levels up from <root>/sql/updates/mysql
COMP_ROOT=$(dirname "$(dirname "$(dirname "$UPDATE_DIR")")")
# Resolve this component's OWN manifest (XML with <extension> at its root)
COMP_MANIFEST=""
for XML_FILE in "$COMP_ROOT"/*.xml; do
[ -f "$XML_FILE" ] || continue
if grep -q "<extension" "$XML_FILE" 2>/dev/null; then
COMP_MANIFEST="$XML_FILE"
break
fi
done
if [ -z "$COMP_MANIFEST" ]; then
echo "- No component manifest found for \`${UPDATE_DIR}\` — skipping version match" >> $GITHUB_STEP_SUMMARY
continue
fi
fi
COMP_VERSION=$(grep -oP '<version>\K[^<]+' "$COMP_MANIFEST" 2>/dev/null | head -1)
[ -z "$COMP_VERSION" ] && continue
# Normalise: strip any pre-release suffix (-dev, -rc.N, ...) for comparison
CV_BASE=$(echo "$COMP_VERSION" | sed -E 's/-.*$//')
# (10) a matching update file must exist for the component version
if [ ! -f "${UPDATE_DIR}/${CV_BASE}.sql" ]; then
echo "::error file=${COMP_MANIFEST}::No update SQL file for version ${CV_BASE}"
echo "- **Missing \`${UPDATE_DIR}/${CV_BASE}.sql\`** — update file must exist for manifest version \`${CV_BASE}\`" >> $GITHUB_STEP_SUMMARY
ERRORS=$((ERRORS + 1))
fi
# (11) no update file may exceed the component version
for UFILE in "$UPDATE_DIR"/*.sql; do
[ -f "$UFILE" ] || continue
UVER=$(basename "$UFILE" .sql)
echo "$UVER" | grep -qP '^\d+\.\d+\.\d+$' || continue
TOP=$(printf '%s\n%s\n' "$CV_BASE" "$UVER" | sort -V | tail -1)
if [ "$UVER" != "$CV_BASE" ] && [ "$TOP" = "$UVER" ]; then
echo "::error file=${UFILE}::Update file ${UVER} exceeds manifest version ${CV_BASE}"
echo "- **Update file \`${UVER}.sql\` exceeds manifest version \`${CV_BASE}\`** — renumber onto the release lane (must be <= manifest)" >> $GITHUB_STEP_SUMMARY
ERRORS=$((ERRORS + 1))
fi
done
done <<< "$UPDATE_DIRS"
fi
fi