A Typer CLI that walks Odoo databases through OpenUpgrade version chains in Docker.
Project description
🚀 ou-runner
One command. Many Odoo majors. Zero hand-holding.
If you've ever used OCA/OpenUpgrade in a Dockerized
setup, you already know the drill: switching branches for every
target major, rebuilding per-version images, hand-rolling pg_dump
and pg_restore between hops, and keeping a side note of how long
each one took.
ou-runner takes that loop off your hands. It walks an Odoo database
from Odoo version X → Z one hop at a time, in Docker, with every dump named,
every hop timed, and every artifact in the folder you ran it from.
Disclaimer. Not affiliated with Odoo S.A. or the OCA OpenUpgrade project.
ou-runnerwraps OCA/OpenUpgrade for convenience; the migration scripts themselves belong to OCA.
Scope.
ou-runnerwas built and tested against an Odoo 14 → 19 migration. Earlier majors (≤13) are out of scope — they may work, but nothing about the version table, Dockerfile rendering, or upgrade-path wiring has been exercised against them.
✨ Features
- 🐳 Docker-managed Odoo 14 → 19 — one compose file, one network, six profiles
- 🔄 Auto-clones OpenUpgrade branches — no manual
git checkout - 💾 Automated pg_dump between hops — each hop's output is the next hop's input
- ⏱️ Built-in migration timing —
migration_times.jsonrecords every run - 🍺
--hold-my-drink— chain every hop from your starting version to the target - 🧹
cleansweeps everything — no global state, nothing in your home folder
Without vs. with ou-runner
flowchart LR
subgraph WITHOUT["😩 Without ou-runner"]
direction TB
W1[Clone OpenUpgrade 15] --> W2[Write Dockerfile 15]
W2 --> W3[docker run postgres + odoo 15]
W3 --> W4[pg_restore v14 dump]
W4 --> W5[odoo -u all --stop-after-init]
W5 --> W6[pg_dump v15]
W6 --> W7[Repeat for 16, 17, 18, 19...]
W7 --> W8[Track times in a spreadsheet]
end
subgraph WITH["🚀 With ou-runner"]
direction TB
R1[ou-runner setup]
R1 --> R2[ou-runner migrate --from 14 --to 19 --hold-my-drink]
R2 --> R3[ou-runner status]
end
Install
With uv (recommended):
uv tool install ou-runner
Or run it on-demand without installing — uvx spins up an ephemeral
environment, runs the command, and gets out of the way:
uvx ou-runner --help
uvx ou-runner setup
Or with pip:
pip install ou-runner
Prerequisites
- Docker (Desktop or Engine) running locally.
- ~10 GB free disk — OpenUpgrade clones and intermediate dumps add up fast.
- A PostgreSQL custom-format dump of the Odoo 14 database you want to migrate (not a plain-text SQL file).
- Python 3.10+ available to
uv(orpip) when installing.
Quick start
ou-runner writes all of its artifacts (dumps, backups, OpenUpgrade
clones, generated Dockerfiles, docker-compose.yml,
migration_times.json) into the current working directory. Pick a
folder per migration:
mkdir my-odoo-migration && cd my-odoo-migration
# 1. Bootstrap the sandbox. setup is interactive — it will ask you
# for the source and target Odoo versions.
ou-runner setup
# 2. Drop your v14 dump where ou-runner expects it.
cp /path/to/your_v14_backup.dump dumps/odoo_14_db.dump
# 3. Migrate one hop at a time, testing between each.
ou-runner migrate --from 14 --to 15
# open http://localhost:8015, log in, smoke-test
ou-runner migrate --from 15 --to 16
# …
# Or, if you trust the chain end-to-end:
ou-runner migrate --from 14 --to 19 --hold-my-drink
# At any point:
ou-runner status # progress chain, dumps, backups, migration times
When you're done, ou-runner clean sweeps every artifact setup and
migrate produced in the current directory. Docker containers and volumes
are not touched — run docker compose down -v if you want those gone
too.
Tip. Every
ou-runner …example below works just as well asuvx ou-runner …if you'd rather not install the tool globally.
What happens during a hop
Every ou-runner migrate --from X --to Y runs these eight steps in order.
Failures halt the hop and (outside --hold-my-drink) drop you into an
interactive prompt so you can inspect, retry, or abort.
flowchart LR
A[Ensure Postgres up] --> B[Stop running Odoo containers]
B --> C[Restore source dump]
C --> D[Backup before migration]
D --> E[Start target version container]
E --> F[odoo -u all --stop-after-init]
F --> G[Restart container in normal mode]
G --> H[pg_dump -Fc to dumps/odoo_to_db.dump]
Chaining hops with --hold-my-drink
OpenUpgrade only supports sequential hops, so going from v14 to v19
means five upgrades. --hold-my-drink strings every intermediate hop
together — each hop's dump becomes the next hop's input — and bypasses
interactive prompts so a failure halts the chain cleanly.
flowchart LR
D14[(dumps/odoo_14_db.dump)] --> H1[hop 14→15]
H1 --> D15[(dumps/odoo_15_db.dump)] --> H2[hop 15→16]
H2 --> D16[(dumps/odoo_16_db.dump)] --> H3[hop 16→17]
H3 --> D17[(dumps/odoo_17_db.dump)] --> H4[hop 17→18]
H4 --> D18[(dumps/odoo_18_db.dump)] --> H5[hop 18→19]
H5 --> D19[(dumps/odoo_19_db.dump)]
Commands
| Command | What it does |
|---|---|
setup |
Bootstrap the sandbox interactively (asks for source/target versions): clone OpenUpgrade branches, render Dockerfiles + docker-compose.yml. |
update |
git pull every openupgrade_<v>/ clone to the latest commits on its branch. |
migrate --from <v> --to <v> |
Run one migration hop. Add --hold-my-drink to chain all hops up to --to. |
start <v> |
Boot a fresh, empty Odoo instance of one version (useful when you want to create a starter dump). |
status |
Show the migration's state: progress chain, recorded times, dumps on disk, backups grouped by version. |
logs <v> [-f] |
Tail the matching Odoo container's logs. |
clean [-y] |
Sweep every artifact setup/migrate produced in the current directory. |
Run ou-runner --help (or ou-runner <command> --help) for full flag
listings.
Versions
| Source | Target | Port | Output dump |
|---|---|---|---|
| 14 | 15 | 8015 | dumps/odoo_15_db.dump |
| 15 | 16 | 8016 | dumps/odoo_16_db.dump |
| 16 | 17 | 8017 | dumps/odoo_17_db.dump |
| 17 | 18 | 8018 | dumps/odoo_18_db.dump |
| 18 | 19 | 8019 | dumps/odoo_19_db.dump |
How it works
ou-runner is a thin orchestrator — it never touches a database
directly. Under the hood it:
- Clones the OCA/OpenUpgrade branches you need into
openupgrade_<version>/folders in your CWD. - Renders per-version
Dockerfile.openupgrade<N>files and a singledocker-compose.ymlthat ties them together. - Drives
pg_dump,pg_restore, andodoo -u all --stop-after-init --upgrade-path=…throughdocker exec, container by container. - Records every hop's wall-clock time in
migration_times.json.
Everything lives in the directory you ran it from. No global state, nothing in your home folder.
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ou_runner-0.1.1.tar.gz.
File metadata
- Download URL: ou_runner-0.1.1.tar.gz
- Upload date:
- Size: 18.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c31737392ced69fd36462dfc47f16e9ebe0c5f46f64c4dfd13d76d475e326107
|
|
| MD5 |
b0f6bcbf597ac87de072588db093254a
|
|
| BLAKE2b-256 |
fc1d8f59c82e23a1dc10c91d5669d443af9993a794de8fb0608da69a283bf4bd
|
Provenance
The following attestation bundles were made for ou_runner-0.1.1.tar.gz:
Publisher:
publish.yml on aidooit/ou-runner
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ou_runner-0.1.1.tar.gz -
Subject digest:
c31737392ced69fd36462dfc47f16e9ebe0c5f46f64c4dfd13d76d475e326107 - Sigstore transparency entry: 1569828541
- Sigstore integration time:
-
Permalink:
aidooit/ou-runner@9aef54812c6d50926037af532246763bc6245410 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/aidooit
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@9aef54812c6d50926037af532246763bc6245410 -
Trigger Event:
push
-
Statement type:
File details
Details for the file ou_runner-0.1.1-py3-none-any.whl.
File metadata
- Download URL: ou_runner-0.1.1-py3-none-any.whl
- Upload date:
- Size: 21.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9e3b161d5c8e350702c0a13dbe5a14297b193c70cdc16c55206214a0959f3315
|
|
| MD5 |
48903cd22eeb2e3200f69191dbe0de82
|
|
| BLAKE2b-256 |
7a9d7c5d3b00f7cf27c2012d5eac9276e0a0c69c275782fcbd3d1a20d66a4011
|
Provenance
The following attestation bundles were made for ou_runner-0.1.1-py3-none-any.whl:
Publisher:
publish.yml on aidooit/ou-runner
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ou_runner-0.1.1-py3-none-any.whl -
Subject digest:
9e3b161d5c8e350702c0a13dbe5a14297b193c70cdc16c55206214a0959f3315 - Sigstore transparency entry: 1569828563
- Sigstore integration time:
-
Permalink:
aidooit/ou-runner@9aef54812c6d50926037af532246763bc6245410 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/aidooit
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@9aef54812c6d50926037af532246763bc6245410 -
Trigger Event:
push
-
Statement type: