Skip to main content

A small set of DevOps utilities for Odoo deployments and local development.

Project description

odoo-devops-tools

A small set of DevOps utilities for Odoo deployments and local development.

The main entrypoint is odt-env — a CLI that provisions and syncs a reproducible Odoo workspace from an INI file.

What odt-env does

  • Clones and updates Odoo and addon repositories
  • Generates a ready-to-run odoo-server.conf
  • Generates helper scripts (run, test, backup/restore, update, …)
  • Optionally provisions a Python virtual environment and a wheelhouse (useful for offline installs / CI builds)

odt-env is designed to be repeatable: re-running it should converge your workspace to what the INI file describes.


Table of contents


Installation

Using pip:

pip install odoo-devops-tools

Or using uv:

uv tool install --reinstall odoo-devops-tools

Verify:

odt-env --help

odt-env

Provision and sync a reproducible Odoo workspace from an INI configuration file.

Requirements

Optional (only for some helper scripts):

  • PostgreSQL client tools (e.g. pg_dump, psql) for backup/restore.

Quick start

1) Typical local dev (sync + venv + configs/scripts)

odt-env /path/to/ROOT/odoo-project.ini --sync-all --create-venv

2) Sync repositories only (no Python provisioning)

odt-env /path/to/ROOT/odoo-project.ini --sync-all

3) CI / build machine: create wheelhouse (no install into venv)

odt-env /path/to/ROOT/odoo-project.ini --sync-all --create-wheelhouse

4) Offline install from an existing wheelhouse

odt-env /path/to/ROOT/odoo-project.ini --create-venv --reuse-wheelhouse

5) Hard rebuild of the venv

odt-env /path/to/ROOT/odoo-project.ini --sync-all --rebuild-venv

If you run no options, odt-env only regenerates configs and helper scripts:

odt-env /path/to/ROOT/odoo-project.ini

Concepts: ROOT vs. DEST_ROOT

  • ROOT is where the workspace is physically created (repos, venv, wheelhouse, generated files).

    • Default: the directory containing the INI file.
    • Override with --root (must point to an existing directory).
  • DEST_ROOT controls what paths get embedded into generated files (configs/scripts).

    • Default: same as ROOT.
    • Override with --dest-root (does not need to exist on the build machine).

A typical deployment workflow is: build under a temporary directory, but generate configs/scripts that reference the final location on the target host:

odt-env /path/to/odoo-project.ini --sync-all --create-wheelhouse \
  --root /tmp/build-root \
  --dest-root /srv/odoo/myproject

Workspace layout

ROOT is the directory containing odoo-project.ini (or the path passed via --root).

If you pass --dest-root, odt-env still writes files under ROOT, but paths embedded in generated files are based on DEST_ROOT.

Default layout:

  • ROOT/odoo/ — Odoo repository
  • ROOT/odoo-addons/<name>/ — addon repositories
  • ROOT/odoo-backups/ — backups directory
  • ROOT/odoo-data/ — data directory (customizable via [config] data_dir)
  • ROOT/odoo-configs/ — generated config (e.g. odoo-server.conf)
  • ROOT/odoo-scripts/ — generated helper scripts
  • ROOT/odoo-logs/ — runtime logs (created by instance.sh)
  • ROOT/venv/ — virtualenv / Python toolchain (when enabled)
  • ROOT/wheelhouse/ — wheel cache for offline installs (when enabled)

Configuration (INI)

Sections overview

odt-env reads an INI file with these sections:

  • [virtualenv] — Python version, managed Python, requirements, constraints…
  • [odoo] — Odoo repo + branch
  • [addons.<name>] — addon repos (repeatable per addon)
  • [config] — values rendered into odoo-server.conf (db, ports, log settings, …)
  • [include] — optional includes (config inheritance)

Example configuration

This example provisions an Odoo 18.0 workspace with two addon repositories:

[virtualenv]
python_version = 3.11
# Optional (default: true): when false, odt-env will NOT install a managed CPython via `uv python install`.
# Instead it will rely on an existing system Python that matches `python_version`.
# managed_python = false
build_constraints =
requirements =
requirements_ignore =

[odoo]
repo = https://github.com/odoo/odoo.git
branch = 18.0
# Optional: If true, keep repo as a shallow, single-branch clone (depth=1). If false (default), do a full clone/fetch.
shallow_clone = true

[addons.oca-web]
repo = https://github.com/OCA/web.git
branch = 18.0

[addons.oca-helpdesk]
repo = https://github.com/OCA/helpdesk.git
branch = 18.0

[config]
http_port = 8069
gevent_port = 8072
db_host = 127.0.0.1
db_port = 5432
db_name = sample_odoo18
db_user = sample_odoo18
db_password = sample_odoo18
log_level = debug
max_cron_threads = 0

Includes (config inheritance)

You can split configuration across multiple INI files (for example a shared base + environment-specific overrides).

Rules:

  • paths are resolved relative to the INI file that declares the include,
  • included files load first; the including file loads last (later values override earlier ones),
  • prefix a file path with ? to make it optional (missing file is skipped).

Example:

odoo-base.ini:

[virtualenv]
python_version = 3.11
build_constraints =
requirements =
requirements_ignore =

[odoo]
repo = https://github.com/odoo/odoo.git
branch = 18.0

[config]
http_port = 8069
gevent_port = 8072
db_host = 127.0.0.1
db_port = 5432
db_name = sample_odoo18
db_user = sample_odoo18
db_password = sample_odoo18

odoo-dev.ini:

[include]
files = odoo-base.ini

[odoo]
branch = develop

[config]
db_name = sample_odoo18_dev

odoo-test.ini:

[include]
files =
  odoo-base.ini
  ?odoo-dev.ini

[config]
db_name = sample_odoo18_test

Variables & interpolation

odt-env uses Python ExtendedInterpolation, so you can reference values with ${section:option}.

It also injects workspace path variables into the INI DEFAULT scope (available from any section):

  • ${ini_dir} — directory containing the INI file
  • ${root_dir} — workspace root directory
  • ${odoo_dir}ROOT/odoo
  • ${addons_dir}ROOT/odoo-addons
  • ${backups_dir}ROOT/odoo-backups
  • ${configs_dir}ROOT/odoo-configs
  • ${config_path} — full path to the generated odoo-server.conf
  • ${scripts_dir}ROOT/odoo-scripts
  • ${venv_python} — full path to the venv Python executable

Note on --dest-root:

  • odt-env always builds under filesystem ROOT.
  • When --dest-root is provided, variables like ${root_dir}, ${odoo_dir}, ${addons_dir}, … are evaluated against DEST_ROOT for the [config] section (so generated odoo-server.conf uses deployment paths).
  • Other sections ([odoo], [addons.*], [virtualenv]) continue to use filesystem ROOT (so git/venv/wheelhouse operations work locally).
  • ${ini_dir} always points to the directory of the entry INI file on the build machine (useful for includes).

Tip: create your own helper section (e.g. [vars]) and reuse it elsewhere:

[vars]
project = sample_odoo18
branch = 18.0

[virtualenv]
python_version = 3.11
requirements =
  -r ${ini_dir}/requirements-dev.txt

[odoo]
repo = https://github.com/odoo/odoo.git
branch = ${vars:branch}

[addons.oca-web]
repo = https://github.com/OCA/web.git
branch = ${odoo:branch}

[config]
db_name = ${vars:project}
data_dir = ${root_dir}/odoo-data/${vars:project}
logfile = ${root_dir}/odoo-logs/${vars:project}.log

addons_path behavior

odt-env always computes a base addons_path for odoo-server.conf that includes:

  • the Odoo core addons directory (ROOT/odoo/addons and/or ROOT/odoo/odoo/addons),
  • every synced addon repository (ROOT/odoo-addons/<name>).

If you set addons_path in [config], it extends (appends to) the computed base list (it does not replace it). Duplicates are removed.

Format:

  • comma-separated list and/or multi-line value,
  • relative paths are resolved relative to ROOT (same as ${root_dir}).

Example:

[config]
addons_path =
  odoo-addons/3rd_party_addons,
  ${addons_dir}/extra_addons,

Shallow clones (shallow_clone)

By default, repositories are kept as full clones (full history, branches, tags). For very large repositories (especially odoo/odoo), you can enable a shallow, single-branch workflow.

Where to set it:

  • [odoo] shallow_clone = true
  • [addons.<name>] shallow_clone = true

Behavior:

  • initial clone: git clone --depth 1 --single-branch --branch <branch> …
  • sync/update: fetch only origin <branch> with --depth 1, then hard-reset to origin/<branch>

Pros:

  • faster clone/fetch
  • less disk usage

Limitations:

  • depth is fixed to 1 (only the branch tip is available),
  • operations requiring history (e.g. long git log, git bisect, git describe on older tags) won’t work as expected,
  • switching from full → shallow does not automatically drop history; delete the repo directory and re-sync to realize the benefits.

Switching back to full:

  • set shallow_clone = false (or remove it) and re-run a sync; odt-env will unshallow and widen the fetch refspec so later fetch --all --tags can pull all branches/tags.

Command-line options

Tip: The quick-start section covers the most common workflows. Use this section as a reference when you need to fine-tune behavior.

Paths & outputs

  • --root — workspace ROOT directory (default: directory containing the INI)
  • --dest-root — deployment root for paths embedded in generated configs/scripts (default: same as ROOT)
  • --no-configs — do not generate config files (e.g. odoo-server.conf)
  • --no-scripts — do not generate helper scripts under ROOT/odoo-scripts/
  • --no-data-dir — do not create the Odoo data folder under ROOT/odoo-data/ (or custom [config] data_dir)

