# odoo-elabore-ci Centralized CI/CD configuration for Elabore's Odoo repositories. ## Purpose This repository manages linting and CI configuration centrally for all Odoo repositories (`*-addons` and `*-tools`) in the Elabore organization on Gitea. **Benefits:** - Single, consistent configuration across all repos - Automatic updates via deployment workflow - Multi-version Odoo support (16.0, 18.0, etc.) - Based on OCA (Odoo Community Association) standards ## Architecture ``` odoo-elabore-ci/ ├── .gitea/workflows/ │ └── deploy-config.yml # Manual deployment workflow (with dry-run) └── config/ ├── common/ # Shared files (all versions) │ ├── .editorconfig │ └── .gitea/ │ ├── workflows/ │ │ └── pre-commit.yml # Lint workflow deployed to each repo │ └── scripts/ │ └── odoo-tests.sh # Odoo test runner used by test.yml ├── 16.0/ # Odoo 16.0 configuration │ ├── .eslintrc.yml │ ├── .prettierrc.yml │ ├── .pre-commit-config.yaml │ ├── .pylintrc │ ├── .pylintrc-mandatory │ ├── .ruff.toml │ └── .gitea/workflows/ │ └── test.yml # Odoo tests workflow (deployed to 16.0 repos) └── 18.0/ # Odoo 18.0 configuration ├── eslint.config.cjs ├── prettier.config.cjs ├── .pre-commit-config.yaml ├── .pylintrc ├── .pylintrc-mandatory ├── .ruff.toml └── .gitea/workflows/ └── test.yml # Odoo tests workflow (deployed to 18.0 repos) ``` ## How It Works ### Deployment Workflow (`deploy-config.yml`) The deployment is **manually triggered** via Gitea Actions interface, giving you full control over what gets deployed and where. **Features:** - **Version filter**: Deploy to all versions or a specific one (16.0, 18.0) - **Repo filter**: Deploy to all repos or specific ones (comma-separated) - **Dry-run mode**: Preview changes without pushing anything - **Direct push**: Commits are pushed directly to target branches (no PR) **Process:** 1. Detects available versions (folders in `config/` other than `common/`) 2. For each target repository: - For each selected Odoo version: - Attempts to clone the corresponding branch - Copies `config/common/` then `config/{version}/` - In dry-run: shows what would change - In live mode: commits and pushes directly to the branch ### CI Workflow (`pre-commit.yml`) Deployed to each target repository, this workflow runs on every Pull Request: 1. Sets up Python 3.11 environment 2. Installs and runs `pre-commit` with all configured hooks 3. Verifies no untracked files were generated ### Test Workflow (`test.yml`) Deployed to each target repository (per Odoo version), this workflow runs the Python tests of the modules changed in a Pull Request, on the self-hosted runner hosted at `ci.elabore.coop`: 1. Runs inside the Elabore doodba image for the repo's Odoo version 2. Starts a PostgreSQL 17.2 service container 3. Detects the installable modules touched by the PR 4. Installs them and runs their tests (`odoo --test-enable`) See [Odoo Tests (CI)](#odoo-tests-ci) for details. ## Linting Tools | Tool | Purpose | Target Files | |------|---------|--------------| | **Ruff** | Python linter + formatter | `.py` | | **Pylint-Odoo** | Odoo-specific rules | `.py`, `__manifest__.py`, XML | | **ESLint** | JavaScript linter | `.js` | | **Prettier** | Multi-language formatter | JS, CSS, XML, JSON, YAML, MD | | **pre-commit-hooks** | Generic checks | Trailing whitespace, merge conflicts, etc. | | **OCA hooks** | Odoo community standards | Manifests, README, translations | ## Odoo Tests (CI) Each target repository gets a `tests` workflow (`.gitea/workflows/test.yml`) that runs the Python tests of the modules changed in a Pull Request. ### How it works | Aspect | Value | |--------|-------| | Runner | self-hosted Gitea runner on `ci.elabore.coop`, label `odoo-ci` | | Job image | `docker.0k.io/mirror/odoo:rc_-ELABORE-LIGHT` (doodba) | | Database | `docker.0k.io/postgres:17.2.0-myc` service container | | Test runner | `.gitea/scripts/odoo-tests.sh` | The workflow: 1. Checks out the PR head with full history. 2. Computes the changed installable modules with `git diff origin/...HEAD` (first-level directories containing `__manifest__.py`). 3. Runs `odoo-tests.sh ` inside the doodba image. The script generates `odoo.conf` from the environment (via the doodba entrypoint), then runs: ``` odoo --test-enable --stop-after-init -i \ --addons-path="$PWD,/opt/odoo/auto/addons" --test-tags "/" ``` The checked-out repository is prepended to the addons path, so the PR's code takes precedence over the modules already baked in the image. If no installable module is touched (e.g. docs-only PR), the test step is skipped. ### Runner (`gitea-runner`) The runner is provided by the `gitea-runner` charm of the [`0k-charms`](https://git.myceliandre.fr/0k/0k-charms) collection. It registers against the Gitea instance with an organization-level token and exposes the `odoo-ci` label; the job image is chosen by each workflow through its `container:` key. Required secrets (Gitea → organization **Elabore** → Settings → Actions → Runners): a **registration token**, configured in the runner's deployment file on `ci.elabore.coop`. It is never stored in this repository. ### Adding a new Odoo version 1. Add `config//.gitea/workflows/test.yml` (copy the closest version, adjust the branch filter and the `container.image` tag). 2. Deploy as usual. ### Limitations - Modules are tested against the dependencies **already present in the Elabore image**. A dependency introduced in another Elabore repo and not yet baked in requires rebuilding that image. - One job runs at a time (`capacity: 1` on the runner). ## Usage Guide ### Deploying Configuration Deployment is done via the Gitea Actions interface: 1. Go to **Gitea** → `odoo-elabore-ci` → **Actions** 2. Select **"Deploy CI Config"** workflow 3. Click **"Run workflow"** 4. Fill in the parameters: | Parameter | Description | Examples | |-----------|-------------|----------| | **Version** | Odoo version to deploy | `all`, `16.0`, `18.0` | | **Repos** | Target repos (empty = all) | `crm-addons, hr-addons` | | **Dry-run** | Preview without pushing | `true` (recommended first) | #### Deployment Examples | I want to... | Version | Repos | Dry-run | |--------------|---------|-------|---------| | Preview all changes | `all` | *(empty)* | ✅ | | Deploy 16.0 to one repo | `16.0` | `crm-addons` | ❌ | | Deploy 18.0 to multiple repos | `18.0` | `crm-addons, hr-addons` | ❌ | | Deploy all versions everywhere | `all` | *(empty)* | ❌ | #### Recommended Workflow ``` 1. Make changes in config/ 2. git commit && git push origin main → Nothing happens (no auto-deploy) 3. Run workflow with DRY-RUN enabled → Review the logs to see what would change 4. If satisfied, run again WITHOUT dry-run → Changes are pushed directly to target branches ``` ### Modifying CI Configuration 1. **Edit files in `config/`**: - `config/common/`: changes applied to all versions - `config/{version}/`: version-specific changes 2. **Commit and push to `main`**: ```bash git add . git commit -m "[IMP] description of change" git push origin main ``` 3. **Trigger deployment manually** (see above) ### Adding a New Odoo Version 1. **Create the configuration directory**: ```bash mkdir config/{new_version} ``` 2. **Copy and adapt files** from the closest version or from an OCA repo: ```bash # Example for Odoo 19.0 based on 18.0 cp config/18.0/* config/19.0/ ``` 3. **Adapt the copied files**: | File | Required Changes | |------|------------------| | `.pylintrc` | `valid-odoo-versions=19.0` | | `.pylintrc-mandatory` | `valid-odoo-versions=19.0` | | `.ruff.toml` | `target-version` if Python version changes | | `.pre-commit-config.yaml` | Hook versions if needed | | `.gitea/workflows/test.yml` | Branch filter and `container.image` tag | 4. **Commit and push**: ```bash git add config/19.0/ git commit -m "[ADD] support for Odoo 19.0 configuration" git push origin main ``` 5. **Deploy** via Gitea Actions: - The new version will appear in the "Version" dropdown - Use dry-run first to verify which repos have a `19.0` branch ## Secrets Configuration The workflow requires a Gitea token with the following permissions: - Read access to all organization repos - Write access (to create PRs) Configure the `ELABORE_BOT_TOKEN` secret in the repository settings. ## Version Differences ### 16.0 vs 18.0 | Aspect | 16.0 | 18.0 | |--------|------|------| | ESLint config | `.eslintrc.yml` | `eslint.config.cjs` (flat config) | | Prettier config | `.prettierrc.yml` | `prettier.config.cjs` | | Node.js | 16.17.0 | 22.9.0 | | Prettier | 2.7.1 | 3.3.3 | | ESLint | 8.x | 9.x | | Additional hooks | - | `whool-init`, `oca-gen-external-dependencies` | ## Configuration Files ### `.pylintrc` vs `.pylintrc-mandatory` - **`.pylintrc`**: All rules (optional + mandatory), non-blocking mode (`--exit-zero`). Useful for IDEs. - **`.pylintrc-mandatory`**: Critical rules only, blocking mode. Used by CI. ### Elabore-Specific Rules Files are customized for Elabore: - `manifest-required-authors=Elabore` - URLs pointing to `https://git.elabore.coop/elabore/` ## Contributing 1. Test changes locally with `pre-commit run --all-files` 2. Follow commit conventions (tags `[IMP]`, `[FIX]`, `[ADD]`, etc.) 3. Auto-generated PRs should be reviewed before merging ## Resources - [OCA Maintainer Tools](https://github.com/OCA/maintainer-tools) - [OCA Pre-commit Hooks](https://github.com/OCA/odoo-pre-commit-hooks) - [Pylint-Odoo](https://github.com/OCA/pylint-odoo) - [Ruff](https://docs.astral.sh/ruff/) - [Pre-commit](https://pre-commit.com/) ## License AGPL-3.0