Problem
Three PRs reviewed on 2026-08-18 — #416, #411 and #414 — each modify modules that shipped in the 2026.08 release without bumping the module's manifest version. Nothing in CI catches this, and the consequences escalate with each case:
The repo rule already exists (CLAUDE-level: any change to a module present in a released version needs a version bump, and schema changes need a migration; "same-version code changes give upgraders no signal and skip migrations/ scripts") — precedents: spp_cel_domain, spp_oauth, spp_attendance, spp_cel_load_testing. It just isn't enforced mechanically, and it keeps recurring.
Proposal
Add a CI job (natural home: ci.yml, downstream of detect-changes, which already computes the changed-module list) that fails when a changed module's __manifest__.py version is identical to the base branch:
For each module in detect-changes.outputs.modules:
- Read
"version" from the module's __manifest__.py on the PR head and on the merge-base with the target branch.
- If the module exists on the base and the version is unchanged → fail, listing the offending modules and pointing at the versioning rule.
- New modules (no manifest on base) pass by definition.
Suggested refinements
- Escape hatch: skip the check when the PR carries a
no-version-bump label, for genuinely inert changes (comment typos, test-only touch-ups). The label keeps the decision visible and reviewable instead of silent.
- Monotonicity: while comparing, also fail if the version decreased or didn't parse as
19.0.x.y.z — cheap to add, catches copy-paste mistakes.
- Migration hint, not enforcement: when a changed module contains changes under
data/ or removes model fields, the job can warn that a migrations/<version>/ entry may be needed. Detecting "schema change" reliably is not mechanical, so this stays advisory — the hard gate is only the version bump itself.
Out of scope
- Enforcing that migrations exist or are correct — reviewer judgment.
- Changelog/HISTORY enforcement — could be a follow-up if this works well.
Acceptance
- A PR modifying any file under a module that exists on the base branch fails CI unless that module's manifest version changed (or the
no-version-bump label is present).
- The failure message names each offending module and its unchanged version.
- New modules and non-module files (docs, workflows, root scripts) don't trigger the check.
Problem
Three PRs reviewed on 2026-08-18 — #416, #411 and #414 — each modify modules that shipped in the 2026.08 release without bumping the module's manifest version. Nothing in CI catches this, and the consequences escalate with each case:
spp_drims,spp_hazard): stored KPI computes changed semantics (units net of allocations, distributed net of returns). Without a bump there is no upgrade, so existing databases keep old-semantics stored values indefinitely — and even with one, no migration recomputes them.spp_starter_sp_mis): the fix moves a config default to anoupdatedata record — but Odoo never updates the storednoupdateflag of an existing xml_id, so without a migration the fix has no effect on any existing database.spp_drims): the newdraftdonation state is a data record that_get_default_statesearches for. Deploying the code without a module upgrade means every new donation is created with no state at all — the donation flow is dead. The Python takes effect on deploy; the data it depends on does not.The repo rule already exists (CLAUDE-level: any change to a module present in a released version needs a version bump, and schema changes need a migration; "same-version code changes give upgraders no signal and skip
migrations/scripts") — precedents: spp_cel_domain, spp_oauth, spp_attendance, spp_cel_load_testing. It just isn't enforced mechanically, and it keeps recurring.Proposal
Add a CI job (natural home:
ci.yml, downstream ofdetect-changes, which already computes the changed-module list) that fails when a changed module's__manifest__.pyversion is identical to the base branch:For each module in
detect-changes.outputs.modules:"version"from the module's__manifest__.pyon the PR head and on the merge-base with the target branch.Suggested refinements
no-version-bumplabel, for genuinely inert changes (comment typos, test-only touch-ups). The label keeps the decision visible and reviewable instead of silent.19.0.x.y.z— cheap to add, catches copy-paste mistakes.data/or removes model fields, the job can warn that amigrations/<version>/entry may be needed. Detecting "schema change" reliably is not mechanical, so this stays advisory — the hard gate is only the version bump itself.Out of scope
Acceptance
no-version-bumplabel is present).