Repository sync

  • --sync-odoo — sync only ROOT/odoo
  • --sync-addons — sync only ROOT/odoo-addons/* (no-op if no [addons.*] sections exist)
  • --sync-all — sync both Odoo + addons

Python / venv / wheelhouse

  • --create-venv — create/update ROOT/venv and install Python dependencies (from wheelhouse)
  • --rebuild-venv — delete + recreate ROOT/venv (implies --create-venv)
  • --create-wheelhouse — build/update the lock + ROOT/wheelhouse/ without installing requirements into venv
    (may still create/update ROOT/venv/ as a Python toolchain)
  • --reuse-wheelhouse — reuse an existing ROOT/wheelhouse/ and install strictly offline (requires --create-venv)
  • --clear-pip-wheel-cache — remove all items from pip’s wheel cache

Python environment & wheelhouse

Python dependencies are installed into the venv only when you pass --create-venv (or --rebuild-venv).

  • venv location: ROOT/venv
  • Python version: [virtualenv] python_version
  • tooling: uv venv and uv pip
  • wheelhouse location: ROOT/wheelhouse/
  • installs use offline mode from wheelhouse (--offline --no-index)

Reuse an existing wheelhouse (offline)

If ROOT/wheelhouse/ is already prepared:

odt-env /path/to/odoo-project.ini --create-venv --reuse-wheelhouse

This skips lock compilation and wheel building and performs a strict offline install from the existing wheelhouse. You can combine it with --sync-all/--sync-odoo/--sync-addons (repo sync still happens; deps install is offline).

Managed Python install

By default, odt-env manages the requested CPython version via uv:

  • Option: [virtualenv] managed_python
  • Default: true

Behavior:

  • managed_python = true: when creating ROOT/venv/, odt-env ensures the requested Python exists by running uv python install.
  • managed_python = false: odt-env skips uv python install and relies on an already-installed system Python that matches python_version.

Example:

[virtualenv]
python_version = 3.11
managed_python = false

Generated helper scripts

Scripts are generated into ROOT/odoo-scripts/. All scripts:

  • use the generated config file (ROOT/odoo-configs/odoo-server.conf),
  • forward extra CLI arguments to the underlying command.

Script list

Linux/macOS:

  • run.sh — start Odoo in the foreground
  • instance.sh — manage Odoo as a background service (start/stop/restart/status) and log to ROOT/odoo-logs/odoo-server.log
  • test.sh — run tests
  • shell.sh — open an interactive Odoo shell
  • initdb.sh — initialize database
  • backup.sh — create a timestamped ZIP backup (DB + filestore) into ROOT/odoo-backups/
  • restore.sh — restore a backup ZIP
  • restore_force.sh — restore and overwrite an existing DB
  • update.sh — update modules, auto-detecting addons to update using file-content hashes stored in the DB
  • update_all.sh — force a full upgrade (-u base)

Windows:

  • run.bat, test.bat, shell.bat, initdb.bat, backup.bat, restore.bat, restore_force.bat, update.bat, update_all.bat

Common usage

Start the server:

./odoo-scripts/run.sh
odoo-scripts\run.bat

Manage the background instance (Linux only):

./odoo-scripts/instance.sh start
./odoo-scripts/instance.sh status
./odoo-scripts/instance.sh restart
./odoo-scripts/instance.sh stop

Update modules:

./odoo-scripts/update.sh
odoo-scripts\update.bat

Run tests:

./odoo-scripts/test.sh -u base
./odoo-scripts/test.sh -u mail,web
./odoo-scripts/test.sh -u my_custom_addon
odoo-scripts\test.bat -u base
odoo-scripts\test.bat -u mail,web
odoo-scripts\test.bat -u my_custom_addon

Backup / restore:

./odoo-scripts/backup.sh
./odoo-scripts/restore.sh PATH/TO/BACKUP.zip
./odoo-scripts/restore_force.sh PATH/TO/BACKUP.zip
odoo-scripts\backup.bat
odoo-scripts\restore.bat PATH\TO\BACKUP.zip
odoo-scripts\restore_force.bat PATH\TO\BACKUP.zip

Safety: local changes policy

If any target repository (Odoo or an addon) contains local uncommitted changes (including untracked files), odt-env aborts. Commit/stash/clean your working tree before running odt-env.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

odoo_devops_tools-1.0.2.tar.gz (31.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

odoo_devops_tools-1.0.2-py3-none-any.whl (26.7 kB view details)

Uploaded Python 3

File details

Details for the file odoo_devops_tools-1.0.2.tar.gz.

File metadata

  • Download URL: odoo_devops_tools-1.0.2.tar.gz
  • Upload date:
  • Size: 31.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for odoo_devops_tools-1.0.2.tar.gz
Algorithm Hash digest
SHA256 66b8da964873d6e0dce5fb2b265b9c9f2c8f7a20cfc6fe307f93830145ee8180
MD5 92890d3fee1225a89331c7764cadc458
BLAKE2b-256 cbaad8883cea784992c0329ba1326e7d1935331b6cc5d5bcccd11712af9b7fb3

See more details on using hashes here.

File details

Details for the file odoo_devops_tools-1.0.2-py3-none-any.whl.

File metadata

File hashes

Hashes for odoo_devops_tools-1.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 fece8ada0f04d65b12eec22ec143d25d0479a1b56c1d7d982b8cc57b9ae9b23b
MD5 0eb39287c8275f3f5d2a47185efc62cd
BLAKE2b-256 980a5844594698ee4e3aaface3950d8f364a3c6b31abba8d6c35899f5d1858ec

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page