Skip to main content
7 min read
142 reads
Odoo

Why a Version Bump Could Break Your Odoo.sh Build

A deep dive into how Odoo.sh cascade upgrades work, why a simple version change can trigger failures in unrelated modules, and the strategies to avoid it.

Introduction

You push a small change to your Odoo module on Odoo.sh. You bump the version in __manifest__.py from 0.5 to 0.6 β€” a routine update. Minutes later, the staging build fails. The error? A warning in a completely different module you didn't even touch.

If this sounds familiar, you've run into one of Odoo.sh's most subtle behaviors: cascade upgrades triggered by version bumps. This article breaks down exactly what happens, why it happens, and how to avoid it.


The Problem: A Simple Version Change Breaks Everything

Imagine you have a module called document_manager that handles certificate generation and letter templates. It has a dependency chain like this:

text
document_manager
  └── hr_connector (depends on document_manager)
        β”œβ”€β”€ hr_connector_charts (depends on hr_connector)
        └── attendance_tracker (depends on hr_connector)

You make a code change in document_manager β€” maybe you refactored a method or added a new field. You bump the version in the manifest. You push to staging.

Build fails.

The error log points to hr_connector, not document_manager. It shows deprecation warnings that have existed in the codebase for months. What happened?


How Odoo.sh Decides What to Upgrade

Here's the key insight most developers miss:

Odoo.sh uses version numbers β€” not file diffs β€” to determine cascade upgrades.

When you push to Odoo.sh, it compares the version field in each module's __manifest__.py against what's currently installed. If the version changed, that module gets upgraded. And critically, all modules that depend on it get upgraded too β€” recursively.

This is different from how code changes are handled. If you modify files in a module without changing its version, Odoo.sh still detects the file changes and updates that specific module. But it does not cascade to dependent modules.

What We Observed

Change TypeModule Updated?Dependents Cascaded?Build Result
No changesNoNoPass
Code change, no version bumpYesNoPass
Version bump onlyYesYesFail
Code change + version bumpYesYesFail

The version bump was the trigger. Not the code.


Why the Cascade Breaks Things

The cascade itself isn't the problem β€” it's what it reveals.

When hr_connector is loaded at server startup (which happens every time), Odoo reads its models and views but doesn't run the full upgrade pipeline. Issues like deprecation warnings, schema mismatches, or view validation errors sit dormant.

But when a cascade upgrade forces hr_connector through the actual -u (upgrade) process, Odoo runs:

  • Model field reconciliation against the database schema
  • View XML validation and re-rendering
  • Data file re-processing
  • Python code re-evaluation with stricter checks

This is when those sleeping issues wake up. Warnings that are silently ignored during startup become test failures during upgrade.


5 Common Issues That Surface During Cascade Upgrades

1. Deprecated API Decorators

python
# This works at startup but generates DeprecationWarning during upgrade
@api.model
def create(self, vals):
    ...

# The correct decorator since Odoo 14+
@api.model_create_multi
def create(self, vals_list):
    ...

2. Deprecated Field Attributes

python
# Old syntax β€” triggers deprecation warning
name = fields.Char(track_visibility='onchange')

# Modern syntax
name = fields.Char(tracking=True)

3. Deprecated View Elements

xml
<!-- Old Kanban syntax -->
<t t-name="kanban-box">

<!-- Modern syntax -->
<t t-name="card">

4. Missing Model Attributes

python
# Missing _description triggers a warning during upgrade
class CustomModel(models.Model):
    _name = 'custom.model'
    # Should have: _description = 'Custom Model'

5. Schema NOT NULL Violations

Fields that were added as required=True but have existing records with NULL values will fail during upgrade reconciliation.


Quick Fix: Skip the Version Bump

The immediate workaround is straightforward: don't bump the version.

Push your code changes without modifying the version field in __manifest__.py. Odoo.sh will still detect the file changes and apply them to your module. Since the version didn't change, no cascade upgrade is triggered, and dependent modules remain untouched.

This is a valid short-term strategy, especially when you need to deploy urgently. But it's not sustainable β€” you lose version tracking, and eventually you'll need to bump.


Permanent Fix: Clean Up the Dependency Chain

The real solution is to fix every warning in every module in the dependency chain. Here's the systematic approach.

Step 1: Test the Upgrade Locally

Run the upgrade command locally against a copy of your production database:

bash
odoo -d your_database -u hr_connector --stop-after-init --log-level=warning

Capture all warnings and errors. This gives you the exact list of issues that Odoo.sh will encounter.

Step 2: Fix Deprecation Warnings

Go through each module in the dependency chain and fix:

  • @api.model on create() methods β€” change to @api.model_create_multi
  • track_visibility attributes β€” change to tracking=True
  • readonly=1 in wizards β€” change to readonly=True
  • Missing _description on models
  • Deprecated view elements like kanban-box β€” change to card

Step 3: Fix Schema Issues

Check for NOT NULL constraint violations:

sql
SELECT column_name, is_nullable
FROM information_schema.columns
WHERE table_name = 'your_table'
AND is_nullable = 'NO';

Ensure all required fields have default values or migration scripts.

Step 4: Test the Full Cascade

Once all fixes are in place, bump the version on the root module and push to a test branch. Verify that the full cascade upgrade completes cleanly.


Bonus: Watch Out for Ghost Files

While debugging this issue, we discovered another subtle problem. When trying to revert to a known-good commit using:

bash
git checkout <good-commit> -- .

This restores all tracked files to their state at that commit. But it does not delete files that were added in later commits. We found over a dozen "ghost files" β€” models, wizards, and data files that didn't exist in the good commit but were still present in the working directory.

These ghost files can introduce import errors, duplicate model registrations, or unexpected data during module upgrade.

The safe way to verify a revert:

bash
# Check for files that exist now but didn't in the target commit
git diff <good-commit> HEAD --name-only --diff-filter=A

# These files need to be explicitly removed

Conclusion

Here are the key takeaways:

  1. Version bumps trigger cascade upgrades β€” Odoo.sh upgrades all dependent modules when a dependency's version changes.
  2. Code changes without version bumps are safe β€” Odoo.sh still applies file changes but doesn't cascade.
  3. Dormant issues surface during upgrades β€” Deprecation warnings and schema issues that are silent during startup become failures during upgrade.
  4. Fix the full chain before bumping β€” Clean up all dependent modules before changing any version number.
  5. Verify reverts completely β€” git checkout -- . doesn't delete added files; always check for ghost files.

Understanding how Odoo.sh handles module upgrades saves hours of debugging. The cascade behavior is documented, but its implications β€” especially around dormant warnings β€” catch even experienced developers off guard.

Next time your staging build fails after a "simple" version bump, you'll know exactly where to look.