From 754e086d9642dcaebab2015f95e4d60613d9c574 Mon Sep 17 00:00:00 2001 From: Florent Xicluna Date: Wed, 22 Apr 2026 10:19:43 +0200 Subject: [PATCH] feat: build different flavors from a single branch --- .github/workflows/build.yaml | 66 ++++--- .github/workflows/hadolint.yaml | 2 - 12.0/Dockerfile | 5 + 13.0/Dockerfile | 5 + 14.0/base_requirements.txt | 2 +- 14.0/extra_requirements.txt | 42 +++++ 14.0/templates/odoo.cfg.tmpl | 2 +- 15.0/extra_requirements.txt | 39 ++++ 15.0/templates/odoo.cfg.tmpl | 2 +- 16.0/extra_requirements.txt | 39 ++++ 16.0/templates/odoo.cfg.tmpl | 2 +- 17.0/extra_requirements.txt | 39 ++++ 17.0/templates/odoo.cfg.tmpl | 2 +- 18.0/extra_requirements.txt | 39 ++++ 18.0/templates/odoo.cfg.tmpl | 2 +- 19.0/templates/odoo.cfg.tmpl | 2 +- HISTORY-core.rst | 177 ++++++++++++++++++ Makefile | 3 +- README.md | 24 ++- bin/{db.sh => db_cache_helpers.sh} | 0 bin/docker-entrypoint.sh | 76 +++----- bin/env_postgres.sh | 12 ++ bin/lint | 2 +- bin/list_dependencies.py | 35 ++-- bin/migrate | 4 +- bin/runmigration | 12 +- bin/runtests | 31 +-- bin/testdb-gen | 4 +- bin/testdb-update | 4 +- build.sh | 2 +- common/Dockerfile | 8 +- ...kerfile-batteries => batteries.Dockerfile} | 1 + common/core.Dockerfile | 112 +++++++++++ common/env_odoo-core.sh | 8 + common/env_odoo.sh | 11 ++ example-core/Dockerfile | 41 ++++ example-core/README.md | 37 ++++ example-core/data/images/logo.png | Bin 0 -> 21601 bytes example-core/docker-compose.yml | 51 +++++ example-core/migration.yml | 11 ++ example-core/odoo/.dockerignore | 14 ++ example-core/odoo/VERSION | 1 + example-core/odoo/addons/README.md | 1 + .../odoo/addons/dummy_test/__init__.py | 0 .../odoo/addons/dummy_test/__manifest__.py | 12 ++ .../odoo/addons/dummy_test/tests/__init__.py | 1 + .../addons/dummy_test/tests/test_dummy.py | 8 + example-core/odoo/setup.py | 26 +++ example-core/odoo/src/README.md | 1 + example-core/pyproject.toml | 21 +++ example-core/requirements.txt | 4 + example-core/setup.py | 17 ++ example-core/songs/__init__.py | 0 example-core/songs/install/__init__.py | 0 example-core/songs/install/base.py | 33 ++++ example-core/songs/install/demo.py | 17 ++ example-core/test-compose.yml | 54 ++++++ example/docker-compose.yml | 1 + example/test-compose.yml | 1 + install/package_odoo.sh | 36 +++- install/purge_dev_package_and_cache.sh | 4 + install/reportlab_init.sh | 13 -- setup.sh | 2 +- test.sh | 43 ++++- 64 files changed, 1104 insertions(+), 162 deletions(-) create mode 100644 14.0/extra_requirements.txt create mode 100644 15.0/extra_requirements.txt create mode 100644 16.0/extra_requirements.txt create mode 100644 17.0/extra_requirements.txt create mode 100644 18.0/extra_requirements.txt create mode 100644 HISTORY-core.rst rename bin/{db.sh => db_cache_helpers.sh} (100%) create mode 100644 bin/env_postgres.sh rename common/{Dockerfile-batteries => batteries.Dockerfile} (81%) create mode 100644 common/core.Dockerfile create mode 100755 common/env_odoo-core.sh create mode 100755 common/env_odoo.sh create mode 100644 example-core/Dockerfile create mode 100644 example-core/README.md create mode 100644 example-core/data/images/logo.png create mode 100644 example-core/docker-compose.yml create mode 100644 example-core/migration.yml create mode 100644 example-core/odoo/.dockerignore create mode 100644 example-core/odoo/VERSION create mode 100644 example-core/odoo/addons/README.md create mode 100644 example-core/odoo/addons/dummy_test/__init__.py create mode 100644 example-core/odoo/addons/dummy_test/__manifest__.py create mode 100644 example-core/odoo/addons/dummy_test/tests/__init__.py create mode 100644 example-core/odoo/addons/dummy_test/tests/test_dummy.py create mode 100644 example-core/odoo/setup.py create mode 100644 example-core/odoo/src/README.md create mode 100644 example-core/pyproject.toml create mode 100644 example-core/requirements.txt create mode 100644 example-core/setup.py create mode 100644 example-core/songs/__init__.py create mode 100644 example-core/songs/install/__init__.py create mode 100644 example-core/songs/install/base.py create mode 100644 example-core/songs/install/demo.py create mode 100644 example-core/test-compose.yml delete mode 100755 install/reportlab_init.sh diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index cdde7f09..3cda1b14 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -3,14 +3,16 @@ name: build on: push: branches: - - "release-4.5.X" - - "dev-4.5.X" + - "main" + - "master" + - "dev" tags: - - "4.*.*" - + - "*.*.*" + - "*.*.*.*.*" pull_request: branches: - - "release-4.5.X" + - "main" + - "master" schedule: - cron: "0 1 * * WED" @@ -31,21 +33,30 @@ jobs: - "17.0" - "18.0" - "19.0" - python_from: - - "python:3.12-slim-trixie" + python: + - "python:3.12" + flavor: + - main + - core include: - odoo_serie: "12.0" - python_from: "python:3.9-slim-trixie" + python: "python:3.9" + flavor: main - odoo_serie: "13.0" - python_from: "python:3.9-slim-trixie" + python: "python:3.9" + flavor: main + - odoo_serie: "14.0" + python: "python:3.9" + flavor: main - odoo_serie: "14.0" - python_from: "python:3.9-slim-trixie" - continue-on-error: ${{ matrix.odoo_serie == '12.0' }} + python: "python:3.9" + flavor: core + continue-on-error: ${{ matrix.odoo_serie == '12.0' || matrix.flavor == 'core' }} steps: - uses: actions/checkout@v6 - - name: Set up Docker Buildx + - name: Setup Docker Buildx id: buildx uses: docker/setup-buildx-action@v4 with: @@ -57,34 +68,42 @@ jobs: with: images: ghcr.io/camptocamp/docker-odoo-project flavor: | - prefix=${{ matrix.odoo_serie }}-,onlatest=true + prefix=${{ matrix.odoo_serie }}${{ matrix.flavor == 'core' && '-core-' || '-' }},onlatest=true tags: | - type=raw,value={{branch}}-latest - type=raw,value={{branch}}-{{date 'YYYYMMDD'}} - type=ref,event=tag + type=ref,event=tag,priority=900,enable=${{ (matrix.flavor == 'main' && contains(github.ref, '/4.')) || (matrix.flavor == 'core' && contains(github.ref, '/5.')) }} type=ref,event=pr - type=schedule,pattern={{branch}}-nightly - type=raw,value={{branch}} + type=schedule,priority=800 + type=raw,priority=500,value=latest,enable={{is_default_branch}} + type=raw,priority=400,value={{date 'YYYYMMDD'}},enable={{is_default_branch}} + type=raw,priority=300,value={{branch}}-latest,enable={{is_not_default_branch}} + type=raw,priority=300,value={{branch}}-{{date 'YYYYMMDD'}},enable={{is_not_default_branch}} + type=raw,priority=200,value={{branch}},enable={{is_not_default_branch}} - name: Setup build dir + id: setup run: | VERSION=${{ matrix.odoo_serie }} SRC=build make setup + echo "Dockerfile=./build/${{ matrix.flavor == 'core' && 'core.' || '' }}Dockerfile" >> $GITHUB_OUTPUT + echo "python-from=${{ matrix.python }}-slim-trixie" >> $GITHUB_OUTPUT + echo "image-tag=ci-${{ matrix.flavor == 'core' && '5' || '4' }}xx-latest:${{ matrix.odoo_serie }}" >> $GITHUB_OUTPUT - name: Build uses: docker/build-push-action@v7 with: context: ./build + file: ${{ steps.setup.outputs.Dockerfile }} build-args: | VERSION=${{ matrix.odoo_serie }} build-contexts: | - python=docker-image://${{ matrix.python_from }} + python=docker-image://${{ steps.setup.outputs.python-from }} push: false load: true - tags: ci-4xx-latest:${{ matrix.odoo_serie }} + tags: ${{ steps.setup.outputs.image-tag }} labels: ${{ steps.docker_meta.outputs.labels }} - name: Test - run: make VERSION=${{ matrix.odoo_serie }} test + run: | + make VERSION=${{ matrix.odoo_serie }} IMAGE_LATEST=${{ steps.setup.outputs.image-tag }} test - name: Scan image id: scan @@ -93,7 +112,7 @@ jobs: sysdig-secure-url: https://eu1.app.sysdig.com stop-on-failed-policy-eval: false stop-on-processing-error: false - image-tag: ci-4xx-latest:${{ matrix.odoo_serie }} + image-tag: ${{ steps.setup.outputs.image-tag }} skip-upload: false sysdig-secure-token: ${{ secrets.SYSDIG_SECURE_TOKEN }} @@ -111,10 +130,11 @@ jobs: uses: docker/build-push-action@v7 with: context: ./build + file: ${{ steps.setup.outputs.Dockerfile }} build-args: | VERSION=${{ matrix.odoo_serie }} build-contexts: | - python=docker-image://${{ matrix.python_from }} + python=docker-image://${{ steps.setup.outputs.python-from }} push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.docker_meta.outputs.tags }} labels: ${{ steps.docker_meta.outputs.labels }} diff --git a/.github/workflows/hadolint.yaml b/.github/workflows/hadolint.yaml index e6af8645..fa9b7fcd 100644 --- a/.github/workflows/hadolint.yaml +++ b/.github/workflows/hadolint.yaml @@ -6,12 +6,10 @@ on: - "main" - "master" - "dev" - - "release-4.5.X" pull_request: branches: - "main" - "master" - - "release-4.5.X" jobs: diff --git a/12.0/Dockerfile b/12.0/Dockerfile index ffdddb24..a151e1b1 100644 --- a/12.0/Dockerfile +++ b/12.0/Dockerfile @@ -54,6 +54,11 @@ COPY ./templates /templates COPY ./before-migrate-entrypoint.d /before-migrate-entrypoint.d COPY ./start-entrypoint.d /start-entrypoint.d COPY ./MANIFEST.in /odoo +COPY --chmod=644 ./env_odoo.sh /odoo-bin/ +# Init PG variables during Shell initialization so it will be available +# when doing 'docker compose exec odoo gosu odoo bash' +RUN set -x; echo >> /etc/bash.bashrc \ + "if [ -f /odoo-bin/env_postgres.sh ]; then . /odoo-bin/env_postgres.sh; fi" ENV ODOO_VERSION=$VERSION \ PATH=/odoo-bin:$PATH \ diff --git a/13.0/Dockerfile b/13.0/Dockerfile index 7c3de904..ac34c5c9 100644 --- a/13.0/Dockerfile +++ b/13.0/Dockerfile @@ -54,6 +54,11 @@ COPY ./templates /templates COPY ./before-migrate-entrypoint.d /before-migrate-entrypoint.d COPY ./start-entrypoint.d /start-entrypoint.d COPY ./MANIFEST.in /odoo +COPY --chmod=644 ./env_odoo.sh /odoo-bin/ +# Init PG variables during Shell initialization so it will be available +# when doing 'docker compose exec odoo gosu odoo bash' +RUN set -x; echo >> /etc/bash.bashrc \ + "if [ -f /odoo-bin/env_postgres.sh ]; then . /odoo-bin/env_postgres.sh; fi" ENV ODOO_VERSION=$VERSION \ PATH=/odoo-bin:$PATH \ diff --git a/14.0/base_requirements.txt b/14.0/base_requirements.txt index 9f2c4828..d4b24760 100644 --- a/14.0/base_requirements.txt +++ b/14.0/base_requirements.txt @@ -77,5 +77,5 @@ pycodestyle==2.12.1 pyflakes==3.2.0 setuptools==79.0.1 unicodecsv==0.14.1 -urllib3==2.6.3 +urllib3==1.26.20 wrapt==1.16.0 diff --git a/14.0/extra_requirements.txt b/14.0/extra_requirements.txt new file mode 100644 index 00000000..a950df34 --- /dev/null +++ b/14.0/extra_requirements.txt @@ -0,0 +1,42 @@ +# Extra python dependencies +algoliasearch==4.1.1 +Adyen==12.3.0 +cachetools==5.5.0 +cerberus==1.3.5 +boto3==1.35.6 +factur-x==3.1 +invoice2data==0.4.5 +mailjet-rest==1.3.4 +openupgradelib==3.6.1 +paramiko==3.4.1 +parse-accept-language==0.1.2 +paypalrestsdk==1.13.3 +phonenumbers==8.13.44 +pyOpenSSL==24.2.1 +pyquerystring==1.1 +pysimplesoap==1.16.2 +requests-mock==1.12.1 +slugify==0.0.1 +stripe==10.8.0 +unidecode==1.3.8 +vcrpy==7.0.0 + +# Library dependency +aiohttp==3.13.3 +asn1crypto==1.5.1 +bcrypt==4.2.0 +botocore==1.35.6 +cffi==1.17.0 +dateparser==1.2.0 +jmespath==1.0.1 +multidict==6.0.5 +pdfminer.six==20251107 +pyasn1==0.6.3 +pycparser==2.22 +pycryptodome==3.20.0 +PyNaCl==1.5.0 +pytesseract==0.3.13 +regex==2024.7.24 +s3transfer==0.10.2 +tzlocal==5.2 +yarl==1.22.0 diff --git a/14.0/templates/odoo.cfg.tmpl b/14.0/templates/odoo.cfg.tmpl index ba29413a..a88d26e6 100644 --- a/14.0/templates/odoo.cfg.tmpl +++ b/14.0/templates/odoo.cfg.tmpl @@ -1,6 +1,6 @@ [options] addons_path = {{ .Env.ADDONS_PATH }} -data_dir = /data/odoo +data_dir = {{ default .Env.DATA_DIR "/data/odoo" }} auto_reload = False db_host = {{ .Env.DB_HOST }} db_name = {{ .Env.DB_NAME }} diff --git a/15.0/extra_requirements.txt b/15.0/extra_requirements.txt new file mode 100644 index 00000000..3df4f9e5 --- /dev/null +++ b/15.0/extra_requirements.txt @@ -0,0 +1,39 @@ +# Extra python dependencies +algoliasearch==4.1.1 +Adyen==12.3.0 +cachetools==5.5.0 +cerberus==1.3.5 +boto3==1.35.6 +factur-x==3.1 +invoice2data==0.4.5 +mailjet-rest==1.3.4 +openupgradelib==3.6.1 +paramiko==3.4.1 +parse-accept-language==0.1.2 +paypalrestsdk==1.13.3 +phonenumbers==8.13.44 +pyquerystring==1.1 +pysimplesoap==1.16.2 +requests-mock==1.12.1 +slugify==0.0.1 +stripe==10.8.0 +unidecode==1.3.8 +vcrpy==7.0.0 + +# Library dependency +aiohttp==3.13.3 +asn1crypto==1.5.1 +bcrypt==4.2.0 +botocore==1.35.6 +dateparser==1.2.0 +jmespath==1.0.1 +multidict==6.0.5 +pdfminer.six==20260107 +pyasn1==0.6.3 +pycryptodome==3.20.0 +PyNaCl==1.5.0 +pytesseract==0.3.13 +regex==2024.7.24 +s3transfer==0.10.2 +tzlocal==5.2 +yarl==1.22.0 diff --git a/15.0/templates/odoo.cfg.tmpl b/15.0/templates/odoo.cfg.tmpl index ba29413a..a88d26e6 100644 --- a/15.0/templates/odoo.cfg.tmpl +++ b/15.0/templates/odoo.cfg.tmpl @@ -1,6 +1,6 @@ [options] addons_path = {{ .Env.ADDONS_PATH }} -data_dir = /data/odoo +data_dir = {{ default .Env.DATA_DIR "/data/odoo" }} auto_reload = False db_host = {{ .Env.DB_HOST }} db_name = {{ .Env.DB_NAME }} diff --git a/16.0/extra_requirements.txt b/16.0/extra_requirements.txt new file mode 100644 index 00000000..3df4f9e5 --- /dev/null +++ b/16.0/extra_requirements.txt @@ -0,0 +1,39 @@ +# Extra python dependencies +algoliasearch==4.1.1 +Adyen==12.3.0 +cachetools==5.5.0 +cerberus==1.3.5 +boto3==1.35.6 +factur-x==3.1 +invoice2data==0.4.5 +mailjet-rest==1.3.4 +openupgradelib==3.6.1 +paramiko==3.4.1 +parse-accept-language==0.1.2 +paypalrestsdk==1.13.3 +phonenumbers==8.13.44 +pyquerystring==1.1 +pysimplesoap==1.16.2 +requests-mock==1.12.1 +slugify==0.0.1 +stripe==10.8.0 +unidecode==1.3.8 +vcrpy==7.0.0 + +# Library dependency +aiohttp==3.13.3 +asn1crypto==1.5.1 +bcrypt==4.2.0 +botocore==1.35.6 +dateparser==1.2.0 +jmespath==1.0.1 +multidict==6.0.5 +pdfminer.six==20260107 +pyasn1==0.6.3 +pycryptodome==3.20.0 +PyNaCl==1.5.0 +pytesseract==0.3.13 +regex==2024.7.24 +s3transfer==0.10.2 +tzlocal==5.2 +yarl==1.22.0 diff --git a/16.0/templates/odoo.cfg.tmpl b/16.0/templates/odoo.cfg.tmpl index ba29413a..a88d26e6 100644 --- a/16.0/templates/odoo.cfg.tmpl +++ b/16.0/templates/odoo.cfg.tmpl @@ -1,6 +1,6 @@ [options] addons_path = {{ .Env.ADDONS_PATH }} -data_dir = /data/odoo +data_dir = {{ default .Env.DATA_DIR "/data/odoo" }} auto_reload = False db_host = {{ .Env.DB_HOST }} db_name = {{ .Env.DB_NAME }} diff --git a/17.0/extra_requirements.txt b/17.0/extra_requirements.txt new file mode 100644 index 00000000..3df4f9e5 --- /dev/null +++ b/17.0/extra_requirements.txt @@ -0,0 +1,39 @@ +# Extra python dependencies +algoliasearch==4.1.1 +Adyen==12.3.0 +cachetools==5.5.0 +cerberus==1.3.5 +boto3==1.35.6 +factur-x==3.1 +invoice2data==0.4.5 +mailjet-rest==1.3.4 +openupgradelib==3.6.1 +paramiko==3.4.1 +parse-accept-language==0.1.2 +paypalrestsdk==1.13.3 +phonenumbers==8.13.44 +pyquerystring==1.1 +pysimplesoap==1.16.2 +requests-mock==1.12.1 +slugify==0.0.1 +stripe==10.8.0 +unidecode==1.3.8 +vcrpy==7.0.0 + +# Library dependency +aiohttp==3.13.3 +asn1crypto==1.5.1 +bcrypt==4.2.0 +botocore==1.35.6 +dateparser==1.2.0 +jmespath==1.0.1 +multidict==6.0.5 +pdfminer.six==20260107 +pyasn1==0.6.3 +pycryptodome==3.20.0 +PyNaCl==1.5.0 +pytesseract==0.3.13 +regex==2024.7.24 +s3transfer==0.10.2 +tzlocal==5.2 +yarl==1.22.0 diff --git a/17.0/templates/odoo.cfg.tmpl b/17.0/templates/odoo.cfg.tmpl index ba29413a..a88d26e6 100644 --- a/17.0/templates/odoo.cfg.tmpl +++ b/17.0/templates/odoo.cfg.tmpl @@ -1,6 +1,6 @@ [options] addons_path = {{ .Env.ADDONS_PATH }} -data_dir = /data/odoo +data_dir = {{ default .Env.DATA_DIR "/data/odoo" }} auto_reload = False db_host = {{ .Env.DB_HOST }} db_name = {{ .Env.DB_NAME }} diff --git a/18.0/extra_requirements.txt b/18.0/extra_requirements.txt new file mode 100644 index 00000000..a1acd11b --- /dev/null +++ b/18.0/extra_requirements.txt @@ -0,0 +1,39 @@ +# Extra python dependencies +algoliasearch==4.1.1 +Adyen==12.3.0 +cachetools==5.5.0 +cerberus==1.3.5 +boto3==1.35.6 +factur-x==3.1 +invoice2data==0.4.5 +mailjet-rest==1.3.4 +openupgradelib==3.6.1 +paramiko==3.4.1 +parse-accept-language==0.1.2 +paypalrestsdk==1.13.3 +phonenumbers==8.13.44 +pyquerystring==1.1 +pysimplesoap==1.16.2 +requests-mock==1.12.1 +slugify==0.0.1 +stripe==10.8.0 +unidecode==1.3.8 +vcrpy==7.0.0 + +# Library dependency +aiohttp==3.13.3 +bcrypt==4.2.0 +botocore==1.35.6 +dateparser==1.2.0 +jmespath==1.0.1 +multidict==6.0.5 +pdfminer.six==20260107 +pyasn1==0.6.3 +pycryptodome==3.20.0 +PyNaCl==1.5.0 +pytesseract==0.3.13 +regex==2024.7.24 +s3transfer==0.10.2 +tzlocal==5.2 +yarl==1.22.0 + diff --git a/18.0/templates/odoo.cfg.tmpl b/18.0/templates/odoo.cfg.tmpl index ee59c659..9c332fad 100644 --- a/18.0/templates/odoo.cfg.tmpl +++ b/18.0/templates/odoo.cfg.tmpl @@ -1,6 +1,6 @@ [options] addons_path = {{ .Env.ADDONS_PATH }} -data_dir = /data/odoo +data_dir = {{ default .Env.DATA_DIR "/data/odoo" }} auto_reload = False db_host = {{ .Env.DB_HOST }} db_name = {{ .Env.DB_NAME }} diff --git a/19.0/templates/odoo.cfg.tmpl b/19.0/templates/odoo.cfg.tmpl index baebbdd0..27573624 100644 --- a/19.0/templates/odoo.cfg.tmpl +++ b/19.0/templates/odoo.cfg.tmpl @@ -1,6 +1,6 @@ [options] addons_path = {{ .Env.ADDONS_PATH }} -data_dir = /data/odoo +data_dir = {{ default .Env.DATA_DIR "/data/odoo" }} db_host = {{ .Env.DB_HOST }} db_name = {{ .Env.DB_NAME }} db_user = {{ .Env.DB_USER }} diff --git a/HISTORY-core.rst b/HISTORY-core.rst new file mode 100644 index 00000000..de4fba9a --- /dev/null +++ b/HISTORY-core.rst @@ -0,0 +1,177 @@ +.. :changelog: + +.. Template: + +.. 0.0.1 (2016-05-09) +.. ++++++++++++++++++ + +.. **Features and Improvements** + +.. **Bugfixes** + +.. **Libraries** + +.. **Build** + +.. **Documentation** + +Release History +--------------- + +latest (unreleased) ++++++++++++++++++++ + +**Features and Improvements** + +* Replace environment variable OPENERP_SERVER with ODOO_RC +* Entrypoint: exit on error when executing run-parts +* Pillow: bump to 12.1.1 (to fix security issues) + +**Bugfixes** + +**Build** + +* Change PostgreSQL deb repo to 'apt-archive' for debian stretch based images + +**Documentation** + +* Switch project example to Python 3 + + +5.3.0.0.0 (2024-08-26) +++++++++++++++++++++++ + +**Features and Improvements** + +* remove pathtools library, use pathlib instead +* remove 14 buster, use bookworm instead +* use bookwork for all supported versions, specific debian version applied +* bump all packages for 15.0/16.0/17.0 +* switch 15.0/16.0/17.0 to python 3.12 on bookworm + + +5.2.1.0.0 (2024-01-19) +++++++++++++++++++++++ + +**Features and Improvements** + +* add openxlrd library +* remove 11.0 version + + +5.2.0.0.0 (2024-01-19) +++++++++++++++++++++++ + +**Features and Improvements** + +* add env variable for LOCAL_CODE_PATH and MIGRATION_CONFIG_FILE +* /bin script to remove gosu dependencies +* clean local-src reference +* print DEPS_ADDONS for debugging + + +5.1.0.0.1 (2023-12-11) +++++++++++++++++++++++ + +**Bugfixes** + +* fix the entrypoint path in the entrypoint script + + +5.1.0.0.0 (2023-11-13) +++++++++++++++++++++++ + +**Features and Improvements** + +* 17.0 version +* Switch to github action +* Image pushed to github repository + + +5.1.0 (2023-11-13) move to 5.1.0.0.0 +++++++++++++++++++++++++++++++++++++ + +**Features and Improvements** + +* Image pushed to github repository + + +5.0.8 (2023-09-12) +++++++++++++++++++ + +**Bugfixes** + +* Remove pip install of src + + +5.0.7 (2023-06-07) +++++++++++++++++++ + +**Bugfixes** + +* Fix entrypoint path for odoo + + +5.0.6 (2023-04-28) +++++++++++++++++++ + +**Features and Improvements** + +* Switch to buster for version 11.0 + + +5.0.5 (2022-12-05) +++++++++++++++++++ + +**Features and Improvements** + +* Fix package version for all versions + + +5.0.4 (2022-11-23) +++++++++++++++++++ + +**Features and Improvements** + +* Fix for V16 pypi + + +5.0.3 (2022-09-01) +++++++++++++++++++ + +**Features and Improvements** + +* Fix coverage + + +5.0.2 (2022-08-31) +++++++++++++++++++ + +**Features and Improvements** + +* Fix path in instance dependencies + + +5.0.1 (2022-08-30) +++++++++++++++++++ + +**Features and Improvements** + +* Fix makefile tag + + +5.0.0 (2022-08-30) +++++++++++++++++++ + +**Features and Improvements** + +* Remove old version (python 2.7) 7.0/8.0/9.0/10.0 +* Remove Gosu.sh +* Run container with odoo user + + +4.x ++++ + +* Flavor 'core' is a fork of traditional image '4.4.5'. + See HISTORY.rst in same folder diff --git a/Makefile b/Makefile index 6806439e..0fc06ca8 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,9 @@ ifndef VERSION $(error VERSION is not set) endif - +ifndef IMAGE_LATEST IMAGE_LATEST=ci-4xx-latest:${VERSION} +endif BUILD_TAG=$(IMAGE_LATEST) export diff --git a/README.md b/README.md index 5f80c942..f2cdb1a5 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,17 @@ code should be added in a Dockerfile inheriting from this image. A project using this image has to respect a defined structure, look at the [example](example). -See also the [Changelog](HISTORY.rst). +See also the [Changelog](HISTORY.rst) and [Changelog of core image 5.x](HISTORY-core.rst). + +## ⚠️ Version 5.0.0 : Some Breaking changes + + - We no longer use gosu + - The `odoo` user is created during the build of the image, and no longer in the entrypoint + - All odoo related files are moved in /odoo + - odoo runs with uid 999; if you need to change this, use for instance `docker compose --build-arg UID=$(id -u)` + - Odoo versions prior to 14.0 are no longer supported + + - Note: image versions 4.5.x are fully supported and maintained. ## ⚠️ Reporting now uses kwkhtmltopdf instead of wkhtmltopdf @@ -59,7 +69,7 @@ The list of packages (with their version) is defined in the extra_requirements.t * [18.0/extra_requirements.txt](18.0/extra_requirements.txt) * [19.0/extra_requirements.txt](19.0/extra_requirements.txt) -You can also see the Dockerfile that generated this image here: [common/Dockerfile-batteries](common/Dockerfile-batteries) +You can also see the Dockerfile that generated this image here: [common/Dockerfile-batteries](common/batteries.Dockerfile) ## Build @@ -182,6 +192,14 @@ and use `anthem` loader straight:: NOTE: `anthem > 0.11.0` is required. +### LOCAL_CODE_PATH + +Specifies path for local(custom) code to be used, by default is /odoo/local-src + +### MIGRATION_CONFIG_FILE + +Specifies path for migration config file, by default is /odoo/migration.yml + ### DEMO `DEMO` can be `True` or `False` and determines whether Odoo will load its Demo @@ -367,7 +385,7 @@ docker compose run --rm odoo dropdb testdb Pytest uses a plugin (https://github.com/camptocamp/pytest-odoo) that corrects the -Odoo namespaces (`openerp.addons`/`odoo.addons`) when running the tests. +Odoo namespaces (`odoo.addons`) when running the tests. ### pytest-cov diff --git a/bin/db.sh b/bin/db_cache_helpers.sh similarity index 100% rename from bin/db.sh rename to bin/db_cache_helpers.sh diff --git a/bin/docker-entrypoint.sh b/bin/docker-entrypoint.sh index f7dc8225..bd3bb0a9 100755 --- a/bin/docker-entrypoint.sh +++ b/bin/docker-entrypoint.sh @@ -1,40 +1,10 @@ #!/bin/bash set -e -# allow to customize the UID of the odoo user, -# so we can share the same than the host's. -# If no user id is set, we use 999 -USER_ID=${LOCAL_USER_ID:-999} - -echo "Starting with UID : $USER_ID" -id -u odoo &> /dev/null || useradd --shell /bin/bash -u $USER_ID -o -c "" -m odoo - -export PGHOST=${DB_HOST} -export PGPORT=${DB_PORT} -export PGUSER=${DB_USER} -export PGDATABASE=${DB_NAME} -export PGAPPNAME=${HOSTNAME} - -# As 'docker compose exec' does not launch the entrypoint -# init PG variable into .bashrc so it will be initialized -# when doing 'docker compose exec odoo gosu odoo bash' -touch /home/odoo/.bashrc -chown odoo:odoo /home/odoo/.bashrc -echo " -export PGHOST=${DB_HOST} -export PGPORT=${DB_PORT} -export PGUSER=${DB_USER} -export PGDATABASE=${DB_NAME} -export PGAPPNAME=${HOSTNAME} -" >> /home/odoo/.bashrc - -# Only set PGPASSWORD if there is no .pgpass file -if [ ! -f /home/odoo/.pgpass ]; then - export PGPASSWORD=${DB_PASSWORD} - echo " - export PGPASSWORD=${DB_PASSWORD} - " >> /home/odoo/.bashrc -fi +. env_postgres.sh +. env_odoo.sh + +echo "Starting with UID: $USER_ID" BASE_CMD=$(basename $1) CMD_ARRAY=($*) @@ -62,13 +32,13 @@ case "$(echo "${DEMO:-false}" | tr '[:upper:]' '[:lower:]')" in esac # Create configuration file from the template -TEMPLATES_DIR=/templates -CONFIG_TARGET=/etc/odoo.cfg -if [ -e $TEMPLATES_DIR/odoo.cfg.tmpl ]; then - dockerize -template $TEMPLATES_DIR/odoo.cfg.tmpl:$CONFIG_TARGET +DATA_DIR="$ODOO_BASE_PATH/data/odoo" +ODOO_RC_TMPL="/templates/odoo.cfg.tmpl" +if [ -e "$ODOO_RC_TMPL" ]; then + DATA_DIR=$DATA_DIR dockerize -template $ODOO_RC_TMPL:${ODOO_RC-$OPENERP_SERVER} fi -if [ ! -f "${CONFIG_TARGET}" ]; then - echo "Error: $TEMPLATES_DIR/odoo.cfg.tmpl is required" +if [ ! -f "${ODOO_RC-$OPENERP_SERVER}" ]; then + echo "Error: $ODOO_RC_TMPL is required" exit 1 fi @@ -101,16 +71,20 @@ fi # Wait until postgres is up wait_postgres.sh -mkdir -p /data/odoo/{addons,filestore,sessions} -if [ ! "$(stat -c '%U' /data/odoo)" = "odoo" ]; then - chown -R odoo: /data/odoo -fi -if [ ! "$(stat -c '%U' /var/log/odoo)" = "odoo" ]; then - chown -R odoo: /var/log/odoo +if [ $EUID -eq 0 ]; then + # Not for core image + mkdir -p $DATA_DIR/{addons,filestore,sessions} + if [ ! "$(stat -c '%U' $DATA_DIR)" = "odoo" ]; then + chown -R odoo: $DATA_DIR + fi + if [ ! "$(stat -c '%U' /var/log/odoo)" = "odoo" ]; then + chown -R odoo: /var/log/odoo + fi fi -if [ "$BASE_CMD" = "odoo" ] || [ "$BASE_CMD" = "odoo.py" ] || ([ "$BASE_CMD" = "gosu" ] && [[ "${ARGS[@]}" =~ "odoo migrate" ]] ); then - BEFORE_MIGRATE_ENTRYPOINT_DIR=/before-migrate-entrypoint.d +if [ "$BASE_CMD" = "odoo" ] || [ "$BASE_CMD" = "odoo.py" ] || [ "$BASE_CMD" = "migrate" ] || + ([ "$BASE_CMD" = "gosu" ] && [[ "${ARGS[@]}" =~ "odoo migrate" ]] ); then + BEFORE_MIGRATE_ENTRYPOINT_DIR=$ODOO_BASE_PATH/before-migrate-entrypoint.d if [ -d "$BEFORE_MIGRATE_ENTRYPOINT_DIR" ]; then run-parts --exit-on-error --verbose "$BEFORE_MIGRATE_ENTRYPOINT_DIR" fi @@ -121,17 +95,17 @@ if [ "$BASE_CMD" = "odoo" ] || [ "$BASE_CMD" = "odoo.py" ]; then if [[ ! " ${ARGS[@]} " =~ " --help " ]] && [[ ! " ${ARGS[@]:0:1} " =~ " shell " ]]; then if [ -z "$MIGRATE" -o "$MIGRATE" = True ]; then - gosu odoo migrate + run_as_odoo migrate fi fi - START_ENTRYPOINT_DIR=/start-entrypoint.d + START_ENTRYPOINT_DIR=$ODOO_BASE_PATH/start-entrypoint.d if [ -d "$START_ENTRYPOINT_DIR" ]; then run-parts --exit-on-error --verbose "$START_ENTRYPOINT_DIR" fi - exec gosu odoo "$@" + exec_as_odoo "$@" fi exec "$@" diff --git a/bin/env_postgres.sh b/bin/env_postgres.sh new file mode 100644 index 00000000..052b7593 --- /dev/null +++ b/bin/env_postgres.sh @@ -0,0 +1,12 @@ + +if [ ${DB_USER-} ]; then + export PGHOST=$DB_HOST + export PGPORT=$DB_PORT + export PGUSER=$DB_USER + export PGDATABASE=$DB_NAME + export PGAPPNAME=$HOSTNAME + # Only set PGPASSWORD if there is no .pgpass file + if [ ! -f ~/.pgpass ]; then + export PGPASSWORD=$DB_PASSWORD + fi +fi diff --git a/bin/lint b/bin/lint index bd5fd5c2..54ff3849 100755 --- a/bin/lint +++ b/bin/lint @@ -1,4 +1,4 @@ #!/bin/bash set -e -flake8 /odoo/local-src --exclude=__init__.py +flake8 ${LOCAL_CODE_PATH:=/odoo/local-src} --exclude=__init__.py diff --git a/bin/list_dependencies.py b/bin/list_dependencies.py index 1ee0da36..30e101e4 100755 --- a/bin/list_dependencies.py +++ b/bin/list_dependencies.py @@ -1,35 +1,40 @@ #!/usr/bin/env python3 -# Provide a list of module which are dependencies -# of local-src modules excluding local-src modules +# Provide a list of modules which are dependencies +# of local modules excluding local modules themselves # # Arguments: -# list of module (coma separated), restrict list of +# list of modules (coma separated), restrict list of # dependencies to the dependencies of this list. # # Usage: # ./odoo/bin/list_dependencies.py local_module1,local_module2 import ast import os +import pathlib import sys -BASE_DIR = os.getcwd() -LOCAL_SRC_DIR = os.path.join(BASE_DIR, "odoo", "local-src") +CWD = pathlib.Path.cwd() + +if path_from_env := os.getenv("LOCAL_CODE_PATH"): + LOCAL_CODE_PATH = CWD / path_from_env +else: + LOCAL_CODE_PATH = CWD / "odoo" / "local-src" dependencies = set() -local_modules = os.listdir(LOCAL_SRC_DIR) +local_modules = {mod.name for mod in LOCAL_CODE_PATH.iterdir()} + if len(sys.argv) > 1: modules = sys.argv[1].split(",") else: modules = local_modules -for mod in modules: + +for mod_name in modules: # read __manifest__ - manifest_path = os.path.join(LOCAL_SRC_DIR, mod, "__manifest__.py") - if not os.path.isfile(manifest_path): - continue - with open(manifest_path) as manifest: - data = ast.literal_eval(manifest.read()) - dependencies.update(data["depends"]) + manifest = LOCAL_CODE_PATH / mod_name / "__manifest__.py" + if manifest.is_file(): + data = ast.literal_eval(manifest.read_text()) + dependencies.update(data["depends"]) -# remove local-src from list of dependencies +# remove local modules from list of dependencies dependencies = dependencies.difference(local_modules) -print(",".join(dependencies) or "base") +print(",".join(sorted(dependencies)) or "base") diff --git a/bin/migrate b/bin/migrate index 3fe7666e..f2c16227 100755 --- a/bin/migrate +++ b/bin/migrate @@ -4,11 +4,9 @@ set -e if ! PGPASSWORD=$DB_PASSWORD psql -lqtA -h $DB_HOST -U $DB_USER | grep -q "^$DB_NAME|"; then PGPASSWORD=$DB_PASSWORD createdb -h $DB_HOST -U $DB_USER -O $DB_USER $DB_NAME fi - -CONFIGFILE=/odoo/migration.yml MARABUNTA_DB_HOST=$DB_HOST \ MARABUNTA_DATABASE=$DB_NAME \ MARABUNTA_DB_USER=$DB_USER \ MARABUNTA_DB_PASSWORD=$DB_PASSWORD \ MARABUNTA_DB_PORT=$DB_PORT \ -unbuffer marabunta --migration-file $CONFIGFILE +unbuffer marabunta --migration-file ${MIGRATION_CONFIG_FILE:=/odoo/migration.yml} diff --git a/bin/runmigration b/bin/runmigration index 59097624..5e8dd82c 100755 --- a/bin/runmigration +++ b/bin/runmigration @@ -32,14 +32,12 @@ # steps on top of it. set -e -source db.sh +. db_cache_helpers.sh +. env_odoo.sh wait_postgres.sh -CREATE_DB_CACHE=${CREATE_DB_CACHE:=false} -LOAD_DB_CACHE=${LOAD_DB_CACHE:=true} - -CACHE_DIR=${CACHE_DIR:=/tmp/cachedb} -DB_NAME=${DB_NAME:=odoo_mig} +# Set default values +: ${CREATE_DB_CACHE:=false} ${LOAD_DB_CACHE:=true} ${CACHE_DIR:=/tmp/cachedb} ${DB_NAME:=odoo_mig} VERSION=$(cat /odoo/VERSION) @@ -71,7 +69,7 @@ if [ "$LOAD_DB_CACHE" != "false" ]; then fi fi -gosu odoo migrate +run_as_odoo migrate DUMP="$CACHE_DIR/odoo_sample_$VERSION.dmp" diff --git a/bin/runtests b/bin/runtests index ad8cacc6..fa369702 100755 --- a/bin/runtests +++ b/bin/runtests @@ -1,6 +1,6 @@ #!/bin/bash # -# Run unit tests of local-src modules +# Run unit tests of local modules # # mainly used from Travis, # it creates a database, @@ -27,29 +27,32 @@ set -e # TODO: if we are not in TRAVIS, make a template then run tests on a copy -source db.sh +. db_cache_helpers.sh wait_postgres.sh -LOCAL_SRC_DIR=/odoo/local-src -ODOO_BIN_PATH=/odoo/src/odoo-bin + +LOCAL_CODE_PATH=${LOCAL_CODE_PATH:-/odoo/local-src} +ODOO_BIN_PATH=/odoo/src/odoo/odoo-bin # Core image layout +if [ ! -e "$ODOO_BIN_PATH" ]; then + ODOO_BIN_PATH=/odoo/src/odoo-bin +fi COVERAGE=$(command -v coverage || true) if [ -z $1 ]; then - LOCAL_ADDONS=$(find ${LOCAL_SRC_DIR}/* -maxdepth 0 -type d -and -not -name server_environment_files -printf "%f\n" | + LOCAL_ADDONS=$(find ${LOCAL_CODE_PATH}/* -maxdepth 0 -type d -and -not -name server_environment_files -printf "%f\n" | awk -vORS=, '{print $1}' | sed 's/,$/\n/') else LOCAL_ADDONS=$1 fi -CREATE_DB_CACHE=${CREATE_DB_CACHE:=false} -LOAD_DB_CACHE=${LOAD_DB_CACHE:=true} - -LOCAL_SRC_DIR=${LOCAL_SRC_DIR:=/odoo/local-src} -CACHE_DIR=${CACHE_DIR:=/tmp/cachedb} +ALL_DEPS_ADDONS=$(list_dependencies.py "$LOCAL_ADDONS") +# Ignore base_automation from dependencies to avoid its register hook +# messing with MRO of modules to be installed after server restart +DEPS_ADDONS=${ALL_DEPS_ADDONS/",base_automation,"/","} -DEPS_ADDONS=$(list_dependencies.py "$LOCAL_ADDONS") +# Set default values +: ${CREATE_DB_CACHE:=false} ${LOAD_DB_CACHE:=true} ${CACHE_DIR:=/tmp/cachedb} ${DB_NAME:=odoo_test} -DB_NAME=${DB_NAME:=odoo_test} if [[ ! -z "$SUBS_MD5" ]]; then DUMP="$CACHE_DIR/odoo_test_$SUBS_MD5.dmp" @@ -77,10 +80,10 @@ if [ "$DUMP_LOADED" = 0 ]; then db_save $DB_NAME $DUMP fi fi -echo "🔧🔧 Install local-src modules 🔧🔧" +echo "🔧🔧 Install local modules -- ${LOCAL_CODE_PATH} 🔧🔧" ODOO_PARAMS="--stop-after-init --workers=0 --database $DB_NAME --test-enable --log-level=test --log-handler=:INFO --db-filter=$DB_NAME -i ${LOCAL_ADDONS}" if [ -n "$COVERAGE" ]; then - "$COVERAGE" run --source="${LOCAL_SRC_DIR}" "${ODOO_BIN_PATH}" $ODOO_PARAMS + "$COVERAGE" run --source="${LOCAL_CODE_PATH}" "${ODOO_BIN_PATH}" $ODOO_PARAMS else echo "Skip Code Coverage - not available" odoo $ODOO_PARAMS diff --git a/bin/testdb-gen b/bin/testdb-gen index 881bc852..a68031c4 100755 --- a/bin/testdb-gen +++ b/bin/testdb-gen @@ -9,6 +9,8 @@ set -e +. env_odoo.sh + if psql -lqtA -h ${DB_HOST} | grep -q "^$DB_NAME|"; then echo "database ${DB_NAME} already exists" exit 1 @@ -16,5 +18,5 @@ fi echo "creating database ${DB_NAME}" createdb -h ${DB_HOST} -O ${DB_USER} ${DB_NAME} -gosu odoo odoo --stop-after-init --workers=0 --log-level=warn "$@" +run_as_odoo odoo --stop-after-init --workers=0 --log-level=warn "$@" echo "done" diff --git a/bin/testdb-update b/bin/testdb-update index 434103cf..5f96c7c4 100755 --- a/bin/testdb-update +++ b/bin/testdb-update @@ -9,11 +9,13 @@ set -e +. env_odoo.sh + if ! psql -lqtA -h ${DB_HOST} | grep -q "^$DB_NAME|"; then echo "database ${DB_NAME} does not exist" exit 1 fi echo "updating database ${DB_NAME}" -gosu odoo odoo --stop-after-init --workers=0 --log-level=warn "$@" +run_as_odoo odoo --stop-after-init --workers=0 --log-level=warn "$@" echo "done" diff --git a/build.sh b/build.sh index 22905166..17b4f266 100755 --- a/build.sh +++ b/build.sh @@ -49,4 +49,4 @@ docker build --progress plain --no-cache \ -f ${TMP}/Dockerfile -t ${BUILD_TAG} ${TMP} docker build --progress plain --no-cache \ --build-context odoo=docker-image://${BUILD_TAG} \ - -f ${TMP}/Dockerfile-batteries -t ${BUILD_TAG}-batteries ${TMP} + -f ${TMP}/batteries.Dockerfile -t ${BUILD_TAG}-batteries ${TMP} diff --git a/common/Dockerfile b/common/Dockerfile index 22a7082f..497e5920 100644 --- a/common/Dockerfile +++ b/common/Dockerfile @@ -7,8 +7,8 @@ ARG VERSION=19.0 # create the working directory and a place to set the logs (if wanted) RUN mkdir -p /odoo /var/log/odoo -COPY ./base_requirements.txt ./platform_requirements.txt ./test_requirements.txt /odoo/ COPY ./install /install +COPY ./*_requirements.txt /odoo/ # Moved because there was a bug while installing `odoo-autodiscover`. There is # an accent in the contributor name @@ -54,12 +54,16 @@ RUN /install/package_odoo.sh \ # wait on postgres RUN /install/gosu.sh && /install/dockerize.sh -COPY ./src_requirements.txt /odoo COPY ./bin /odoo-bin COPY ./templates /templates COPY ./before-migrate-entrypoint.d /before-migrate-entrypoint.d COPY ./start-entrypoint.d /start-entrypoint.d COPY ./MANIFEST.in /odoo +COPY --chmod=644 ./env_odoo.sh /odoo-bin/ +# Init PG variables during Shell initialization so it will be available +# when doing 'docker compose exec odoo gosu odoo bash' +RUN set -x; echo >> /etc/bash.bashrc \ + "if [ -f /odoo-bin/env_postgres.sh ]; then . /odoo-bin/env_postgres.sh; fi" ENV ODOO_VERSION=$VERSION \ PATH=/odoo-bin:$PATH \ diff --git a/common/Dockerfile-batteries b/common/batteries.Dockerfile similarity index 81% rename from common/Dockerfile-batteries rename to common/batteries.Dockerfile index b4505fb9..66eb3936 100644 --- a/common/Dockerfile-batteries +++ b/common/batteries.Dockerfile @@ -1,3 +1,4 @@ +# hadolint ignore=DL3006 # Use `docker build --build-context ...` FROM odoo LABEL maintainer="Camptocamp" diff --git a/common/core.Dockerfile b/common/core.Dockerfile new file mode 100644 index 00000000..ca091d84 --- /dev/null +++ b/common/core.Dockerfile @@ -0,0 +1,112 @@ +# hadolint ignore=DL3006 # Use `docker build --build-context ...` +FROM python +LABEL maintainer="Camptocamp" + +ARG VERSION=19.0 +ARG UID=999 +ARG GID=999 + +# create the working directory and a place to set the logs (if wanted) +RUN groupadd -g $GID odoo \ + && adduser --disabled-password --no-create-home --gecos '' \ + --home /odoo --uid $UID --gid $GID odoo \ + && install -m 770 -o odoo -d /templates /var/log/odoo \ + /odoo /odoo/.venv /odoo/src \ + /odoo/data \ + /odoo/data/odoo \ + /odoo/data/odoo/addons \ + /odoo/data/odoo/filestore \ + /odoo/data/odoo/sessions \ + /odoo/odoo-bin \ + /odoo/before-migrate-entrypoint.d \ + /odoo/start-entrypoint.d \ + && install -m 660 -o odoo /dev/null /odoo/odoo.cfg \ + && install -m 660 -o odoo /dev/null /odoo/.bashrc + +COPY --chown=odoo:root --chmod=770 ./install /install +COPY --chown=odoo:root --chmod=660 ./*_requirements.txt /odoo + +# Moved because there was a bug while installing `odoo-autodiscover`. There is +# an accent in the contributor name +ENV LANG=C.UTF-8 \ + LC_ALL=C.UTF-8 \ + PATH=/odoo/.venv/bin:$PATH \ + PYTHONPATH=/odoo/ + +# build and dev packages +ENV BUILD_PACKAGE="\ + build-essential \ + gcc \ + libevent-dev \ + libfreetype6-dev \ + libxml2-dev \ + libxslt1-dev \ + libsasl2-dev \ + libldap2-dev \ + libssl-dev \ + libjpeg-dev \ + libpng-dev \ + zlib1g-dev \ + libcairo2-dev" + + +# Default SHELL is ["/bin/sh", "-c"] +SHELL ["/bin/sh", "-e", "-x", "-c"] + + +# Install some deps, lessc and less-plugin-clean-css, and wkhtmltopdf +RUN /install/package_odoo.sh core \ + && /install/setup-pip.sh \ + && /install/postgres.sh \ + && /install/kwkhtml_client.sh \ + && /install/kwkhtml_client_force_python3.sh \ + && /install/dev_package.sh \ + && su odoo -c "umask 007 \ + && python3 -m venv /odoo/.venv --system-site-packages \ + && /odoo/.venv/bin/pip install -r /odoo/base_requirements.txt \ + -r /odoo/extra_requirements.txt \ + -r /odoo/test_requirements.txt" \ + && chgrp -R root /odoo/.venv \ + # Grab dockerize to generate template and wait on postgres + && /install/dockerize.sh \ + # Purge build packages, to reduce layer size + && /install/purge_dev_package_and_cache.sh + +COPY --chown=odoo:root --chmod=770 ./bin /odoo/odoo-bin +COPY --chown=odoo:root --chmod=660 ./templates /templates +COPY --chown=odoo:root --chmod=770 ./before-migrate-entrypoint.d /odoo/before-migrate-entrypoint.d +COPY --chown=odoo:root --chmod=770 ./start-entrypoint.d /odoo/start-entrypoint.d +COPY --chown=odoo:root --chmod=660 ./MANIFEST.in /odoo +COPY --chmod=644 ./env_odoo-core.sh /odoo/odoo-bin/env_odoo.sh +# Init PG variables during Shell initialization so it will be available +# when doing 'docker compose exec odoo bash' +RUN set -x; echo >> /etc/bash.bashrc \ + "if [ -f /odoo-bin/env_postgres.sh ]; then . /odoo-bin/env_postgres.sh; fi" + + +USER odoo +RUN echo "export PATH=$PATH" >> ~/.bashrc + +ENV ODOO_VERSION=$VERSION \ + PATH=/odoo/odoo-bin:/odoo/.local/bin:$PATH \ + OPENBLAS_NUM_THREADS=1 \ + DB_HOST=db \ + DB_PORT=5432 \ + DB_NAME=odoodb \ + DB_USER=odoo \ + DB_PASSWORD=odoo \ + DEMO=False \ + ODOO_BASE_URL=http://localhost:8069 \ + ODOO_REPORT_URL=http://localhost:8069 \ + # the place where you put the data of your project (csv, ...) + ODOO_DATA_PATH=/odoo/data \ + LOCAL_CODE_PATH=/odoo/odoo/addons \ + ADDONS_PATH=/odoo/odoo/addons,/odoo/odoo/src/odoo/addons \ + MIGRATION_CONFIG_FILE=/odoo/migration.yml \ + ODOO_RC=/odoo/odoo.cfg + +VOLUME ["/data/odoo", "/var/log/odoo"] +EXPOSE 8069 8072 + +ENTRYPOINT ["docker-entrypoint.sh"] +CMD ["odoo"] diff --git a/common/env_odoo-core.sh b/common/env_odoo-core.sh new file mode 100755 index 00000000..5a4d3d6f --- /dev/null +++ b/common/env_odoo-core.sh @@ -0,0 +1,8 @@ + +ODOO_BASE_PATH="/odoo" +USER_ID=$EUID + +[ $USER_ID -eq 0 ] && { echo "Cannot run as root"; exit 1; } + +run_as_odoo () { "$@"; } +exec_as_odoo () { exec "$@"; } diff --git a/common/env_odoo.sh b/common/env_odoo.sh new file mode 100755 index 00000000..71408267 --- /dev/null +++ b/common/env_odoo.sh @@ -0,0 +1,11 @@ + +ODOO_BASE_PATH="" + +# allow to customize the UID of the odoo user, +# so we can share the same than the host's. +# If no user id is set, we use 999 +USER_ID=${LOCAL_USER_ID:-999} +id -u odoo &> /dev/null || useradd --shell /bin/bash -u $USER_ID -o -c "" -m odoo + +run_as_odoo () { gosu odoo "$@"; } +exec_as_odoo () { exec gosu odoo "$@"; } diff --git a/example-core/Dockerfile b/example-core/Dockerfile new file mode 100644 index 00000000..311fc2d6 --- /dev/null +++ b/example-core/Dockerfile @@ -0,0 +1,41 @@ +FROM ghcr.io/camptocamp/docker-odoo-project:16.0-master-latest +LABEL maintainer="Camptocamp" + + +# For installing odoo you have two possibility +# 1. either adding the whole root directory +#COPY . /odoo + +# 2. or adding each directory, this solution will reduce the build and download +# time of the image on the server (layers are reused) +RUN mkdir -p /odoo/src/odoo +COPY ./odoo/src/odoo /odoo/src/odoo +COPY ./odoo/addons /odoo/odoo/addons +COPY ./data /odoo/data +COPY ./songs /odoo/songs +COPY ./setup.py /odoo/ +COPY ./VERSION /odoo/ +COPY ./migration.yml /odoo/ +USER root +# RUN apt-get update \ +# && apt-get install -y --no-install-recommends parallel libsasl2-dev libldap2-dev libssl-dev libmagic1 libpq-dev build-essential python3-dev libffi-dev pkg-config libcairo2-dev libgirepository1.0-dev\ +# && apt-get clean \ +# && rm -rf /var/lib/apt/lists/* + +# RUN set -x; \ +# apt-get update \ +# && apt-get install -y --no-install-recommends \ +# python3-shapely \ +# && apt-get clean \ +# && rm -rf /var/lib/apt/lists/* + +COPY ./requirements.txt /odoo/ +USER odoo +WORKDIR /odoo +# run in a virtualenv +RUN /odoo/.venv/bin/pip install -r requirements.txt \ + && /odoo/.venv/bin/pip install -e /odoo/src/odoo + +# Project's specifics packages + +ENV ADDONS_PATH=/odoo/odoo/addons,/odoo/src/odoo/addons diff --git a/example-core/README.md b/example-core/README.md new file mode 100644 index 00000000..7b6781d8 --- /dev/null +++ b/example-core/README.md @@ -0,0 +1,37 @@ +# Odoo Project Example + +The base images does nothing alone, it only contains the dependencies and a few +tools, but you need to create an inheriting image with the odoo and addons +code. + +Follow the steps: + +1. Create directories. This is mandatory, they will be copied in the image + + mkdir -p odoo/addons data songs + +2. Add a submodule for Odoo (official or OCA/OCB) + + git submodule init + git submodule add git@github.com:odoo/odoo.git odoo/src + +3. Optionally add submodules for external addons in `odoo/external-src` + + git submodule add git@github.com:OCA/server-tools.git odoo/external-src/server-tools + +4. Optionally add custom addons in `odoo/addons` + +6. Create the Dockerfile, the bare minimum being (see also [the example + file](Dockerfile) that installs additional dependencies): + + FROM camptocamp/odoo-project:11.0 + LABEL maintainer="" + + ENV ADDONS_PATH=/odoo/odoo/addons,/odoo/external-src/server-tools,/odoo/src/odoo/addons + +7. Build your image + + docker build -t youruser/odoo-project-example . + +8. Optionally create a [docker-compose.yml](docker-compose.yml) file. This + example is a development composition. diff --git a/example-core/data/images/logo.png b/example-core/data/images/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..cefdea6fb2d599d8f23874e07cb6b9852ba2c236 GIT binary patch literal 21601 zcmV({K+?a7P)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{03ZNKL_t(|+GKr8uWn0nRAg4I zecf%0EZ)Wjgl$M&ej>J!4j`$Hs2=N-h3<=co#4j){+qm1^efO%$ zWRMYAwJ+T|y65co{;F1HWMpKd{qeu}m-+ndzXSXJ_pyKTw~;^oDdw;L8vL*SRoM4` z4(kWMhxu#20&D|*w(;%1{{hBt{AJkqfc=^8!+-7r@y8qX4CIdza{*_kXzYcmKgR z_`wer{>ra?;6MGxpW=^x41^iNfbai;BP{WwpCx|uv%oL?6~`a`6o`@dC;#Ys_%HwC z6XScpKmW%+k1*heKMDNrp9KERfBz}|!~_5A@BKV}=}!;*Bm+MV;P-dnZ~fxLpZ#$B za04Hn_}{Vdz2SHU@NYlA#lQRZr}(Ge|33brJO11IC-`sgALF;*ayKJg6_f8HPbZu}6xF@F(1&7UCgEq-VJFZ{Cq0)FlJi};Q4%lN_3_v7!}uY7cmEECIsVhP{{jE_`~L{P>c5K5{1(5re+$30e-nRW z{!KX2U^xHF1ac>^H|jlxjI2KZ(j68+?tn!iGl2-?=Ev-~z8H{5*ap8xA_K?(umSA) znh^;EkeSF`@6WXQcht`SOYkRvxxokE(~x?%JIw2SW_7XZk6{jjJK!+P0hj?kvc87% zeV)jy&vgJRfE9+!K-RZ_Tm6iYK&JQaXfQ-3b|!ZHgh(@F^7GDb4A)#8Z5wXW_2louTTOOsOXS&pa_TQSLWv<_;p})!vcuSOOOc*>x-d3hC2Km z^&)1Xeh4$b6Jyrly4UfT0dC2E^TqUfv7Nsf^mnfp)`!78`r-t5H~Hq*1 z5|PmtfL9To1DU%nXO$DgFE21QFH43ZQlGNpNUa-u>PCdDRd15*vWB`%bKbK{_Pz-AIxr$8C1?KO`urL@IoWJLQ zVd%*QFwEeL21EBAfLUUu-UAroTmc<^0)c>=BQ0T8(X>ux0htJ^kM+caB@Z4GNZzX8 zJvXmkFiiKMo?0FZ(&}^4>adn|=&8q%h$uu+&2W_j*~3hhFKT{@szoD*W5vrLejrW_+I+B7hwg{v)#v#vR7r0StPXK$;

