Skip to content

CI/CD — GitHub Actions

Q7 wires two automated checks that run on every push to main and every pull request:

Workflow File What it does Typical runtime
Lint .github/workflows/lint.yml Runs the full pre-commit toolchain — ruff (format + lint), pylint_odoo, oca-checks-odoo-module, XML/YAML hygiene ~1 min
Tests .github/workflows/tests.yml Spins up Postgres 15 + Odoo 18, installs every roots_hemms_* addon with --test-enable, fails on any test/install error ~5-8 min

A third workflow, Docs (docs.yml), was already shipped pre-Q7 and builds the MkDocs site on every push that touches docs/ or mkdocs.yml.

Triggers

Both Q7 workflows trigger on:

  • push to main — gate before docs build
  • pull_request against main — gate before merge
  • workflow_dispatch — manual trigger from the Actions tab

To keep CI cheap, each workflow has paths: filters so docs-only PRs don't burn lint/test minutes, and concurrency: cancels in-progress runs when a newer commit lands on the same ref.

Lint workflow

- uses: actions/setup-python@v5
  with:
    python-version: '3.10'
- uses: pre-commit/action@v3.0.1

The pre-commit/action caches hook environments by hash of .pre-commit-config.yaml, so subsequent runs are seconds — first run takes ~1 min to fetch ruff, pylint_odoo, and oca-checks.

The configuration mirrors OCA/maintenance 18.0 with three intentional deviations documented at the top of .pre-commit-config.yaml:

  • oca-gen-addon-readme skipped (no readme/ directories yet)
  • oca-fix-manifest-website skipped (HEMMS uses https://roots.tech, not the OCA repo URL)
  • prettier-xml + eslint commented out (re-enable when a JS asset bundle ships)

Tests workflow

services:
  postgres:
    image: postgres:15
container:
  image: odoo:18.0

The job runs inside the official odoo:18.0 Docker image with a sibling Postgres 15 service container. Because Q6 (Mass Import) reads XLSX via openpyxl which is not bundled with the Odoo image, a single extra pip install step adds it before tests run:

- run: pip install --break-system-packages --quiet openpyxl

Module selection

Rather than list all 10 roots_hemms_* modules, CI installs four leaf modules which transitively pull every other module via depends:

Leaf Pulls (transitively)
roots_hemms_mass_import Q6 + roots_hemms_ha_report + roots_hemms_pm + roots_hemms_asset_master
roots_hemms_spare_parts Q2 + roots_hemms_pm + roots_hemms_asset_master + roots_hemms_criticality
roots_hemms_signature Q4 + roots_hemms_asset_inspection + roots_hemms_service_contracts
roots_hemms_ha_report Q5 + roots_hemms_signature + roots_hemms_pm + roots_hemms_asset_inspection + ...

The constant lives in two synchronized places:

  • .github/workflows/tests.ymlMODULES_TO_TEST env var
  • MakefileHEMMS_MODULES variable

If you add a top-of-tree HEMMS module, update both.

Detecting test failures

Odoo's exit code is 0 even when tests fail — it only reflects whether the CLI command itself crashed. The verify step scrapes odoo.log for three signatures:

grep -E "^(FAIL|ERROR): " odoo.log       # unittest runner per-test
grep -E "odoo\.tests\.runner.*(FAIL|ERROR)" odoo.log   # framework
! grep -q "Modules loaded\."             # install crashed

Any match → job fails and the full odoo.log is uploaded as an artifact (odoo-log, 7-day retention) so you can debug without re-running CI.

Local CI parity

Reproduce CI on your laptop:

# Lint — same hooks GH runs
make lint

# Tests — runs inside the running private sandbox container
make up-private              # if not already up
make test                    # installs into a throw-away DB

# Both together
make ci

If you don't have the local Docker stack, install the lint venv manually:

python3.10 -m venv .venv-lint
.venv-lint/bin/pip install ruff==0.6.8 pylint-odoo==9.1.3
.venv-lint/bin/ruff check addons/roots/
.venv-lint/bin/pylint --rcfile=.pylintrc addons/roots/

Status badges

Add to your README (replace OWNER/REPO):

![Lint](https://github.com/jakapolr/hemms-demo/actions/workflows/lint.yml/badge.svg)
![Tests](https://github.com/jakapolr/hemms-demo/actions/workflows/tests.yml/badge.svg)
![Docs](https://github.com/jakapolr/hemms-demo/actions/workflows/docs.yml/badge.svg)

Future hardening

These items are deliberately deferred from Q7 — capture in the next plan revision if they become priorities:

  • Matrix Postgres versions (15 + 16) — once we have a customer running 16
  • Code coverage reportcoverage.py integration + Codecov upload
  • Demo data smoke test — install with --with-demo and assert expected record counts (right now demo loads but isn't asserted)
  • Two-DB matrix (hemms_demo vs hemms_private) — Q5 has documented behavioural differences between fresh-install and Q2-installed databases that aren't exercised in CI