Add version hierarchy validation and CI improvements for version management #28
90
.github/workflows/version_branch.yml
vendored
90
.github/workflows/version_branch.yml
vendored
@@ -28,6 +28,15 @@ on:
|
|||||||
options:
|
options:
|
||||||
- "true"
|
- "true"
|
||||||
- "false"
|
- "false"
|
||||||
|
branch_prefix:
|
||||||
|
description: "Branch prefix for version (version/ for stable, rc/ for release candidate, dev/ for development)"
|
||||||
|
required: false
|
||||||
|
default: "dev/"
|
||||||
|
type: choice
|
||||||
|
options:
|
||||||
|
- "dev/"
|
||||||
|
- "rc/"
|
||||||
|
- "version/"
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.repository }}-${{ github.event.inputs.new_version }}
|
group: ${{ github.workflow }}-${{ github.repository }}-${{ github.event.inputs.new_version }}
|
||||||
@@ -51,7 +60,7 @@ jobs:
|
|||||||
REPORT_ONLY: ${{ github.event.inputs.report_only }}
|
REPORT_ONLY: ${{ github.event.inputs.report_only }}
|
||||||
COMMIT_CHANGES: ${{ github.event.inputs.commit_changes }}
|
COMMIT_CHANGES: ${{ github.event.inputs.commit_changes }}
|
||||||
BASE_BRANCH: ${{ github.ref_name }}
|
BASE_BRANCH: ${{ github.ref_name }}
|
||||||
BRANCH_PREFIX: 'dev/'
|
BRANCH_PREFIX: ${{ github.event.inputs.branch_prefix || 'dev/' }}
|
||||||
ERROR_LOG: /tmp/version_branch_errors.log
|
ERROR_LOG: /tmp/version_branch_errors.log
|
||||||
CI_HELPERS: /tmp/moko_ci_helpers.sh
|
CI_HELPERS: /tmp/moko_ci_helpers.sh
|
||||||
REPORT_PATH: /tmp/version-bump-report.json
|
REPORT_PATH: /tmp/version-bump-report.json
|
||||||
@@ -124,10 +133,16 @@ jobs:
|
|||||||
[[ -n "${NEW_VERSION}" ]] || { echo "[ERROR] new_version missing" >&2; 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; }
|
[[ "${NEW_VERSION}" =~ ^[0-9]{2}[.][0-9]{2}[.][0-9]{2}$ ]] || { echo "[ERROR] Invalid version format: ${NEW_VERSION}" >&2; exit 2; }
|
||||||
|
|
||||||
if [[ "${BRANCH_PREFIX}" != "dev/" ]]; then
|
# Validate BRANCH_PREFIX is one of the allowed values
|
||||||
echo "[FATAL] BRANCH_PREFIX is locked by policy. Expected 'dev/' but got '${BRANCH_PREFIX}'." >&2
|
case "${BRANCH_PREFIX}" in
|
||||||
|
"dev/"|"rc/"|"version/")
|
||||||
|
echo "[INFO] ✓ Branch prefix '${BRANCH_PREFIX}' is valid"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "[FATAL] BRANCH_PREFIX must be one of: dev/, rc/, version/ (got: '${BRANCH_PREFIX}')" >&2
|
||||||
exit 2
|
exit 2
|
||||||
fi
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
if ! moko_bool "${REPORT_ONLY}" && [[ "${COMMIT_CHANGES}" != "true" ]]; then
|
if ! moko_bool "${REPORT_ONLY}" && [[ "${COMMIT_CHANGES}" != "true" ]]; then
|
||||||
echo "[FATAL] commit_changes must be 'true' when report_only is 'false' to ensure the branch is auditable." >&2
|
echo "[FATAL] commit_changes must be 'true' when report_only is 'false' to ensure the branch is auditable." >&2
|
||||||
@@ -230,11 +245,13 @@ jobs:
|
|||||||
source "$CI_HELPERS"
|
source "$CI_HELPERS"
|
||||||
moko_init "Branch namespace collision defense"
|
moko_init "Branch namespace collision defense"
|
||||||
|
|
||||||
# Skip collision check for the static 'dev/' prefix
|
# Skip collision check for known static prefixes
|
||||||
if [[ "${BRANCH_PREFIX}" == "dev/" ]]; then
|
case "${BRANCH_PREFIX}" in
|
||||||
echo "[INFO] Skipping collision check for static prefix 'dev/'" >&2
|
"dev/"|"rc/"|"version/")
|
||||||
|
echo "[INFO] Skipping collision check for known prefix '${BRANCH_PREFIX}'" >&2
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
PREFIX_TOP="${BRANCH_PREFIX%%/*}"
|
PREFIX_TOP="${BRANCH_PREFIX%%/*}"
|
||||||
if git ls-remote --exit-code --heads origin "${PREFIX_TOP}" >/dev/null 2>&1; then
|
if git ls-remote --exit-code --heads origin "${PREFIX_TOP}" >/dev/null 2>&1; then
|
||||||
@@ -270,6 +287,63 @@ jobs:
|
|||||||
git checkout -B "${BRANCH_NAME}" "origin/${BASE_BRANCH}"
|
git checkout -B "${BRANCH_NAME}" "origin/${BASE_BRANCH}"
|
||||||
echo "BRANCH_NAME=${BRANCH_NAME}" >> "$GITHUB_ENV"
|
echo "BRANCH_NAME=${BRANCH_NAME}" >> "$GITHUB_ENV"
|
||||||
|
|
||||||
|
- name: Validate version hierarchy (prevent creating in lower priority branches)
|
||||||
|
if: ${{ env.REPORT_ONLY != 'true' }}
|
||||||
|
run: |
|
||||||
|
source "$CI_HELPERS"
|
||||||
|
moko_init "Validate version hierarchy"
|
||||||
|
|
||||||
|
# Version hierarchy (highest to lowest priority):
|
||||||
|
# 1. version/X.Y.Z - production/stable versions
|
||||||
|
# 2. rc/X.Y.Z - release candidate versions
|
||||||
|
# 3. dev/X.Y.Z - development versions
|
||||||
|
#
|
||||||
|
# Rule: If a version exists in a higher priority branch,
|
||||||
|
# do not allow creating it in a lower priority branch
|
||||||
|
|
||||||
|
BRANCH_NAME="${BRANCH_PREFIX}${NEW_VERSION}"
|
||||||
|
|
||||||
|
echo "[INFO] Checking version hierarchy for: ${NEW_VERSION}"
|
||||||
|
echo "[INFO] Current branch prefix: ${BRANCH_PREFIX}"
|
||||||
|
|
||||||
|
# Determine current priority level
|
||||||
|
case "${BRANCH_PREFIX}" in
|
||||||
|
"version/")
|
||||||
|
echo "[INFO] Creating stable version branch - no hierarchy checks needed"
|
||||||
|
;;
|
||||||
|
"rc/")
|
||||||
|
echo "[INFO] Creating RC branch - checking if version exists in stable"
|
||||||
|
if git ls-remote --exit-code --heads origin "version/${NEW_VERSION}" >/dev/null 2>&1; then
|
||||||
|
echo "[FATAL] Version ${NEW_VERSION} already exists in stable branch: version/${NEW_VERSION}" >&2
|
||||||
|
echo "[FATAL] Cannot create RC version for a version that already exists in stable" >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
echo "[INFO] ✓ No conflict with stable versions"
|
||||||
|
;;
|
||||||
|
"dev/")
|
||||||
|
echo "[INFO] Creating dev branch - checking if version exists in stable or RC"
|
||||||
|
|
||||||
|
# Check stable versions
|
||||||
|
if git ls-remote --exit-code --heads origin "version/${NEW_VERSION}" >/dev/null 2>&1; then
|
||||||
|
echo "[FATAL] Version ${NEW_VERSION} already exists in stable branch: version/${NEW_VERSION}" >&2
|
||||||
|
echo "[FATAL] Cannot create dev version for a version that already exists in stable" >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check RC versions
|
||||||
|
if git ls-remote --exit-code --heads origin "rc/${NEW_VERSION}" >/dev/null 2>&1; then
|
||||||
|
echo "[FATAL] Version ${NEW_VERSION} already exists in RC branch: rc/${NEW_VERSION}" >&2
|
||||||
|
echo "[FATAL] Cannot create dev version for a version that already exists in RC" >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "[INFO] ✓ No conflict with stable or RC versions"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "[WARN] Unknown branch prefix: ${BRANCH_PREFIX}, skipping hierarchy check"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
- name: Enforce update feed files absent (update.xml, updates.xml)
|
- name: Enforce update feed files absent (update.xml, updates.xml)
|
||||||
if: ${{ env.REPORT_ONLY != 'true' }}
|
if: ${{ env.REPORT_ONLY != 'true' }}
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
Reference in New Issue
Block a user