-
Notifications
You must be signed in to change notification settings - Fork 0
1.9 Step | CloneOdooRepo
Clones the Odoo sources into
<install_dir>/odoo, reversibly. It lives insrc/steps/clone_odoo_repo.rs. The first of the three sub-steps the Bash monolithinstall_odoois broken into (clone → venv → pip). Every operation runs as the odoo user (least privilege), not as root.
In Bash, install_odoo is one block. Here it becomes three steps with distinct undos:
| Sub-step | Undo |
|---|---|
| 1.9 CloneOdooRepo |
rm -rf of the sources (+ the container if empty) |
| 1.10 CreateVirtualenv | rm -rf sandbox |
| 1.11 InstallPythonRequirements | none (absorbed by 1.10) |
Decomposing a monolith into sub-steps with clear undo boundaries — and discovering that one has no undo of its own precisely because another covers it — is a pattern that recurs (nginx, control script).
| Phase | Behaviour |
|---|---|
| snapshot | detects the state of the sources (detect_odoo_source): absent / git on the right branch / tarball (odoo-bin without .git) / invalid directory |
| run | creates the directory structure as odoo — claiming CreatedByUs there, before touching the network — then clones (with retries and a fallback). Preexisting → skip. dry_run → log |
| undo |
CreatedByUs only: rm -rf of the repo and repos/, plus removal of the install_dir container if empty
|
-
git on the expected branch →
Preexisting(git-existing), skip. -
tarball (odoo-bin, no .git) →
Preexisting(tarball-existing), skip. - a different branch → error: it may hold work in progress. It is not silently regenerated (“remove it by hand … if you want to re-clone”).
-
invalid directory (neither .git nor odoo-bin, under our
install_dir) → warning + regeneration. -
absent →
CreatedByUsafter the run.
git clone (N retries, attempt*2s backoff, artifacts cleaned between attempts)
└─ failed after N attempts → tarball fallback (codeload.github.com)
└─ the tarball failed too → error
Git arguments faithful to Bash: -c http.version=HTTP/1.1 -c core.compression=0 clone … --branch <ver> --single-branch --no-tags --depth <N>. Default depth 5 (GIT_DEPTH), default retries 3
(GIT_CLONE_RETRIES). The source mode (git or tarball) is recorded in the snapshot for the
post-mortem.
Both the clone and the tarball are network operations, so they carry a timeout
(ODOO_NETWORK_TIMEOUT_SECS, 300s by default, 0 disables it) enforced inside the SystemOps
boundary. A timeout consumes one attempt. Local long operations do not get one: cutting them short
would do more damage than waiting.
The timeout kills the worker, not the shell in front of it. These commands run through
sudo, so the process the installer spawns issudoand the one doing the work is its child. Killing only the child leftgitalive, holding the pipes open, and the timeout error — already decided — was never reported: an installation found in the field stuck for seven minutes with not one line of log, indistinguishable from having no timeout at all. Network commands now run in a process group of their own and the expiry kills the group. One consequence, deliberate: a Ctrl-C does not reach them either, so they are carried to completion like any other step in progress, and the log says so.
The temporary tarball is downloaded inside the sources directory, not into /tmp. It is created
by us and then handed to the odoo user — because tar reads it as odoo — and O_CREAT on
somebody else's file inside a sticky, world-writable directory is refused by fs.protected_regular,
root included. So the fallback could never succeed, and nobody had noticed: a fallback only runs
when the clone has already failed, and in CI it never does. The sources directory belongs to the user
that reads it, is not sticky, and is inside the perimeter the undo removes with rm -rf.
This step lives inside <install_dir> (/opt/odoo/odoo18, say), one level below /opt/odoo. Here
rm -rf is legitimate: it is our sources directory, created entirely by us. /opt/odoo remains
1.1 PrepareOptRoot's business.
The container install_dir is removed only if empty, after the venv and config undos have run
first (reverse order) — the same pattern as /opt/odoo. If it holds anything else (including
pre-existing material), it is left intact.
-
git_cloneis a single attempt inside theSystemOpsboundary; the retry, backoff and fallback are orchestrated by the step (testable with a mock that fails N times). - Best-effort undo on every removal.
- Tests: absent (clone + undo rm -rf), git-existing (no-op), branch mismatch (error), retries (3 attempts + 2 cleanups), tarball fallback (fires; if it fails too → error).
Start here
Key concepts
References
For developers
Technical detail — how it works inside
Steps:
- 1.1 PrepareOptRoot
- 1.2 CreateOdooUser
- 1.3 SetupLogDir
- 1.3b SetupCacheDir
- 1.4 AptPackages (delta)
- 1.5 InstallWkhtmltopdf
- 1.6 SetupPostgres
- 1.7 CreateDbRole
- 1.8 CreateDatabase
- 1.9 CloneOdooRepo
- 1.10 CreateVirtualenv
- 1.11 InstallPythonRequirements
- 1.12 GenerateConfig
- 1.12b SetupDataDir
- 1.13 InitializeOdooDatabase
- 1.14 SetupSystemd
- 1.15 Nginx (6 sub-steps)
- 1.16 WriteControlScript + PatchBashrc
Cross-cutting: