Update version_branch.yml

This commit is contained in:
2025-12-16 16:35:52 -06:00
parent 56f2a113cf
commit 951be2907e

View File

@@ -1,10 +1,10 @@
name: Create version branch and bump versions
name: Create version branch and bump versions (src and docs only)
on:
workflow_dispatch:
inputs:
new_version:
description: "New version in format NN.NN.NN (example 01.03.00)"
description: "New version in format NN.NN.NN (example 03.01.00)"
required: true
base_branch:
description: "Base branch to branch from"
@@ -47,22 +47,21 @@ jobs:
shell: bash
run: |
set -Eeuo pipefail
trap 'echo "[FATAL] Validation error at line $LINENO" >&2' ERR
trap 'echo "[FATAL] Validation error at line $LINENO" >&2; echo "[FATAL] Last command: $BASH_COMMAND" >&2' ERR
echo "[INFO] Inputs received:"
echo " NEW_VERSION=${NEW_VERSION}"
echo " BASE_BRANCH=${BASE_BRANCH}"
echo " BRANCH_PREFIX=${BRANCH_PREFIX}"
echo " COMMIT_CHANGES=${COMMIT_CHANGES}"
[[ -n "${NEW_VERSION}" ]] || { echo "[ERROR] new_version missing"; exit 2; }
[[ "${NEW_VERSION}" =~ ^[0-9]{2}\.[0-9]{2}\.[0-9]{2}$ ]] || {
echo "[ERROR] Invalid version format: ${NEW_VERSION}"
exit 2
}
[[ -n "${NEW_VERSION}" ]] || { echo "[ERROR] new_version missing" >&2; exit 2; }
[[ "${NEW_VERSION}" =~ ^[0-9]{2}\.[0-9]{2}\.[0-9]{2}$ ]] || { echo "[ERROR] Invalid version format: ${NEW_VERSION}" >&2; exit 2; }
git show-ref --verify --quiet "refs/remotes/origin/${BASE_BRANCH}" || {
echo "[ERROR] Base branch does not exist on origin: ${BASE_BRANCH}"
git branch -a
git ls-remote --exit-code --heads origin "${BASE_BRANCH}" >/dev/null 2>&1 || {
echo "[ERROR] Base branch does not exist on origin: ${BASE_BRANCH}" >&2
echo "[INFO] Remote branches:"
git ls-remote --heads origin | awk '{sub("refs/heads/","",$2); print $2}'
exit 2
}
@@ -72,6 +71,8 @@ jobs:
shell: bash
run: |
set -Eeuo pipefail
trap 'echo "[FATAL] Git identity step failed at line $LINENO" >&2; echo "[FATAL] Last command: $BASH_COMMAND" >&2' ERR
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
echo "[INFO] Git identity configured"
@@ -80,78 +81,198 @@ jobs:
shell: bash
run: |
set -Eeuo pipefail
trap 'echo "[FATAL] Branch creation failed at line $LINENO" >&2' ERR
trap 'echo "[FATAL] Branch creation failed at line $LINENO" >&2; echo "[FATAL] Last command: $BASH_COMMAND" >&2' ERR
BRANCH_NAME="${BRANCH_PREFIX}${NEW_VERSION}"
echo "[INFO] Creating branch ${BRANCH_NAME}"
echo "[INFO] Creating branch: ${BRANCH_NAME} from origin/${BASE_BRANCH}"
git fetch --all --tags --prune
if git ls-remote --exit-code --heads origin "${BRANCH_NAME}" >/dev/null 2>&1; then
echo "[ERROR] Branch already exists on origin: ${BRANCH_NAME}"
echo "[ERROR] Branch already exists on origin: ${BRANCH_NAME}" >&2
exit 2
fi
git checkout -B "${BRANCH_NAME}" "origin/${BASE_BRANCH}"
echo "BRANCH_NAME=${BRANCH_NAME}" >> "$GITHUB_ENV"
- name: Bump versions in headers and XML
- name: Preflight discovery (src and docs only)
shell: bash
run: |
set -Eeuo pipefail
trap 'echo "[FATAL] Version bump failed at line $LINENO" >&2' ERR
trap 'echo "[FATAL] Preflight failed at line $LINENO" >&2; echo "[FATAL] Last command: $BASH_COMMAND" >&2' ERR
TARGET_DIRS=("src" "docs")
echo "[INFO] Confirming target directories exist"
FOUND_ANY=0
for d in "${TARGET_DIRS[@]}"; do
if [[ -d "${d}" ]]; then
echo "[INFO] Found directory: ${d}"
FOUND_ANY=1
else
echo "[WARN] Missing directory: ${d}"
fi
done
if [[ "${FOUND_ANY}" -ne 1 ]]; then
echo "[ERROR] Neither ./src nor ./docs exists in this checkout" >&2
exit 2
fi
echo "[INFO] Searching for VERSION: lines under src and docs"
HIT_VERSION=0
for d in "${TARGET_DIRS[@]}"; do
[[ -d "${d}" ]] || continue
COUNT=$(grep -RIn --exclude-dir=.git "^[[:space:]]*VERSION[[:space:]]*:" "${d}" | wc -l || true)
echo "[INFO] VERSION: hits in ${d}: ${COUNT}"
HIT_VERSION=$((HIT_VERSION + COUNT))
done
echo "[INFO] Searching for XML <version> tags under src and docs"
HIT_XML=0
for d in "${TARGET_DIRS[@]}"; do
[[ -d "${d}" ]] || continue
COUNT=$(grep -RIn --exclude-dir=.git "<version" "${d}" | wc -l || true)
echo "[INFO] <version> hits in ${d}: ${COUNT}"
HIT_XML=$((HIT_XML + COUNT))
done
echo "[INFO] Total VERSION: hits: ${HIT_VERSION}"
echo "[INFO] Total <version> hits: ${HIT_XML}"
- name: Bump versions in headers and XML (src and docs only)
shell: bash
run: |
set -Eeuo pipefail
trap 'echo "[FATAL] Version bump failed at line $LINENO" >&2; echo "[FATAL] Last command: $BASH_COMMAND" >&2' ERR
python3 - <<'PY'
import os
import re
from pathlib import Path
import os
from collections import defaultdict
new_version = os.environ.get("NEW_VERSION", "").strip()
if not new_version:
raise SystemExit("[FATAL] NEW_VERSION env var missing")
new_version = os.environ["NEW_VERSION"]
root = Path(".").resolve()
targets = [root / "src", root / "docs"]
header_re = re.compile(r"(?m)^(\\s*VERSION\\s*:\\s*)(\\d{2}\\.\\d{2}\\.\\d{2})(\\s*)$")
xml_re = re.compile(r"(?is)(<version\\s*>)(\\s*\\d{2}\\.\\d{2}\\.\\d{2}\\s*)(</version\\s*>)")
header_re = re.compile(r"(?m)^(\s*VERSION\s*:\s*)(\S+)(\s*)$")
xml_re = re.compile(r"(?is)(<version\s*>)([^<]*?)(</version\s*>)")
skip_ext = {".json", ".png", ".jpg", ".jpeg", ".gif", ".svg", ".ico", ".pdf", ".zip", ".7z", ".tar", ".gz", ".woff", ".woff2", ".ttf", ".otf", ".mp3", ".mp4"}
skip_dirs = {".git", "node_modules", "vendor", ".venv", "dist", "build"}
counters = defaultdict(int)
updated = []
for p in root.rglob("*"):
if not p.is_file():
continue
if p.suffix.lower() == ".json":
continue
try:
text = p.read_text(encoding="utf-8")
except Exception:
continue
def should_skip(p: Path) -> bool:
if p.suffix.lower() in skip_ext:
counters["skipped_by_ext"] += 1
return True
parts = {x.lower() for x in p.parts}
if any(d in parts for d in skip_dirs):
counters["skipped_by_dir"] += 1
return True
return False
original = text
text = header_re.sub(r"\\1" + new_version + r"\\3", text)
if p.suffix.lower() == ".xml":
text = xml_re.sub(r"\\1" + new_version + r"\\3", text)
existing_targets = [t for t in targets if t.exists() and t.is_dir()]
if not existing_targets:
raise SystemExit("[ERROR] Neither ./src nor ./docs exists in this checkout")
if text != original:
p.write_text(text, encoding="utf-8")
updated.append(str(p))
print("[INFO] Scanning directories:")
for t in existing_targets:
print(f" - {t}")
for base in existing_targets:
for p in base.rglob("*"):
if not p.is_file():
continue
if should_skip(p):
continue
try:
text = p.read_text(encoding="utf-8")
except UnicodeDecodeError:
counters["skipped_non_utf8"] += 1
continue
except Exception as e:
counters["skipped_read_error"] += 1
print(f"[WARN] Read error: {p} :: {e}")
continue
original = text
text, n1 = header_re.subn(r"\\1" + new_version + r"\\3", text)
if n1:
counters["header_replacements"] += n1
if p.suffix.lower() == ".xml":
text2, n2 = xml_re.subn(r"\\1" + new_version + r"\\3", text)
text = text2
if n2:
counters["xml_replacements"] += n2
if text != original:
try:
p.write_text(text, encoding="utf-8")
updated.append(str(p))
except Exception as e:
raise SystemExit(f"[FATAL] Write failed: {p} :: {e}")
print("[INFO] Scan summary")
for k in sorted(counters.keys()):
print(f" {k}: {counters[k]}")
print(f"[INFO] Updated files: {len(updated)}")
for f in updated[:200]:
print(f" [UPDATED] {f}")
if len(updated) > 200:
print(f" [INFO] (truncated) +{len(updated) - 200} more")
if not updated:
raise SystemExit("[ERROR] No files updated. Check headers and XML manifests.")
print(f"[INFO] Updated {len(updated)} files")
for f in updated:
print(f" - {f}")
print("[ERROR] No files updated within src and docs")
print("[DIAG] Confirm these exist in src or docs:")
print(" - A line containing: VERSION: <value>")
print(" - An XML tag: <version>...</version>")
raise SystemExit(1)
PY
- name: Show git status
shell: bash
run: |
set -Eeuo pipefail
trap 'echo "[FATAL] git status failed at line $LINENO" >&2; echo "[FATAL] Last command: $BASH_COMMAND" >&2' ERR
git status --porcelain=v1
- name: Commit changes
if: ${{ env.COMMIT_CHANGES == 'true' }}
shell: bash
run: |
set -Eeuo pipefail
git status --porcelain
git add -A
trap 'echo "[FATAL] Commit failed at line $LINENO" >&2; echo "[FATAL] Last command: $BASH_COMMAND" >&2' ERR
if [[ -z "$(git status --porcelain=v1)" ]]; then
echo "[INFO] No changes detected. Skipping commit and push."
exit 0
fi
git add src docs
git commit -m "chore(release): bump version to ${NEW_VERSION}"
- name: Push branch
if: ${{ env.COMMIT_CHANGES == 'true' }}
shell: bash
run: |
set -Eeuo pipefail
git push --set-upstream origin "${BRANCH_PREFIX}${NEW_VERSION}"
trap 'echo "[FATAL] Push failed at line $LINENO" >&2; echo "[FATAL] Last command: $BASH_COMMAND" >&2' ERR
git push --set-upstream origin "${BRANCH_NAME}"
- name: Output branch name
shell: bash
run: |
set -Eeuo pipefail
echo "[INFO] Created branch: ${BRANCH_NAME}"