#!/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. The Odoo manifest # version is derived as 17.0... (Odoo-series prefix + # the product version), e.g. product 0.4.8 -> manifest 17.0.0.4.8. # # Usage: # scripts/bump-version.sh patch # 0.4.8 -> 0.4.9 # scripts/bump-version.sh minor # 0.4.8 -> 0.5.0 # scripts/bump-version.sh major # 0.4.8 -> 1.0.0 # scripts/bump-version.sh set 1.2.3 # set an explicit version # scripts/bump-version.sh tag # create annotated git tag v # # from the CHANGELOG section # # Typical flow for a release: # 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 + uses the CHANGELOG notes # 5) git push && git push --tags # 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" ODOO_SERIES="17.0" die() { echo "error: $*" >&2; exit 1; } 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" tagname="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