odoo-toolkit 4.1.2__tar.gz → 4.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- odoo_toolkit-4.2.0/.devcontainer/Dockerfile +5 -0
- odoo_toolkit-4.2.0/.devcontainer/devcontainer.json +48 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/.github/workflows/ci.yml +2 -1
- odoo_toolkit-4.2.0/.github/workflows/sync-odoo-ruff.yml +27 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/.github/workflows/sync-runbot.yml +1 -1
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/PKG-INFO +74 -5
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/README.md +73 -4
- odoo_toolkit-4.2.0/odoo_toolkit/code.py +62 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/dev/run.py +31 -1
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/dev/runtime.py +62 -10
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/docker/dev.Dockerfile +3 -3
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/docker/runbot/Docker18.Dockerfile +1 -1
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/docker/runbot/Docker19.Dockerfile +1 -1
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/docker/runbot/Docker191.Dockerfile +1 -1
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/docker/runbot/Docker194.Dockerfile +1 -1
- odoo_toolkit-4.2.0/odoo_toolkit/docker/runbot/Docker20.Dockerfile +139 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/docker/runbot/DockerMaster.Dockerfile +1 -1
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/main.py +9 -2
- odoo_toolkit-4.2.0/odoo_toolkit/multiverse_config/.devcontainer/devcontainer.json +47 -0
- odoo_toolkit-4.2.0/odoo_toolkit/multiverse_config/.vscode/extensions.json +11 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/multiverse_config/requirements.txt +1 -0
- odoo_toolkit-4.1.2/odoo_toolkit/multiverse_config/ruff.toml → odoo_toolkit-4.2.0/odoo_toolkit/multiverse_config/ruff-odoo.toml +13 -4
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/mv/config.py +47 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/mv/remotes.py +6 -1
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/mv/setup.py +235 -13
- odoo_toolkit-4.2.0/odoo_toolkit/update_check.py +111 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/versions.json +1 -1
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/wl/common.py +1 -5
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/pyproject.toml +13 -1
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/tests/conftest.py +6 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/tests/dev/test_runtime.py +84 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/tests/mv/test_remotes.py +14 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/tests/mv/test_setup.py +180 -1
- odoo_toolkit-4.2.0/tests/test_code.py +96 -0
- odoo_toolkit-4.2.0/tests/test_update_check.py +84 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/uv.lock +64 -2
- odoo_toolkit-4.1.2/odoo_toolkit/multiverse_config/.vscode/extensions.json +0 -16
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/.github/dependabot.yml +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/.github/workflows/images.yml +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/.github/workflows/release.yml +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/.gitignore +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/.vscode/settings.json +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/LICENSE +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/images/mailpit.png +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/__init__.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/__main__.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/common.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/dev/__init__.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/dev/common.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/dev/db.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/dev/images.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/dev/stop.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/docker/compose.yaml +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/docker/pgadmin/servers.json +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/docker/runbot/Docker17.Dockerfile +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/git_cli.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/multiverse_config/.vscode/launch.json +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/multiverse_config/.vscode/settings.json +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/multiverse_config/.vscode/tasks.json +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/multiverse_config/build-constraints.txt +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/multiverse_config/compat-requirements.txt +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/mv/__init__.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/mv/cleanup.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/mv/link.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/mv/repos.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/mv/reset.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/mv/switch.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/po/__init__.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/po/cldr-common-48.2/LICENSE +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/po/cldr-common-48.2/common/dtd/ldmlSupplemental.dtd +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/po/cldr-common-48.2/common/supplemental/plurals.xml +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/po/cldr.csv +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/po/common.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/po/create.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/po/export.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/po/update.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/versions.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/wl/__init__.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/wl/authors.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/wl/config.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/wl/copy.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/wl/download.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/wl/update_teams.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/odoo_toolkit/wl/upload.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/scripts/build_images.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/scripts/sync_runbot.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/tests/__init__.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/tests/dev/__init__.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/tests/dev/test_common.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/tests/dev/test_images.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/tests/mv/__init__.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/tests/mv/conftest.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/tests/mv/test_config.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/tests/mv/test_switch_reset.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/tests/po/__init__.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/tests/po/test_export.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/tests/po/test_po_files.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/tests/test_git_cli.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/tests/test_http.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/tests/test_versions.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/tests/wl/__init__.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/tests/wl/test_authors.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/tests/wl/test_client.py +0 -0
- {odoo_toolkit-4.1.2 → odoo_toolkit-4.2.0}/tests/wl/test_commands.py +0 -0
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
FROM mcr.microsoft.com/devcontainers/python:3.12
|
|
2
|
+
|
|
3
|
+
# Claude Code keeps its login in a volume mounted here. Docker gives a new volume the owner of this folder, so the user of
|
|
4
|
+
# the dev container can write in it.
|
|
5
|
+
RUN mkdir /home/vscode/.claude && chown vscode:vscode /home/vscode/.claude
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "odoo-toolkit",
|
|
3
|
+
"build": {
|
|
4
|
+
"dockerfile": "Dockerfile"
|
|
5
|
+
},
|
|
6
|
+
"remoteUser": "vscode",
|
|
7
|
+
"updateRemoteUserUID": true,
|
|
8
|
+
"runArgs": ["--cap-drop=ALL", "--security-opt=no-new-privileges", "--init"],
|
|
9
|
+
"mounts": [
|
|
10
|
+
"source=odoo-toolkit-claude,target=/home/vscode/.claude,type=volume",
|
|
11
|
+
"source=${localWorkspaceFolder}/.devcontainer,target=${containerWorkspaceFolder}/.devcontainer,type=bind,readonly",
|
|
12
|
+
"source=${localWorkspaceFolder}/.vscode,target=${containerWorkspaceFolder}/.vscode,type=bind,readonly",
|
|
13
|
+
"source=${localWorkspaceFolder}/.git/hooks,target=${containerWorkspaceFolder}/.git/hooks,type=bind,readonly"
|
|
14
|
+
],
|
|
15
|
+
"containerEnv": {
|
|
16
|
+
"CLAUDE_CONFIG_DIR": "/home/vscode/.claude",
|
|
17
|
+
"UV_PROJECT_ENVIRONMENT": "/home/vscode/.venv",
|
|
18
|
+
"UV_LINK_MODE": "copy"
|
|
19
|
+
},
|
|
20
|
+
"remoteEnv": {
|
|
21
|
+
"PATH": "/home/vscode/.venv/bin:/home/vscode/.local/bin:${containerEnv:PATH}",
|
|
22
|
+
"SSH_AUTH_SOCK": null
|
|
23
|
+
},
|
|
24
|
+
"onCreateCommand": "pip install --user --quiet uv && uv sync --quiet",
|
|
25
|
+
"postStartCommand": "git config --global --unset-all credential.helper || true",
|
|
26
|
+
"postAttachCommand": "rm -f /tmp/vscode-ssh-auth-*.sock",
|
|
27
|
+
"otherPortsAttributes": {
|
|
28
|
+
"onAutoForward": "ignore"
|
|
29
|
+
},
|
|
30
|
+
"customizations": {
|
|
31
|
+
"vscode": {
|
|
32
|
+
"extensions": [
|
|
33
|
+
"anthropic.claude-code",
|
|
34
|
+
"charliermarsh.ruff",
|
|
35
|
+
"ms-python.python",
|
|
36
|
+
"ms-python.debugpy",
|
|
37
|
+
"njpwerner.autodocstring"
|
|
38
|
+
],
|
|
39
|
+
"settings": {
|
|
40
|
+
"python.defaultInterpreterPath": "/home/vscode/.venv/bin/python",
|
|
41
|
+
"remote.autoForwardPorts": false,
|
|
42
|
+
"git.terminalAuthentication": false,
|
|
43
|
+
"github.gitAuthentication": false,
|
|
44
|
+
"git.enableCommitSigning": false
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -15,7 +15,8 @@ jobs:
|
|
|
15
15
|
steps:
|
|
16
16
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
17
17
|
- uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
|
|
18
|
-
- run:
|
|
18
|
+
- run: uv run ruff check odoo_toolkit scripts tests
|
|
19
|
+
- run: uv run pyright
|
|
19
20
|
|
|
20
21
|
test:
|
|
21
22
|
strategy:
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
name: Sync Odoo's Ruff rules
|
|
2
|
+
|
|
3
|
+
# Checks every week whether Odoo changed the ruff.toml of its master branch, and opens a pull request with the changes.
|
|
4
|
+
# `otk mv setup` copies it into the multiverse, for the repositories that don't have a version of Odoo to extend.
|
|
5
|
+
on:
|
|
6
|
+
schedule:
|
|
7
|
+
- cron: "0 5 * * 0"
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
contents: write
|
|
12
|
+
pull-requests: write
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
sync:
|
|
16
|
+
runs-on: ubuntu-24.04
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
19
|
+
- run: curl --fail --silent --show-error --location --output odoo_toolkit/multiverse_config/ruff-odoo.toml https://raw.githubusercontent.com/odoo/odoo/master/ruff.toml
|
|
20
|
+
- uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
|
|
21
|
+
with:
|
|
22
|
+
branch: sync-odoo-ruff
|
|
23
|
+
commit-message: "[IMP] mv: sync Odoo's Ruff rules"
|
|
24
|
+
title: "[IMP] mv: sync Odoo's Ruff rules"
|
|
25
|
+
body: |
|
|
26
|
+
The ruff.toml of Odoo's master branch changed. Review the diff.
|
|
27
|
+
delete-branch: true
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: odoo-toolkit
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.2.0
|
|
4
4
|
Summary: This toolkit contains a few useful tools for Odoo development.
|
|
5
5
|
Author-email: Dylan Kiss <dyki@odoo.com>
|
|
6
6
|
License-File: LICENSE
|
|
@@ -35,6 +35,9 @@ $ uv tool install --force git+https://github.com/dylankiss/odoo-toolkit.git
|
|
|
35
35
|
> [!TIP]
|
|
36
36
|
> You can run any command with the `--help` option to find out all options you can use.
|
|
37
37
|
|
|
38
|
+
> [!NOTE]
|
|
39
|
+
> At most once a day, in the background, the toolkit checks [PyPI](https://pypi.org/project/odoo-toolkit/) for a new version and tells you after the command has run. It doesn't check in scripts, in CI, or when the toolkit isn't installed from PyPI, like a linked development version. Set `OTK_NO_UPDATE_CHECK` to any value to turn it off.
|
|
40
|
+
|
|
38
41
|
> [!TIP]
|
|
39
42
|
> Anywhere you can provide modules as arguments or options, you can also use [glob patterns](https://docs.python.org/3/library/fnmatch.html) to match multiple similar ones.
|
|
40
43
|
|
|
@@ -257,6 +260,15 @@ What stays between runs:
|
|
|
257
260
|
|
|
258
261
|
Your SSH agent (the one in `SSH_AUTH_SOCK`, like Bitwarden's or 1Password's) is available in the container, for Odoo modules that run Git commands. Your keys never leave your machine.
|
|
259
262
|
|
|
263
|
+
With [OrbStack](https://orbstack.dev), which provides its own agent forwarding, an agent like Bitwarden's needs an `IdentityAgent` line in your `~/.ssh/config`. Add it below any `Include` lines, then restart OrbStack:
|
|
264
|
+
|
|
265
|
+
```
|
|
266
|
+
Host *
|
|
267
|
+
IdentityAgent "~/Library/Containers/com.bitwarden.desktop/Data/.bitwarden-ssh-agent.sock"
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
Use the socket in your `SSH_AUTH_SOCK` for the path, which is different for other agents, like 1Password's.
|
|
271
|
+
|
|
260
272
|
On Linux, the container runs as your user, so the files Odoo writes are yours. The images on Docker Hub run as user ID 1000, the first user on most Linux machines. With another user ID, build the image on your machine once with `--build`.
|
|
261
273
|
|
|
262
274
|
> [!TIP]
|
|
@@ -271,7 +283,7 @@ It starts PostgreSQL and Mailpit if needed, and runs Odoo with:
|
|
|
271
283
|
- the database and mail server set up,
|
|
272
284
|
- no time limits, so requests don't stop while you're paused in the debugger.
|
|
273
285
|
|
|
274
|
-
Use `--community` to only load Odoo Community, or `--exclude` to leave out repositories, like `-x enterprise`. Pass any other Odoo options after `--`. Stop Odoo with `Ctrl+C`.
|
|
286
|
+
Use `--community` to only load Odoo Community, or `--exclude` to leave out repositories, like `-x enterprise`. Use `--volume` and `--env` to give the container files and settings of your machine, like the configuration of a linked repository. Pass any other Odoo options after `--`. Stop Odoo with `Ctrl+C`.
|
|
275
287
|
|
|
276
288
|
### Usage
|
|
277
289
|
|
|
@@ -283,6 +295,7 @@ e.g.
|
|
|
283
295
|
$ otk dev run -- -d mydb -i sale
|
|
284
296
|
$ otk dev run --port 8070 --debug -- -d mydb
|
|
285
297
|
$ otk dev run --community -- -d community-db
|
|
298
|
+
$ otk dev run -v ~/etc-odoo:/etc/odoo:ro -e KEY=value -- -d mydb
|
|
286
299
|
```
|
|
287
300
|
|
|
288
301
|
### Options
|
|
@@ -293,6 +306,8 @@ $ otk dev run --community -- -d community-db
|
|
|
293
306
|
* `--upgrade`: Add the upgrade scripts of `upgrade` and `upgrade-util` to the upgrade path.
|
|
294
307
|
* `--community`: Only load the modules of Odoo Community (`odoo/addons`).
|
|
295
308
|
* `-x, --exclude TEXT`: Leave these repositories out of the addons path, like `enterprise` or `odoofin,design-themes`.
|
|
309
|
+
* `-v, --volume TEXT`: Mount a file or folder of your machine in the container, like `~/etc-odoo:/etc/odoo:ro`. Can be used several times. A path starting with `~` or `.` is made absolute, and the path must exist.
|
|
310
|
+
* `-e, --env TEXT`: Set an environment variable in the container, like `REQUESTS_CA_BUNDLE=/etc/ca.pem`. Can be used several times.
|
|
296
311
|
* `--build`: Build the image on your machine instead of pulling it.
|
|
297
312
|
* `--pull`: Pull the latest image, even if you have one already.
|
|
298
313
|
* `--db-port INTEGER`: The port to reach PostgreSQL on, on your machine. Defaults to the one it runs on, or `5432`. Changing it restarts PostgreSQL.
|
|
@@ -626,7 +641,7 @@ The easiest way to set this up is by creating a directory for your multiverse se
|
|
|
626
641
|
> [!IMPORTANT]
|
|
627
642
|
> Make sure you have set up your GitHub SSH key beforehand in order to clone the repositories, and installed [`uv`](https://docs.astral.sh/uv/getting-started/installation/) and `npm`.
|
|
628
643
|
|
|
629
|
-
You can run the command as many times as you want. It only adds what's missing, and never touches your own files. Pass `--reset-config` to recreate the Python environments
|
|
644
|
+
You can run the command as many times as you want. It only adds what's missing, and never touches your own files. Pass `--update-config` to overwrite the configuration files with the latest ones, or `--reset-config` to recreate the Python environments as well. Without `-b` or `-r`, it updates the versions and repositories that are already set up.
|
|
630
645
|
|
|
631
646
|
### Repositories
|
|
632
647
|
|
|
@@ -697,6 +712,7 @@ After all that is done, your directory structure should look like this with the
|
|
|
697
712
|
├── 19.0
|
|
698
713
|
│ ├── .venv (Python virtual environment)
|
|
699
714
|
│ ├── .vscode (Visual Studio Code configuration)
|
|
715
|
+
│ ├── ruff.toml (extends the one of odoo, for the other repositories)
|
|
700
716
|
│ ├── odoo (19.0)
|
|
701
717
|
│ ├── enterprise (19.0)
|
|
702
718
|
│ ├── design-themes (19.0)
|
|
@@ -709,11 +725,33 @@ After all that is done, your directory structure should look like this with the
|
|
|
709
725
|
├── upgrade (master)
|
|
710
726
|
├── upgrade-util (master)
|
|
711
727
|
├── requirements.txt
|
|
712
|
-
|
|
728
|
+
├── ruff-odoo.toml (Odoo's Ruff rules of master)
|
|
729
|
+
└── ruff.toml (extends ruff-odoo.toml)
|
|
713
730
|
```
|
|
714
731
|
|
|
715
732
|
Open a version directory (like `code <multiverse-folder>/19.0`) in your editor to work on that version.
|
|
716
733
|
|
|
734
|
+
### Dev Container
|
|
735
|
+
|
|
736
|
+
With `--devcontainer`, every version directory gets a [dev container](https://containers.dev) configuration. Open the version in Visual Studio Code and run **Dev Containers: Reopen in Container**. The window, its extensions and any AI agent in it then only see your multiverse directory (mounted at the same path as on your machine): not your home folder, SSH keys or Git credentials.
|
|
737
|
+
|
|
738
|
+
- Opening the container starts the shared services (`otk dev db`), since it joins their network. Odoo starts from the **Odoo (container): run and debug** launch configuration, because `otk dev run` needs Docker.
|
|
739
|
+
- Git commands that need GitHub (fetch, pull, push) don't work in the container. Run them from a terminal on your machine.
|
|
740
|
+
- The `.devcontainer`, `.vscode` and `.venv` folders are read-only in the container, because they hold what runs on your machine later (like tasks and the dev container's own configuration). Change them from your machine, for example with `otk mv setup --update-config`.
|
|
741
|
+
- Everything else in the multiverse can be read and changed in the container, and it has network access, including to the databases of `otk dev`. Don't keep secrets or data you can't share in your multiverse or those databases if you use AI agents.
|
|
742
|
+
- Only windows opened in the container are isolated, not agents you start from a terminal on your machine.
|
|
743
|
+
- Visual Studio Code shares your Git config and credential helper with every dev container, which a project can't turn off. Add `"dev.containers.copyGitConfig": false` and `"dev.containers.gitCredentialHelperConfigLocation": "none"` to your user settings.
|
|
744
|
+
- Extensions and settings you want in the dev containers of this multiverse, like a spell checker, go in a `[devcontainer]` table in `multiverse.toml`, which `--update-config` applies. Extensions you want in every dev container go in the `dev.containers.defaultExtensions` user setting.
|
|
745
|
+
|
|
746
|
+
```toml
|
|
747
|
+
[devcontainer]
|
|
748
|
+
extensions = ["streetsidesoftware.code-spell-checker"]
|
|
749
|
+
|
|
750
|
+
[devcontainer.settings]
|
|
751
|
+
"cSpell.allowCompoundWords" = true
|
|
752
|
+
```
|
|
753
|
+
- Claude Code is installed, but your login on your machine stays out. Log in once in the container: it's kept in the `otk-claude` volume, which all your dev containers share, so it survives rebuilds.
|
|
754
|
+
|
|
717
755
|
### Usage
|
|
718
756
|
|
|
719
757
|
```console
|
|
@@ -729,8 +767,10 @@ $ otk mv setup -b 18.0 -b 19.0 -b master -r odoo -r enterprise -r upgrade -r upg
|
|
|
729
767
|
* `-b, --branches TEXT`: The Odoo versions to set up, like `19.0` or `saas-19.2`. Defaults to the ones already set up, or every supported version for a new multiverse.
|
|
730
768
|
* `-r, --repositories TEXT`: The repositories to set up, like `odoo`, or `odoo-ps/psbe-internal` for another GitHub owner. Defaults to the ones already set up, or `odoo`, `enterprise`, `design-themes`, `upgrade` and `upgrade-util` for a new multiverse, plus the ones in `multiverse.toml`.
|
|
731
769
|
* `-d, --multiverse-dir PATH`: The directory to set up the multiverse in. Defaults to this directory.
|
|
732
|
-
* `--
|
|
770
|
+
* `--update-config`: Overwrite the configuration files of every version, like the Visual Studio Code and dev container ones, to get the latest from the toolkit. The Python virtual environments are kept.
|
|
771
|
+
* `--reset-config`: Recreate the Python virtual environments as well as overwriting the configuration files of every version.
|
|
733
772
|
* `--vscode / --no-vscode`: Write the Visual Studio Code configuration in each version directory. [default: `--vscode`]
|
|
773
|
+
* `--devcontainer / --no-devcontainer`: Write a dev container configuration in each version directory, to open it in Visual Studio Code in a container that only sees your multiverse, for example to keep AI agents away from the rest of your machine. Versions that already have one keep it up to date, unless you pass `--no-devcontainer`.
|
|
734
774
|
* `--branch-suffix TEXT`: The suffix of your own branches on the `dev` remote, like `abcd` for `master-fix-xyz-abcd`. It's remembered for later commands. Defaults to the remembered one, or else the part of your Git email before the `@`.
|
|
735
775
|
* `--help`: Show this message and exit.
|
|
736
776
|
|
|
@@ -837,3 +877,32 @@ $ otk mv cleanup [OPTIONS]
|
|
|
837
877
|
* `--branch-suffix TEXT`: The suffix of your own branches on the `dev` remote, like `abcd` for `master-fix-xyz-abcd`. Defaults to the one given to `otk mv setup`, or else the part of your Git email before the `@`.
|
|
838
878
|
* `-y, --yes`: Don't ask for confirmation.
|
|
839
879
|
* `--help`: Show this message and exit.
|
|
880
|
+
|
|
881
|
+
## `otk code`
|
|
882
|
+
|
|
883
|
+
Open a version directory of your multiverse in Visual Studio Code, like `otk code 19.0`.
|
|
884
|
+
|
|
885
|
+
Run it anywhere inside your multiverse. Without a version, it opens the version directory you are in. If the version has a [dev container](#otk-mv-setup) (from `otk mv setup --devcontainer`), it opens in it. With a [profile](https://code.visualstudio.com/docs/configure/profiles), the window always has your extensions and settings for Odoo, so you don't have to associate every version directory with it in Visual Studio Code. Set it once in `multiverse.toml` to use it every time:
|
|
886
|
+
|
|
887
|
+
```toml
|
|
888
|
+
[code]
|
|
889
|
+
profile = "Odoo"
|
|
890
|
+
```
|
|
891
|
+
|
|
892
|
+
It needs the `code` command: run **Shell Command: Install 'code' command in PATH** in Visual Studio Code.
|
|
893
|
+
|
|
894
|
+
### Usage
|
|
895
|
+
|
|
896
|
+
```console
|
|
897
|
+
$ otk code [OPTIONS] [VERSION]
|
|
898
|
+
```
|
|
899
|
+
|
|
900
|
+
### Arguments
|
|
901
|
+
|
|
902
|
+
* `[VERSION]`: The version to open, like `19.0`. Defaults to the version directory you are in.
|
|
903
|
+
|
|
904
|
+
### Options
|
|
905
|
+
|
|
906
|
+
* `-p, --profile TEXT`: The Visual Studio Code profile to open it with, like `Odoo`. Defaults to `profile` in the `[code]` table of `multiverse.toml`. A profile that doesn't exist yet is created empty.
|
|
907
|
+
* `--local`: Open it on your machine, even if it has a dev container.
|
|
908
|
+
* `--help`: Show this message and exit.
|
|
@@ -22,6 +22,9 @@ $ uv tool install --force git+https://github.com/dylankiss/odoo-toolkit.git
|
|
|
22
22
|
> [!TIP]
|
|
23
23
|
> You can run any command with the `--help` option to find out all options you can use.
|
|
24
24
|
|
|
25
|
+
> [!NOTE]
|
|
26
|
+
> At most once a day, in the background, the toolkit checks [PyPI](https://pypi.org/project/odoo-toolkit/) for a new version and tells you after the command has run. It doesn't check in scripts, in CI, or when the toolkit isn't installed from PyPI, like a linked development version. Set `OTK_NO_UPDATE_CHECK` to any value to turn it off.
|
|
27
|
+
|
|
25
28
|
> [!TIP]
|
|
26
29
|
> Anywhere you can provide modules as arguments or options, you can also use [glob patterns](https://docs.python.org/3/library/fnmatch.html) to match multiple similar ones.
|
|
27
30
|
|
|
@@ -244,6 +247,15 @@ What stays between runs:
|
|
|
244
247
|
|
|
245
248
|
Your SSH agent (the one in `SSH_AUTH_SOCK`, like Bitwarden's or 1Password's) is available in the container, for Odoo modules that run Git commands. Your keys never leave your machine.
|
|
246
249
|
|
|
250
|
+
With [OrbStack](https://orbstack.dev), which provides its own agent forwarding, an agent like Bitwarden's needs an `IdentityAgent` line in your `~/.ssh/config`. Add it below any `Include` lines, then restart OrbStack:
|
|
251
|
+
|
|
252
|
+
```
|
|
253
|
+
Host *
|
|
254
|
+
IdentityAgent "~/Library/Containers/com.bitwarden.desktop/Data/.bitwarden-ssh-agent.sock"
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
Use the socket in your `SSH_AUTH_SOCK` for the path, which is different for other agents, like 1Password's.
|
|
258
|
+
|
|
247
259
|
On Linux, the container runs as your user, so the files Odoo writes are yours. The images on Docker Hub run as user ID 1000, the first user on most Linux machines. With another user ID, build the image on your machine once with `--build`.
|
|
248
260
|
|
|
249
261
|
> [!TIP]
|
|
@@ -258,7 +270,7 @@ It starts PostgreSQL and Mailpit if needed, and runs Odoo with:
|
|
|
258
270
|
- the database and mail server set up,
|
|
259
271
|
- no time limits, so requests don't stop while you're paused in the debugger.
|
|
260
272
|
|
|
261
|
-
Use `--community` to only load Odoo Community, or `--exclude` to leave out repositories, like `-x enterprise`. Pass any other Odoo options after `--`. Stop Odoo with `Ctrl+C`.
|
|
273
|
+
Use `--community` to only load Odoo Community, or `--exclude` to leave out repositories, like `-x enterprise`. Use `--volume` and `--env` to give the container files and settings of your machine, like the configuration of a linked repository. Pass any other Odoo options after `--`. Stop Odoo with `Ctrl+C`.
|
|
262
274
|
|
|
263
275
|
### Usage
|
|
264
276
|
|
|
@@ -270,6 +282,7 @@ e.g.
|
|
|
270
282
|
$ otk dev run -- -d mydb -i sale
|
|
271
283
|
$ otk dev run --port 8070 --debug -- -d mydb
|
|
272
284
|
$ otk dev run --community -- -d community-db
|
|
285
|
+
$ otk dev run -v ~/etc-odoo:/etc/odoo:ro -e KEY=value -- -d mydb
|
|
273
286
|
```
|
|
274
287
|
|
|
275
288
|
### Options
|
|
@@ -280,6 +293,8 @@ $ otk dev run --community -- -d community-db
|
|
|
280
293
|
* `--upgrade`: Add the upgrade scripts of `upgrade` and `upgrade-util` to the upgrade path.
|
|
281
294
|
* `--community`: Only load the modules of Odoo Community (`odoo/addons`).
|
|
282
295
|
* `-x, --exclude TEXT`: Leave these repositories out of the addons path, like `enterprise` or `odoofin,design-themes`.
|
|
296
|
+
* `-v, --volume TEXT`: Mount a file or folder of your machine in the container, like `~/etc-odoo:/etc/odoo:ro`. Can be used several times. A path starting with `~` or `.` is made absolute, and the path must exist.
|
|
297
|
+
* `-e, --env TEXT`: Set an environment variable in the container, like `REQUESTS_CA_BUNDLE=/etc/ca.pem`. Can be used several times.
|
|
283
298
|
* `--build`: Build the image on your machine instead of pulling it.
|
|
284
299
|
* `--pull`: Pull the latest image, even if you have one already.
|
|
285
300
|
* `--db-port INTEGER`: The port to reach PostgreSQL on, on your machine. Defaults to the one it runs on, or `5432`. Changing it restarts PostgreSQL.
|
|
@@ -613,7 +628,7 @@ The easiest way to set this up is by creating a directory for your multiverse se
|
|
|
613
628
|
> [!IMPORTANT]
|
|
614
629
|
> Make sure you have set up your GitHub SSH key beforehand in order to clone the repositories, and installed [`uv`](https://docs.astral.sh/uv/getting-started/installation/) and `npm`.
|
|
615
630
|
|
|
616
|
-
You can run the command as many times as you want. It only adds what's missing, and never touches your own files. Pass `--reset-config` to recreate the Python environments
|
|
631
|
+
You can run the command as many times as you want. It only adds what's missing, and never touches your own files. Pass `--update-config` to overwrite the configuration files with the latest ones, or `--reset-config` to recreate the Python environments as well. Without `-b` or `-r`, it updates the versions and repositories that are already set up.
|
|
617
632
|
|
|
618
633
|
### Repositories
|
|
619
634
|
|
|
@@ -684,6 +699,7 @@ After all that is done, your directory structure should look like this with the
|
|
|
684
699
|
├── 19.0
|
|
685
700
|
│ ├── .venv (Python virtual environment)
|
|
686
701
|
│ ├── .vscode (Visual Studio Code configuration)
|
|
702
|
+
│ ├── ruff.toml (extends the one of odoo, for the other repositories)
|
|
687
703
|
│ ├── odoo (19.0)
|
|
688
704
|
│ ├── enterprise (19.0)
|
|
689
705
|
│ ├── design-themes (19.0)
|
|
@@ -696,11 +712,33 @@ After all that is done, your directory structure should look like this with the
|
|
|
696
712
|
├── upgrade (master)
|
|
697
713
|
├── upgrade-util (master)
|
|
698
714
|
├── requirements.txt
|
|
699
|
-
|
|
715
|
+
├── ruff-odoo.toml (Odoo's Ruff rules of master)
|
|
716
|
+
└── ruff.toml (extends ruff-odoo.toml)
|
|
700
717
|
```
|
|
701
718
|
|
|
702
719
|
Open a version directory (like `code <multiverse-folder>/19.0`) in your editor to work on that version.
|
|
703
720
|
|
|
721
|
+
### Dev Container
|
|
722
|
+
|
|
723
|
+
With `--devcontainer`, every version directory gets a [dev container](https://containers.dev) configuration. Open the version in Visual Studio Code and run **Dev Containers: Reopen in Container**. The window, its extensions and any AI agent in it then only see your multiverse directory (mounted at the same path as on your machine): not your home folder, SSH keys or Git credentials.
|
|
724
|
+
|
|
725
|
+
- Opening the container starts the shared services (`otk dev db`), since it joins their network. Odoo starts from the **Odoo (container): run and debug** launch configuration, because `otk dev run` needs Docker.
|
|
726
|
+
- Git commands that need GitHub (fetch, pull, push) don't work in the container. Run them from a terminal on your machine.
|
|
727
|
+
- The `.devcontainer`, `.vscode` and `.venv` folders are read-only in the container, because they hold what runs on your machine later (like tasks and the dev container's own configuration). Change them from your machine, for example with `otk mv setup --update-config`.
|
|
728
|
+
- Everything else in the multiverse can be read and changed in the container, and it has network access, including to the databases of `otk dev`. Don't keep secrets or data you can't share in your multiverse or those databases if you use AI agents.
|
|
729
|
+
- Only windows opened in the container are isolated, not agents you start from a terminal on your machine.
|
|
730
|
+
- Visual Studio Code shares your Git config and credential helper with every dev container, which a project can't turn off. Add `"dev.containers.copyGitConfig": false` and `"dev.containers.gitCredentialHelperConfigLocation": "none"` to your user settings.
|
|
731
|
+
- Extensions and settings you want in the dev containers of this multiverse, like a spell checker, go in a `[devcontainer]` table in `multiverse.toml`, which `--update-config` applies. Extensions you want in every dev container go in the `dev.containers.defaultExtensions` user setting.
|
|
732
|
+
|
|
733
|
+
```toml
|
|
734
|
+
[devcontainer]
|
|
735
|
+
extensions = ["streetsidesoftware.code-spell-checker"]
|
|
736
|
+
|
|
737
|
+
[devcontainer.settings]
|
|
738
|
+
"cSpell.allowCompoundWords" = true
|
|
739
|
+
```
|
|
740
|
+
- Claude Code is installed, but your login on your machine stays out. Log in once in the container: it's kept in the `otk-claude` volume, which all your dev containers share, so it survives rebuilds.
|
|
741
|
+
|
|
704
742
|
### Usage
|
|
705
743
|
|
|
706
744
|
```console
|
|
@@ -716,8 +754,10 @@ $ otk mv setup -b 18.0 -b 19.0 -b master -r odoo -r enterprise -r upgrade -r upg
|
|
|
716
754
|
* `-b, --branches TEXT`: The Odoo versions to set up, like `19.0` or `saas-19.2`. Defaults to the ones already set up, or every supported version for a new multiverse.
|
|
717
755
|
* `-r, --repositories TEXT`: The repositories to set up, like `odoo`, or `odoo-ps/psbe-internal` for another GitHub owner. Defaults to the ones already set up, or `odoo`, `enterprise`, `design-themes`, `upgrade` and `upgrade-util` for a new multiverse, plus the ones in `multiverse.toml`.
|
|
718
756
|
* `-d, --multiverse-dir PATH`: The directory to set up the multiverse in. Defaults to this directory.
|
|
719
|
-
* `--
|
|
757
|
+
* `--update-config`: Overwrite the configuration files of every version, like the Visual Studio Code and dev container ones, to get the latest from the toolkit. The Python virtual environments are kept.
|
|
758
|
+
* `--reset-config`: Recreate the Python virtual environments as well as overwriting the configuration files of every version.
|
|
720
759
|
* `--vscode / --no-vscode`: Write the Visual Studio Code configuration in each version directory. [default: `--vscode`]
|
|
760
|
+
* `--devcontainer / --no-devcontainer`: Write a dev container configuration in each version directory, to open it in Visual Studio Code in a container that only sees your multiverse, for example to keep AI agents away from the rest of your machine. Versions that already have one keep it up to date, unless you pass `--no-devcontainer`.
|
|
721
761
|
* `--branch-suffix TEXT`: The suffix of your own branches on the `dev` remote, like `abcd` for `master-fix-xyz-abcd`. It's remembered for later commands. Defaults to the remembered one, or else the part of your Git email before the `@`.
|
|
722
762
|
* `--help`: Show this message and exit.
|
|
723
763
|
|
|
@@ -824,3 +864,32 @@ $ otk mv cleanup [OPTIONS]
|
|
|
824
864
|
* `--branch-suffix TEXT`: The suffix of your own branches on the `dev` remote, like `abcd` for `master-fix-xyz-abcd`. Defaults to the one given to `otk mv setup`, or else the part of your Git email before the `@`.
|
|
825
865
|
* `-y, --yes`: Don't ask for confirmation.
|
|
826
866
|
* `--help`: Show this message and exit.
|
|
867
|
+
|
|
868
|
+
## `otk code`
|
|
869
|
+
|
|
870
|
+
Open a version directory of your multiverse in Visual Studio Code, like `otk code 19.0`.
|
|
871
|
+
|
|
872
|
+
Run it anywhere inside your multiverse. Without a version, it opens the version directory you are in. If the version has a [dev container](#otk-mv-setup) (from `otk mv setup --devcontainer`), it opens in it. With a [profile](https://code.visualstudio.com/docs/configure/profiles), the window always has your extensions and settings for Odoo, so you don't have to associate every version directory with it in Visual Studio Code. Set it once in `multiverse.toml` to use it every time:
|
|
873
|
+
|
|
874
|
+
```toml
|
|
875
|
+
[code]
|
|
876
|
+
profile = "Odoo"
|
|
877
|
+
```
|
|
878
|
+
|
|
879
|
+
It needs the `code` command: run **Shell Command: Install 'code' command in PATH** in Visual Studio Code.
|
|
880
|
+
|
|
881
|
+
### Usage
|
|
882
|
+
|
|
883
|
+
```console
|
|
884
|
+
$ otk code [OPTIONS] [VERSION]
|
|
885
|
+
```
|
|
886
|
+
|
|
887
|
+
### Arguments
|
|
888
|
+
|
|
889
|
+
* `[VERSION]`: The version to open, like `19.0`. Defaults to the version directory you are in.
|
|
890
|
+
|
|
891
|
+
### Options
|
|
892
|
+
|
|
893
|
+
* `-p, --profile TEXT`: The Visual Studio Code profile to open it with, like `Odoo`. Defaults to `profile` in the `[code]` table of `multiverse.toml`. A profile that doesn't exist yet is created empty.
|
|
894
|
+
* `--local`: Open it on your machine, even if it has a dev container.
|
|
895
|
+
* `--help`: Show this message and exit.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import shutil
|
|
2
|
+
import subprocess
|
|
3
|
+
from typing import Annotated
|
|
4
|
+
from urllib.parse import quote
|
|
5
|
+
|
|
6
|
+
from typer import Argument, Exit, Option
|
|
7
|
+
|
|
8
|
+
from .common import print_error
|
|
9
|
+
from .mv.config import NOT_IN_VERSION_DIR, find_multiverse_dir, find_version_dir, get_code_profile, get_current_dir
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def code(
|
|
13
|
+
version: Annotated[
|
|
14
|
+
str | None,
|
|
15
|
+
Argument(help="The version to open, like `19.0`. Defaults to the version directory you are in."),
|
|
16
|
+
] = None,
|
|
17
|
+
profile: Annotated[
|
|
18
|
+
str | None,
|
|
19
|
+
Option(
|
|
20
|
+
"--profile",
|
|
21
|
+
"-p",
|
|
22
|
+
help="The Visual Studio Code profile to open it with, like `Odoo`. Defaults to `profile` in the `[code]` "
|
|
23
|
+
"table of `multiverse.toml`. A profile that doesn't exist yet is created empty.",
|
|
24
|
+
),
|
|
25
|
+
] = None,
|
|
26
|
+
local: Annotated[
|
|
27
|
+
bool,
|
|
28
|
+
Option("--local", help="Open it on your machine, even if it has a dev container."),
|
|
29
|
+
] = False,
|
|
30
|
+
) -> None:
|
|
31
|
+
"""Open :keyboard: an Odoo Multiverse version directory in Visual Studio Code.
|
|
32
|
+
|
|
33
|
+
Run this command anywhere inside your multiverse, and it opens the version directory you are in, or the one you
|
|
34
|
+
name. If it has a dev container (see `otk mv setup --devcontainer`), it opens in it, so the window and any AI agent
|
|
35
|
+
in it only see your multiverse. With a profile, the window always has your extensions and settings for Odoo,
|
|
36
|
+
without having to associate every version directory with it in Visual Studio Code.\n
|
|
37
|
+
\n
|
|
38
|
+
It needs the `code` command: run *Shell Command: Install 'code' command in PATH* in Visual Studio Code.
|
|
39
|
+
"""
|
|
40
|
+
if not (code_command := shutil.which("code")):
|
|
41
|
+
print_error("The [b]code[/b] command isn't available. Run *Shell Command: Install 'code' command in PATH*.\n")
|
|
42
|
+
raise Exit(1)
|
|
43
|
+
|
|
44
|
+
if version:
|
|
45
|
+
if not (multiverse_dir := find_multiverse_dir(get_current_dir())):
|
|
46
|
+
print_error(NOT_IN_VERSION_DIR)
|
|
47
|
+
raise Exit(1)
|
|
48
|
+
version_dir = multiverse_dir / version
|
|
49
|
+
if not version_dir.is_dir() or find_version_dir(version_dir) != version_dir:
|
|
50
|
+
print_error(f"There is no version directory [b]{version}[/b] in [u]{multiverse_dir}[/u].\n")
|
|
51
|
+
raise Exit(1)
|
|
52
|
+
elif not (version_dir := find_version_dir()):
|
|
53
|
+
print_error(NOT_IN_VERSION_DIR)
|
|
54
|
+
raise Exit(1)
|
|
55
|
+
|
|
56
|
+
profile = profile or get_code_profile(version_dir.parent)
|
|
57
|
+
target = [str(version_dir)]
|
|
58
|
+
if not local and (version_dir / ".devcontainer" / "devcontainer.json").is_file():
|
|
59
|
+
# A dev container is addressed by the hex of its folder on your machine, and the folder it opens inside it.
|
|
60
|
+
host_path = str(version_dir).encode().hex()
|
|
61
|
+
target = ["--folder-uri", f"vscode-remote://dev-container+{host_path}{quote(str(version_dir))}"]
|
|
62
|
+
subprocess.run([code_command, *(["--profile", profile] if profile else []), *target], check=False)
|
|
@@ -21,6 +21,7 @@ from .runtime import (
|
|
|
21
21
|
get_git_identity,
|
|
22
22
|
get_ssh_agent,
|
|
23
23
|
is_port_free,
|
|
24
|
+
normalize_volume,
|
|
24
25
|
)
|
|
25
26
|
|
|
26
27
|
app = Typer()
|
|
@@ -55,6 +56,24 @@ def run(
|
|
|
55
56
|
help="Leave these repositories out of the addons path, like `enterprise` or `odoofin,design-themes`.",
|
|
56
57
|
),
|
|
57
58
|
] = EMPTY_LIST,
|
|
59
|
+
volume: Annotated[
|
|
60
|
+
list[str],
|
|
61
|
+
Option(
|
|
62
|
+
"--volume",
|
|
63
|
+
"-v",
|
|
64
|
+
help="Mount a file or folder of your machine in the container, like `~/etc-odoo:/etc/odoo:ro`. Can be "
|
|
65
|
+
"used several times.",
|
|
66
|
+
),
|
|
67
|
+
] = EMPTY_LIST,
|
|
68
|
+
env: Annotated[
|
|
69
|
+
list[str],
|
|
70
|
+
Option(
|
|
71
|
+
"--env",
|
|
72
|
+
"-e",
|
|
73
|
+
help="Set an environment variable in the container, like `REQUESTS_CA_BUNDLE=/etc/ca.pem`. Can be used "
|
|
74
|
+
"several times.",
|
|
75
|
+
),
|
|
76
|
+
] = EMPTY_LIST,
|
|
58
77
|
build: Annotated[bool, Option("--build", help="Build the image on your machine instead of pulling it.")] = False,
|
|
59
78
|
pull: Annotated[bool, Option("--pull", help="Pull the latest image, even if you have one already.")] = False,
|
|
60
79
|
db_port: Annotated[
|
|
@@ -82,10 +101,19 @@ def run(
|
|
|
82
101
|
\n
|
|
83
102
|
The addons path contains every repository of the version directory with modules in it, like `enterprise`,
|
|
84
103
|
`odoo/addons`, and linked repositories like `odoofin`. Use `--community` to only load Odoo Community, or
|
|
85
|
-
`--exclude` to leave out repositories.
|
|
104
|
+
`--exclude` to leave out repositories. Use `--volume` and `--env` to give the container files and settings of your
|
|
105
|
+
machine, like the configuration of a linked repository. Pass any other Odoo options after `--`, like
|
|
106
|
+
`otk dev run -- -d mydb -i sale`.
|
|
86
107
|
"""
|
|
87
108
|
version_dir, version = get_version_dir()
|
|
88
109
|
exclude = normalize_list_option(exclude)
|
|
110
|
+
volumes = [normalize_volume(spec) for spec in volume]
|
|
111
|
+
for spec in volumes:
|
|
112
|
+
source = spec.partition(":")[0]
|
|
113
|
+
# Docker would create a missing folder as `root`, instead of telling you the path is wrong.
|
|
114
|
+
if source.startswith("/") and not Path(source).exists():
|
|
115
|
+
print_error(f"Can't mount [u]{source}[/u], since it doesn't exist.\n")
|
|
116
|
+
raise Exit(1)
|
|
89
117
|
if unknown := sorted(set(exclude) - {path.name for path in get_repo_dirs(version_dir, include_linked=True)}):
|
|
90
118
|
print_warning(f"There is no [b]{'[/b], [b]'.join(unknown)}[/b] in [u]{version_dir}[/u] to leave out.\n")
|
|
91
119
|
|
|
@@ -109,6 +137,8 @@ def run(
|
|
|
109
137
|
arch=arch,
|
|
110
138
|
exclude=exclude,
|
|
111
139
|
community=community,
|
|
140
|
+
volumes=volumes,
|
|
141
|
+
env=env,
|
|
112
142
|
)
|
|
113
143
|
command = build_run_command(
|
|
114
144
|
options,
|
|
@@ -42,8 +42,13 @@ VOLUMES = {
|
|
|
42
42
|
"otk-filestore": f"{HOME}/.local/share/Odoo",
|
|
43
43
|
"otk-pycache": f"{HOME}/.cache/pycache",
|
|
44
44
|
}
|
|
45
|
+
# Where Claude Code keeps its login in a dev container: a volume of its own, so your login on your machine stays out.
|
|
46
|
+
# The Odoo containers don't get it.
|
|
47
|
+
CLAUDE_DIR = f"{HOME}/.claude"
|
|
48
|
+
DEVCONTAINER_VOLUMES = {**VOLUMES, "otk-claude": CLAUDE_DIR}
|
|
45
49
|
# Where your SSH agent is available in the container, for Odoo modules that run Git commands.
|
|
46
50
|
SSH_AGENT_SOCKET = "/run/otk-ssh-agent.sock"
|
|
51
|
+
ORBSTACK_SSH_AGENT = "/run/host-services/ssh-auth.sock"
|
|
47
52
|
# Mounting the multiverse at one of these paths, or at one containing them, would hide files the image needs.
|
|
48
53
|
SYSTEM_PATHS = ("/bin", "/etc", HOME, "/lib", "/opt", "/root", "/sbin", "/tmp", "/usr", "/var", "/venv") # noqa: S108
|
|
49
54
|
|
|
@@ -64,6 +69,9 @@ class RunOptions:
|
|
|
64
69
|
exclude: list[str] = field(default_factory=list[str])
|
|
65
70
|
# Whether to only load Odoo Community's modules.
|
|
66
71
|
community: bool = False
|
|
72
|
+
# More `--volume` and `--env` arguments for the container, like `/etc/odoo:/etc/odoo:ro` and `KEY=value`.
|
|
73
|
+
volumes: list[str] = field(default_factory=list[str])
|
|
74
|
+
env: list[str] = field(default_factory=list[str])
|
|
67
75
|
# Run this command instead of Odoo, like `bash`.
|
|
68
76
|
command: list[str] | None = None
|
|
69
77
|
# The architecture to run. Another than the machine's runs emulated, which is slower.
|
|
@@ -121,12 +129,19 @@ def get_upgrade_paths(version_dir: Path) -> list[Path]:
|
|
|
121
129
|
return [path for path in candidates if path.is_dir()]
|
|
122
130
|
|
|
123
131
|
|
|
124
|
-
def
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
132
|
+
def get_odoo_args(
|
|
133
|
+
version_dir: Path, *, exclude: Collection[str] = (), community: bool = False, upgrade: bool = False,
|
|
134
|
+
) -> list[str]:
|
|
135
|
+
"""Get the Odoo options that load the modules of a version and connect Odoo to the shared services.
|
|
136
|
+
|
|
137
|
+
:param version_dir: The version directory.
|
|
138
|
+
:param exclude: The repositories to leave out of the addons path, like `enterprise`.
|
|
139
|
+
:param community: Whether to only load Odoo Community's modules.
|
|
140
|
+
:param upgrade: Whether to add the upgrade scripts, if their repositories are linked into the version.
|
|
141
|
+
:return: The options, without the path of `odoo-bin`.
|
|
142
|
+
"""
|
|
143
|
+
addons_paths = get_addons_paths(version_dir, exclude=exclude, community=community)
|
|
144
|
+
args = [
|
|
130
145
|
f"--addons-path={','.join(str(path) for path in addons_paths)}",
|
|
131
146
|
f"--db_host={DB_HOST}",
|
|
132
147
|
"--db_user=odoo",
|
|
@@ -141,9 +156,19 @@ def build_odoo_command(options: RunOptions) -> list[str]:
|
|
|
141
156
|
"--limit-time-cpu=99999",
|
|
142
157
|
"--limit-time-real=99999",
|
|
143
158
|
]
|
|
144
|
-
if
|
|
145
|
-
|
|
146
|
-
|
|
159
|
+
if upgrade and (upgrade_paths := get_upgrade_paths(version_dir)):
|
|
160
|
+
args.append(f"--upgrade-path={','.join(str(path) for path in upgrade_paths)}")
|
|
161
|
+
return args
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def build_odoo_command(options: RunOptions) -> list[str]:
|
|
165
|
+
"""Build the command that starts Odoo in the container."""
|
|
166
|
+
version_dir = options.version_dir
|
|
167
|
+
command = [
|
|
168
|
+
str(version_dir / "odoo" / "odoo-bin"),
|
|
169
|
+
*get_odoo_args(version_dir, exclude=options.exclude, community=options.community, upgrade=options.upgrade),
|
|
170
|
+
*options.odoo_args,
|
|
171
|
+
]
|
|
147
172
|
if options.debug_port:
|
|
148
173
|
# Only say the debugger is ready once it listens, since Visual Studio Code attaches right away.
|
|
149
174
|
launcher = (
|
|
@@ -200,12 +225,39 @@ def build_run_command(
|
|
|
200
225
|
run += ["--env", f"PYTHONPYCACHEPREFIX={VOLUMES['otk-pycache']}"]
|
|
201
226
|
for key, value in git_identity.items():
|
|
202
227
|
run += ["--env", f"{key}={value}"]
|
|
228
|
+
for volume in options.volumes:
|
|
229
|
+
run += ["--volume", volume]
|
|
230
|
+
for variable in options.env:
|
|
231
|
+
run += ["--env", variable]
|
|
203
232
|
run += get_ssh_agent_args(ssh_agent)
|
|
204
233
|
return [*run, get_image_tag(options.version), *command]
|
|
205
234
|
|
|
206
235
|
|
|
236
|
+
def normalize_volume(volume: str) -> str:
|
|
237
|
+
"""Make the path on your machine in a `--volume` absolute, since Docker takes a relative one for a volume's name.
|
|
238
|
+
|
|
239
|
+
`~` stands for your home folder, and `.` or `..` for the current folder. Names of volumes stay as they are.
|
|
240
|
+
"""
|
|
241
|
+
source, separator, rest = volume.partition(":")
|
|
242
|
+
if separator and source.startswith(("~", ".")):
|
|
243
|
+
source = str(Path(source).expanduser().resolve())
|
|
244
|
+
return f"{source}{separator}{rest}"
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
def is_orbstack() -> bool:
|
|
248
|
+
"""Check whether Docker runs on OrbStack, which can't mount the socket of your SSH agent from your machine."""
|
|
249
|
+
result = subprocess.run(["docker", "info", "--format", "{{.Name}}"], capture_output=True, text=True, check=False)
|
|
250
|
+
return result.stdout.strip() == "orbstack"
|
|
251
|
+
|
|
252
|
+
|
|
207
253
|
def get_ssh_agent() -> Path | None:
|
|
208
|
-
"""Get the socket of your SSH agent (like the one of Bitwarden or 1Password), if one is running.
|
|
254
|
+
"""Get the socket of your SSH agent (like the one of Bitwarden or 1Password), if one is running.
|
|
255
|
+
|
|
256
|
+
OrbStack provides your agent at a fixed path in its virtual machine instead. It uses the `IdentityAgent` of your
|
|
257
|
+
`~/.ssh/config`, if you have one.
|
|
258
|
+
"""
|
|
259
|
+
if sys.platform == "darwin" and is_orbstack():
|
|
260
|
+
return Path(ORBSTACK_SSH_AGENT)
|
|
209
261
|
socket_path = os.environ.get("SSH_AUTH_SOCK")
|
|
210
262
|
if not socket_path:
|
|
211
263
|
return None
|