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 00000000..cefdea6f Binary files /dev/null and b/example-core/data/images/logo.png differ 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: