gOdoo-cli 0.15.1__tar.gz → 0.17.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.
Files changed (112) hide show
  1. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/PKG-INFO +1 -1
  2. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/addons/godoo_test_succ_mod/__manifest__.py +1 -1
  3. godoo_cli-0.17.0/config/nginx-proxy_headers.conf +13 -0
  4. godoo_cli-0.17.0/config/nginx.conf +116 -0
  5. godoo_cli-0.17.0/config/postgresql.conf +75 -0
  6. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/docker/Dockerfile +4 -2
  7. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/docker/depends_build.sh +1 -0
  8. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/odoo_manifest.yml +9 -3
  9. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/__about__.py +1 -1
  10. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/cli.py +16 -2
  11. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/commands/odoo_bin/bootstrap.py +3 -2
  12. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/commands/odoo_bin/godoo_test/test_run.py +2 -1
  13. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/commands/odoo_bin/shell.py +32 -11
  14. godoo_cli-0.17.0/src/godoo_cli/commands/odoo_bin/shell_scripts/pregenerate_assets.py +34 -0
  15. godoo_cli-0.17.0/src/godoo_cli/commands/odoo_bin/shell_scripts/render_report.py +122 -0
  16. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/commands/source_get.py +54 -26
  17. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/git/__init__.py +0 -2
  18. godoo_cli-0.17.0/src/godoo_cli/git/git_odoo_addons.py +133 -0
  19. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/git/git_repo.py +4 -2
  20. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/helpers/modules_py.py +25 -4
  21. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/helpers/pip.py +3 -3
  22. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/helpers/system.py +116 -3
  23. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/models/__init__.py +2 -0
  24. godoo_cli-0.17.0/src/godoo_cli/models/godoo_git_repo.py +184 -0
  25. godoo_cli-0.17.0/src/godoo_cli/models/godoo_manifest.py +230 -0
  26. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/models/godoo_models.py +17 -1
  27. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/models/godoo_modules.py +3 -0
  28. godoo_cli-0.15.1/config/nginx.conf +0 -86
  29. godoo_cli-0.15.1/config/postgresql.conf +0 -18
  30. godoo_cli-0.15.1/src/godoo_cli/git/git_odoo.py +0 -81
  31. godoo_cli-0.15.1/src/godoo_cli/git/git_odoo_addons.py +0 -110
  32. godoo_cli-0.15.1/src/godoo_cli/helpers/odoo_manifest.py +0 -133
  33. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/.codecovrc +0 -0
  34. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/.devcontainer/devcontainer.json +0 -0
  35. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/.env.sample +0 -0
  36. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/.eslintignore +0 -0
  37. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/.eslintrc.yml +0 -0
  38. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/.github/FUNDING.yml +0 -0
  39. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/.github/workflows/README.md +0 -0
  40. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/.github/workflows/quality.yml +0 -0
  41. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/.github/workflows/version-bump.yml +0 -0
  42. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/.github/workflows/version-publish.yml +0 -0
  43. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/.gitignore +0 -0
  44. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/.pre-commit-config.yaml +0 -0
  45. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/.prettierrc.yml +0 -0
  46. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/.vscode/launch.json +0 -0
  47. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/LICENSE +0 -0
  48. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/README.md +0 -0
  49. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/addons/.gitkeep +0 -0
  50. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/addons/godoo_test_succ_mod/__init__.py +0 -0
  51. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/addons/godoo_test_succ_mod/models/__init__.py +0 -0
  52. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/addons/godoo_test_succ_mod/tests/__init__.py +0 -0
  53. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/addons/godoo_test_succ_mod/tests/data.py +0 -0
  54. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/addons/godoo_test_succ_mod/tests/test_succ.py +0 -0
  55. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/assets/godoo-main-cli.png +0 -0
  56. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/assets/odoo_logo.png +0 -0
  57. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/config/supervisord.conf +0 -0
  58. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/docker/cups/Dockerfile +0 -0
  59. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/docker/cups/config/cups-pdf.conf +0 -0
  60. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/docker/cups/config/cupsd.conf +0 -0
  61. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/docker/cups/cups_entrypoint.sh +0 -0
  62. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/docker/depends_runtime.sh +0 -0
  63. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/docker/docker-compose.base.yml +0 -0
  64. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/docker/docker-compose.devcontainer-traefik.yml +0 -0
  65. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/docker/docker-compose.devcontainer.yml +0 -0
  66. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/docker/docker-compose.traefik.yml +0 -0
  67. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/docker/psql.gpg +0 -0
  68. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/godoo_src.code-workspace +0 -0
  69. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/makefile +0 -0
  70. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/pyproject.toml +0 -0
  71. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/scripts/container_requirements.sh +0 -0
  72. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/scripts/launchodoo.sh +0 -0
  73. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/scripts/migrations/development/shrink_database.py +0 -0
  74. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/scripts/reset_devcontainer.sh +0 -0
  75. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/__init__.py +0 -0
  76. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/__main__.py +0 -0
  77. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/cli_common.py +0 -0
  78. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/commands/__init__.py +0 -0
  79. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/commands/backup/__init__.py +0 -0
  80. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/commands/backup/cli.py +0 -0
  81. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/commands/backup/dump.py +0 -0
  82. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/commands/backup/load.py +0 -0
  83. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/commands/backup/pull.py +0 -0
  84. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/commands/backup/util.py +0 -0
  85. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/commands/config.py +0 -0
  86. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/commands/db/__init__.py +0 -0
  87. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/commands/db/cli.py +0 -0
  88. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/commands/db/passwords.py +0 -0
  89. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/commands/db/query.py +0 -0
  90. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/commands/odoo_bin/__init__.py +0 -0
  91. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/commands/odoo_bin/cli_generate.py +0 -0
  92. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/commands/odoo_bin/godoo_test/__init__.py +0 -0
  93. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/commands/odoo_bin/godoo_test/cli.py +0 -0
  94. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/commands/odoo_bin/godoo_test/test_load_data.py +0 -0
  95. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/commands/odoo_bin/launch.py +0 -0
  96. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/commands/odoo_bin/shell_scripts/odoo_banner.py +0 -0
  97. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/commands/rpc/__init__.py +0 -0
  98. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/commands/rpc/cli.py +0 -0
  99. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/commands/rpc/config_parameters.py +0 -0
  100. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/commands/rpc/importer.py +0 -0
  101. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/commands/rpc/modules.py +0 -0
  102. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/commands/rpc/translations.py +0 -0
  103. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/git/git_url.py +0 -0
  104. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/git/zip_download.py +0 -0
  105. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/helpers/__init__.py +0 -0
  106. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/helpers/cli.py +0 -0
  107. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/helpers/modules_git.py +0 -0
  108. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/helpers/odoo_files.py +0 -0
  109. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/godoo_cli/models/db_connection.py +0 -0
  110. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/src/tests/test_git_clone.py +0 -0
  111. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/thirdparty/.gitkeep +0 -0
  112. {godoo_cli-0.15.1 → godoo_cli-0.17.0}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gOdoo-cli