kJM~hD6iW-;HNRb zdv1S*Fa|?=W_`})k0-F1i3rrkF$kP+pB3UqBHik#^+Nil6yWtk6v(SXhZ)8I%p7Kc zF|4A%I5@$KpecEXymW4+^xZ#8UO+%8BO-4M-2V%uG$bt1pwG?Wsk~o@Rq22io!_@Z zz6l%fbvE?(???k(25an=2t;mz+C(LUT^Ar@GPe(4J2D5b4Y|R~P(L&>k?!@%EUWh= zbA31}y;!9b3_js})fldF=ea1>MI(Rr!UXP>D_ww)Suh#8b%`<)=Q(R^UoXB@1Td?LK#05^T ztPab;))wB&#JHkMiNz?fd?gAt{kXo0IL8wWw)&U5s7vNwR0sXD2^VMlj;+=&ee z@xkn-(ohI$@awoDlJdC~KKPn`^crnG+j%emPMKd1T)ihVDgszO_2cA3Vj^=QZ7@fp zz@h#wAQ;ZlFN+IM-M;Or+pVIAss$pQ*!cw!3+zQ2(hiEvz8L7Drmy{A`NtX3!>fhq&t&l#Q~ivccqiTlWLB@iR{B7m$|d&)h> zl^R$MD)eU^xbvbrzust|tvExx&BT=%EI_NmP|%OQ1eITB;sc4vJ2!zCFq^Dt#0ym3 zwgAj05Z*5gFo0cQu24Pkgl=3`epjfBRk_`Q|INY<0(&X69~TZ#`Xu)PH~6$V23&b#WwOT=5=4~%F!VJ z$TW}uyois&G6c>Og=rM{JPn(dQ_-V9(4t7eoMc_y(6q_{VQkA>wGHf&k$c$nFljvF@U%6j^ zkRcSTSe-m-Iuis7Y9A~KNe0!&70?@_(g48n(5euxk2@F4T;$UU_(dc+!Vk?$qMK=; zUg}6j0~BFa;EwNOpq^=PtEf4c$KCRRIEu;o_o)cFJY*VcJ{XCe`#@5QCe)m~ge5sb z5Q`x2m!%fsqc&C?*_LE)Mt?Pzm)SvM5znfv2B? zT|u4TFLGfQ26&)ggd9LjSPlX@hvjUWEoiL0tf63z^0K2L^FT&Ylw@t4*l+l9QCuzQBQ|WU?v&EVepYG zCkZT>H&y!&zZx&fj*J2!9>5fEtxH8iVk9bUz^l7yK@y07(9{5`xRC}-I2LJKw}YXK zH_opX(_vXxr6E-W7O*5|P-R^;f=CJnHfG`*0Fy!I0rKJD4PLAP3$IdK<|*?Q-~1Q5GeFV*$ICQ^`9iLJLsRS9;YMezL<0rcb(vN(`J?+X2=o@$=JC%HEV zd=w=(hGDa_Xd^J(yFhn~F7uLyIlK^i9k!p+izQmHEK5^2kT=%E1KbT7V=*Iey7}}M z`p>jt`&i$5R}|6FV%SB^^W(ND99PX>RCIoaClHsh5LlRo4_NmDMghQl2m(ia!5H;K z!2qiZ(j7u^0s+|aX8)3T2Vo}#5ZUjgDxgZm&A+F@y(rkID6r#%W037jKbIf~#@wyS zK)%#!^7th8;D#~k(8nxfZC-8GB7ma1hQb`iuQo>I<`a3dF99qWUhN`c4^!jKDpqQ7 zBy;{@`J6onCx)mnpKw0G>IZ-aI#C#)L0uO6x0RJMsv?46VBi#g8yoxL0q}uHK34ev z`Ar3`6uK`)&oDZV1Jw_xDu4iyv@Lk%Xw;i^fG|Gg!~yE}@465fiM@pf>icg-jlC|K z*ArkX7_KLfxt%W}Y0K{W&skVtK87)k9DrfYB9DBc2zHP*9_*iY7qWB&E{4!94%RA4 zY*qkZis)--6;bYka$y6;T}QwZos6q0bqtL9oz!5`@5DB8UM+g{`;Am@G!vMBd8HPT zL#hTc12gS`#o$2?KH-)3tuFw}y=3gw!KX1j6du5;NT9B+@yU+_MhfT!c2xcgULKWt zn}=;9VD8v)(ncnTz}X+~?sZYSW^$4m z65iDdaBtA4=3IsU-E^?SKbrncJQeOSI_xK$#LrC^8~-hYZmj2Z`|U#W)%go{hj&Ol z!-&8tU@_ds=AY2}9a|)k)i0l3aW%>7r`1JpbLv{W$xxs5)MEg1IOY_80L-UE0%Nje zY)(udYBi)~!5D$be!-U%&{~-6r#?CfSo8JjDYQrfD)$tslg*%PEHG6OT-64yGO)k0 z4mEd`cUhdk=@ok8lB#eR0k8`LWH_Sr03U_)1H=Gml@B&MgoZ->A!uA7J0g%#J#l9j zF)|Um!g8?Dvo{C|lNX>$z_o$36TX2l6N}L!w`2zncp{uEAj$EtWIkj)@7W!@DghIo ziSZc5Lz;LPhF3=r?nM9DUBR%Zw8PNuqu9G-TRJJSfC>CL$yQu__!H`-g$Ra!XMP_T z%=;HH)Xk#oIN~5^RoggE=TDblCozmARwh0uWGNI8WM+#1QpaGXjVkq23Pv@AGK!$F z9EJAN8D9L7dDW!|qSI8WU=Lkw+`WqH4~Xz7!eoabHn3J=1;OB|tb>o@0XCyWsmjVCA2kR9D@8bIZo8iLL{!+nDuhZgMKUehm~bBSZe^2`H4MCP zMgXwa;fCjuA52IeU_qeA+)hO(>p%jKILa5vqhd?-b1uOSGzVRUN;f*;AlK>5Nw1~({6N|h=B!>vPb=P9^q*0t{7YIZHyg_Y1T*_gyILfN4-3&fd zVNt0lts;xsBF27TRuL+KE2|12%1==dS(jk%)7k5$5QCb?oGfHltRaC=@JS$Zn5d^( zDWCx$`2ZO3MwNLh0&f7m>xBuXg{{g${ck?i>8Bf)gR-@8xB``QP7F}MuP%i81U4ly zb@g7m(X*-CNz_G}%+;#3!9zqI5@_>*h&+-Jm0-pWos*ZJEE%21L4DMbXgb(Q>zj#* z6^8Kd$WnqdZ^fdp)#+gve*(*vgH)NjF<~tKa*)3d7#uqiz6n>+QJi+vBfL?R zqf)?1vQ?P~GwgloMzW&7$~s(xVJ)K5tiO-VND>rflr9BuhGimk^X&4_IIm#Tz>5V` z==Wd~X&Q2nA9xHo4K}m8hM-tf4W6{h`P1u(6bOW&nLZtSGHp~di~?ZR{kJ^K5eMi= z(UXZG=FZqIZW5^CthFw(N=96Qlig~cpxXLGo|cg3?oy)I$&J~uG^MW+7!1TZWX%Az ze4`Gy6+Dvq?;=B1oD!~N)rloaHw`O`7|O6h{9a{XPGIfA1K4>;puo`tv_8IS`*cTI z@UYovk;GeqPhOUh^=i*~4Ta33BN#&p;)J_*pG(iz7_-D*p&E ztbg&i6fU8fxO?8-b#Lqn(TFTEWS1`P{yJ+HQL-`$=n37g!~*c{3b!wScPGn2U@`nl zWu_-PH1#vAG?^jqW(rghT<@=Xze>V$sB8ue!{e74Na9no)2K>2 zeLzD)!%7pY^RDqJY*{#p7*k(gXQz-j2gi0)TCJ zfdVpdCLLTJO&(OglgP0GaaEcHL7HLJ$N_d#gxLJNZLIGJ1UGZ*%B(byi8lxqrSgp8=`suB!tXPxtAUX0~nRstqlwgd~E6vSh9+l zuxzGK+(c$#ZqM#JA5Ob+nsZ{Tz?)I@kX@Q-G+?8W^frdaujH7=~@eF+^)*p3+l|BbAk2Pjdl2DxZ$wFp@vc+DoDkMF5FL z(+UEaB7n37WF0kO)XgA6=?X8b(E5Ng9gA_zyX7_cGT8l716@_X!$A+fB;#lNjD3D} zTbp~V%b?*;=@qjh#z_HUDHCsDfXxzZ^FTL@%$#a*<`)u(n+L8-p$V^7^?jmC!7UJ& zCHPPUkZ`PB8A`0+#sQK$dv>%jf-nXAsC`sjIJJJx{OzMiqcJ57&qDiB0*wGh^1w?G zB>lhU0#pvFL1db5R0L=;fVsQ5nz$x(NmH9Buwch-Qvh*Fa}OEQ4A`_cjlUlw)XBr%qluFNk?T+NnMz6~TJg|!56oAGcf0<1F@ zP;blPr~4A2FhCfwgFY_}dq+PLxgNp%O)eitQ-$<0#p=(K+vus zy}BgVpp+XAUwQ$T+Wj25pFTtnXy(NST9w0RS~yR;8l;yq>o?^g*Hq9EbC?Eb6WCb1 zjJumUfFn&k{y0K}tgfU6P6Mkuf(1-BJe2n%dC*D$Iuw?6959Row)4X9$z3QwxU#_B zn@kH?m+Lb`1d;H`iZ*ZPLR1ByXtMCned@`d z+UZ>dyeULnsbxiWj!$PK-~eWQO%X)sYCzq*B9aIs?EpRSKm&jc$9TNB0I1w!$t3yM z)Y}1jt|y*j=EjtP0py5F8+dev_Y6R_cR75bLM+w$&jx8`^(t)Y@JtZ9If7H$3&~r8 zIzd($nLQd7B%{>c$y8q;*p$PU;n38~0V6;Ur&>WrUtR~WQ6=4S<#{T3tO%QgQ(JDl zAlcKfD+LU*)4(>ec1XMzw%Ar!fit6g+7(gk=mI3Q)@6%J7CBCH$ox9kaYo3K;d;zd z|J$HA2&X`V+=8|6B*-sFhLb1%yL|zE(1B-sp@B`^OLFKM9BW$Gqz%|oAN0^j z%@3HyY)929C;Fd|%|V0pTM z;6<=&c5o0gNZ46G?o2R&Ak(ZWtkUIO)7jmRFfujhF|$Nqu11jpZ%I&S-LUwiv`bHE zrwCXRBf-hoZB+$`ABT}TmR{9S#E)4ufq3C0cvy+%xdYjDGZA+B;5AssGOkjP$Q?Oi zNQB`t+c89w!$l+4h49QTD&rb3^-43KR9xj{ScmxL3D`oDUrqx(@$tNW-)1qXp8Cy# zdcUL=;LIDi#^BWZCr7Zar~Wj9<442E&#Q9aWbA9e%6i|jLkBOFcc>TsWt+GtVpR;;mw_`T6#+;=uOus`!|u^< zPW{d^C|WYcstN=EOF~vBV3Tt2X|U%IM3Ov$10$_{G5!1S0@)#77EL^q48~o7Jsob< z=dC`*VdP5jD?}x3;pBbq5i$Zj_6L%aK$fDy7b}KfBS{ybK3}#ll93t$b2Hxv@xN)E zvlnmhiZd%(PcexcfK@}m4~6zODLb@ks=S$<1~3e7ta^K#YNOP&tT@zN6AEXQq9@KD zYpa+Xl^UwCW9<;4Bsk`gkQdNn|6ikGN#z?;fcOJA2QtX~4Z4HWzxlJ|8OksY!5GCZ zhP+g~RODvDb5raYNAsUS5lf{A=aZWkj!;V26oSb!;GQ=KIdj-?JOQ}_sCOWp0Du1Z zawxJ6+3{w5i^Xr?aJqAOu9n)Zpgf0Tde*EwVq~drFzS0Q(@Bfyl+LW6e7jB(g7nw5y2r88|>v zngjD)y?_m`L$bgUaYF<;koeqrm49`B%XS~U1QN?C0(=s%?W_Y|Wjlx+6?#`Dwp(@n z6!;RSy12}j04a*>%<{2ckKwSfs=q(=6e~>E!N~^3Lc^q*6v|2=FofrknagZ~^l~Bo zYs{Oe%~ZPC;nnY1{XXbqGsx5#)ZA3rNp%-c6mbSMDTh8T6(S+%Q5OI5y>Tx z9fTiBc*W@@l%go`xk>r@nZ8xVoD^`3dAe{Q)$2pNJ)eH3a;O^WJsKvDq2d!Lv3B64 z?|_~xi2b84kO|n?U=t=UG=6+?6ak#1m-zjpU~}~0s{jU>l{}&k4z@PpC$H~t1l}Gr zukpj(9x*bqvdgB*WcKOfbO1Ri;0d;a;Y9w?EZ@sdR!g!~uVMf>y_;Ut@TM$!A^YPu z2Rc``iP;_WqPfw0@5t)x8ZUR3KG=c!jy>OO>n-L{A z5JfK`nJmd^%tbg!ipHM3_*6AktaX2A-Jh!Ofq;f7UDA!*U!sUnR$5TRX$*l@_z2a< zcVwq&hhAgf8ptECJF<|-0xZmJp=44|g^b;L|IdKg{R0F&=}xatbZMXu6&0 zbOOYYz{^ILO}_A?gXJtzDWLRtHp;olRXXWK3{t>qsItVUlc1)iVXo z9R6(J;WW_56aHtm|0RY@7C9k2D*_D(MJ9RqQAUc4-|5M(jeudEO*>SA*Qc{#(=rJJKwAQl@Xnnw*Xh?<>OJ5|Dw69JA5YxC}$ z2Z#a854Ln42}E{r0wX$wYe>)l03ZNKL_t)yZ_N+5Lc0SaT3erN03m`CLKK2p!p6V` zOGTrRgn4}(g0~WU#?j>2<`ZAQEHuNIK>$hM$C2#P3vPhrTwaGKb`WRu;0v~>%l6jw z$RiC`=znY;-QhK$Y9`tlJ!D$LepG(HNWAHIJ3M<=0xzXs`q6rGg9IdnNDRpiyEhr+>SrN+|C+3i+O+f)V*20AuH{aZBaC?L=kcI z!a;^`qf|d_pr{nkFQWBRBI$SLSsamk@-k-g_pT>*dP%tF@eA@<6YbUAWB+>?2_gCj z5A@t!k^zJar05vtGMY*|6@UgaXyIm#c0Pd}iEj%#BC?N*XccJz3eKZXOSXBWYh*6WhHrwmE!v9Pf zN$aYgP`=p{kUbm%Z7mD>0Cq*dunE$wDMxOL?x7kzgJ2rxjuw4fHjPJ#o0S3*tD*uu ziChgDbu;s7_YxFFQXQ<8aXDm_Z(x?6fL$|*(kZt0K;wzvZ zO1vZ!bKD`{`fF(%-23_6Sn300wprv%>-mFjE?xdZRc2PzqVcnmoF!a#Y;xfW5+Bm( ztxcIW+rleoHty;S%9qcYzu#Am*SvuyR+N(^#+2Yflj$*z!<@0aOV;6d}cb=kA})xy+*&KqY`U7f0A3cQ=@_0c=UqXYlFWd4OFw zL**AWP+fp`pLEe;W~0d?>DzU!Pzg@%ZZE4>0)hHf_Qtg|siK4yGbArhN&)0&g2#Iu2O+goxw9@?PSU&&D}g~Pm8s}p z1=@O*#x=@KdqaUfMG_m;(VO(P`}bL1BiXj~V^3|BNVMkoQ#+DbOn z-t6HI86A4IVR8pLO$Fm<0OXPξ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 literal 0 HcmV?d00001 diff --git a/example-core/docker-compose.yml b/example-core/docker-compose.yml new file mode 100644 index 00000000..4a58a1a0 --- /dev/null +++ b/example-core/docker-compose.yml @@ -0,0 +1,51 @@ +# Composition for development + +services: + odoo: + tty: true + stdin_open: true + build: ./odoo + ports: + - 8069 + depends_on: + - db + volumes: + - "data-odoo:/data/odoo" + - "data-odoo-pytest-cache:/odoo/.cache" + # to speed build of image customise your .dockerignore (this is an help there) + - "./odoo/src/odoo:/odoo/src/odoo/odoo" + - "./odoo/src/addons:/odoo/src/odoo/addons" + environment: + - DB_USER=odoo + - DB_PASS=odoo + - DB_NAME=odoodb + - ADMIN_PASSWD=# set me + - RUNNING_ENV=dev + - LOG_HANDLER=:WARN + - LOCAL_CODE_PATH=/odoo/odoo/addons + - MARABUNTA_MODE=demo # could be 'full' for the db with all the data + - MARABUNTA_ALLOW_SERIE=True # should not be set in production + + db: + image: postgres:9.6 + ports: + - 5432 + environment: + - POSTGRES_USER=odoo + - POSTGRES_PASSWORD=odoo + volumes: + - "data-db:/var/lib/postgresql/data" + + # can be useful for dev when longpolling is required + nginx: + image: camptocamp/odoo-nginx:11.0-1.3.0 + ports: + - 80:80 + depends_on: + - odoo + +volumes: + data-odoo: + data-db: + # store pytest cache, allowing to use --lf or --ff (replay last or first failures) + data-odoo-pytest-cache: diff --git a/example-core/migration.yml b/example-core/migration.yml new file mode 100644 index 00000000..059a962d --- /dev/null +++ b/example-core/migration.yml @@ -0,0 +1,11 @@ +migration: + options: + install_command: odoo + versions: + - version: setup + operations: + pre: + - "sh -c 'psql -c \"CREATE EXTENSION pg_trgm;\"'" + addons: + upgrade: + - sale diff --git a/example-core/odoo/.dockerignore b/example-core/odoo/.dockerignore new file mode 100644 index 00000000..85594c27 --- /dev/null +++ b/example-core/odoo/.dockerignore @@ -0,0 +1,14 @@ +**/.git/**/* +**/.git +**/.gitignore +**/.travis.yml +**/LICENSE +**/*.pyc +**/README.md + +# for speeding build of image in dev, you can build a light image +# without all odoo code source by ignoring the following directory +# just uncomment following lines +# local-src/**/* +# external-src/**/* +# src/addons diff --git a/example-core/odoo/VERSION b/example-core/odoo/VERSION new file mode 100644 index 00000000..946789e6 --- /dev/null +++ b/example-core/odoo/VERSION @@ -0,0 +1 @@ +16.0.0 diff --git a/example-core/odoo/addons/README.md b/example-core/odoo/addons/README.md new file mode 100644 index 00000000..5203d41c --- /dev/null +++ b/example-core/odoo/addons/README.md @@ -0,0 +1 @@ +Here you should have your local addons, committed in this repository. diff --git a/example-core/odoo/addons/dummy_test/__init__.py b/example-core/odoo/addons/dummy_test/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/example-core/odoo/addons/dummy_test/__manifest__.py b/example-core/odoo/addons/dummy_test/__manifest__.py new file mode 100644 index 00000000..b1ec78db --- /dev/null +++ b/example-core/odoo/addons/dummy_test/__manifest__.py @@ -0,0 +1,12 @@ +{'name': 'Dummy Test', + 'description': "Dummy module to check that Travis runs tests. ", + 'version': '1.0', + 'author': 'Camptocamp', + 'license': 'AGPL-3', + 'category': 'Others', + 'depends': ['base', + ], + 'website': 'http://www.camptocamp.com', + 'data': [], + 'installable': True, + } diff --git a/example-core/odoo/addons/dummy_test/tests/__init__.py b/example-core/odoo/addons/dummy_test/tests/__init__.py new file mode 100644 index 00000000..9eb66b83 --- /dev/null +++ b/example-core/odoo/addons/dummy_test/tests/__init__.py @@ -0,0 +1 @@ +from . import test_dummy diff --git a/example-core/odoo/addons/dummy_test/tests/test_dummy.py b/example-core/odoo/addons/dummy_test/tests/test_dummy.py new file mode 100644 index 00000000..56dad3b9 --- /dev/null +++ b/example-core/odoo/addons/dummy_test/tests/test_dummy.py @@ -0,0 +1,8 @@ +import unittest + + +class TestDummy(unittest.TestCase): + + def test_dummy(self): + """ Dummy test to verify that tests run """ + self.assertTrue(True) diff --git a/example-core/odoo/setup.py b/example-core/odoo/setup.py new file mode 100644 index 00000000..45770874 --- /dev/null +++ b/example-core/odoo/setup.py @@ -0,0 +1,26 @@ +from setuptools import setup, find_packages + +with open('VERSION') as fd: + version = fd.read().strip() + +setup( + name="my-project-name", + version=version, + description="project description", + license='GNU Affero General Public License v3 or later (AGPLv3+)', + author="Author...", + author_email="email...", + url="url...", + packages=['songs'] + ['songs.%s' % p for p in find_packages('./songs')], + include_package_data=True, + classifiers=[ + 'Development Status :: 4 - Beta', + 'License :: OSI Approved', + 'License :: OSI Approved :: ' + 'GNU Affero General Public License v3 or later (AGPLv3+)', + 'Programming Language :: Python', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.12', + 'Programming Language :: Python :: Implementation :: CPython', + ], +) diff --git a/example-core/odoo/src/README.md b/example-core/odoo/src/README.md new file mode 100644 index 00000000..526eba6a --- /dev/null +++ b/example-core/odoo/src/README.md @@ -0,0 +1 @@ +Here you should have Odoo's code as submodule diff --git a/example-core/pyproject.toml b/example-core/pyproject.toml new file mode 100644 index 00000000..fcff93b5 --- /dev/null +++ b/example-core/pyproject.toml @@ -0,0 +1,21 @@ +[build-system] +requires=['setuptools-odoo', 'wheel', "setuptools>=67.0"] + +[tool.black] +line-length = 88 +skip-string-normalization = 'True' +include = '\.pyi?$' +exclude = ''' +/( + \.git + | \.mypy_cache + | \.tox + | \.venv + | src/odoo + | src/enterprise + | odoo/paid-modules + | data +)/ +| /__openerp__.py +| /__manifest__.py +''' diff --git a/example-core/requirements.txt b/example-core/requirements.txt new file mode 100644 index 00000000..4e5089a8 --- /dev/null +++ b/example-core/requirements.txt @@ -0,0 +1,4 @@ +# project's packages, customize for your needs: +unidecode==0.4.14 +setuptools-odoo +wheel diff --git a/example-core/setup.py b/example-core/setup.py new file mode 100644 index 00000000..fe4b2703 --- /dev/null +++ b/example-core/setup.py @@ -0,0 +1,17 @@ +from setuptools import find_packages, setup + +with open('VERSION') as fd: + version = fd.read().strip() + +setup( + name="odoo-project", + version=version, + description="Odoo Project", + license='GNU Affero General Public License v3 or later (AGPLv3+)', + author="Camptocamp", + author_email="info@camptocamp.com", + url="www.camptocamp.com", + packages=['songs'] + ['songs.%s' % p for p in find_packages('./songs')], + include_package_data=True, + odoo_addons=True, +) diff --git a/example-core/songs/__init__.py b/example-core/songs/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/example-core/songs/install/__init__.py b/example-core/songs/install/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/example-core/songs/install/base.py b/example-core/songs/install/base.py new file mode 100644 index 00000000..5f99e3db --- /dev/null +++ b/example-core/songs/install/base.py @@ -0,0 +1,33 @@ +# Copyright 2016 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) + +from base64 import b64encode +from pkg_resources import Requirement, resource_string +from anthem.lyrics.records import create_or_update + + +def setup_company(ctx, req): + """Setup company""" + company = ctx.env.ref("base.main_company") + company.name = "Rainbow Holding" + + # load logo on company + logo_content = resource_string(req, "data/images/logo.png") + logo = b64encode(logo_content) + company.logo = logo + + values = { + "name": "Rainbow company", + "street": "Rainbow Street 1", + "zip": "1000", + "city": "There", + "parent_id": company.id, + "logo": logo, + } + create_or_update(ctx, "res.company", "__setup__.company_rainbow", values) + + +def main(ctx): + """Create demo data""" + req = Requirement.parse("odoo-project") + setup_company(ctx, req) diff --git a/example-core/songs/install/demo.py b/example-core/songs/install/demo.py new file mode 100644 index 00000000..6f485ecb --- /dev/null +++ b/example-core/songs/install/demo.py @@ -0,0 +1,17 @@ +# Copyright 2016 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) + +from anthem.lyrics.records import create_or_update + + +def create_partners(ctx): + names = [('Khiank Mountaingut', 'partner_1'), + ('Kher Fernthorn', 'partner_2'), + ('Sheing Coaldigger', 'partner_3'), + ] + for name, xmlid in names: + create_or_update(ctx, 'res.partner', xmlid, {'name': name}) + + +def main(ctx): + create_partners(ctx) diff --git a/example-core/test-compose.yml b/example-core/test-compose.yml new file mode 100644 index 00000000..694ac612 --- /dev/null +++ b/example-core/test-compose.yml @@ -0,0 +1,54 @@ +# Composition used to run automated tests on the images +# Used by the Makefile at the repository's root + +services: + odoo: + build: . + depends_on: + - db + - kwkhtmltopdf + volumes: + - "data-odoo:/data/odoo" + - "./odoo/addons:/odoo/odoo/addons" + environment: + - DB_USER=odoo + - DB_PASS=odoo + - DB_NAME=odoodb + - RUNNING_ENV=dev + - LOG_HANDLER=:WARN + - MARABUNTA_MODE=demo # could be 'full' for the db with all the data + - KWKHTMLTOPDF_SERVER_URL=http://kwkhtmltopdf:8080 + - ODOO_REPORT_URL=http://odoo:8069 + - LOCAL_CODE_PATH=/odoo/odoo/addons + - MIGRATION_CONFIG_FILE=/odoo/migration.yml + # cached database dumps config for `runmigration` and `runtests` + - CREATE_DB_CACHE=false # set it to 'true' to create dumps + - LOAD_DB_CACHE=true # by default will always search for existing dumps + # SUBS_MD5 is `runtests` only, you need to define it to identify dumps, + # a good practice is to generate it based on the content you have in + # your dependencies (`odoo/src`, `odoo/external-src`) + # See README.md for more. + - SUBS_MD5= + # MIG_LOAD_VERSION is `runmigration` only, define it if you want to load + # a prior release dump that doesn't match `odoo/VERSION` number. + # See README.md for more. + - MIG_LOAD_VERSION_CEIL= + + db: + image: postgres:13.0 + ports: + - 5432 + environment: + - POSTGRES_USER=odoo + - POSTGRES_PASSWORD=odoo + volumes: + - "data-db:/var/lib/postgresql/data" + + kwkhtmltopdf: + image: acsone/kwkhtmltopdf + ports: + - 8080 + +volumes: + data-odoo: + data-db: diff --git a/example/docker-compose.yml b/example/docker-compose.yml index 63f571f2..5f530610 100644 --- a/example/docker-compose.yml +++ b/example/docker-compose.yml @@ -21,6 +21,7 @@ services: - ADMIN_PASSWD=# set me - RUNNING_ENV=dev - LOG_HANDLER=:WARN + - LOCAL_CODE_PATH=/odoo/local-src - MARABUNTA_MODE=demo # could be 'full' for the db with all the data - MARABUNTA_ALLOW_SERIE=True # should not be set in production diff --git a/example/test-compose.yml b/example/test-compose.yml index 71d6bde5..395deee2 100644 --- a/example/test-compose.yml +++ b/example/test-compose.yml @@ -18,6 +18,7 @@ services: - MARABUNTA_MODE=demo # could be 'full' for the db with all the data - KWKHTMLTOPDF_SERVER_URL=http://kwkhtmltopdf:8080 - ODOO_REPORT_URL=http://odoo:8069 + - LOCAL_CODE_PATH=/odoo/local-src - MIGRATION_CONFIG_FILE=/odoo/migration.yml # cached database dumps config for `runmigration` and `runtests` - CREATE_DB_CACHE=false # set it to 'true' to create dumps diff --git a/install/package_odoo.sh b/install/package_odoo.sh index 0685c429..4ba8cb0d 100755 --- a/install/package_odoo.sh +++ b/install/package_odoo.sh @@ -1,23 +1,47 @@ #!/bin/bash set -eo pipefail -apt-get update -o Acquire::AllowInsecureRepositories=true -apt-get install -y --no-install-recommends \ +ODOO_PACKAGE=" \ antiword \ ca-certificates \ curl \ dirmngr \ + expect \ ghostscript \ - graphviz \ gnupg2 \ + graphviz \ less \ + libxslt1.1 \ nano \ node-clean-css \ node-less \ poppler-utils \ - libxslt1.1 \ + tcl \ xfonts-75dpi \ xfonts-base \ xz-utils \ - tcl \ - expect +" + +if [ "${1-}" = "core" ]; then + ODOO_PACKAGE="$ODOO_PACKAGE \ + adduser \ + fonts-dejavu-core \ + fonts-font-awesome \ + fonts-freefont-otf \ + fonts-freefont-ttf \ + fonts-inconsolata \ + fonts-noto-core \ + fonts-roboto-unhinted \ + git \ + gnupg2 \ + gsfonts \ + libjs-underscore \ + lsb-base \ + patch \ + procps \ + vim-tiny \ +" +fi + +apt-get update -o Acquire::AllowInsecureRepositories=true +apt-get install -y --no-install-recommends $ODOO_PACKAGE diff --git a/install/purge_dev_package_and_cache.sh b/install/purge_dev_package_and_cache.sh index 92011c6b..a0489a7f 100755 --- a/install/purge_dev_package_and_cache.sh +++ b/install/purge_dev_package_and_cache.sh @@ -4,3 +4,7 @@ set -eo pipefail apt-get remove -y $BUILD_PACKAGE libpq-dev apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false -o APT::AutoRemove::SuggestsImportant=false $PURGE_PACKAGE rm -rf /var/lib/apt/lists/* /root/.cache/pip/* + +# Remove METADATA of vendored dependencies +# which triggered a vulnerability report, without easy way to fix it. +rm -vrf /odoo/.venv/lib/python3*/site-packages/setuptools/_vendor/*.dist-info diff --git a/install/reportlab_init.sh b/install/reportlab_init.sh deleted file mode 100755 index 12383cd3..00000000 --- a/install/reportlab_init.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash -set -xe -python3 -c "import urllib.request -url = 'http://www.reportlab.com/ftp/pfbfer.zip' -urllib.request.urlretrieve(url, '/tmp/pfbfer.zip')" -apt update -apt install unzip -y -mkdir /usr/lib/python3/dist-packages/reportlab/fonts -cd /usr/lib/python3/dist-packages/reportlab/fonts -unzip /tmp/pfbfer.zip -rm -rf /tmp/pfbfer.zip - - diff --git a/setup.sh b/setup.sh index d5a260ec..0db999c5 100644 --- a/setup.sh +++ b/setup.sh @@ -17,7 +17,7 @@ if [ -z "$VERSION" ]; then exit 1 fi -SRC=${SRC:=(mktemp -d)} +SRC=${SRC:=$(mktemp -d)} echo "Creating $SRC" mkdir -p $SRC diff --git a/test.sh b/test.sh index 420536b1..8bcdce6e 100755 --- a/test.sh +++ b/test.sh @@ -16,14 +16,33 @@ set -Exeuo pipefail # * IMAGE_LATEST (tag of the 'latest' image built) # -if [ -z "$VERSION" ]; then +if [ -z "${VERSION-}" ]; then echo "VERSION environment variable is missing" exit 1 fi -if [ -z "$IMAGE_LATEST" ]; then - export IMAGE_LATEST=odoo:${VERSION} +if [ -z "${IMAGE_LATEST-}" ]; then + if [ -n "${BUILD_TAG-}" ]; then + IMAGE_LATEST="${BUILD_TAG}" + else + IMAGE_LATEST="odoo:${VERSION}" + fi fi - +export IMAGE_LATEST + +case $IMAGE_LATEST in + *-5xx-*) + TEST_SRC=./example-core + BASE_PATH=. + LOCAL_CODE_PATH=./odoo/addons + ODOO_PATH=./odoo/src/odoo + ;; + *) + TEST_SRC=./example + BASE_PATH=./odoo + LOCAL_CODE_PATH=./odoo/local-src + ODOO_PATH=./odoo/src + ;; +esac # Allow version flavor like 12.0-buster VERSION=$(echo $VERSION | cut -d '-' -f '1') @@ -61,18 +80,22 @@ docoruncmd() { docker compose -f test-compose.yml run --rm -e LOCAL_USER_ID=$(id -u) $@ } -cp -ra ./example/. "$TMP/" +cp -ra "$TEST_SRC/." "$TMP/" cd "$TMP" echo '>>> Downloading Odoo src' -rm -rf "$TMP/odoo/src" +rm -rf "$ODOO_PATH" wget -nv -O /tmp/odoo.tar.gz "$ODOO_URL" -tar xfz /tmp/odoo.tar.gz -C odoo/ -mv "odoo/odoo-$VERSION" odoo/src +tar xfz /tmp/odoo.tar.gz -C "./odoo" +mkdir -p $(dirname -- "$ODOO_PATH") +mv "./odoo/odoo-$VERSION" "$ODOO_PATH" echo "+++++++++++++ $IMAGE_LATEST" echo '>>> Run test for base image' -sed "s|FROM .*|FROM ${IMAGE_LATEST}|" -i odoo/Dockerfile +sed "s|FROM .*|FROM ${IMAGE_LATEST}|" -i "$BASE_PATH/Dockerfile" +sed "s|\(.version.: .\)[0-9.]*\(.*\)|\\1${VERSION}.0.0.0\\2|" -i "$LOCAL_CODE_PATH/dummy_test/__manifest__.py" +echo $VERSION.0.0.0 > "$BASE_PATH/VERSION" + mkdir .cachedb echo '>>> * migration: standard' @@ -85,7 +108,7 @@ docoruncmd odoo dropdb odoodb echo '>>> * migration: use the dump and migrate to new version' docorunmigration -e LOAD_DB_CACHE="true" docodown -cat <>migration.yml +cat <>"$BASE_PATH/migration.yml" - version: ${VERSION}.0.1 operations: post: