chore: make versioning series-aware for multi-Odoo-version branches

Prepares for the odoo/odoo-style branch-per-Odoo-release model (19.0, 14.0).

- bump-version.sh resolves the Odoo series from .odoo-series file > branch
  name > 17.0 fallback; manifest version becomes <series>.<product>; release
  tags are namespaced as <series>-v<product> (e.g. 19.0-v0.5.0).
- CLAUDE.md §15: new "Odoo version branches" subsection + series-aware
  sources-of-truth table, release process, and rules.
- README: branch-model pointer (19.0 latest stable, 14.0 ITSulu).

main stays the 17.0 baseline; 19.0 and 14.0 branches are created from here.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Nicholas Riegel 2026-05-30 11:14:12 -04:00
parent c039b5f0cb
commit 5ed2851ee5
3 changed files with 96 additions and 29 deletions

View file

@ -937,25 +937,58 @@ The project uses a three-part version number, **`MAJOR.MINOR.PATCH`**, each part
| **MINOR** | One or more features added, or a meaningful performance improvement. | new LLM provider, new wizard, 2× faster generation |
| **PATCH** | A single group of commits, or one large commit. | bug-fix batch, doc pass, refactor, dependency bump |
### Odoo version branches (one series per branch — the odoo/odoo model)
The addon targets **multiple Odoo Community releases, one per long-lived branch**, exactly like
[odoo/odoo](https://github.com/odoo/odoo) (`19.0`, `18.0`, …, `14.0`). Initially we ship:
| Branch | Odoo series | Why |
|---|---|---|
| `19.0` | Odoo Community 19.0 | Latest stable — primary supported line |
| `14.0` | Odoo Community 14.0 | The version ITSulu currently runs in production |
Rules:
- **Each Odoo series lives on its own branch.** Never mix two Odoo versions in one branch.
The branch name *is* the series (`19.0`, `14.0`).
- The **product version** (`VERSION`, e.g. `0.5.0`) is shared across series — the same feature
set, ported per Odoo release. The Odoo **manifest** version is `<series>.<product>`
`19.0.0.5.0` on `19.0`, `14.0.0.5.0` on `14.0`.
- `bump-version.sh` resolves the series from `.odoo-series` (a one-line file at repo root),
else the branch name, else `17.0`. The `Dockerfile` base image (`FROM odoo:<series>`) and
the manifest prefix must match the branch.
- **Release tags are namespaced by series** so one product version ships on several branches:
`19.0-v0.5.0`, `14.0-v0.5.0`. (The pre-multi-version release `v0.4.8` predates this scheme.)
- A feature is "done" only when it lands on **every** supported series branch. Port a fix to
each branch (cherry-pick or re-implement) — Odoo APIs differ across 14 → 19, so a clean
cherry-pick is the exception, not the rule.
- Odoo-version-specific gotchas (mail.template syntax, `blog.post` fields, rendering APIs) are
in §11.5 and the §12 failure table. Always confirm which series you are on before fixing.
### Sources of truth & where the version lives
The repo-root **`VERSION`** file is the single source of truth. These are kept in sync:
| File | Form | Notes |
| File | Form (example on branch `19.0`) | Notes |
|---|---|---|
| `VERSION` | `0.4.8` | Source of truth — plain text, one line |
| `addons/itsulu_blog_publisher/__manifest__.py` | `'version': '17.0.0.4.8'` | Odoo manifest = `<odoo_series>.<product_version>` = `17.0` + `0.4.8` |
| `README.md` | `**Version:** 0.4.8` | Header line + status footer |
| `CHANGELOG.md` | `## v0.4.8 — <date>` | Release notes section per version |
| git tag | `v0.4.8` | Annotated tag; message = the CHANGELOG section |
| `VERSION` | `0.5.0` | Source of truth for the product version — plain text, one line. Same across series branches |
| `.odoo-series` | `19.0` | The Odoo series this branch targets (one line). Drives manifest prefix + tag namespace |
| `addons/itsulu_blog_publisher/__manifest__.py` | `'version': '19.0.0.5.0'` | Odoo manifest = `<series>.<product>` |
| `Dockerfile` | `FROM odoo:19.0` | Base image must match the series |
| `README.md` | `**Version:** 0.5.0` | Header line + status footer |
| `CHANGELOG.md` | `## v0.5.0 — <date>` | Release notes section per product version |
| git tag | `19.0-v0.5.0` | Annotated tag, namespaced by series; message = the CHANGELOG section |
**Never hand-edit the version in multiple files.** Use the helper script — it updates all of
them from `VERSION` and derives the Odoo manifest version (`17.0.<MAJOR>.<MINOR>.<PATCH>`).
**Never hand-edit the version in multiple files.** Run `bump-version.sh` on the target series
branch — it reads `VERSION` + the resolved series and updates `VERSION`, the manifest
(`<series>.<MAJOR>.<MINOR>.<PATCH>`), and README together.
### Release process (every version change)
```bash
# 1. Bump the version (updates VERSION, manifest, README)
# Run ON the target series branch (e.g. git checkout 19.0).
# 1. Bump the version (updates VERSION, manifest with the branch's series, README)
scripts/bump-version.sh patch # or: minor | major | set X.Y.Z
# 2. Write the release notes — add a "## vX.Y.Z — <date>" section to CHANGELOG.md
@ -965,11 +998,13 @@ scripts/bump-version.sh patch # or: minor | major | set X.Y.Z
# 3. Commit the bump + notes together
git add -A && git commit -m "release: vX.Y.Z"
# 4. Tag the release — the tag message is taken from the CHANGELOG section
# 4. Tag the release — names the tag <series>-vX.Y.Z, message from the CHANGELOG section
scripts/bump-version.sh tag
# 5. Push branch and tag
git push && git push origin vX.Y.Z
# 5. Push branch and the series-namespaced tag (e.g. 19.0-v0.5.0)
git push && git push origin "$(cat .odoo-series 2>/dev/null || echo 17.0)-v$(cat VERSION)"
# 6. Port the same change to the other series branches (14.0, …) and tag each there.
```
### Release-notes style (common language)
@ -990,12 +1025,14 @@ Infrastructure / Documentation** as applicable.
### Rules
- One tag per version; tags are immutable. If a release is wrong, ship the next PATCH — never
move a tag.
- Tag on the release branch **after** the work is merged/finalised, so the tag points at the
- One tag per `<series>` + product version; tags are immutable. If a release is wrong, ship the
next PATCH — never move a tag. (`v0.4.8` is the pre-multi-version exception.)
- Tag on the series branch **after** the work is merged/finalised, so the tag points at the
commit that actually ships.
- The Odoo manifest version must always be `17.0.` + the `VERSION` value. The `-u` upgrade path
relies on the manifest version increasing, so bump before deploying schema/data changes.
- The Odoo manifest version must always be `<branch series>.` + the `VERSION` value (e.g.
`19.0.0.5.0`). The `-u` upgrade path relies on the manifest version increasing, so bump before
deploying schema/data changes.
- A change is not "released" until it is on **every** supported series branch with its own tag.
---

View file

@ -6,6 +6,12 @@ Automated blog post generation and publishing for Odoo 17 Community Edition, pow
> **Versioning**`MAJOR.MINOR.PATCH` (each 0999). MAJOR = major release for sale / significant change; MINOR = features or performance improvements; PATCH = a single group of commits. See [CHANGELOG.md](CHANGELOG.md) for release notes and [CLAUDE.md](CLAUDE.md) §15 for the full scheme.
> **Odoo version branches** — like [odoo/odoo](https://github.com/odoo/odoo), each Odoo
> Community release lives on its own branch. Supported targets:
> **[`19.0`](../../tree/19.0)** (latest stable) and **[`14.0`](../../tree/14.0)** (the version
> ITSulu runs). Check out the branch matching your Odoo version. Release tags are namespaced by
> series, e.g. `19.0-v0.5.0`.
## Features
### ✨ Core Functionality

View file

@ -7,24 +7,31 @@
# 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.<MAJOR>.<MINOR>.<PATCH> (Odoo-series prefix +
# the product version), e.g. product 0.4.8 -> manifest 17.0.0.4.8.
# 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 <SERIES>.<MAJOR>.<MINOR>.<PATCH>,
# 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.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 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 # create annotated git tag v<VERSION>
# scripts/bump-version.sh tag # annotated tag <series>-v<VERSION>
# # from the CHANGELOG section
#
# Typical flow for a release:
# 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 + uses the CHANGELOG notes
# 5) git push && git push --tags
# 4) scripts/bump-version.sh tag # tags <series>-vX.Y.Z + CHANGELOG notes
# 5) git push && git push origin <series>-vX.Y.Z
#
set -euo pipefail
@ -33,10 +40,25 @@ VERSION_FILE="$ROOT/VERSION"
MANIFEST="$ROOT/addons/itsulu_blog_publisher/__manifest__.py"
README="$ROOT/README.md"
CHANGELOG="$ROOT/CHANGELOG.md"
ODOO_SERIES="17.0"
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"
@ -93,7 +115,9 @@ case "$cmd" in
;;
tag)
v="$current"
tagname="v${v}"
# 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}" '