3
- Version: 0.15.1
3
+ Version: 0.17.0
4
4
  Summary: Wrapper around Odoo-Bin with some convinience RPC functions.
5
5
  Project-URL: repository, https://github.com/OpenJKSoftware/gOdoo
6
6
  Author-email: Joshua Kreuder <Joshua_Kreuder@outlook.com>
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "godoo Test Succ Module",
3
- "version": "16.0.1.0.0",
3
+ "version": "19.0.1.0.0",
4
4
  "author": "Joshua Kreuder",
5
5
  "license": "AGPL-3",
6
6
  "depends": ["base"],
@@ -0,0 +1,13 @@
1
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
2
+ proxy_set_header X-Forwarded-Proto $scheme;
3
+ proxy_set_header X-Real-IP $remote_addr;
4
+ proxy_set_header Upgrade $http_upgrade;
5
+ proxy_set_header Connection $connection_upgrade;
6
+ proxy_set_header X-Forwarded-Host $host;
7
+
8
+ # Enable HTTP/1.1 keepalive to upstream
9
+ proxy_http_version 1.1;
10
+ proxy_set_header Connection "";
11
+
12
+ add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
13
+ proxy_cookie_flags session_id samesite=lax secure; # requires nginx 1.19.8
@@ -0,0 +1,116 @@
1
+ worker_processes 4;
2
+ # user www-data;
3
+ pid /var/log/nginx/nginx.pid;
4
+ error_log /var/log/nginx/error.log info;
5
+
6
+ events {
7
+ use epoll;
8
+ worker_connections 1000;
9
+ multi_accept on; # Accept multiple connections at once
10
+ }
11
+
12
+ http {
13
+ include /etc/nginx/mime.types;
14
+ server_tokens off;
15
+
16
+ # Performance: Buffering and keepalive
17
+ sendfile on;
18
+ tcp_nopush on;
19
+ tcp_nodelay on;
20
+ keepalive_timeout 65;
21
+ keepalive_requests 1000;
22
+
23
+ # Performance: Buffer sizes for Odoo's large responses
24
+ proxy_buffer_size 128k;
25
+ proxy_buffers 4 256k;
26
+ proxy_busy_buffers_size 256k;
27
+
28
+ # Gzip compression (moved here for all responses)
29
+ gzip on;
30
+ gzip_vary on;
31
+ gzip_proxied any;
32
+ gzip_comp_level 6;
33
+ gzip_min_length 1000;
34
+ gzip_types text/css text/scss text/plain text/xml application/xml application/json application/javascript application/x-javascript text/javascript image/svg+xml;
35
+
36
+ #odoo server
37
+ upstream odoo {
38
+ server 127.0.0.1:8069;
39
+ keepalive 32; # Keep connections to Odoo open
40
+ }
41
+ upstream odoochat {
42
+ server 127.0.0.1:8072;
43
+ keepalive 8;
44
+ }
45
+ map $http_upgrade $connection_upgrade {
46
+ default upgrade;
47
+ '' close;
48
+ }
49
+
50
+ map $sent_http_content_type $content_type_csp {
51
+ default "";
52
+ ~image/ "default-src 'none'";
53
+ }
54
+
55
+ set_real_ip_from 10.1.0.0/16;
56
+ set_real_ip_from 172.20.0.0/24;
57
+ real_ip_header X-Forwarded-For;
58
+ real_ip_recursive on;
59
+
60
+ server {
61
+ listen 80;
62
+
63
+ proxy_read_timeout 720s;
64
+ proxy_connect_timeout 720s;
65
+ proxy_send_timeout 720s;
66
+ client_max_body_size 4G; # Set the maximum upload size to 4 gigabytes
67
+
68
+ add_header 'Content-Security-Policy' 'upgrade-insecure-requests';
69
+
70
+ # Redirect websocket requests to odoo gevent port
71
+ location /websocket {
72
+ proxy_pass http://odoochat;
73
+ include /etc/nginx/proxy_headers.conf;
74
+ }
75
+
76
+ # Redirect requests to odoo backend server
77
+ location / {
78
+ proxy_pass http://odoo;
79
+ proxy_redirect off;
80
+ include /etc/nginx/proxy_headers.conf;
81
+ }
82
+ location @odoo {
83
+ proxy_pass http://odoo;
84
+ proxy_redirect off;
85
+ include /etc/nginx/proxy_headers.conf;
86
+ }
87
+
88
+ location ~ ^/[^/]+/static/.+$ {
89
+ root /odoo;
90
+ # We could figure out a way to automagically adapt this try_files to also include thirdparty addons
91
+ try_files /godoo_workspace/addons$uri /odoo/addons$uri /odoo/odoo/addons$uri /thirdparty/OE_odoo-enterprise$uri /thirdparty/custom/single_mods$uri $uri @odoo;
92
+ expires 7d;
93
+ access_log off;
94
+ include /etc/nginx/mime.types;
95
+ add_header Content-Security-Policy $content_type_csp;
96
+ add_header Cache-Control "public";
97
+ }
98
+
99
+ location /web/filestore {
100
+ internal;
101
+ alias /var/lib/odoo/filestore;
102
+ }
103
+
104
+ # Cache web assets (JS/CSS bundles) - Odoo uses cache-busting URLs
105
+ location ~* /web/assets/ {
106
+ proxy_pass http://odoo;
107
+ proxy_redirect off;
108
+ include /etc/nginx/proxy_headers.conf;
109
+ expires 7d;
110
+ access_log off;
111
+ add_header Cache-Control "public";
112
+ }
113
+
114
+ }
115
+
116
+ }
@@ -0,0 +1,75 @@
1
+ # PostgreSQL 17 - Odoo 16 Staging
2
+ # 4-core HyperV VM, 23GB RAM shared with prod+plausible
3
+ # Staging is rarely used - minimal resource allocation
4
+
5
+ # CONNECTION
6
+ # Few concurrent users expected
7
+ max_connections = 40
8
+ superuser_reserved_connections = 2
9
+ max_files_per_process = 100
10
+
11
+ # MEMORY (Minimal: ~500MB allocation)
12
+ # Staging should be lean - just enough to function
13
+ shared_buffers = 256MB
14
+ effective_cache_size = 512MB
15
+ maintenance_work_mem = 64MB
16
+ work_mem = 8MB
17
+ hash_mem_multiplier = 2.0
18
+
19
+ # WAL & CHECKPOINT
20
+ wal_buffers = 8MB
21
+ min_wal_size = 256MB
22
+ max_wal_size = 1GB
23
+ checkpoint_timeout = 15min
24
+ checkpoint_completion_target = 0.9
25
+
26
+ # PARALLELISM (Minimal - don't compete with prod)
27
+ max_worker_processes = 2
28
+ max_parallel_workers_per_gather = 0
29
+ max_parallel_workers = 1
30
+ max_parallel_maintenance_workers = 1
31
+
32
+ # I/O (NVMe)
33
+ random_page_cost = 1.1
34
+ effective_io_concurrency = 50
35
+ maintenance_io_concurrency = 25
36
+
37
+ # PLANNER
38
+ default_statistics_target = 50
39
+ jit = off
40
+
41
+ # BGWRITER
42
+ bgwriter_delay = 500ms
43
+ bgwriter_lru_maxpages = 50
44
+ bgwriter_lru_multiplier = 2.0
45
+
46
+ # AUTOVACUUM (Less aggressive for staging)
47
+ autovacuum = on
48
+ autovacuum_max_workers = 1
49
+ autovacuum_naptime = 60s
50
+ autovacuum_vacuum_scale_factor = 0.1
51
+ autovacuum_analyze_scale_factor = 0.05
52
+ autovacuum_vacuum_cost_delay = 10ms
53
+ autovacuum_vacuum_cost_limit = 200
54
+
55
+ # TRANSACTION
56
+ max_prepared_transactions = 0
57
+
58
+ # LOGGING
59
+ log_line_prefix = '%m [%p-%l] %u@%d app=%a '
60
+ log_lock_waits = on
61
+ log_temp_files = 0
62
+ log_autovacuum_min_duration = 0
63
+ # More verbose for debugging staging issues
64
+ log_min_duration_statement = 1000
65
+ track_io_timing = on
66
+
67
+ # PERFORMANCE
68
+ shared_preload_libraries = 'pg_stat_statements'
69
+ pg_stat_statements.track = all
70
+ pg_stat_statements.max = 1000
71
+
72
+ # ODOO TUNING
73
+ statement_timeout = 0
74
+ lock_timeout = 30000
75
+ idle_in_transaction_session_timeout = 600000
@@ -51,10 +51,11 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
51
51
  # Remove whats between the ----- and replace with: RUN pip install godoo
52
52
  # Install only dependencies, so they only reinstall when lock or toml where changed
53
53
  COPY pyproject.toml uv.lock README.md ./
54
- RUN --mount=type=cache,target=$UV_CACHE_DIR,uid=1000,gid=1000 uv sync --no-install-project --compile-bytecode
54
+ COPY ./src/godoo_cli/__about__.py ./src/godoo_cli/__about__.py
55
+ RUN --mount=type=cache,target=$UV_CACHE_DIR,uid=1000,gid=1000 uv sync --no-install-project --compile-bytecode --frozen
55
56
 
56
57
  COPY --chown=$USERNAME:$USERNAME ./src ./src
57
- RUN --mount=type=cache,target=$UV_CACHE_DIR,uid=1000,gid=1000 uv sync --all-extras --compile-bytecode
58
+ RUN --mount=type=cache,target=$UV_CACHE_DIR,uid=1000,gid=1000 uv sync --all-extras --compile-bytecode --frozen
58
59
  # In the Devcontainer stage we remove everything in $WORKSPACE and replace it with a Bind-Mount
59
60
  # ------------------------------------------------------------------------------------------------------
60
61
  # Godoo Pypi Install via pip
@@ -116,6 +117,7 @@ COPY --from=oodo_addon_source $ODOO_THIRDPARTY_LOCATION $ODOO_THIRDPARTY_LOCATIO
116
117
  COPY --from=odoo_requirements $VIRTUAL_ENV $VIRTUAL_ENV
117
118
 
118
119
  COPY ../config/nginx.conf /etc/nginx/nginx.conf
120
+ COPY ../config/nginx-proxy_headers.conf /etc/nginx/proxy_headers.conf
119
121
  COPY ../config/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
120
122
  COPY ../scripts/launchodoo.sh launchodoo.sh
121
123
  COPY ../scripts/migrations migrations
@@ -23,6 +23,7 @@ apt-get install -y -q --no-install-recommends \
23
23
  curl \
24
24
  unzip \
25
25
  postgresql-client-17 \
26
+ libpq-dev \
26
27
  libldap2-dev \
27
28
  libssl-dev \
28
29
  libsasl2-dev \
@@ -11,10 +11,16 @@
11
11
  odoo:
12
12
  # The Odoo section describes where to Clone the odoo source code form. (the one with odoo-bin)
13
13
  url: https://github.com/odoo/odoo/
14
- branch: 16.0 # Branch is mandatory on Odoo Repo but not on OCA Repos
14
+ branch: 19.0 # Branch is mandatory on Odoo Repo but not on OCA Repos
15
15
  thirdparty:
16
16
  # In the thirdparty section we can add more Repos to download.
17
17
  # This can also be an ssh style Url for Odoo Enterprise for example.
18
18
  OCA: # This repo folder will be called "OCA_server-tools" when downloading.
19
- - url: https://github.com/OCA/server-tools
20
- branch: 16.0
19
+ - url:
20
+ https://github.com/OCA/server-tools
21
+ # branch: 19.0 # Branch is optional here. If not specified, the default branch of the Repo will be used.
22
+ # commit: abcdef1234567890abcdef1234567890abcdef12 # Commit is also optional. If not specified, the branch will be used and pulled on every `godoo source get`.
23
+ - url: https://github.com/OCA/product-attribute.git
24
+ # merge_from: # We can also Create local merge commits on top of the downloaded Repo.
25
+ # - url: https://github.com/fd-oerp/product-attribute.git
26
+ # branch: 19.0-mig-product_sequence
@@ -2,7 +2,7 @@
2
2
 
3
3
  from packaging import version
4
4
 
5
- __version__ = "0.15.1" # Initial version, will be managed by Hatch
5
+ __version__ = "0.17.0" # Initial version, will be managed by Hatch
6
6
 
7
7
 
8
8
  def get_version_tuple() -> tuple[int, int, int]:
@@ -38,14 +38,28 @@ def main_callback(
38
38
  help="Verbose Logging with Error stacktraces",
39
39
  ),
40
40
  ] = False,
41
+ log_filter: Annotated[
42
+ Optional[str],
43
+ typer.Option(
44
+ "--log-filter",
45
+ "-lf",
46
+ envvar="GODOO_LOG_FILTER",
47
+ help="Regex pattern to filter log output by logger name (e.g. 'odoo.test.suite')",
48
+ ),
49
+ ] = None,
41
50
  ):
42
- """Configure the CLI's logging level.
51
+ """Configure the CLI's logging level and optional log filter.
43
52
 
44
53
  Args:
45
54
  verbose: If True, enables verbose logging with error stacktraces.
46
55
  Can be set via --verbose flag or GODOO_VERBOSE environment variable.
56
+ log_filter: Optional regex pattern to filter log records by logger name.
57
+ Can be set via --log-filter flag or GODOO_LOG_FILTER environment variable.
47
58
  """
48
- set_logging(verbose=bool(verbose) if verbose is not None else False)
59
+ set_logging(
60
+ verbose=bool(verbose) if verbose is not None else False,
61
+ log_filter=log_filter,
62
+ )
49
63
 
50
64
 
51
65
  def main_cli():
@@ -14,7 +14,7 @@ from typing import Annotated, Optional, Union
14
14
  import typer
15
15
 
16
16
  from ...cli_common import CommonCLI
17
- from ...helpers.modules_py import _install_py_reqs_by_odoo_cmd
17
+ from ...helpers.modules_py import install_base_python_reqs, install_py_reqs_by_odoo_cmd
18
18
  from ...helpers.system import run_cmd
19
19
  from ...models import GodooConfig
20
20
  from ..db.query import DbBootstrapStatus, _is_bootstrapped
@@ -188,7 +188,8 @@ def bootstrap_odoo(
188
188
  cmd_string = re.sub(r"--init base,web", "", cmd_string)
189
189
 
190
190
  # Always update Pip reqs regardless of --no-update-source
191
- _install_py_reqs_by_odoo_cmd(addon_paths=addon_paths, odoo_bin_cmd=cmd_string)
191
+ install_base_python_reqs(odoo_install_folder=odoo_main_path)
192
+ install_py_reqs_by_odoo_cmd(addon_paths=addon_paths, odoo_bin_cmd=cmd_string)
192
193
 
193
194
  LOGGER.info("Launching Bootstrap Commandline")
194
195
  ret = run_cmd(cmd_string).returncode
@@ -131,7 +131,8 @@ def odoo_run_tests( # noqa: C901
131
131
  module_list = ",".join(module_names)
132
132
 
133
133
  LOGGER.info("Testing Odoo Modules:\n%s", sorted(module_names))
134
- if "account" in [p.name for p in depends]:
134
+ if "account" in [p.name for p in depends] and godoo_conf.odoo_version.major <= 16:
135
+ # l10n_generic_coa got removed in Odoo 16
135
136
  bootstrap_args = [f"--init {module_list},l10n_generic_coa"]
136
137
  else:
137
138
  bootstrap_args = [f"--init {module_list}"]
@@ -6,6 +6,7 @@ Odoo environment. It supports both interactive and script-based operations.
6
6
  """
7
7
 
8
8
  import logging
9
+ import subprocess
9
10
  import sys
10
11
  from pathlib import Path
11
12
  from typing import Annotated, Optional
@@ -103,6 +104,10 @@ def odoo_shell_run_script(
103
104
  odoo_conf_path: Annotated[Path, CLI.odoo_paths.conf_path],
104
105
  db_name: Annotated[str, CLI.database.db_name],
105
106
  db_user: Annotated[str, CLI.database.db_user],
107
+ script_args: Annotated[
108
+ Optional[list[str]],
109
+ typer.Argument(help="Arguments to pass to the script"),
110
+ ] = None,
106
111
  db_host: Annotated[str, CLI.database.db_host] = "",
107
112
  db_port: Annotated[int, CLI.database.db_port] = 0,
108
113
  db_password: Annotated[str, CLI.database.db_password] = "",
@@ -111,6 +116,7 @@ def odoo_shell_run_script(
111
116
 
112
117
  This function executes a Python script in the Odoo shell environment,
113
118
  supporting both configuration file and direct database connection parameters.
119
+ Additional arguments after the script name are passed to the script as script_args list.
114
120
 
115
121
  Returns:
116
122
  int: 0 for success, non-zero for failure.
@@ -121,7 +127,7 @@ def odoo_shell_run_script(
121
127
  return CLI.returner(1)
122
128
 
123
129
  shell_cmd = f"{odoo_main_path.absolute()!s}/odoo-bin shell --no-http"
124
- if odoo_conf_path.exists():
130
+ if odoo_conf_path and odoo_conf_path.exists():
125
131
  shell_cmd += f" -c {odoo_conf_path.absolute()!s}"
126
132
  else:
127
133
  LOGGER.warning("No Odoo Config File found at %s", odoo_conf_path)
@@ -130,8 +136,28 @@ def odoo_shell_run_script(
130
136
  return CLI.returner(1)
131
137
  shell_cmd += f" --db_host={db_host} --db_port={db_port} --database={db_name} --db_user={db_user} --db_password={db_password}"
132
138
 
133
- LOGGER.info("Running Script: %s", script_path)
134
- run_cmd(shell_cmd, stdin=script_path.open("r"))
139
+ # Prepare script with arguments
140
+ script_content = script_path.read_text()
141
+
142
+ # If script_args provided, prepend them as a list variable
143
+ if script_args:
144
+ args_str = repr(list(script_args)) # Safely convert to Python list literal
145
+ script_with_args = f"script_args = {args_str}\n\n{script_content}"
146
+ LOGGER.info("Running Script: %s with args: %s", script_path, script_args)
147
+ else:
148
+ script_with_args = f"script_args = []\n\n{script_content}"
149
+ LOGGER.info("Running Script: %s", script_path)
150
+
151
+ proc = subprocess.Popen(
152
+ shell_cmd,
153
+ shell=True,
154
+ stdin=subprocess.PIPE,
155
+ stdout=sys.stdout,
156
+ stderr=sys.stderr,
157
+ text=True,
158
+ )
159
+ proc.communicate(input=script_with_args)
160
+ return CLI.returner(proc.returncode)
135
161
 
136
162
 
137
163
  def odoo_pregenerate_assets(godoo_conf: GodooConfig):
@@ -144,15 +170,10 @@ def odoo_pregenerate_assets(godoo_conf: GodooConfig):
144
170
  NotImplementedError: If the Odoo version is not supported.
145
171
  """
146
172
  odoo_version = odoo_bin_get_version(odoo_main_repo_path=godoo_conf.odoo_install_folder)
147
- if odoo_version.major == 16:
148
- pregen_command = "env['ir.qweb']._pregenerate_assets_bundles();env.cr.commit()"
149
- else:
150
- msg = f"Odoo Version {odoo_version.raw} not supported in gOdoo for pregenerate_assets"
151
- LOGGER.error(msg)
152
- raise NotImplementedError(msg)
153
173
  LOGGER.info("Pregenerating Assets for Odoo version %s", odoo_version.raw)
154
- odoo_shell(
155
- pipe_in_command=pregen_command,
174
+ # Use the pregenerate_assets script which attempts multiple internal APIs.
175
+ odoo_shell_run_script(
176
+ script_name="pregenerate_assets",
156
177
  odoo_main_path=godoo_conf.odoo_install_folder,
157
178
  odoo_conf_path=godoo_conf.odoo_conf_path,
158
179
  db_name=godoo_conf.db_name,
@@ -0,0 +1,34 @@
1
+ """Script used by gOdoo to pregenerate asset bundles in the Odoo filestore.
2
+
3
+ The script tries several internal APIs to be tolerant across multiple
4
+ Odoo versions (16+). It prints which method succeeded or prints
5
+ diagnostic information if all attempts fail.
6
+ """
7
+
8
+ import contextlib
9
+
10
+ from odoo import api
11
+
12
+ env: api.Environment = env # Just to silence pyright # pyright: ignore # NOQA
13
+
14
+ try:
15
+ env["ir.qweb"]._pregenerate_assets_bundles()
16
+ print("pregenerated: ir.qweb._pregenerate_assets_bundles")
17
+ except Exception:
18
+ try:
19
+ env["ir.qweb"]._pregenerate_assets()
20
+ print("pregenerated: ir.qweb._pregenerate_assets")
21
+ except Exception:
22
+ try:
23
+ env["ir.asset"]._pregenerate_bundles()
24
+ print("pregenerated: ir.asset._pregenerate_bundles")
25
+ except Exception:
26
+ print("pregenerate failed; exceptions:")
27
+ import traceback
28
+
29
+ with contextlib.suppress(Exception):
30
+ traceback.print_exc()
31
+
32
+ # Commit any DB changes
33
+ with contextlib.suppress(Exception):
34
+ env.cr.commit()
@@ -0,0 +1,122 @@
1
+ """Render an Odoo report to HTML and print to stdout.
2
+
3
+ This script renders a QWeb report for given record IDs and outputs the HTML.
4
+ It is executed in the Odoo shell environment via:
5
+
6
+ godoo shell-script render_report <report_name> <record_id> [<record_id> ...]
7
+
8
+ Example:
9
+ godoo shell-script render_report sale.report_saleorder 1
10
+ godoo shell-script render_report sale.report_saleorder 1 2 3
11
+
12
+ Flags:
13
+ --keep-base64 Keep base64 content instead of replacing with placeholder
14
+
15
+ """
16
+
17
+ import logging
18
+ import re
19
+ import sys
20
+ from xml.dom import minidom
21
+
22
+ from odoo import api
23
+
24
+ LOGGER = logging.getLogger(__name__)
25
+
26
+ env: api.Environment = env # Just to silence pyright # pyright: ignore # NOQA
27
+
28
+ # script_args is injected by godoo shell-script command
29
+ script_args: list[str] = script_args # pyright: ignore # NOQA
30
+
31
+
32
+ def replace_base64_with_placeholder(html_string: str) -> str:
33
+ """Replace base64 content with a placeholder.
34
+
35
+ Replaces long base64 strings (data URIs, embedded images, etc.) with
36
+ a placeholder to make output more readable.
37
+
38
+ Parameters
39
+ ----------
40
+ html_string : str
41
+ HTML string potentially containing base64 content
42
+
43
+ Returns:
44
+ -------
45
+ str
46
+ HTML string with base64 content replaced by placeholder
47
+ """
48
+ # Match data URIs with base64 content and replace with placeholder
49
+ # Matches patterns like: data:image/png;base64,... or similar
50
+ pattern = r"data:[^/]+/[^;]+;base64,[A-Za-z0-9+/]+={0,2}"
51
+ replacement = "data:[MIME];base64,[BASE64_CONTENT_PLACEHOLDER]"
52
+ return re.sub(pattern, replacement, html_string)
53
+
54
+
55
+ def render_report(report_name: str, record_ids: list[int], replace_base64: bool = True):
56
+ """Render an Odoo report to HTML.
57
+
58
+ Parameters
59
+ ----------
60
+ report_name : str
61
+ Name of the report to render (e.g., 'sale.report_saleorder')
62
+ record_ids : list[int]
63
+ List of record IDs to render
64
+ replace_base64 : bool, optional
65
+ Replace base64 content with placeholder (True by default)
66
+ """
67
+ try:
68
+ report_model = env["ir.actions.report"]
69
+ html_content, _ = report_model._render_qweb_html(report_name, record_ids)
70
+
71
+ if html_content:
72
+ # Decode bytes to string
73
+ html_string = html_content.decode("utf-8") if isinstance(html_content, bytes) else html_content
74
+
75
+ # Replace base64 content with placeholder if enabled
76
+ if replace_base64:
77
+ html_string = replace_base64_with_placeholder(html_string)
78
+
79
+ # Try to pretty print the HTML
80
+ try:
81
+ dom = minidom.parseString(html_string)
82
+ pretty_html = dom.toprettyxml(indent=" ")
83
+ # Remove extra blank lines that minidom adds
84
+ print("\n".join([line for line in pretty_html.split("\n") if line.strip()]))
85
+ except Exception:
86
+ # If pretty printing fails, just print the raw HTML
87
+ print(html_string)
88
+ else:
89
+ LOGGER.error("Failed to render report: %s", report_name)
90
+ sys.exit(1)
91
+
92
+ except ValueError:
93
+ LOGGER.exception("Report not found")
94
+ sys.exit(1)
95
+ except Exception:
96
+ LOGGER.exception("Error rendering report %s", report_name)
97
+ sys.exit(1)
98
+
99
+
100
+ # Main execution: Parse script_args and call render_report
101
+ if not script_args:
102
+ LOGGER.error("Usage: godoo shell-script render_report <report_name> <record_id> [<record_id> ...] [--keep-base64]")
103
+ sys.exit(1)
104
+
105
+ if len(script_args) < 2:
106
+ LOGGER.error("Missing arguments. Need at least report_name and one record_id")
107
+ sys.exit(1)
108
+
109
+ # Check for --keep-base64 flag
110
+ keep_base64_flag = "--keep-base64" in script_args
111
+ filtered_args = [arg for arg in script_args if arg != "--keep-base64"]
112
+
113
+ # Now extract report_name and record_ids from filtered args
114
+ if len(filtered_args) < 2:
115
+ LOGGER.error("Missing arguments. Need at least report_name and one record_id")
116
+ sys.exit(1)
117
+
118
+ report_name = filtered_args[0]
119
+ record_ids = [int(rid) for rid in filtered_args[1:]]
120
+
121
+ # render_report with replace_base64 being False if --keep-base64 was passed
122
+ render_report(report_name, record_ids, replace_base64=not keep_base64_flag)