#!/usr/bin/env bash # # bump-version.sh — ITSulu Blog Publisher version manager # # Versioning scheme: MAJOR.MINOR.PATCH (each part 0–999) # MAJOR major release for sale; significant feature upgrade / significant change # MINOR feature(s) added, or a performance improvement # PATCH a single group of commits, or one large commit # # The repo-root VERSION file is the single source of truth for the PRODUCT # version (same feature-set across Odoo branches). We support one Odoo series # per branch (the odoo/odoo model: branches 19.0, 14.0, ...). The Odoo series # is resolved from the .odoo-series file, else the branch name, else 17.0. # # The Odoo manifest version is derived as ..., # e.g. on branch 19.0 with product 0.5.0 -> manifest 19.0.0.5.0. # # Release tags are namespaced by series so one product version can ship on # multiple branches: 19.0-v0.5.0, 14.0-v0.5.0. # # Usage: # scripts/bump-version.sh patch # 0.5.0 -> 0.5.1 # scripts/bump-version.sh minor # 0.5.0 -> 0.6.0 # scripts/bump-version.sh major # 0.5.0 -> 1.0.0 # scripts/bump-version.sh set 1.2.3 # set an explicit version # scripts/bump-version.sh tag # annotated tag -v # # from the CHANGELOG section # # Typical flow for a release (run ON the target series branch): # 1) scripts/bump-version.sh minor # 2) edit CHANGELOG.md — fill in the new "## vX.Y.Z" section (plain language) # 3) git add -A && git commit -m "release: vX.Y.Z" # 4) scripts/bump-version.sh tag # tags -vX.Y.Z + CHANGELOG notes # 5) git push && git push origin -vX.Y.Z # set -euo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" VERSION_FILE="$ROOT/VERSION" MANIFEST="$ROOT/addons/itsulu_blog_publisher/__manifest__.py" README="$ROOT/README.md" CHANGELOG="$ROOT/CHANGELOG.md" SERIES_FILE="$ROOT/.odoo-series" die() { echo "error: $*" >&2; exit 1; } # The Odoo series this branch targets. We support one Odoo version per branch # (the odoo/odoo model: branches 19.0, 14.0, ...). Resolution order: # 1) .odoo-series file at repo root (explicit, authoritative) # 2) current git branch name, if it looks like a series (e.g. 19.0, 14.0) # 3) fallback 17.0 (legacy default) resolve_series() { if [ -f "$SERIES_FILE" ]; then tr -d '[:space:]' < "$SERIES_FILE"; return fi local br; br="$(git -C "$ROOT" rev-parse --abbrev-ref HEAD 2>/dev/null || echo '')" if [[ "$br" =~ ^[0-9]+\.0$ ]]; then echo "$br"; return; fi echo "17.0" } ODOO_SERIES="$(resolve_series)" read_version() { [ -f "$VERSION_FILE" ] || die "VERSION file not found at $VERSION_FILE" tr -d '[:space:]' < "$VERSION_FILE" } validate() { local v="$1" [[ "$v" =~ ^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$ ]] \ || die "invalid version '$v' — expected MAJOR.MINOR.PATCH, each part 0–999" for part in "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}" "${BASH_REMATCH[3]}"; do [ "$part" -le 999 ] || die "version part '$part' exceeds 999" done } write_everywhere() { local v="$1" echo "$v" > "$VERSION_FILE" # Odoo manifest: 17.0... (series prefix + product version) sed -i -E "s/('version': ')[0-9.]+(')/\1${ODOO_SERIES}.${v}\2/" "$MANIFEST" # README version line: **Version:** X.Y.Z if grep -qE '^\*\*Version:\*\*' "$README"; then sed -i -E "s/^(\*\*Version:\*\*) .*/\1 ${v}/" "$README" fi echo " VERSION -> $v" echo " manifest -> ${ODOO_SERIES}.${v}" echo " README -> **Version:** ${v}" } cmd="${1:-}"; arg="${2:-}" current="$(read_version)" case "$cmd" in major|minor|patch) IFS='.' read -r MA MI PA <<< "$current" case "$cmd" in major) MA=$((MA+1)); MI=0; PA=0 ;; minor) MI=$((MI+1)); PA=0 ;; patch) PA=$((PA+1)) ;; esac new="${MA}.${MI}.${PA}" validate "$new" echo "Bumping ($cmd): $current -> $new" write_everywhere "$new" echo echo "Next: add a '## v${new}' section to CHANGELOG.md, commit, then: scripts/bump-version.sh tag" ;; set) [ -n "$arg" ] || die "usage: bump-version.sh set " validate "$arg" echo "Setting version: $current -> $arg" write_everywhere "$arg" echo echo "Next: add a '## v${arg}' section to CHANGELOG.md, commit, then: scripts/bump-version.sh tag" ;; tag) v="$current" # Multi-version tags are namespaced by Odoo series so the same product # version can ship on several branches: e.g. 19.0-v0.5.0 and 14.0-v0.5.0. tagname="${ODOO_SERIES}-v${v}" git -C "$ROOT" rev-parse "$tagname" >/dev/null 2>&1 && die "tag $tagname already exists" # Extract this version's section from CHANGELOG (from "## vX.Y.Z" to the next "## v" or "---"). notes="$(awk -v ver="## v${v}" ' $0 ~ "^"ver" " || $0 == ver {flag=1} flag && /^---[[:space:]]*$/ {exit} flag && /^## v/ && $0 !~ ver {exit} flag {print} ' "$CHANGELOG")" [ -n "$notes" ] || die "no CHANGELOG.md section found for ## v${v}" echo "Creating annotated tag $tagname with release notes:" echo "----------------------------------------" echo "$notes" echo "----------------------------------------" git -C "$ROOT" tag -a "$tagname" -m "$notes" echo "Tagged $tagname. Push with: git push origin $tagname" ;; ""|-h|--help|help) grep -E '^#( |$)' "$0" | sed -E 's/^# ?//' echo "current version: $current" ;; *) die "unknown command '$cmd' (try: major | minor | patch | set | tag | help)" ;; esac