diff --git a/.editorconfig b/.editorconfig index 0721c303..b03e0976 100644 --- a/.editorconfig +++ b/.editorconfig @@ -8,5 +8,5 @@ charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true -[*.{md,yaml,yml}] +[*.{md,json,yaml,yml,yaml}] indent_size = 2 diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000..7ced7084 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,29 @@ +--- +name: Bug report +about: Report a bug +title: "" +labels: bug +assignees: "" +--- + + + +## Describe the bug + +A clear and concise description of what the bug is. + +## To Reproduce + +**Affected versions**: + +Steps to reproduce the behavior: + +1. +2. +3. + +**Expected behavior** A clear and concise description of what you expected to happen. + +**Additional context** Add any other context about the problem here. (e.g. OS, Docker +version, ...) diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000..14ada72c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: false +contact_links: + - name: Question or general talk + url: https://github.com/Tecnativa/doodba/discussions + about: Please ask and answer questions here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 00000000..5be53c3b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,18 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: "" +labels: enhancement +assignees: "" +--- + +**Is your feature request related to a problem?** If so, please provide clear and +concise description of what the problem is. + +**Describe the solution you'd like** A clear and concise description of what you want to +happen. + +**Describe alternatives you've considered** A clear and concise description of any +alternative solutions or features you've considered. + +**Additional context** Add any other context about the feature request here. diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 00000000..037e2f7f --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,339 @@ +name: ci + +on: + pull_request: + push: + branches: + - master + schedule: + # See https://crontab.guru/weekly + - cron: 0 0 * * 0 + +jobs: + pre-commit: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v4 + with: + python-version: "3.11" + - name: Set PY + run: | + echo "PY=$(python -c 'import hashlib, + sys;print(hashlib.sha256(sys.version.encode()+sys.executable.encode()).hexdigest())')" >> $GITHUB_ENV + - uses: actions/cache@v4 + with: + path: ~/.cache/pre-commit + key: pre-commit|${{ env.PY }}|${{ hashFiles('.pre-commit-config.yaml') }} + - uses: pre-commit/action@v3.0.1 + + build-push-pr: + # Build & push PR images so tests and local dev can pull them + if: github.event_name == 'pull_request' + runs-on: ubuntu-24.04 + needs: pre-commit + strategy: + fail-fast: false + matrix: + # Test modern Odoo versions with latest Postgres version + odoo_version: ["19.0"] + platforms: ["linux/amd64,linux/arm64"] + include: + # Older odoo versions don't support latest postgres and Python versions + - odoo_version: "18.0" + platforms: "linux/amd64,linux/arm64" + - odoo_version: "17.0" + platforms: "linux/amd64,linux/arm64" + - odoo_version: "16.0" + platforms: "linux/amd64,linux/arm64" + - odoo_version: "15.0" + platforms: "linux/amd64,linux/arm64" + - odoo_version: "14.0" + platforms: "linux/amd64,linux/arm64" + - odoo_version: "13.0" + platforms: "linux/amd64" + env: + # Indicates what's the equivalent to tecnativa/doodba:latest image + LATEST_RELEASE: "19.0" + DOCKER_REPO: tecnativa/doodba + GHCR_HOST: ghcr.io + steps: + - name: Clean Docker system before build + run: | + docker system prune -af --volumes || true + docker builder prune -af || true + # Set build date as env variable to be used later + - name: Set build date + run: echo "BUILD_DATE=$(date '+%Y-%m-%dT%H:%M:%S.%N%:z')" >> $GITHUB_ENV + # Prepare + - uses: actions/checkout@v4 + # Setup QEMU + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + - name: Reset QEMU + if: ${{ matrix.odoo_version == '15.0' }} + run: docker run --rm --privileged multiarch/qemu-user-static --reset -p yes + # Setup buildx + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Login to Docker Hub + if: + github.repository == 'tecnativa/doodba' && + github.event.pull_request.head.repo.full_name == github.repository + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_LOGIN }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Login to GitHub Container Registry + if: + github.repository == 'tecnativa/doodba' && + github.event.pull_request.head.repo.full_name == github.repository + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ secrets.BOT_LOGIN }} + password: ${{ secrets.BOT_TOKEN }} + - name: Build base image + uses: docker/build-push-action@v6 + with: + context: . + file: ./${{ matrix.odoo_version }}.Dockerfile + platforms: ${{ matrix.platforms }} + push: + ${{ github.repository == 'tecnativa/doodba' && + github.event.pull_request.head.repo.full_name == github.repository }} + tags: | + ${{ env.DOCKER_REPO }}:${{ matrix.odoo_version }}-pr-${{ github.event.pull_request.number }}-test + ${{ env.GHCR_HOST }}/${{ env.DOCKER_REPO }}${{ env.DOCKER_REPO_SUFFIX }}:${{ matrix.odoo_version }}-pr-${{ github.event.pull_request.number }}-test + target: base + build-args: | + VCS_REF=${{ github.sha }} + BUILD_DATE=${{ env.BUILD_DATE }} + ODOO_VERSION=${{ matrix.odoo_version }} + - name: Build onbuild image + uses: docker/build-push-action@v6 + with: + context: . + file: ./${{ matrix.odoo_version }}.Dockerfile + platforms: ${{ matrix.platforms }} + push: + ${{ github.repository == 'tecnativa/doodba' && + github.event.pull_request.head.repo.full_name == github.repository }} + tags: | + ${{ env.DOCKER_REPO }}:${{ matrix.odoo_version }}-pr-${{ github.event.pull_request.number }}-test-onbuild + ${{ env.GHCR_HOST }}/${{ env.DOCKER_REPO }}${{ env.DOCKER_REPO_SUFFIX }}:${{ matrix.odoo_version }}-pr-${{ github.event.pull_request.number }}-test-onbuild + target: onbuild + build-args: | + VCS_REF=${{ github.sha }} + BUILD_DATE=${{ env.BUILD_DATE }} + ODOO_VERSION=${{ matrix.odoo_version }} + - name: Clean Docker system after build + run: | + docker system prune -af --volumes || true + docker builder prune -af || true + + test-pr: + # Run tests in PR using the freshly pushed images + if: github.event_name == 'pull_request' + runs-on: ubuntu-24.04 + needs: build-push-pr + strategy: + fail-fast: false + matrix: + odoo_version: ["19.0"] + pg_version: ["17"] + python_version: ["3.12"] + include: + - odoo_version: "18.0" + pg_version: "16" + python_version: "3.10" + - odoo_version: "17.0" + pg_version: "15" + python_version: "3.10" + - odoo_version: "16.0" + pg_version: "14" + python_version: "3.10" + - odoo_version: "15.0" + pg_version: "14" + python_version: "3.9" + - odoo_version: "14.0" + pg_version: "14" + python_version: "3.9" + - odoo_version: "13.0" + pg_version: "14" + python_version: "3.9" + env: + DOCKER_BUILDKIT: 1 + DOCKER_TAG: + ${{ matrix.odoo_version }}-pr-${{ github.event.pull_request.number }}-test + PG_VERSIONS: ${{ matrix.pg_version }} + ODOO_MINOR: ${{ matrix.odoo_version }} + # signal to tests that they can use the prebuilt images from registries and do not need to build the image in setupClass + USE_PREBUILT_IMAGES: + ${{ github.repository == 'tecnativa/doodba' && + github.event.pull_request.head.repo.full_name == github.repository }} + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python_version }} + - uses: docker/setup-compose-action@v1 + with: + version: latest + - run: pip install poetry + - name: Patch $PATH + run: echo "$HOME/.local/bin" >> $GITHUB_PATH + - run: poetry install + - run: poetry run python -m unittest -v tests + + test: + if: github.event_name != 'pull_request' + runs-on: ubuntu-24.04 + needs: pre-commit + strategy: + fail-fast: false + matrix: + odoo_version: ["19.0"] + pg_version: ["17"] + python_version: ["3.12"] + include: + - odoo_version: "18.0" + pg_version: "16" + python_version: "3.10" + - odoo_version: "17.0" + pg_version: "15" + python_version: "3.10" + - odoo_version: "16.0" + pg_version: "14" + python_version: "3.10" + - odoo_version: "15.0" + pg_version: "14" + python_version: "3.9" + - odoo_version: "14.0" + pg_version: "14" + python_version: "3.9" + - odoo_version: "13.0" + pg_version: "14" + python_version: "3.9" + env: + DOCKER_BUILDKIT: 1 + PG_VERSIONS: ${{ matrix.pg_version }} + ODOO_MINOR: ${{ matrix.odoo_version }} + DOCKER_TAG: ${{ matrix.odoo_version }} + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python_version }} + - uses: docker/setup-compose-action@v1 + with: + version: latest + - run: pip install poetry + - name: Patch $PATH + run: echo "$HOME/.local/bin" >> $GITHUB_PATH + - run: poetry install + - run: poetry run python -m unittest -v tests + + build-push-official: + # Only publish final images from master after tests pass + if: github.repository == 'tecnativa/doodba' && github.ref == 'refs/heads/master' + runs-on: ubuntu-24.04 + needs: test + strategy: + fail-fast: false + matrix: + # Test modern Odoo versions with latest Postgres version + odoo_version: ["19.0"] + platforms: ["linux/amd64,linux/arm64"] + include: + # Older odoo versions don't support latest postgres and Python versions + - odoo_version: "18.0" + platforms: "linux/amd64,linux/arm64" + - odoo_version: "17.0" + platforms: "linux/amd64,linux/arm64" + - odoo_version: "16.0" + platforms: "linux/amd64,linux/arm64" + - odoo_version: "15.0" + platforms: "linux/amd64,linux/arm64" + - odoo_version: "14.0" + platforms: "linux/amd64,linux/arm64" + - odoo_version: "13.0" + platforms: "linux/amd64" + env: + # Indicates what tag matches tecnativa/doodba:latest + LATEST_RELEASE: "19.0" + # Define the docker hub repository location and github container registry host + DOCKER_REPO: tecnativa/doodba + GHCR_HOST: ghcr.io + steps: + - name: Clean Docker system before build + run: | + docker system prune -af --volumes || true + docker builder prune -af || true + # Set build date as env variable to be used later + - name: Set build date + run: echo "BUILD_DATE=$(date '+%Y-%m-%dT%H:%M:%S.%N%:z')" >> $GITHUB_ENV + # Prepare + - uses: actions/checkout@v4 + # Setup QEMU + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + - name: Reset QEMU + if: ${{ matrix.odoo_version == '15.0' }} + run: docker run --rm --privileged multiarch/qemu-user-static --reset -p yes + # Setup buildx + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_LOGIN }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ secrets.BOT_LOGIN }} + password: ${{ secrets.BOT_TOKEN }} + - name: Build base image + uses: docker/build-push-action@v6 + with: + context: . + file: ./${{ matrix.odoo_version }}.Dockerfile + platforms: ${{ matrix.platforms }} + push: + ${{ github.repository == 'tecnativa/doodba' && github.ref == + 'refs/heads/master' }} + tags: | + ${{ env.DOCKER_REPO }}:${{ matrix.odoo_version }} + ${{ env.GHCR_HOST }}/${{ env.DOCKER_REPO }}${{ env.DOCKER_REPO_SUFFIX }}:${{ matrix.odoo_version }} + ${{ matrix.odoo_version == env.LATEST_RELEASE && format('{0}:latest', env.DOCKER_REPO) || '' }} + ${{ matrix.odoo_version == env.LATEST_RELEASE && format('{0}/{1}{2}:latest', env.GHCR_HOST, env.DOCKER_REPO, env.DOCKER_REPO_SUFFIX) || '' }} + target: base + build-args: | + VCS_REF=${{ github.sha }} + BUILD_DATE=${{ env.BUILD_DATE }} + ODOO_VERSION=${{ matrix.odoo_version }} + - name: Build onbuild image + uses: docker/build-push-action@v6 + with: + context: . + file: ./${{ matrix.odoo_version }}.Dockerfile + platforms: ${{ matrix.platforms }} + push: + ${{ github.repository == 'tecnativa/doodba' && github.ref == + 'refs/heads/master' }} + tags: | + ${{ env.DOCKER_REPO }}:${{ matrix.odoo_version }}-onbuild + ${{ env.GHCR_HOST }}/${{ env.DOCKER_REPO }}${{ env.DOCKER_REPO_SUFFIX }}:${{ matrix.odoo_version }}-onbuild + ${{ matrix.odoo_version == env.LATEST_RELEASE && format('{0}:latest-onbuild', env.DOCKER_REPO) || '' }} + ${{ matrix.odoo_version == env.LATEST_RELEASE && format('{0}/{1}{2}:latest-onbuild', env.GHCR_HOST, env.DOCKER_REPO, env.DOCKER_REPO_SUFFIX) || '' }} + target: onbuild + build-args: | + VCS_REF=${{ github.sha }} + BUILD_DATE=${{ env.BUILD_DATE }} + ODOO_VERSION=${{ matrix.odoo_version }} + - name: Clean Docker system after build + run: | + docker system prune -af --volumes || true + docker builder prune -af || true diff --git a/.gitignore b/.gitignore index e6b57d33..58a133fd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ .vscode **.pyc +# Tests garbage +tests/scaffoldings/repo_merge/custom/src/odoo +tests/scaffoldings/test_artifacts/test-artifacts diff --git a/.isort.cfg b/.isort.cfg new file mode 100644 index 00000000..b732c289 --- /dev/null +++ b/.isort.cfg @@ -0,0 +1,12 @@ +# From https://github.com/OCA/maintainer-quality-tools/blob/master/sample_files/pre-commit-13.0/.isort.cfg +[settings] +multi_line_output=3 +include_trailing_comma=True +force_grid_wrap=0 +combine_as_imports=True +use_parentheses=True +line_length=88 +known_odoo=odoo +known_odoo_addons=odoo.addons +sections=FUTURE,STDLIB,THIRDPARTY,ODOO,ODOO_ADDONS,FIRSTPARTY,LOCALFOLDER +known_third_party=click,click_odoo,doodbalib,yaml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..12f1f4dd --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,39 @@ +default_language_version: + python: python3 +repos: + - repo: https://github.com/psf/black + rev: 22.3.0 + hooks: + - id: black + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.3.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: debug-statements + - id: fix-encoding-pragma + - id: check-case-conflict + - id: check-docstring-first + - id: check-executables-have-shebangs + - id: check-merge-conflict + - id: check-xml + - id: mixed-line-ending + args: ["--fix=lf"] + - repo: https://github.com/asottile/seed-isort-config + rev: v2.2.0 + hooks: + - id: seed-isort-config + - repo: https://github.com/pre-commit/mirrors-isort + rev: v5.10.1 + hooks: + - id: isort + - repo: https://github.com/pre-commit/mirrors-prettier + rev: v2.7.1 + hooks: + - id: prettier + - repo: https://github.com/Lucas-C/pre-commit-hooks-nodejs + rev: v1.1.2 + hooks: + - id: markdown-toc + args: [--bullets=-, -i] + exclude: .github/ diff --git a/.prettierrc.yml b/.prettierrc.yml new file mode 100644 index 00000000..6f6302fc --- /dev/null +++ b/.prettierrc.yml @@ -0,0 +1,6 @@ +# Defaults for all prettier-supported languages +bracketSpacing: false +printWidth: 88 +proseWrap: always +semi: true +trailingComma: "es5" diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 8bb1e3d8..00000000 --- a/.travis.yml +++ /dev/null @@ -1,39 +0,0 @@ -sudo: required - -language: python - -python: - - "3.6" - -services: - - docker - -git: - depth: 1 - -branches: - only: - - master - -env: - global: - # Variables found by default in Docker Hub builder - - DOCKER_REPO=tecnativa/doodba - matrix: - - DOCKER_TAG=8.0 - - DOCKER_TAG=9.0 - - DOCKER_TAG=10.0 - - DOCKER_TAG=11.0 - -before_install: - - sudo apt-get update - - sudo apt-get -y -o Dpkg::Options::=--force-confnew install docker-ce - - pip install -r requirements-ci.txt - -install: - - chown -R $USER:$USER . - - chmod -R +r . - - ./hooks/build - -script: - - python -m unittest -v tests diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..5eb59ba3 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,17 @@ +{ + "python.autoComplete.extraPaths": ["./lib", "./tests"], + "editor.formatOnSaveTimeout": 1000, + "python.formatting.provider": "black", + "python.formatting.blackArgs": [], + "python.linting.flake8Args": ["--max-line-length=88"], + "python.linting.flake8Enabled": true, + "python.linting.pylintEnabled": true, + "python.pythonPath": "python3", + "editor.formatOnSave": true, + + "[dockerfile]": { + "editor.formatOnSave": false + }, + "python.analysis.extraPaths": ["./lib", "./tests"], + "python.languageServer": "None" +} diff --git a/10.0.Dockerfile b/10.0.Dockerfile deleted file mode 120000 index 04c2b0a4..00000000 --- a/10.0.Dockerfile +++ /dev/null @@ -1 +0,0 @@ -8.0.Dockerfile \ No newline at end of file diff --git a/11.0.Dockerfile b/11.0.Dockerfile index b3b10875..b1b01acb 100644 --- a/11.0.Dockerfile +++ b/11.0.Dockerfile @@ -1,29 +1,32 @@ -FROM debian:9 AS base +FROM python:3.5-stretch AS base -# Enable Odoo user and filestore -RUN useradd -md /home/odoo -s /bin/false odoo \ - && mkdir -p /var/lib/odoo \ - && chown -R odoo:odoo /var/lib/odoo \ - && sync -VOLUME ["/var/lib/odoo"] EXPOSE 8069 8072 +ARG GEOIP_UPDATER_VERSION=4.1.5 +ARG MQT=https://github.com/OCA/maintainer-quality-tools.git ARG WKHTMLTOPDF_VERSION=0.12.5 ARG WKHTMLTOPDF_CHECKSUM='1140b0ab02aa6e17346af2f14ed0de807376de475ba90e1db3975f112fbd20bb' ENV DB_FILTER=.* \ DEPTH_DEFAULT=1 \ DEPTH_MERGE=100 \ EMAIL=https://hub.docker.com/r/tecnativa/odoo \ + GEOIP_ACCOUNT_ID="" \ + GEOIP_LICENSE_KEY="" \ GIT_AUTHOR_NAME=docker-odoo \ INITIAL_LANG="" \ LC_ALL=C.UTF-8 \ + LIST_DB=false \ NODE_PATH=/usr/local/lib/node_modules:/usr/lib/node_modules \ OPENERP_SERVER=/opt/odoo/auto/odoo.conf \ PATH="/home/odoo/.local/bin:$PATH" \ PIP_NO_CACHE_DIR=0 \ + PTVSD_ARGS="--host 0.0.0.0 --port 6899 --wait --multiprocess" \ + PTVSD_ENABLE=0 \ + DEBUGPY_ARGS="--listen 0.0.0.0:6899 --wait-for-client" \ + DEBUGPY_ENABLE=0 \ PUDB_RDB_HOST=0.0.0.0 \ PUDB_RDB_PORT=6899 \ - PYTHONOPTIMIZE=1 \ + PYTHONOPTIMIZE="" \ UNACCENT=true \ WAIT_DB=true \ WDB_NO_BROWSER_AUTO_OPEN=True \ @@ -31,32 +34,42 @@ ENV DB_FILTER=.* \ WDB_WEB_PORT=1984 \ WDB_WEB_SERVER=localhost +# Debian stretch was moved to archive (and stretch-updates does not exist in archive) +RUN sed -i 's,http://deb.debian.org,http://archive.debian.org,g;s,http://security.debian.org,http://archive.debian.org,g;s,\(.*stretch-updates\),#\1,' /etc/apt/sources.list + # Other requirements and recommendations to run Odoo # See https://github.com/$ODOO_SOURCE/blob/$ODOO_VERSION/debian/control RUN apt-get -qq update \ && apt-get -yqq upgrade \ && apt-get install -yqq --no-install-recommends \ - python3 ruby-compass \ - fontconfig libfreetype6 libxml2 libxslt1.1 libjpeg62-turbo zlib1g \ - libfreetype6 liblcms2-2 libtiff5 tk tcl libpq5 \ - libldap-2.4-2 libsasl2-2 libx11-6 libxext6 libxrender1 \ - locales-all zlibc \ - bzip2 ca-certificates curl gettext-base git gnupg2 nano vim \ - openssh-client telnet xz-utils \ - && echo 'deb http://apt.postgresql.org/pub/repos/apt/ stretch-pgdg main' >> /etc/apt/sources.list.d/postgresql.list \ + chromium \ + fonts-liberation2 \ + gettext \ + gnupg2 \ + locales-all \ + ruby-compass \ + nano \ + ruby \ + telnet \ + vim \ + zlibc \ + apt-transport-https \ + ca-certificates \ + && echo 'deb https://apt-archive.postgresql.org/pub/repos/apt stretch-pgdg main' >> /etc/apt/sources.list.d/postgresql.list \ && curl -SL https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - \ - && curl https://bootstrap.pypa.io/get-pip.py | python3 /dev/stdin \ + && curl https://bootstrap.pypa.io/pip/3.5/get-pip.py | python3 /dev/stdin \ && curl -sL https://deb.nodesource.com/setup_6.x | bash - \ && apt-get update \ - && apt-get install -yqq --no-install-recommends nodejs postgresql-client \ + && apt-get install -yqq --no-install-recommends nodejs \ && curl -SLo wkhtmltox.deb https://github.com/wkhtmltopdf/wkhtmltopdf/releases/download/${WKHTMLTOPDF_VERSION}/wkhtmltox_${WKHTMLTOPDF_VERSION}-1.stretch_amd64.deb \ && echo "${WKHTMLTOPDF_CHECKSUM} wkhtmltox.deb" | sha256sum -c - \ && apt-get install -yqq --no-install-recommends ./wkhtmltox.deb \ && rm wkhtmltox.deb \ && wkhtmltopdf --version \ - && apt-get -yqq purge python2.7 \ - && apt-get -yqq autoremove \ - && rm -Rf /var/lib/apt/lists/* + && curl --silent -L --output geoipupdate_${GEOIP_UPDATER_VERSION}_linux_amd64.deb https://github.com/maxmind/geoipupdate/releases/download/v${GEOIP_UPDATER_VERSION}/geoipupdate_${GEOIP_UPDATER_VERSION}_linux_amd64.deb \ + && dpkg -i geoipupdate_${GEOIP_UPDATER_VERSION}_linux_amd64.deb \ + && rm geoipupdate_${GEOIP_UPDATER_VERSION}_linux_amd64.deb \ + && rm -Rf /var/lib/apt/lists/* /tmp/* # Special case to get latest Less and PhantomJS RUN ln -s /usr/bin/nodejs /usr/local/bin/node \ @@ -64,55 +77,80 @@ RUN ln -s /usr/bin/nodejs /usr/local/bin/node \ && rm -Rf ~/.npm /tmp/* # Special case to get bootstrap-sass, required by Odoo for Sass assets -RUN gem install --no-rdoc --no-ri --no-update-sources bootstrap-sass --version '<4' \ +RUN gem install --no-rdoc --no-ri --no-update-sources execjs --version '<2.9.1' \ + && gem install --no-rdoc --no-ri --no-update-sources autoprefixer-rails --version '<9.8.6' \ + && gem install --no-rdoc --no-ri --no-update-sources bootstrap-sass --version '<3.4' \ && rm -Rf ~/.gem /var/lib/gems/*/cache/ # Other facilities WORKDIR /opt/odoo RUN pip install \ - astor git-aggregator openupgradelib ptvsd==3.0.0 pudb wdb -COPY bin/* /usr/local/bin/ -COPY lib/odoobaselib /usr/local/lib/python3.5/dist-packages/odoobaselib + astor \ + # Install fix from https://github.com/acsone/click-odoo-contrib/pull/93 + git+https://github.com/Tecnativa/click-odoo-contrib.git@fix-active-modules-hashing \ + "git-aggregator<3.0.0" \ + "pg_activity<2.0.0" \ + plumbum \ + ptvsd \ + debugpy \ + pydevd-odoo \ + pudb \ + watchdog \ + wdb \ + geoip2 \ + inotify \ + && sync +COPY bin-deprecated/* bin/* /usr/local/bin/ +COPY lib/doodbalib /usr/local/lib/python3.5/site-packages/doodbalib +RUN ln -s /usr/local/lib/python3.5/site-packages/doodbalib \ + /usr/local/lib/python3.5/site-packages/odoobaselib COPY build.d common/build.d COPY conf.d common/conf.d COPY entrypoint.d common/entrypoint.d -RUN mkdir -p auto/addons custom/src/private \ +RUN rm -f /opt/odoo/common/conf.d/60-geoip-ge17.conf \ + && mv /opt/odoo/common/conf.d/60-geoip-lt17.conf /opt/odoo/common/conf.d/60-geoip.conf +RUN mkdir -p auto/addons auto/geoip custom/src/private \ && ln /usr/local/bin/direxec common/entrypoint \ && ln /usr/local/bin/direxec common/build \ && chmod -R a+rx common/entrypoint* common/build* /usr/local/bin \ - && chmod -R a+rX /usr/local/lib/python3.5/dist-packages/odoobaselib \ - && ln -s $(which python3) /usr/local/bin/python \ + && chmod -R a+rX /usr/local/lib/python3.5/site-packages/doodbalib \ + && cp -a /etc/GeoIP.conf /etc/GeoIP.conf.orig \ + && mv /etc/GeoIP.conf /opt/odoo/auto/geoip/GeoIP.conf \ + && ln -s /opt/odoo/auto/geoip/GeoIP.conf /etc/GeoIP.conf \ + && sed -i 's/.*DatabaseDirectory .*$/DatabaseDirectory \/opt\/odoo\/auto\/geoip\//g' /opt/odoo/auto/geoip/GeoIP.conf \ && sync +# Doodba-QA dependencies in a separate virtualenv +COPY qa /qa +RUN python -m venv --system-site-packages /qa/venv \ + && . /qa/venv/bin/activate \ + # HACK: Upgrade pip: higher version needed to install pyproject.toml based packages + && pip install -U pip \ + && pip install --no-cache-dir \ + click \ + coverage \ + flake8 \ + git+https://github.com/OCA/pylint-odoo.git@refs/pull/329/head \ + six \ + && npm install --loglevel error --prefix /qa 'eslint@<6' \ + && deactivate \ + && mkdir -p /qa/artifacts \ + && git clone --depth 1 $MQT /qa/mqt + # Execute installation script by Odoo version # This is at the end to benefit from cache at build time # https://docs.docker.com/engine/reference/builder/#/impact-on-build-caching ARG ODOO_SOURCE=OCA/OCB ARG ODOO_VERSION=11.0 ENV ODOO_VERSION="$ODOO_VERSION" -RUN apt-get update \ - && apt-get install -y \ - build-essential \ - libevent-dev \ - libjpeg-dev \ - libldap2-dev \ - libsasl2-dev \ - libssl-dev \ - libxml2-dev \ - libxslt1-dev \ - python3-dev \ - zlib1g-dev \ - && pip install -r https://raw.githubusercontent.com/$ODOO_SOURCE/$ODOO_VERSION/requirements.txt \ - && pip install pg_activity \ +RUN debs="libldap2-dev libsasl2-dev" \ + && apt-get update \ + && apt-get install -yqq --no-install-recommends $debs \ + && pip install \ + -r https://raw.githubusercontent.com/$ODOO_SOURCE/$ODOO_VERSION/requirements.txt \ && (python3 -m compileall -q /usr/local/lib/python3.5/ || true) \ - && apt-get purge -yqq build-essential '*-dev' \ - && apt-mark -qq manual '*' \ - && rm -Rf /var/lib/apt/lists/* - -# HACK Special case for Werkzeug -USER odoo -RUN pip install --user Werkzeug==0.14.1 -USER root + && apt-get purge -yqq $debs \ + && rm -Rf /var/lib/apt/lists/* /tmp/* # Metadata ARG VCS_REF @@ -128,15 +166,31 @@ LABEL org.label-schema.schema-version="$VERSION" \ # Onbuild version, with all the magic FROM base AS onbuild +# Enable setting custom uids for odoo user during build of scaffolds +ONBUILD ARG UID=1000 +ONBUILD ARG GID=1000 + +# Enable Odoo user and filestore +ONBUILD RUN groupadd -g $GID odoo -o \ + && useradd -l -md /home/odoo -s /bin/false -u $UID -g $GID odoo \ + && mkdir -p /var/lib/odoo \ + && chown -R odoo:odoo /var/lib/odoo /qa/artifacts \ + && chmod a=rwX /qa/artifacts \ + && sync + # Subimage triggers ONBUILD ENTRYPOINT ["/opt/odoo/common/entrypoint"] ONBUILD CMD ["/usr/local/bin/odoo"] ONBUILD ARG AGGREGATE=true -ONBUILD ARG AUTO_REQUIREMENTS=false +ONBUILD ARG DEFAULT_REPO_PATTERN="https://github.com/OCA/{}.git" +ONBUILD ARG DEFAULT_REPO_PATTERN_ODOO="https://github.com/OCA/OCB.git" ONBUILD ARG DEPTH_DEFAULT=1 ONBUILD ARG DEPTH_MERGE=100 ONBUILD ARG CLEAN=true ONBUILD ARG COMPILE=true +ONBUILD ARG FONT_MONO="Liberation Mono" +ONBUILD ARG FONT_SANS="Liberation Sans" +ONBUILD ARG FONT_SERIF="Liberation Serif" ONBUILD ARG PIP_INSTALL_ODOO=true ONBUILD ARG ADMIN_PASSWORD=admin ONBUILD ARG SMTP_SERVER=smtp @@ -154,6 +208,8 @@ ONBUILD ARG PGPORT=5432 ONBUILD ARG PGDATABASE=prod # Config variables ONBUILD ENV ADMIN_PASSWORD="$ADMIN_PASSWORD" \ + DEFAULT_REPO_PATTERN="$DEFAULT_REPO_PATTERN" \ + DEFAULT_REPO_PATTERN_ODOO="$DEFAULT_REPO_PATTERN_ODOO" \ UNACCENT="$UNACCENT" \ PGUSER="$PGUSER" \ PGPASSWORD="$PGPASSWORD" \ @@ -169,12 +225,17 @@ ONBUILD ENV ADMIN_PASSWORD="$ADMIN_PASSWORD" \ EMAIL_FROM="$EMAIL_FROM" \ WITHOUT_DEMO="$WITHOUT_DEMO" ONBUILD ARG LOCAL_CUSTOM_DIR=./custom -ONBUILD COPY $LOCAL_CUSTOM_DIR /opt/odoo/custom -# https://docs.python.org/2.7/library/logging.html#levels +ONBUILD COPY --chown=root:odoo $LOCAL_CUSTOM_DIR /opt/odoo/custom + +# https://docs.python.org/3/library/logging.html#levels ONBUILD ARG LOG_LEVEL=INFO ONBUILD RUN mkdir -p /opt/odoo/custom/ssh \ && ln -s /opt/odoo/custom/ssh ~root/.ssh \ && chmod -R u=rwX,go= /opt/odoo/custom/ssh \ && sync +ONBUILD ARG DB_VERSION=latest ONBUILD RUN /opt/odoo/common/build && sync +ONBUILD VOLUME ["/var/lib/odoo"] ONBUILD USER odoo +# HACK Special case for Werkzeug +ONBUILD RUN pip install --user Werkzeug==0.14.1 diff --git a/12.0.Dockerfile b/12.0.Dockerfile new file mode 100644 index 00000000..b3e3f731 --- /dev/null +++ b/12.0.Dockerfile @@ -0,0 +1,236 @@ +FROM python:3.5-stretch AS base + +EXPOSE 8069 8072 + +ARG GEOIP_UPDATER_VERSION=4.1.5 +ARG MQT=https://github.com/OCA/maintainer-quality-tools.git +ARG WKHTMLTOPDF_VERSION=0.12.5 +ARG WKHTMLTOPDF_CHECKSUM='1140b0ab02aa6e17346af2f14ed0de807376de475ba90e1db3975f112fbd20bb' +ENV DB_FILTER=.* \ + DEPTH_DEFAULT=1 \ + DEPTH_MERGE=100 \ + EMAIL=https://hub.docker.com/r/tecnativa/odoo \ + GEOIP_ACCOUNT_ID="" \ + GEOIP_LICENSE_KEY="" \ + GIT_AUTHOR_NAME=docker-odoo \ + INITIAL_LANG="" \ + LC_ALL=C.UTF-8 \ + LIST_DB=false \ + NODE_PATH=/usr/local/lib/node_modules:/usr/lib/node_modules \ + OPENERP_SERVER=/opt/odoo/auto/odoo.conf \ + PATH="/home/odoo/.local/bin:$PATH" \ + PIP_NO_CACHE_DIR=0 \ + PTVSD_ARGS="--host 0.0.0.0 --port 6899 --wait --multiprocess" \ + PTVSD_ENABLE=0 \ + DEBUGPY_ARGS="--listen 0.0.0.0:6899 --wait-for-client" \ + DEBUGPY_ENABLE=0 \ + PUDB_RDB_HOST=0.0.0.0 \ + PUDB_RDB_PORT=6899 \ + PYTHONOPTIMIZE="" \ + UNACCENT=true \ + WAIT_DB=true \ + WDB_NO_BROWSER_AUTO_OPEN=True \ + WDB_SOCKET_SERVER=wdb \ + WDB_WEB_PORT=1984 \ + WDB_WEB_SERVER=localhost + +# Debian stretch was moved to archive (and stretch-updates does not exist in archive) +RUN sed -i 's,http://deb.debian.org,http://archive.debian.org,g;s,http://security.debian.org,http://archive.debian.org,g;s,\(.*stretch-updates\),#\1,' /etc/apt/sources.list + +# Other requirements and recommendations to run Odoo +# See https://github.com/$ODOO_SOURCE/blob/$ODOO_VERSION/debian/control +RUN apt-get -qq update \ + && apt-get -yqq upgrade \ + && apt-get install -yqq --no-install-recommends \ + chromium \ + ffmpeg \ + fonts-liberation2 \ + gettext \ + gnupg2 \ + locales-all \ + nano \ + ruby \ + telnet \ + vim \ + zlibc \ + apt-transport-https \ + ca-certificates \ + && echo 'deb https://apt-archive.postgresql.org/pub/repos/apt stretch-pgdg main' >> /etc/apt/sources.list.d/postgresql.list \ + && curl -SL https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - \ + && curl https://bootstrap.pypa.io/pip/3.5/get-pip.py | python3 /dev/stdin \ + && curl -sL https://deb.nodesource.com/setup_8.x | bash - \ + && apt-get update \ + && apt-get install -yqq --no-install-recommends nodejs \ + && curl -SLo wkhtmltox.deb https://github.com/wkhtmltopdf/wkhtmltopdf/releases/download/${WKHTMLTOPDF_VERSION}/wkhtmltox_${WKHTMLTOPDF_VERSION}-1.stretch_amd64.deb \ + && echo "${WKHTMLTOPDF_CHECKSUM} wkhtmltox.deb" | sha256sum -c - \ + && apt-get install -yqq --no-install-recommends ./wkhtmltox.deb \ + && rm wkhtmltox.deb \ + && wkhtmltopdf --version \ + && curl --silent -L --output geoipupdate_${GEOIP_UPDATER_VERSION}_linux_amd64.deb https://github.com/maxmind/geoipupdate/releases/download/v${GEOIP_UPDATER_VERSION}/geoipupdate_${GEOIP_UPDATER_VERSION}_linux_amd64.deb \ + && dpkg -i geoipupdate_${GEOIP_UPDATER_VERSION}_linux_amd64.deb \ + && rm geoipupdate_${GEOIP_UPDATER_VERSION}_linux_amd64.deb \ + && rm -Rf /var/lib/apt/lists/* /tmp/* + +# Special case to get latest Less +RUN ln -s /usr/bin/nodejs /usr/local/bin/node \ + && npm install -g less \ + && rm -Rf ~/.npm /tmp/* + +# Other facilities +WORKDIR /opt/odoo +RUN pip install \ + astor \ + # Install fix from https://github.com/acsone/click-odoo-contrib/pull/93 + git+https://github.com/Tecnativa/click-odoo-contrib.git@fix-active-modules-hashing \ + "git-aggregator<3.0.0" \ + "pg_activity<2.0.0" \ + plumbum \ + ptvsd \ + debugpy \ + pydevd-odoo \ + pudb \ + python-magic \ + watchdog \ + wdb \ + geoip2 \ + inotify \ + && sync +COPY bin-deprecated/* bin/* /usr/local/bin/ +COPY lib/doodbalib /usr/local/lib/python3.5/site-packages/doodbalib +COPY build.d common/build.d +COPY conf.d common/conf.d +COPY entrypoint.d common/entrypoint.d +RUN rm -f /opt/odoo/common/conf.d/60-geoip-ge17.conf \ + && mv /opt/odoo/common/conf.d/60-geoip-lt17.conf /opt/odoo/common/conf.d/60-geoip.conf +RUN mkdir -p auto/addons auto/geoip custom/src/private \ + && ln /usr/local/bin/direxec common/entrypoint \ + && ln /usr/local/bin/direxec common/build \ + && chmod -R a+rx common/entrypoint* common/build* /usr/local/bin \ + && chmod -R a+rX /usr/local/lib/python3.5/site-packages/doodbalib \ + && cp -a /etc/GeoIP.conf /etc/GeoIP.conf.orig \ + && mv /etc/GeoIP.conf /opt/odoo/auto/geoip/GeoIP.conf \ + && ln -s /opt/odoo/auto/geoip/GeoIP.conf /etc/GeoIP.conf \ + && sed -i 's/.*DatabaseDirectory .*$/DatabaseDirectory \/opt\/odoo\/auto\/geoip\//g' /opt/odoo/auto/geoip/GeoIP.conf \ + && sync + +# Doodba-QA dependencies in a separate virtualenv +COPY qa /qa +RUN python -m venv --system-site-packages /qa/venv \ + && . /qa/venv/bin/activate \ + # HACK: Upgrade pip: higher version needed to install pyproject.toml based packages + && pip install -U pip \ + && pip install --no-cache-dir \ + click \ + coverage \ + flake8 \ + git+https://github.com/OCA/pylint-odoo.git@refs/pull/329/head \ + six \ + && npm install --loglevel error --prefix /qa 'eslint@<7' \ + && deactivate \ + && mkdir -p /qa/artifacts \ + && git clone --depth 1 $MQT /qa/mqt + +# Execute installation script by Odoo version +# This is at the end to benefit from cache at build time +# https://docs.docker.com/engine/reference/builder/#/impact-on-build-caching +ARG ODOO_SOURCE=OCA/OCB +ARG ODOO_VERSION=12.0 +ENV ODOO_VERSION="$ODOO_VERSION" +RUN debs="libldap2-dev libsasl2-dev" \ + && apt-get update \ + && apt-get install -yqq --no-install-recommends $debs \ + && pip install \ + -r https://raw.githubusercontent.com/$ODOO_SOURCE/$ODOO_VERSION/requirements.txt \ + phonenumbers \ + 'websocket-client~=0.53' \ + && (python3 -m compileall -q /usr/local/lib/python3.5/ || true) \ + && apt-get purge -yqq $debs \ + && rm -Rf /var/lib/apt/lists/* /tmp/* + +# Metadata +ARG VCS_REF +ARG BUILD_DATE +ARG VERSION +LABEL org.label-schema.schema-version="$VERSION" \ + org.label-schema.vendor=Tecnativa \ + org.label-schema.license=Apache-2.0 \ + org.label-schema.build-date="$BUILD_DATE" \ + org.label-schema.vcs-ref="$VCS_REF" \ + org.label-schema.vcs-url="https://github.com/Tecnativa/doodba" + +# Onbuild version, with all the magic +FROM base AS onbuild + +# Enable setting custom uids for odoo user during build of scaffolds +ONBUILD ARG UID=1000 +ONBUILD ARG GID=1000 + +# Enable Odoo user and filestore +ONBUILD RUN groupadd -g $GID odoo -o \ + && useradd -l -md /home/odoo -s /bin/false -u $UID -g $GID odoo \ + && mkdir -p /var/lib/odoo \ + && chown -R odoo:odoo /var/lib/odoo /qa/artifacts \ + && chmod a=rwX /qa/artifacts \ + && sync + +# Subimage triggers +ONBUILD ENTRYPOINT ["/opt/odoo/common/entrypoint"] +ONBUILD CMD ["/usr/local/bin/odoo"] +ONBUILD ARG AGGREGATE=true +ONBUILD ARG DEFAULT_REPO_PATTERN="https://github.com/OCA/{}.git" +ONBUILD ARG DEFAULT_REPO_PATTERN_ODOO="https://github.com/OCA/OCB.git" +ONBUILD ARG DEPTH_DEFAULT=1 +ONBUILD ARG DEPTH_MERGE=100 +ONBUILD ARG CLEAN=true +ONBUILD ARG COMPILE=true +ONBUILD ARG FONT_MONO="Liberation Mono" +ONBUILD ARG FONT_SANS="Liberation Sans" +ONBUILD ARG FONT_SERIF="Liberation Serif" +ONBUILD ARG PIP_INSTALL_ODOO=true +ONBUILD ARG ADMIN_PASSWORD=admin +ONBUILD ARG SMTP_SERVER=smtp +ONBUILD ARG SMTP_PORT=25 +ONBUILD ARG SMTP_USER=false +ONBUILD ARG SMTP_PASSWORD=false +ONBUILD ARG SMTP_SSL=false +ONBUILD ARG EMAIL_FROM="" +ONBUILD ARG PROXY_MODE=false +ONBUILD ARG WITHOUT_DEMO=all +ONBUILD ARG PGUSER=odoo +ONBUILD ARG PGPASSWORD=odoopassword +ONBUILD ARG PGHOST=db +ONBUILD ARG PGPORT=5432 +ONBUILD ARG PGDATABASE=prod +# Config variables +ONBUILD ENV ADMIN_PASSWORD="$ADMIN_PASSWORD" \ + DEFAULT_REPO_PATTERN="$DEFAULT_REPO_PATTERN" \ + DEFAULT_REPO_PATTERN_ODOO="$DEFAULT_REPO_PATTERN_ODOO" \ + UNACCENT="$UNACCENT" \ + PGUSER="$PGUSER" \ + PGPASSWORD="$PGPASSWORD" \ + PGHOST="$PGHOST" \ + PGPORT=$PGPORT \ + PGDATABASE="$PGDATABASE" \ + PROXY_MODE="$PROXY_MODE" \ + SMTP_SERVER="$SMTP_SERVER" \ + SMTP_PORT=$SMTP_PORT \ + SMTP_USER="$SMTP_USER" \ + SMTP_PASSWORD="$SMTP_PASSWORD" \ + SMTP_SSL="$SMTP_SSL" \ + EMAIL_FROM="$EMAIL_FROM" \ + WITHOUT_DEMO="$WITHOUT_DEMO" +ONBUILD ARG LOCAL_CUSTOM_DIR=./custom +ONBUILD COPY --chown=root:odoo $LOCAL_CUSTOM_DIR /opt/odoo/custom + +# https://docs.python.org/3/library/logging.html#levels +ONBUILD ARG LOG_LEVEL=INFO +ONBUILD RUN mkdir -p /opt/odoo/custom/ssh \ + && ln -s /opt/odoo/custom/ssh ~root/.ssh \ + && chmod -R u=rwX,go= /opt/odoo/custom/ssh \ + && sync +ONBUILD ARG DB_VERSION=latest +ONBUILD RUN /opt/odoo/common/build && sync +ONBUILD VOLUME ["/var/lib/odoo"] +ONBUILD USER odoo +# HACK Special case for Werkzeug +ONBUILD RUN pip install --user Werkzeug==0.14.1 diff --git a/13.0.Dockerfile b/13.0.Dockerfile new file mode 100644 index 00000000..52006396 --- /dev/null +++ b/13.0.Dockerfile @@ -0,0 +1,239 @@ +FROM python:3.6-slim-buster AS base + +EXPOSE 8069 8072 + +ARG GEOIP_UPDATER_VERSION=4.1.5 +ARG MQT=https://github.com/OCA/maintainer-quality-tools.git +ARG WKHTMLTOPDF_VERSION=0.12.5 +ARG WKHTMLTOPDF_CHECKSUM='dfab5506104447eef2530d1adb9840ee3a67f30caaad5e9bcb8743ef2f9421bd' +ENV DB_FILTER=.* \ + DEPTH_DEFAULT=1 \ + DEPTH_MERGE=100 \ + EMAIL=https://hub.docker.com/r/tecnativa/odoo \ + GEOIP_ACCOUNT_ID="" \ + GEOIP_LICENSE_KEY="" \ + GIT_AUTHOR_NAME=docker-odoo \ + INITIAL_LANG="" \ + LC_ALL=C.UTF-8 \ + LIST_DB=false \ + NODE_PATH=/usr/local/lib/node_modules:/usr/lib/node_modules \ + OPENERP_SERVER=/opt/odoo/auto/odoo.conf \ + PATH="/home/odoo/.local/bin:$PATH" \ + PIP_NO_CACHE_DIR=0 \ + PTVSD_ARGS="--host 0.0.0.0 --port 6899 --wait --multiprocess" \ + PTVSD_ENABLE=0 \ + DEBUGPY_ARGS="--listen 0.0.0.0:6899 --wait-for-client" \ + DEBUGPY_ENABLE=0 \ + PUDB_RDB_HOST=0.0.0.0 \ + PUDB_RDB_PORT=6899 \ + PYTHONOPTIMIZE="" \ + UNACCENT=true \ + WAIT_DB=true \ + WDB_NO_BROWSER_AUTO_OPEN=True \ + WDB_SOCKET_SERVER=wdb \ + WDB_WEB_PORT=1984 \ + WDB_WEB_SERVER=localhost + +# Debian buster was moved to archive +RUN sed -i 's,http://deb.debian.org,http://archive.debian.org,g;s,http://security.debian.org,http://archive.debian.org,g' /etc/apt/sources.list +# Other requirements and recommendations +# See https://github.com/$ODOO_SOURCE/blob/$ODOO_VERSION/debian/control +RUN apt-get -qq update \ + && apt-get install -yqq --no-install-recommends \ + curl \ + && curl -SLo wkhtmltox.deb https://github.com/wkhtmltopdf/wkhtmltopdf/releases/download/${WKHTMLTOPDF_VERSION}/wkhtmltox_${WKHTMLTOPDF_VERSION}-1.buster_amd64.deb \ + && echo "${WKHTMLTOPDF_CHECKSUM} wkhtmltox.deb" | sha256sum -c - \ + && apt-get install -yqq --no-install-recommends \ + ./wkhtmltox.deb \ + chromium \ + ffmpeg \ + fonts-liberation2 \ + gettext \ + git \ + gnupg2 \ + locales-all \ + nano \ + npm \ + openssh-client \ + telnet \ + vim \ + zlibc \ + && echo 'deb https://apt-archive.postgresql.org/pub/repos/apt buster-pgdg main' >> /etc/apt/sources.list.d/postgresql.list \ + && curl -SL https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - \ + && apt-get update \ + && apt-get install -yqq --no-install-recommends \ + && curl --silent -L --output geoipupdate_${GEOIP_UPDATER_VERSION}_linux_amd64.deb https://github.com/maxmind/geoipupdate/releases/download/v${GEOIP_UPDATER_VERSION}/geoipupdate_${GEOIP_UPDATER_VERSION}_linux_amd64.deb \ + && dpkg -i geoipupdate_${GEOIP_UPDATER_VERSION}_linux_amd64.deb \ + && rm geoipupdate_${GEOIP_UPDATER_VERSION}_linux_amd64.deb \ + && apt-get autopurge -yqq \ + && rm -Rf wkhtmltox.deb /var/lib/apt/lists/* /tmp/* \ + && sync + +WORKDIR /opt/odoo +COPY bin/* /usr/local/bin/ +COPY lib/doodbalib /usr/local/lib/python3.6/site-packages/doodbalib +COPY build.d common/build.d +COPY conf.d common/conf.d +COPY entrypoint.d common/entrypoint.d +RUN rm -f /opt/odoo/common/conf.d/60-geoip-ge17.conf \ + && mv /opt/odoo/common/conf.d/60-geoip-lt17.conf /opt/odoo/common/conf.d/60-geoip.conf +RUN mkdir -p auto/addons auto/geoip custom/src/private \ + && ln /usr/local/bin/direxec common/entrypoint \ + && ln /usr/local/bin/direxec common/build \ + && chmod -R a+rx common/entrypoint* common/build* /usr/local/bin \ + && chmod -R a+rX /usr/local/lib/python3.6/site-packages/doodbalib \ + && cp -a /etc/GeoIP.conf /etc/GeoIP.conf.orig \ + && mv /etc/GeoIP.conf /opt/odoo/auto/geoip/GeoIP.conf \ + && ln -s /opt/odoo/auto/geoip/GeoIP.conf /etc/GeoIP.conf \ + && sed -i 's/.*DatabaseDirectory .*$/DatabaseDirectory \/opt\/odoo\/auto\/geoip\//g' /opt/odoo/auto/geoip/GeoIP.conf \ + && sync + +# Doodba-QA dependencies in a separate virtualenv +COPY qa /qa +RUN python -m venv --system-site-packages /qa/venv \ + && . /qa/venv/bin/activate \ + && pip install \ + click \ + coverage \ + six \ + && deactivate \ + && mkdir -p /qa/artifacts \ + && git clone --depth 1 $MQT /qa/mqt + +ARG ODOO_SOURCE=OCA/OCB +ARG ODOO_VERSION=13.0 +ENV ODOO_VERSION="$ODOO_VERSION" + +# Install Odoo hard & soft dependencies, and Doodba utilities +RUN build_deps=" \ + build-essential \ + libfreetype6-dev \ + libfribidi-dev \ + libghc-zlib-dev \ + libharfbuzz-dev \ + libjpeg-dev \ + liblcms2-dev \ + libldap2-dev \ + libopenjp2-7-dev \ + libpq-dev \ + libsasl2-dev \ + libtiff5-dev \ + libwebp-dev \ + libxml2-dev \ + libxslt-dev \ + tcl-dev \ + tk-dev \ + zlib1g-dev \ + " \ + && apt-get update \ + && apt-get install -yqq --no-install-recommends $build_deps \ + && pip install \ + -r https://raw.githubusercontent.com/$ODOO_SOURCE/$ODOO_VERSION/requirements.txt \ + 'websocket-client~=0.56' \ + astor \ + "git-aggregator<3.0.0" \ + # Install fix from https://github.com/acsone/click-odoo-contrib/pull/93 + git+https://github.com/Tecnativa/click-odoo-contrib.git@fix-active-modules-hashing \ + "pg_activity<2.0.0" \ + phonenumbers \ + plumbum \ + ptvsd \ + debugpy \ + pydevd-odoo \ + pudb \ + python-magic \ + watchdog \ + wdb \ + geoip2 \ + inotify \ + && (python3 -m compileall -q /usr/local/lib/python3.6/ || true) \ + && apt-get purge -yqq $build_deps \ + && apt-get autopurge -yqq \ + && rm -Rf /var/lib/apt/lists/* /tmp/* + +# Metadata +ARG VCS_REF +ARG BUILD_DATE +ARG VERSION +LABEL org.label-schema.schema-version="$VERSION" \ + org.label-schema.vendor=Tecnativa \ + org.label-schema.license=Apache-2.0 \ + org.label-schema.build-date="$BUILD_DATE" \ + org.label-schema.vcs-ref="$VCS_REF" \ + org.label-schema.vcs-url="https://github.com/Tecnativa/doodba" + +# Onbuild version, with all the magic +FROM base AS onbuild + +# Enable setting custom uids for odoo user during build of scaffolds +ONBUILD ARG UID=1000 +ONBUILD ARG GID=1000 + +# Enable Odoo user and filestore +ONBUILD RUN groupadd -g $GID odoo -o \ + && useradd -l -md /home/odoo -s /bin/false -u $UID -g $GID odoo \ + && mkdir -p /var/lib/odoo \ + && chown -R odoo:odoo /var/lib/odoo /qa/artifacts \ + && chmod a=rwX /qa/artifacts \ + && sync + +# Subimage triggers +ONBUILD ENTRYPOINT ["/opt/odoo/common/entrypoint"] +ONBUILD CMD ["/usr/local/bin/odoo"] +ONBUILD ARG AGGREGATE=true +ONBUILD ARG DEFAULT_REPO_PATTERN="https://github.com/OCA/{}.git" +ONBUILD ARG DEFAULT_REPO_PATTERN_ODOO="https://github.com/OCA/OCB.git" +ONBUILD ARG DEPTH_DEFAULT=1 +ONBUILD ARG DEPTH_MERGE=100 +ONBUILD ARG CLEAN=true +ONBUILD ARG COMPILE=true +ONBUILD ARG FONT_MONO="Liberation Mono" +ONBUILD ARG FONT_SANS="Liberation Sans" +ONBUILD ARG FONT_SERIF="Liberation Serif" +ONBUILD ARG PIP_INSTALL_ODOO=true +ONBUILD ARG ADMIN_PASSWORD=admin +ONBUILD ARG SMTP_SERVER=smtp +ONBUILD ARG SMTP_PORT=25 +ONBUILD ARG SMTP_USER=false +ONBUILD ARG SMTP_PASSWORD=false +ONBUILD ARG SMTP_SSL=false +ONBUILD ARG EMAIL_FROM="" +ONBUILD ARG PROXY_MODE=false +ONBUILD ARG WITHOUT_DEMO=all +ONBUILD ARG PGUSER=odoo +ONBUILD ARG PGPASSWORD=odoopassword +ONBUILD ARG PGHOST=db +ONBUILD ARG PGPORT=5432 +ONBUILD ARG PGDATABASE=prod + +# Config variables +ONBUILD ENV ADMIN_PASSWORD="$ADMIN_PASSWORD" \ + DEFAULT_REPO_PATTERN="$DEFAULT_REPO_PATTERN" \ + DEFAULT_REPO_PATTERN_ODOO="$DEFAULT_REPO_PATTERN_ODOO" \ + UNACCENT="$UNACCENT" \ + PGUSER="$PGUSER" \ + PGPASSWORD="$PGPASSWORD" \ + PGHOST="$PGHOST" \ + PGPORT=$PGPORT \ + PGDATABASE="$PGDATABASE" \ + PROXY_MODE="$PROXY_MODE" \ + SMTP_SERVER="$SMTP_SERVER" \ + SMTP_PORT=$SMTP_PORT \ + SMTP_USER="$SMTP_USER" \ + SMTP_PASSWORD="$SMTP_PASSWORD" \ + SMTP_SSL="$SMTP_SSL" \ + EMAIL_FROM="$EMAIL_FROM" \ + WITHOUT_DEMO="$WITHOUT_DEMO" +ONBUILD ARG LOCAL_CUSTOM_DIR=./custom +ONBUILD COPY --chown=root:odoo $LOCAL_CUSTOM_DIR /opt/odoo/custom + +# https://docs.python.org/3/library/logging.html#levels +ONBUILD ARG LOG_LEVEL=INFO +ONBUILD RUN mkdir -p /opt/odoo/custom/ssh \ + && ln -s /opt/odoo/custom/ssh ~root/.ssh \ + && chmod -R u=rwX,go= /opt/odoo/custom/ssh \ + && sync +ONBUILD ARG DB_VERSION=latest +ONBUILD RUN /opt/odoo/common/build && sync +ONBUILD VOLUME ["/var/lib/odoo"] +ONBUILD USER odoo diff --git a/14.0.Dockerfile b/14.0.Dockerfile new file mode 100644 index 00000000..446eb047 --- /dev/null +++ b/14.0.Dockerfile @@ -0,0 +1,256 @@ +FROM python:3.8-slim-buster AS base + +EXPOSE 8069 8072 + +ARG TARGETARCH +ARG GEOIP_UPDATER_VERSION=6.0.0 +ARG WKHTMLTOPDF_VERSION=0.12.5 +ARG WKHTMLTOPDF_AMD64_CHECKSUM='dfab5506104447eef2530d1adb9840ee3a67f30caaad5e9bcb8743ef2f9421bd' +ARG WKHTMLTOPDF_ARM64_CHECKSUM="3344e3a72f4cb4c1218cf48ac5fa9e88bef62aa7fa6f2295be7d5bc1fef100b1" +ENV DB_FILTER=.* \ + DEPTH_DEFAULT=1 \ + DEPTH_MERGE=100 \ + EMAIL=https://hub.docker.com/r/tecnativa/odoo \ + GEOIP_ACCOUNT_ID="" \ + GEOIP_LICENSE_KEY="" \ + GIT_AUTHOR_NAME=docker-odoo \ + INITIAL_LANG="" \ + LC_ALL=C.UTF-8 \ + LIST_DB=false \ + NODE_PATH=/usr/local/lib/node_modules:/usr/lib/node_modules \ + OPENERP_SERVER=/opt/odoo/auto/odoo.conf \ + PATH="/home/odoo/.local/bin:$PATH" \ + PIP_NO_CACHE_DIR=0 \ + DEBUGPY_ARGS="--listen 0.0.0.0:6899 --wait-for-client" \ + DEBUGPY_ENABLE=0 \ + PUDB_RDB_HOST=0.0.0.0 \ + PUDB_RDB_PORT=6899 \ + PYTHONOPTIMIZE="" \ + UNACCENT=true \ + WAIT_DB=true \ + WDB_NO_BROWSER_AUTO_OPEN=True \ + WDB_SOCKET_SERVER=wdb \ + WDB_WEB_PORT=1984 \ + WDB_WEB_SERVER=localhost + +# Debian buster was moved to archive +RUN sed -i 's,http://deb.debian.org,http://archive.debian.org,g;s,http://security.debian.org,http://archive.debian.org,g' /etc/apt/sources.list +# Other requirements and recommendations +# See https://github.com/$ODOO_SOURCE/blob/$ODOO_VERSION/debian/control +RUN apt-get -qq update \ + && apt-get install -yqq --no-install-recommends \ + curl; \ + if [ "$TARGETARCH" = "arm64" ]; then \ + if [ "$WKHTMLTOPDF_VERSION" != "0.12.6.1" ]; then \ + echo "Error: WKHTMLTOPDF_VERSION must be exactly 0.12.6.1 for arm builds. Forcing version to 0.12.6.1"; \ + export WKHTMLTOPDF_VERSION="0.12.6.1";\ + fi; \ + WKHTMLTOPDF_URL="https://github.com/wkhtmltopdf/packaging/releases/download/${WKHTMLTOPDF_VERSION}-2/wkhtmltox_${WKHTMLTOPDF_VERSION}-2.bullseye_${TARGETARCH}.deb" \ + WKHTMLTOPDF_CHECKSUM=$WKHTMLTOPDF_ARM64_CHECKSUM; \ + elif [ "$TARGETARCH" = "amd64" ]; then \ + WKHTMLTOPDF_URL="https://github.com/wkhtmltopdf/wkhtmltopdf/releases/download/${WKHTMLTOPDF_VERSION}/wkhtmltox_${WKHTMLTOPDF_VERSION}-1.buster_${TARGETARCH}.deb" \ + WKHTMLTOPDF_CHECKSUM=$WKHTMLTOPDF_AMD64_CHECKSUM; \ + else \ + echo "Unsupported architecture: $TARGETARCH" >&2; \ + exit 1; \ + fi \ + && curl -SLo wkhtmltox.deb ${WKHTMLTOPDF_URL} \ + && echo "Downloading wkhtmltopdf from: ${WKHTMLTOPDF_URL}" \ + && echo "Expected wkhtmltox checksum: ${WKHTMLTOPDF_CHECKSUM}" \ + && echo "Computed wkhtmltox checksum: $(sha256sum wkhtmltox.deb | awk '{ print $1 }')" \ + && echo "${WKHTMLTOPDF_CHECKSUM} wkhtmltox.deb" | sha256sum -c - \ + && apt-get install -yqq --no-install-recommends \ + ./wkhtmltox.deb \ + chromium \ + ffmpeg \ + fonts-liberation2 \ + gettext \ + git \ + gnupg2 \ + locales-all \ + nano \ + npm \ + openssh-client \ + telnet \ + vim \ + zlibc \ + && echo 'deb https://apt-archive.postgresql.org/pub/repos/apt buster-pgdg main' >> /etc/apt/sources.list.d/postgresql.list \ + && curl -SL https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - \ + && apt-get update \ + && curl --silent -L --output geoipupdate_${GEOIP_UPDATER_VERSION}_linux_${TARGETARCH}.deb https://github.com/maxmind/geoipupdate/releases/download/v${GEOIP_UPDATER_VERSION}/geoipupdate_${GEOIP_UPDATER_VERSION}_linux_${TARGETARCH}.deb \ + && dpkg -i geoipupdate_${GEOIP_UPDATER_VERSION}_linux_${TARGETARCH}.deb \ + && rm geoipupdate_${GEOIP_UPDATER_VERSION}_linux_${TARGETARCH}.deb \ + && apt-get autopurge -yqq \ + && rm -Rf wkhtmltox.deb /var/lib/apt/lists/* /tmp/* \ + && sync + +WORKDIR /opt/odoo +COPY bin/* /usr/local/bin/ +COPY lib/doodbalib /usr/local/lib/python3.8/site-packages/doodbalib +COPY build.d common/build.d +COPY conf.d common/conf.d +COPY entrypoint.d common/entrypoint.d +RUN rm -f /opt/odoo/common/conf.d/60-geoip-ge17.conf \ + && mv /opt/odoo/common/conf.d/60-geoip-lt17.conf /opt/odoo/common/conf.d/60-geoip.conf +RUN mkdir -p auto/addons auto/geoip custom/src/private \ + && ln /usr/local/bin/direxec common/entrypoint \ + && ln /usr/local/bin/direxec common/build \ + && chmod -R a+rx common/entrypoint* common/build* /usr/local/bin \ + && chmod -R a+rX /usr/local/lib/python3.8/site-packages/doodbalib \ + && cp -a /etc/GeoIP.conf /etc/GeoIP.conf.orig \ + && mv /etc/GeoIP.conf /opt/odoo/auto/geoip/GeoIP.conf \ + && ln -s /opt/odoo/auto/geoip/GeoIP.conf /etc/GeoIP.conf \ + && sed -i 's/.*DatabaseDirectory .*$/DatabaseDirectory \/opt\/odoo\/auto\/geoip\//g' /opt/odoo/auto/geoip/GeoIP.conf \ + && sync + +# Doodba-QA dependencies in a separate virtualenv +COPY qa /qa +RUN python -m venv --system-site-packages /qa/venv \ + && . /qa/venv/bin/activate \ + && pip install \ + click \ + coverage \ + six \ + && deactivate \ + && mkdir -p /qa/artifacts + +ARG ODOO_SOURCE=OCA/OCB +ARG ODOO_VERSION=14.0 +ENV ODOO_VERSION="$ODOO_VERSION" + +# Install Odoo hard & soft dependencies, and Doodba utilities +RUN build_deps=" \ + build-essential \ + libfreetype6-dev \ + libfribidi-dev \ + libghc-zlib-dev \ + libharfbuzz-dev \ + libjpeg-dev \ + liblcms2-dev \ + libldap2-dev \ + libopenjp2-7-dev \ + libpq-dev \ + libsasl2-dev \ + libtiff5-dev \ + libwebp-dev \ + libxml2-dev \ + libxslt-dev \ + tcl-dev \ + tk-dev \ + zlib1g-dev \ + " \ + && apt-get update \ + && apt-get install -yqq --no-install-recommends $build_deps \ + && curl -o requirements.txt https://raw.githubusercontent.com/$ODOO_SOURCE/$ODOO_VERSION/requirements.txt \ + && echo "Setting gevent and greenlet versions to 21.12.0 and 1.1.0 (compatible with Debian Buster)" \ + && sed -i -E "s/(gevent==)[0-9\.]+/\121.12.0/; s/(greenlet==)[0-9\.]+/\11.1.0/" requirements.txt \ + && pip install -r requirements.txt \ + 'websocket-client~=0.56' \ + astor \ + # Install fix from https://github.com/acsone/click-odoo-contrib/pull/93 + git+https://github.com/Tecnativa/click-odoo-contrib.git@fix-active-modules-hashing \ + debugpy \ + pydevd-odoo \ + geoip2 \ + "git-aggregator<3.0.0" \ + inotify \ + pdfminer.six \ + pg_activity \ + phonenumbers \ + plumbum \ + pudb \ + pyOpenSSL \ + python-magic \ + watchdog \ + wdb \ + && (python3 -m compileall -q /usr/local/lib/python3.8/ || true) \ + && apt-get purge -yqq $build_deps \ + && apt-get autopurge -yqq \ + && rm -Rf /var/lib/apt/lists/* /tmp/* + +# Metadata +ARG VCS_REF +ARG BUILD_DATE +ARG VERSION +LABEL org.label-schema.schema-version="$VERSION" \ + org.label-schema.vendor=Tecnativa \ + org.label-schema.license=Apache-2.0 \ + org.label-schema.build-date="$BUILD_DATE" \ + org.label-schema.vcs-ref="$VCS_REF" \ + org.label-schema.vcs-url="https://github.com/Tecnativa/doodba" + +# Onbuild version, with all the magic +FROM base AS onbuild + +# Enable setting custom uids for odoo user during build of scaffolds +ONBUILD ARG UID=1000 +ONBUILD ARG GID=1000 + +# Enable Odoo user and filestore +ONBUILD RUN groupadd -g $GID odoo -o \ + && useradd -l -md /home/odoo -s /bin/false -u $UID -g $GID odoo \ + && mkdir -p /var/lib/odoo \ + && chown -R odoo:odoo /var/lib/odoo /qa/artifacts \ + && chmod a=rwX /qa/artifacts \ + && sync + +# Subimage triggers +ONBUILD ENTRYPOINT ["/opt/odoo/common/entrypoint"] +ONBUILD CMD ["/usr/local/bin/odoo"] +ONBUILD ARG AGGREGATE=true +ONBUILD ARG DEFAULT_REPO_PATTERN="https://github.com/OCA/{}.git" +ONBUILD ARG DEFAULT_REPO_PATTERN_ODOO="https://github.com/OCA/OCB.git" +ONBUILD ARG DEPTH_DEFAULT=1 +ONBUILD ARG DEPTH_MERGE=100 +ONBUILD ARG CLEAN=true +ONBUILD ARG COMPILE=true +ONBUILD ARG FONT_MONO="Liberation Mono" +ONBUILD ARG FONT_SANS="Liberation Sans" +ONBUILD ARG FONT_SERIF="Liberation Serif" +ONBUILD ARG PIP_INSTALL_ODOO=true +ONBUILD ARG ADMIN_PASSWORD=admin +ONBUILD ARG SMTP_SERVER=smtp +ONBUILD ARG SMTP_PORT=25 +ONBUILD ARG SMTP_USER=false +ONBUILD ARG SMTP_PASSWORD=false +ONBUILD ARG SMTP_SSL=false +ONBUILD ARG EMAIL_FROM="" +ONBUILD ARG PROXY_MODE=false +ONBUILD ARG WITHOUT_DEMO=all +ONBUILD ARG PGUSER=odoo +ONBUILD ARG PGPASSWORD=odoopassword +ONBUILD ARG PGHOST=db +ONBUILD ARG PGPORT=5432 +ONBUILD ARG PGDATABASE=prod + +# Config variables +ONBUILD ENV ADMIN_PASSWORD="$ADMIN_PASSWORD" \ + DEFAULT_REPO_PATTERN="$DEFAULT_REPO_PATTERN" \ + DEFAULT_REPO_PATTERN_ODOO="$DEFAULT_REPO_PATTERN_ODOO" \ + UNACCENT="$UNACCENT" \ + PGUSER="$PGUSER" \ + PGPASSWORD="$PGPASSWORD" \ + PGHOST="$PGHOST" \ + PGPORT=$PGPORT \ + PGDATABASE="$PGDATABASE" \ + PROXY_MODE="$PROXY_MODE" \ + SMTP_SERVER="$SMTP_SERVER" \ + SMTP_PORT=$SMTP_PORT \ + SMTP_USER="$SMTP_USER" \ + SMTP_PASSWORD="$SMTP_PASSWORD" \ + SMTP_SSL="$SMTP_SSL" \ + EMAIL_FROM="$EMAIL_FROM" \ + WITHOUT_DEMO="$WITHOUT_DEMO" +ONBUILD ARG LOCAL_CUSTOM_DIR=./custom +ONBUILD COPY --chown=root:odoo $LOCAL_CUSTOM_DIR /opt/odoo/custom + +# https://docs.python.org/3/library/logging.html#levels +ONBUILD ARG LOG_LEVEL=INFO +ONBUILD RUN mkdir -p /opt/odoo/custom/ssh \ + && ln -s /opt/odoo/custom/ssh ~root/.ssh \ + && chmod -R u=rwX,go= /opt/odoo/custom/ssh \ + && sync +ONBUILD ARG DB_VERSION=latest +ONBUILD RUN /opt/odoo/common/build && sync +ONBUILD VOLUME ["/var/lib/odoo"] +ONBUILD USER odoo diff --git a/15.0.Dockerfile b/15.0.Dockerfile new file mode 100644 index 00000000..a9146618 --- /dev/null +++ b/15.0.Dockerfile @@ -0,0 +1,257 @@ +FROM python:3.8-slim-bullseye AS base + +EXPOSE 8069 8072 + +ARG TARGETARCH +ARG GEOIP_UPDATER_VERSION=6.0.0 +ARG WKHTMLTOPDF_VERSION=0.12.5 +ARG WKHTMLTOPDF_AMD64_CHECKSUM='dfab5506104447eef2530d1adb9840ee3a67f30caaad5e9bcb8743ef2f9421bd' +ARG WKHTMLTOPDF_ARM64_CHECKSUM="3344e3a72f4cb4c1218cf48ac5fa9e88bef62aa7fa6f2295be7d5bc1fef100b1" +ENV DB_FILTER=.* \ + DEPTH_DEFAULT=1 \ + DEPTH_MERGE=100 \ + EMAIL=https://hub.docker.com/r/tecnativa/odoo \ + GEOIP_ACCOUNT_ID="" \ + GEOIP_LICENSE_KEY="" \ + GIT_AUTHOR_NAME=docker-odoo \ + INITIAL_LANG="" \ + LC_ALL=C.UTF-8 \ + LIST_DB=false \ + NODE_PATH=/usr/local/lib/node_modules:/usr/lib/node_modules \ + OPENERP_SERVER=/opt/odoo/auto/odoo.conf \ + PATH="/home/odoo/.local/bin:$PATH" \ + PIP_NO_CACHE_DIR=0 \ + DEBUGPY_ARGS="--listen 0.0.0.0:6899 --wait-for-client" \ + DEBUGPY_ENABLE=0 \ + PUDB_RDB_HOST=0.0.0.0 \ + PUDB_RDB_PORT=6899 \ + PYTHONOPTIMIZE="" \ + UNACCENT=true \ + WAIT_DB=true \ + WDB_NO_BROWSER_AUTO_OPEN=True \ + WDB_SOCKET_SERVER=wdb \ + WDB_WEB_PORT=1984 \ + WDB_WEB_SERVER=localhost + +# Other requirements and recommendations +# See https://github.com/$ODOO_SOURCE/blob/$ODOO_VERSION/debian/control +RUN apt-get -qq update \ + && apt-get install -yqq --no-install-recommends \ + curl; \ + if [ "$TARGETARCH" = "arm64" ]; then \ + if [ "$WKHTMLTOPDF_VERSION" != "0.12.6.1" ]; then \ + echo "Error: WKHTMLTOPDF_VERSION must be exactly 0.12.6.1 for arm builds. Forcing version to 0.12.6.1"; \ + export WKHTMLTOPDF_VERSION="0.12.6.1";\ + fi; \ + WKHTMLTOPDF_URL="https://github.com/wkhtmltopdf/packaging/releases/download/${WKHTMLTOPDF_VERSION}-2/wkhtmltox_${WKHTMLTOPDF_VERSION}-2.bullseye_${TARGETARCH}.deb" \ + WKHTMLTOPDF_CHECKSUM=$WKHTMLTOPDF_ARM64_CHECKSUM; \ + elif [ "$TARGETARCH" = "amd64" ]; then \ + WKHTMLTOPDF_URL="https://github.com/wkhtmltopdf/wkhtmltopdf/releases/download/${WKHTMLTOPDF_VERSION}/wkhtmltox_${WKHTMLTOPDF_VERSION}-1.buster_${TARGETARCH}.deb" \ + WKHTMLTOPDF_CHECKSUM=$WKHTMLTOPDF_AMD64_CHECKSUM; \ + else \ + echo "Unsupported architecture: $TARGETARCH" >&2; \ + exit 1; \ + fi \ + && curl -SLo wkhtmltox.deb ${WKHTMLTOPDF_URL} \ + && echo "Downloading wkhtmltopdf from: ${WKHTMLTOPDF_URL}" \ + && echo "Expected wkhtmltox checksum: ${WKHTMLTOPDF_CHECKSUM}" \ + && echo "Computed wkhtmltox checksum: $(sha256sum wkhtmltox.deb | awk '{ print $1 }')" \ + && echo "${WKHTMLTOPDF_CHECKSUM} wkhtmltox.deb" | sha256sum -c - \ + && (dpkg -i wkhtmltox.deb || apt-get -y install -f) \ + && apt-get install -yqq --no-install-recommends \ + chromium \ + ffmpeg \ + fonts-liberation2 \ + gettext \ + git \ + gnupg2 \ + locales-all \ + nano \ + npm \ + openssh-client \ + telnet \ + vim \ + && echo 'deb https://apt.postgresql.org/pub/repos/apt/ bullseye-pgdg main' >> /etc/apt/sources.list.d/postgresql.list \ + && curl -SL https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - \ + && apt-get update \ + && curl --silent -L --output geoipupdate_${GEOIP_UPDATER_VERSION}_linux_${TARGETARCH}.deb https://github.com/maxmind/geoipupdate/releases/download/v${GEOIP_UPDATER_VERSION}/geoipupdate_${GEOIP_UPDATER_VERSION}_linux_${TARGETARCH}.deb \ + && dpkg -i geoipupdate_${GEOIP_UPDATER_VERSION}_linux_${TARGETARCH}.deb \ + && rm geoipupdate_${GEOIP_UPDATER_VERSION}_linux_${TARGETARCH}.deb \ + && apt-get autopurge -yqq \ + && rm -Rf wkhtmltox.deb /var/lib/apt/lists/* /tmp/* \ + && sync + +WORKDIR /opt/odoo +COPY bin/* /usr/local/bin/ +COPY lib/doodbalib /usr/local/lib/python3.8/site-packages/doodbalib +COPY build.d common/build.d +COPY conf.d common/conf.d +COPY entrypoint.d common/entrypoint.d +RUN rm -f /opt/odoo/common/conf.d/60-geoip-ge17.conf \ + && mv /opt/odoo/common/conf.d/60-geoip-lt17.conf /opt/odoo/common/conf.d/60-geoip.conf +RUN mkdir -p auto/addons auto/geoip custom/src/private \ + && ln /usr/local/bin/direxec common/entrypoint \ + && ln /usr/local/bin/direxec common/build \ + && chmod -R a+rx common/entrypoint* common/build* /usr/local/bin \ + && chmod -R a+rX /usr/local/lib/python3.8/site-packages/doodbalib \ + && cp -a /etc/GeoIP.conf /etc/GeoIP.conf.orig \ + && mv /etc/GeoIP.conf /opt/odoo/auto/geoip/GeoIP.conf \ + && ln -s /opt/odoo/auto/geoip/GeoIP.conf /etc/GeoIP.conf \ + && sed -i 's/.*DatabaseDirectory .*$/DatabaseDirectory \/opt\/odoo\/auto\/geoip\//g' /opt/odoo/auto/geoip/GeoIP.conf \ + && sync + +# Doodba-QA dependencies in a separate virtualenv +COPY qa /qa +RUN python -m venv --system-site-packages /qa/venv \ + && . /qa/venv/bin/activate \ + && pip install \ + click \ + coverage \ + && deactivate \ + && mkdir -p /qa/artifacts + +ARG ODOO_SOURCE=OCA/OCB +ARG ODOO_VERSION=15.0 +ENV ODOO_VERSION="$ODOO_VERSION" + +# Install Odoo hard & soft dependencies, and Doodba utilities +RUN build_deps=" \ + build-essential \ + libfreetype6-dev \ + libfribidi-dev \ + libghc-zlib-dev \ + libharfbuzz-dev \ + libjpeg-dev \ + liblcms2-dev \ + libldap2-dev \ + libopenjp2-7-dev \ + libpq-dev \ + libsasl2-dev \ + libtiff5-dev \ + libwebp-dev \ + libxml2-dev \ + libxslt-dev \ + tcl-dev \ + tk-dev \ + zlib1g-dev \ + " \ + && apt-get update \ + && DEBIAN_FRONTEND=noninteractive apt-get install -yqq --no-install-recommends $build_deps \ + && curl -o requirements.txt https://raw.githubusercontent.com/$ODOO_SOURCE/$ODOO_VERSION/requirements.txt \ + && echo "Setting gevent and greenlet versions to 21.12.0 and 1.1.0 (compatible with Debian Bullseye)" \ + && sed -i -E "s/(gevent==)[0-9\.]+/\121.12.0/; \ + s/(greenlet==)[0-9\.]+/\11.1.0/; \ + s/(reportlab==)[0-9\.]+/reportlab==3.6.13/" requirements.txt \ + && pip install -r requirements.txt \ + 'websocket-client~=0.56' \ + astor \ + click-odoo-contrib \ + debugpy \ + pydevd-odoo \ + flanker[validator] \ + geoip2 \ + "git-aggregator<3.0.0" \ + inotify \ + pdfminer.six \ + pg_activity \ + phonenumbers \ + plumbum \ + pudb \ + pyOpenSSL \ + python-magic \ + watchdog \ + wdb \ + && (python3 -m compileall -q /usr/local/lib/python3.8/ || true) \ + # generate flanker cached tables during install when /usr/local/lib/ is still intended to be written to + # https://github.com/Tecnativa/doodba/issues/486 + && python3 -c 'from flanker.addresslib import address' >/dev/null 2>&1 \ + && apt-get purge -yqq $build_deps \ + && apt-get autopurge -yqq \ + && rm -Rf /var/lib/apt/lists/* /tmp/* + +# Metadata +ARG VCS_REF +ARG BUILD_DATE +ARG VERSION +LABEL org.label-schema.schema-version="$VERSION" \ + org.label-schema.vendor=Tecnativa \ + org.label-schema.license=Apache-2.0 \ + org.label-schema.build-date="$BUILD_DATE" \ + org.label-schema.vcs-ref="$VCS_REF" \ + org.label-schema.vcs-url="https://github.com/Tecnativa/doodba" + +# Onbuild version, with all the magic +FROM base AS onbuild + +# Enable setting custom uids for odoo user during build of scaffolds +ONBUILD ARG UID=1000 +ONBUILD ARG GID=1000 + +# Enable Odoo user and filestore +ONBUILD RUN groupadd -g $GID odoo -o \ + && useradd -l -md /home/odoo -s /bin/false -u $UID -g $GID odoo \ + && mkdir -p /var/lib/odoo \ + && chown -R odoo:odoo /var/lib/odoo /qa/artifacts \ + && chmod a=rwX /qa/artifacts \ + && sync + +# Subimage triggers +ONBUILD ENTRYPOINT ["/opt/odoo/common/entrypoint"] +ONBUILD CMD ["/usr/local/bin/odoo"] +ONBUILD ARG AGGREGATE=true +ONBUILD ARG DEFAULT_REPO_PATTERN="https://github.com/OCA/{}.git" +ONBUILD ARG DEFAULT_REPO_PATTERN_ODOO="https://github.com/OCA/OCB.git" +ONBUILD ARG DEPTH_DEFAULT=1 +ONBUILD ARG DEPTH_MERGE=100 +ONBUILD ARG CLEAN=true +ONBUILD ARG COMPILE=true +ONBUILD ARG FONT_MONO="Liberation Mono" +ONBUILD ARG FONT_SANS="Liberation Sans" +ONBUILD ARG FONT_SERIF="Liberation Serif" +ONBUILD ARG PIP_INSTALL_ODOO=true +ONBUILD ARG ADMIN_PASSWORD=admin +ONBUILD ARG SMTP_SERVER=smtp +ONBUILD ARG SMTP_PORT=25 +ONBUILD ARG SMTP_USER=false +ONBUILD ARG SMTP_PASSWORD=false +ONBUILD ARG SMTP_SSL=false +ONBUILD ARG EMAIL_FROM="" +ONBUILD ARG PROXY_MODE=false +ONBUILD ARG WITHOUT_DEMO=all +ONBUILD ARG PGUSER=odoo +ONBUILD ARG PGPASSWORD=odoopassword +ONBUILD ARG PGHOST=db +ONBUILD ARG PGPORT=5432 +ONBUILD ARG PGDATABASE=prod + +# Config variables +ONBUILD ENV ADMIN_PASSWORD="$ADMIN_PASSWORD" \ + DEFAULT_REPO_PATTERN="$DEFAULT_REPO_PATTERN" \ + DEFAULT_REPO_PATTERN_ODOO="$DEFAULT_REPO_PATTERN_ODOO" \ + UNACCENT="$UNACCENT" \ + PGUSER="$PGUSER" \ + PGPASSWORD="$PGPASSWORD" \ + PGHOST="$PGHOST" \ + PGPORT=$PGPORT \ + PGDATABASE="$PGDATABASE" \ + PROXY_MODE="$PROXY_MODE" \ + SMTP_SERVER="$SMTP_SERVER" \ + SMTP_PORT=$SMTP_PORT \ + SMTP_USER="$SMTP_USER" \ + SMTP_PASSWORD="$SMTP_PASSWORD" \ + SMTP_SSL="$SMTP_SSL" \ + EMAIL_FROM="$EMAIL_FROM" \ + WITHOUT_DEMO="$WITHOUT_DEMO" +ONBUILD ARG LOCAL_CUSTOM_DIR=./custom +ONBUILD COPY --chown=root:odoo $LOCAL_CUSTOM_DIR /opt/odoo/custom + +# https://docs.python.org/3/library/logging.html#levels +ONBUILD ARG LOG_LEVEL=INFO +ONBUILD RUN mkdir -p /opt/odoo/custom/ssh \ + && ln -s /opt/odoo/custom/ssh ~root/.ssh \ + && chmod -R u=rwX,go= /opt/odoo/custom/ssh \ + && sync +ONBUILD ARG DB_VERSION=latest +ONBUILD RUN /opt/odoo/common/build && sync +ONBUILD VOLUME ["/var/lib/odoo"] +ONBUILD USER odoo diff --git a/16.0.Dockerfile b/16.0.Dockerfile new file mode 100644 index 00000000..3a32cea6 --- /dev/null +++ b/16.0.Dockerfile @@ -0,0 +1,262 @@ +FROM python:3.10-slim-bookworm AS base + +EXPOSE 8069 8072 + +ARG TARGETARCH +ARG GEOIP_UPDATER_VERSION=6.0.0 +ARG WKHTMLTOPDF_VERSION=0.12.6.1 +ARG WKHTMLTOPDF_AMD64_CHECKSUM='98ba0d157b50d36f23bd0dedf4c0aa28c7b0c50fcdcdc54aa5b6bbba81a3941d' +ARG WKHTMLTOPDF_ARM64_CHECKSUM="b6606157b27c13e044d0abbe670301f88de4e1782afca4f9c06a5817f3e03a9c" +ARG WKHTMLTOPDF_URL="https://github.com/wkhtmltopdf/packaging/releases/download/${WKHTMLTOPDF_VERSION}-3/wkhtmltox_${WKHTMLTOPDF_VERSION}-3.bookworm_${TARGETARCH}.deb" +ARG LAST_SYSTEM_UID=499 +ARG LAST_SYSTEM_GID=499 +ARG FIRST_UID=500 +ARG FIRST_GID=500 + +ENV DB_FILTER=.* \ + DEPTH_DEFAULT=1 \ + DEPTH_MERGE=100 \ + EMAIL=https://hub.docker.com/r/tecnativa/odoo \ + GEOIP_ACCOUNT_ID="" \ + GEOIP_LICENSE_KEY="" \ + GIT_AUTHOR_NAME=docker-odoo \ + INITIAL_LANG="" \ + LC_ALL=C.UTF-8 \ + LIST_DB=false \ + NODE_PATH=/usr/local/lib/node_modules:/usr/lib/node_modules \ + OPENERP_SERVER=/opt/odoo/auto/odoo.conf \ + PATH="/home/odoo/.local/bin:$PATH" \ + PIP_NO_CACHE_DIR=0 \ + DEBUGPY_ARGS="--listen 0.0.0.0:6899 --wait-for-client" \ + DEBUGPY_ENABLE=0 \ + PUDB_RDB_HOST=0.0.0.0 \ + PUDB_RDB_PORT=6899 \ + PYTHONOPTIMIZE="" \ + UNACCENT=true \ + WAIT_DB=true \ + WDB_NO_BROWSER_AUTO_OPEN=True \ + WDB_SOCKET_SERVER=wdb \ + WDB_WEB_PORT=1984 \ + WDB_WEB_SERVER=localhost + + +# Other requirements and recommendations +# See https://github.com/$ODOO_SOURCE/blob/$ODOO_VERSION/debian/control +RUN echo "LAST_SYSTEM_UID=$LAST_SYSTEM_UID\nLAST_SYSTEM_GID=$LAST_SYSTEM_GID\nFIRST_UID=$FIRST_UID\nFIRST_GID=$FIRST_GID" >> /etc/adduser.conf \ + && echo "SYS_UID_MAX $LAST_SYSTEM_UID\nSYS_GID_MAX $LAST_SYSTEM_GID" >> /etc/login.defs \ + && sed -i -E "s/^UID_MIN\s+[0-9]+.*/UID_MIN $FIRST_UID/;s/^GID_MIN\s+[0-9]+.*/GID_MIN $FIRST_GID/" /etc/login.defs \ + && useradd --system -u $LAST_SYSTEM_UID -s /usr/sbin/nologin -d / systemd-network \ + && apt-get -qq update \ + && apt-get install -yqq --no-install-recommends curl \ + && if [ "$TARGETARCH" = "arm64" ]; then \ + WKHTMLTOPDF_CHECKSUM=$WKHTMLTOPDF_ARM64_CHECKSUM; \ + elif [ "$TARGETARCH" = "amd64" ]; then \ + WKHTMLTOPDF_CHECKSUM=$WKHTMLTOPDF_AMD64_CHECKSUM; \ + else \ + echo "Unsupported architecture: $TARGETARCH" >&2; \ + exit 1; \ + fi \ + && curl -SLo wkhtmltox.deb ${WKHTMLTOPDF_URL} \ + && echo "Downloading wkhtmltopdf from: ${WKHTMLTOPDF_URL}" \ + && echo "Expected wkhtmltox checksum: ${WKHTMLTOPDF_CHECKSUM}" \ + && echo "Computed wkhtmltox checksum: $(sha256sum wkhtmltox.deb | awk '{ print $1 }')" \ + && echo "${WKHTMLTOPDF_CHECKSUM} wkhtmltox.deb" | sha256sum -c - \ + && apt-get install -yqq --no-install-recommends \ + ./wkhtmltox.deb \ + chromium \ + ffmpeg \ + fonts-liberation2 \ + gettext \ + git \ + gnupg2 \ + locales-all \ + nano \ + npm \ + openssh-client \ + telnet \ + vim \ + && echo 'deb https://apt.postgresql.org/pub/repos/apt/ bookworm-pgdg main' >> /etc/apt/sources.list.d/postgresql.list \ + && curl -SL https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - \ + && apt-get update \ + && curl --silent -L --output geoipupdate_${GEOIP_UPDATER_VERSION}_linux_${TARGETARCH}.deb https://github.com/maxmind/geoipupdate/releases/download/v${GEOIP_UPDATER_VERSION}/geoipupdate_${GEOIP_UPDATER_VERSION}_linux_${TARGETARCH}.deb \ + && dpkg -i geoipupdate_${GEOIP_UPDATER_VERSION}_linux_${TARGETARCH}.deb \ + && rm geoipupdate_${GEOIP_UPDATER_VERSION}_linux_${TARGETARCH}.deb \ + && apt-get autopurge -yqq \ + && rm -Rf wkhtmltox.deb /var/lib/apt/lists/* /tmp/* \ + && sync + +WORKDIR /opt/odoo +COPY bin/* /usr/local/bin/ +COPY lib/doodbalib /usr/local/lib/python3.10/site-packages/doodbalib +COPY build.d common/build.d +COPY conf.d common/conf.d +COPY entrypoint.d common/entrypoint.d +RUN rm -f /opt/odoo/common/conf.d/60-geoip-ge17.conf \ + && mv /opt/odoo/common/conf.d/60-geoip-lt17.conf /opt/odoo/common/conf.d/60-geoip.conf +RUN mkdir -p auto/addons auto/geoip custom/src/private \ + && ln /usr/local/bin/direxec common/entrypoint \ + && ln /usr/local/bin/direxec common/build \ + && chmod -R a+rx common/entrypoint* common/build* /usr/local/bin \ + && chmod -R a+rX /usr/local/lib/python3.10/site-packages/doodbalib \ + && cp -a /etc/GeoIP.conf /etc/GeoIP.conf.orig \ + && mv /etc/GeoIP.conf /opt/odoo/auto/geoip/GeoIP.conf \ + && ln -s /opt/odoo/auto/geoip/GeoIP.conf /etc/GeoIP.conf \ + && sed -i 's/.*DatabaseDirectory .*$/DatabaseDirectory \/opt\/odoo\/auto\/geoip\//g' /opt/odoo/auto/geoip/GeoIP.conf \ + && sync + +# Doodba-QA dependencies in a separate virtualenv +COPY qa /qa +RUN python -m venv --system-site-packages /qa/venv \ + && . /qa/venv/bin/activate \ + && pip install \ + click \ + coverage \ + && deactivate \ + && mkdir -p /qa/artifacts + +ARG ODOO_SOURCE=OCA/OCB +ARG ODOO_VERSION=16.0 +ENV ODOO_VERSION="$ODOO_VERSION" + +# Install Odoo hard & soft dependencies, and Doodba utilities +RUN build_deps=" \ + build-essential \ + libfreetype6-dev \ + libfribidi-dev \ + libghc-zlib-dev \ + libharfbuzz-dev \ + libjpeg-dev \ + liblcms2-dev \ + libldap2-dev \ + libopenjp2-7-dev \ + libpq-dev \ + libsasl2-dev \ + libtiff5-dev \ + libwebp-dev \ + libxml2-dev \ + libxslt-dev \ + tcl-dev \ + tk-dev \ + zlib1g-dev \ + " \ + && apt-get update \ + && apt-get install -yqq --no-install-recommends $build_deps \ + && curl -o requirements.txt https://raw.githubusercontent.com/$ODOO_SOURCE/$ODOO_VERSION/requirements.txt \ + # disable gevent version recommendation from odoo and use 22.10.2 used in debian bookworm as python3-gevent + && sed -i -E "s/(gevent==)21\.8\.0( ; sys_platform != 'win32' and python_version > '3.9' and python_version <= '3.10')/\122.10.2\2/;s/(greenlet==)1.1.2( ; sys_platform != 'win32' and python_version > '3.9' and python_version <= '3.10')/\12.0.2\2/" requirements.txt \ + # need to upgrade setuptools, since the fixes for CVE-2024-6345 rolled out in base images we get errors "error: invalid command 'bdist_wheel'" + && pip install --upgrade setuptools \ + && pip install -r requirements.txt \ + 'websocket-client~=0.56' \ + astor \ + click-odoo-contrib \ + debugpy \ + pydevd-odoo \ + git+https://github.com/mailgun/flanker.git@v0.9.15#egg=flanker[validator] \ + geoip2 \ + "git-aggregator==4.0" \ + inotify \ + pdfminer.six \ + pg_activity \ + phonenumbers \ + plumbum \ + pudb \ + pyOpenSSL \ + python-magic \ + watchdog \ + wdb \ + && (python3 -m compileall -q /usr/local/lib/python3.10/ || true) \ + # generate flanker cached tables during install when /usr/local/lib/ is still intended to be written to + # https://github.com/Tecnativa/doodba/issues/486 + && python3 -c 'from flanker.addresslib import address' >/dev/null 2>&1 \ + && apt-get purge -yqq $build_deps \ + && apt-get autopurge -yqq \ + && rm -Rf /var/lib/apt/lists/* /tmp/* + +# Metadata +ARG VCS_REF +ARG BUILD_DATE +ARG VERSION +LABEL org.label-schema.schema-version="$VERSION" \ + org.label-schema.vendor=Tecnativa \ + org.label-schema.license=Apache-2.0 \ + org.label-schema.build-date="$BUILD_DATE" \ + org.label-schema.vcs-ref="$VCS_REF" \ + org.label-schema.vcs-url="https://github.com/Tecnativa/doodba" + +# Onbuild version, with all the magic +FROM base AS onbuild + +# Enable setting custom uids for odoo user during build of scaffolds +ONBUILD ARG UID=1000 +ONBUILD ARG GID=1000 + +# Enable Odoo user and filestore +ONBUILD RUN groupadd -g $GID odoo -o \ + && useradd -l -md /home/odoo -s /bin/false -u $UID -g $GID odoo \ + && mkdir -p /var/lib/odoo \ + && chown -R odoo:odoo /var/lib/odoo /qa/artifacts \ + && chmod a=rwX /qa/artifacts \ + && sync + +# Subimage triggers +ONBUILD ENTRYPOINT ["/opt/odoo/common/entrypoint"] +ONBUILD CMD ["/usr/local/bin/odoo"] +ONBUILD ARG AGGREGATE=true +ONBUILD ARG DEFAULT_REPO_PATTERN="https://github.com/OCA/{}.git" +ONBUILD ARG DEFAULT_REPO_PATTERN_ODOO="https://github.com/OCA/OCB.git" +ONBUILD ARG DEPTH_DEFAULT=1 +ONBUILD ARG DEPTH_MERGE=100 +ONBUILD ARG CLEAN=true +ONBUILD ARG COMPILE=true +ONBUILD ARG FONT_MONO="Liberation Mono" +ONBUILD ARG FONT_SANS="Liberation Sans" +ONBUILD ARG FONT_SERIF="Liberation Serif" +ONBUILD ARG PIP_INSTALL_ODOO=true +ONBUILD ARG ADMIN_PASSWORD=admin +ONBUILD ARG SMTP_SERVER=smtp +ONBUILD ARG SMTP_PORT=25 +ONBUILD ARG SMTP_USER=false +ONBUILD ARG SMTP_PASSWORD=false +ONBUILD ARG SMTP_SSL=false +ONBUILD ARG EMAIL_FROM="" +ONBUILD ARG PROXY_MODE=false +ONBUILD ARG WITHOUT_DEMO=all +ONBUILD ARG PGUSER=odoo +ONBUILD ARG PGPASSWORD=odoopassword +ONBUILD ARG PGHOST=db +ONBUILD ARG PGPORT=5432 +ONBUILD ARG PGDATABASE=prod + +# Config variables +ONBUILD ENV ADMIN_PASSWORD="$ADMIN_PASSWORD" \ + DEFAULT_REPO_PATTERN="$DEFAULT_REPO_PATTERN" \ + DEFAULT_REPO_PATTERN_ODOO="$DEFAULT_REPO_PATTERN_ODOO" \ + UNACCENT="$UNACCENT" \ + PGUSER="$PGUSER" \ + PGPASSWORD="$PGPASSWORD" \ + PGHOST="$PGHOST" \ + PGPORT=$PGPORT \ + PGDATABASE="$PGDATABASE" \ + PROXY_MODE="$PROXY_MODE" \ + SMTP_SERVER="$SMTP_SERVER" \ + SMTP_PORT=$SMTP_PORT \ + SMTP_USER="$SMTP_USER" \ + SMTP_PASSWORD="$SMTP_PASSWORD" \ + SMTP_SSL="$SMTP_SSL" \ + EMAIL_FROM="$EMAIL_FROM" \ + WITHOUT_DEMO="$WITHOUT_DEMO" +ONBUILD ARG LOCAL_CUSTOM_DIR=./custom +ONBUILD COPY --chown=root:odoo $LOCAL_CUSTOM_DIR /opt/odoo/custom + +# https://docs.python.org/3/library/logging.html#levels +ONBUILD ARG LOG_LEVEL=INFO +ONBUILD RUN [ -d ~root/.ssh ] && rm -r ~root/.ssh; \ + mkdir -p /opt/odoo/custom/ssh \ + && ln -s /opt/odoo/custom/ssh ~root/.ssh \ + && chmod -R u=rwX,go= /opt/odoo/custom/ssh \ + && sync +ONBUILD ARG DB_VERSION=latest +ONBUILD RUN /opt/odoo/common/build && sync +ONBUILD VOLUME ["/var/lib/odoo"] +ONBUILD USER odoo diff --git a/17.0.Dockerfile b/17.0.Dockerfile new file mode 100644 index 00000000..2d50f2a3 --- /dev/null +++ b/17.0.Dockerfile @@ -0,0 +1,261 @@ +FROM python:3.10-slim-bookworm AS base + +EXPOSE 8069 8072 + +ARG TARGETARCH +ARG GEOIP_UPDATER_VERSION=6.0.0 +ARG WKHTMLTOPDF_VERSION=0.12.6.1 +ARG WKHTMLTOPDF_AMD64_CHECKSUM='98ba0d157b50d36f23bd0dedf4c0aa28c7b0c50fcdcdc54aa5b6bbba81a3941d' +ARG WKHTMLTOPDF_ARM64_CHECKSUM="b6606157b27c13e044d0abbe670301f88de4e1782afca4f9c06a5817f3e03a9c" +ARG WKHTMLTOPDF_URL="https://github.com/wkhtmltopdf/packaging/releases/download/${WKHTMLTOPDF_VERSION}-3/wkhtmltox_${WKHTMLTOPDF_VERSION}-3.bookworm_${TARGETARCH}.deb" +ARG LAST_SYSTEM_UID=499 +ARG LAST_SYSTEM_GID=499 +ARG FIRST_UID=500 +ARG FIRST_GID=500 +ENV DB_FILTER=.* \ + DEPTH_DEFAULT=1 \ + DEPTH_MERGE=100 \ + EMAIL=https://hub.docker.com/r/tecnativa/odoo \ + GEOIP_ACCOUNT_ID="" \ + GEOIP_LICENSE_KEY="" \ + GIT_AUTHOR_NAME=docker-odoo \ + INITIAL_LANG="" \ + LC_ALL=C.UTF-8 \ + LIST_DB=false \ + NODE_PATH=/usr/local/lib/node_modules:/usr/lib/node_modules \ + OPENERP_SERVER=/opt/odoo/auto/odoo.conf \ + PATH="/home/odoo/.local/bin:$PATH" \ + PIP_NO_CACHE_DIR=0 \ + DEBUGPY_ARGS="--listen 0.0.0.0:6899 --wait-for-client" \ + DEBUGPY_ENABLE=0 \ + PUDB_RDB_HOST=0.0.0.0 \ + PUDB_RDB_PORT=6899 \ + PYTHONOPTIMIZE="" \ + UNACCENT=true \ + WAIT_DB=true \ + WDB_NO_BROWSER_AUTO_OPEN=True \ + WDB_SOCKET_SERVER=wdb \ + WDB_WEB_PORT=1984 \ + WDB_WEB_SERVER=localhost + +# Other requirements and recommendations +# See https://github.com/$ODOO_SOURCE/blob/$ODOO_VERSION/debian/control +RUN echo "LAST_SYSTEM_UID=$LAST_SYSTEM_UID\nLAST_SYSTEM_GID=$LAST_SYSTEM_GID\nFIRST_UID=$FIRST_UID\nFIRST_GID=$FIRST_GID" >> /etc/adduser.conf \ + && echo "SYS_UID_MAX $LAST_SYSTEM_UID\nSYS_GID_MAX $LAST_SYSTEM_GID" >> /etc/login.defs \ + && sed -i -E "s/^UID_MIN\s+[0-9]+.*/UID_MIN $FIRST_UID/;s/^GID_MIN\s+[0-9]+.*/GID_MIN $FIRST_GID/" /etc/login.defs \ + && useradd --system -u $LAST_SYSTEM_UID -s /usr/sbin/nologin -d / systemd-network \ + && apt-get -qq update \ + && apt-get install -yqq --no-install-recommends \ + curl \ + && if [ "$TARGETARCH" = "arm64" ]; then \ + WKHTMLTOPDF_CHECKSUM=$WKHTMLTOPDF_ARM64_CHECKSUM; \ + elif [ "$TARGETARCH" = "amd64" ]; then \ + WKHTMLTOPDF_CHECKSUM=$WKHTMLTOPDF_AMD64_CHECKSUM; \ + else \ + echo "Unsupported architecture: $TARGETARCH" >&2; \ + exit 1; \ + fi \ + && curl -SLo wkhtmltox.deb ${WKHTMLTOPDF_URL} \ + && echo "Downloading wkhtmltopdf from: ${WKHTMLTOPDF_URL}" \ + && echo "Expected wkhtmltox checksum: ${WKHTMLTOPDF_CHECKSUM}" \ + && echo "Computed wkhtmltox checksum: $(sha256sum wkhtmltox.deb | awk '{ print $1 }')" \ + && echo "${WKHTMLTOPDF_CHECKSUM} wkhtmltox.deb" | sha256sum -c - \ + && apt-get install -yqq --no-install-recommends \ + ./wkhtmltox.deb \ + chromium \ + ffmpeg \ + fonts-liberation2 \ + gettext \ + git \ + gnupg2 \ + locales-all \ + nano \ + npm \ + openssh-client \ + telnet \ + vim \ + && echo 'deb https://apt.postgresql.org/pub/repos/apt/ bookworm-pgdg main' >> /etc/apt/sources.list.d/postgresql.list \ + && curl -SL https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - \ + && apt-get update \ + && curl --silent -L --output geoipupdate_${GEOIP_UPDATER_VERSION}_linux_${TARGETARCH}.deb https://github.com/maxmind/geoipupdate/releases/download/v${GEOIP_UPDATER_VERSION}/geoipupdate_${GEOIP_UPDATER_VERSION}_linux_${TARGETARCH}.deb \ + && dpkg -i geoipupdate_${GEOIP_UPDATER_VERSION}_linux_${TARGETARCH}.deb \ + && rm geoipupdate_${GEOIP_UPDATER_VERSION}_linux_${TARGETARCH}.deb \ + && apt-get autopurge -yqq \ + && rm -Rf wkhtmltox.deb /var/lib/apt/lists/* /tmp/* \ + && sync + +WORKDIR /opt/odoo +COPY bin/* /usr/local/bin/ +COPY lib/doodbalib /usr/local/lib/python3.10/site-packages/doodbalib +COPY build.d common/build.d +COPY conf.d common/conf.d +COPY entrypoint.d common/entrypoint.d +RUN rm -f /opt/odoo/common/conf.d/60-geoip-lt17.conf \ + && mv /opt/odoo/common/conf.d/60-geoip-ge17.conf /opt/odoo/common/conf.d/60-geoip.conf +RUN mkdir -p auto/addons auto/geoip custom/src/private \ + && ln /usr/local/bin/direxec common/entrypoint \ + && ln /usr/local/bin/direxec common/build \ + && chmod -R a+rx common/entrypoint* common/build* /usr/local/bin \ + && chmod -R a+rX /usr/local/lib/python3.10/site-packages/doodbalib \ + && cp -a /etc/GeoIP.conf /etc/GeoIP.conf.orig \ + && mv /etc/GeoIP.conf /opt/odoo/auto/geoip/GeoIP.conf \ + && ln -s /opt/odoo/auto/geoip/GeoIP.conf /etc/GeoIP.conf \ + && sed -i 's/.*DatabaseDirectory .*$/DatabaseDirectory \/opt\/odoo\/auto\/geoip\//g' /opt/odoo/auto/geoip/GeoIP.conf \ + && sync + +# Doodba-QA dependencies in a separate virtualenv +COPY qa /qa +RUN python -m venv --system-site-packages /qa/venv \ + && . /qa/venv/bin/activate \ + && pip install \ + click \ + coverage \ + && deactivate \ + && mkdir -p /qa/artifacts + +ARG ODOO_SOURCE=OCA/OCB +ARG ODOO_VERSION=17.0 +ENV ODOO_VERSION="$ODOO_VERSION" + +# Install Odoo hard & soft dependencies, and Doodba utilities +RUN build_deps=" \ + build-essential \ + libfreetype6-dev \ + libfribidi-dev \ + libghc-zlib-dev \ + libharfbuzz-dev \ + libjpeg-dev \ + liblcms2-dev \ + libldap2-dev \ + libopenjp2-7-dev \ + libpq-dev \ + libsasl2-dev \ + libtiff5-dev \ + libwebp-dev \ + libxml2-dev \ + libxslt-dev \ + tcl-dev \ + tk-dev \ + zlib1g-dev \ + " \ + && apt-get update \ + && apt-get install -yqq --no-install-recommends $build_deps \ + && curl -o requirements.txt https://raw.githubusercontent.com/$ODOO_SOURCE/$ODOO_VERSION/requirements.txt \ + # disable gevent version recommendation from odoo and use 22.10.2 used in debian bookworm as python3-gevent + && sed -i -E "s/(gevent==)21\.8\.0( ; sys_platform != 'win32' and python_version == '3.10')/\122.10.2\2/;s/(greenlet==)1.1.2( ; sys_platform != 'win32' and python_version == '3.10')/\12.0.2\2/" requirements.txt \ + # need to upgrade setuptools, since the fixes for CVE-2024-6345 rolled out in base images we get errors "error: invalid command 'bdist_wheel'" + && pip install --upgrade setuptools \ + && pip install -r requirements.txt \ + 'websocket-client~=0.56' \ + astor \ + click-odoo-contrib \ + debugpy \ + pydevd-odoo \ + git+https://github.com/mailgun/flanker.git@v0.9.15#egg=flanker[validator] \ + geoip2 \ + "git-aggregator==4.0" \ + inotify \ + pdfminer.six \ + pg_activity \ + phonenumbers \ + plumbum \ + pudb \ + pyOpenSSL \ + python-magic \ + watchdog \ + wdb \ + && (python3 -m compileall -q /usr/local/lib/python3.10/ || true) \ + # generate flanker cached tables during install when /usr/local/lib/ is still intended to be written to + # https://github.com/Tecnativa/doodba/issues/486 + && python3 -c 'from flanker.addresslib import address' >/dev/null 2>&1 \ + && apt-get purge -yqq $build_deps \ + && apt-get autopurge -yqq \ + && rm -Rf /var/lib/apt/lists/* /tmp/* + +# Metadata +ARG VCS_REF +ARG BUILD_DATE +ARG VERSION +LABEL org.label-schema.schema-version="$VERSION" \ + org.label-schema.vendor=Tecnativa \ + org.label-schema.license=Apache-2.0 \ + org.label-schema.build-date="$BUILD_DATE" \ + org.label-schema.vcs-ref="$VCS_REF" \ + org.label-schema.vcs-url="https://github.com/Tecnativa/doodba" + +# Onbuild version, with all the magic +FROM base AS onbuild + +# Enable setting custom uids for odoo user during build of scaffolds +ONBUILD ARG UID=1000 +ONBUILD ARG GID=1000 + +# Enable Odoo user and filestore +ONBUILD RUN groupadd -g $GID odoo -o \ + && useradd -l -md /home/odoo -s /bin/false -u $UID -g $GID odoo \ + && mkdir -p /var/lib/odoo \ + && chown -R odoo:odoo /var/lib/odoo /qa/artifacts \ + && chmod a=rwX /qa/artifacts \ + && sync + +# Subimage triggers +ONBUILD ENTRYPOINT ["/opt/odoo/common/entrypoint"] +ONBUILD CMD ["/usr/local/bin/odoo"] +ONBUILD ARG AGGREGATE=true +ONBUILD ARG DEFAULT_REPO_PATTERN="https://github.com/OCA/{}.git" +ONBUILD ARG DEFAULT_REPO_PATTERN_ODOO="https://github.com/OCA/OCB.git" +ONBUILD ARG DEPTH_DEFAULT=1 +ONBUILD ARG DEPTH_MERGE=100 +ONBUILD ARG CLEAN=true +ONBUILD ARG COMPILE=true +ONBUILD ARG FONT_MONO="Liberation Mono" +ONBUILD ARG FONT_SANS="Liberation Sans" +ONBUILD ARG FONT_SERIF="Liberation Serif" +ONBUILD ARG PIP_INSTALL_ODOO=true +ONBUILD ARG ADMIN_PASSWORD=admin +ONBUILD ARG SMTP_SERVER=smtp +ONBUILD ARG SMTP_PORT=25 +ONBUILD ARG SMTP_USER=false +ONBUILD ARG SMTP_PASSWORD=false +ONBUILD ARG SMTP_SSL=false +ONBUILD ARG EMAIL_FROM="" +ONBUILD ARG PROXY_MODE=false +ONBUILD ARG WITHOUT_DEMO=all +ONBUILD ARG PGUSER=odoo +ONBUILD ARG PGPASSWORD=odoopassword +ONBUILD ARG PGHOST=db +ONBUILD ARG PGPORT=5432 +ONBUILD ARG PGDATABASE=prod + +# Config variables +ONBUILD ENV ADMIN_PASSWORD="$ADMIN_PASSWORD" \ + DEFAULT_REPO_PATTERN="$DEFAULT_REPO_PATTERN" \ + DEFAULT_REPO_PATTERN_ODOO="$DEFAULT_REPO_PATTERN_ODOO" \ + UNACCENT="$UNACCENT" \ + PGUSER="$PGUSER" \ + PGPASSWORD="$PGPASSWORD" \ + PGHOST="$PGHOST" \ + PGPORT=$PGPORT \ + PGDATABASE="$PGDATABASE" \ + PROXY_MODE="$PROXY_MODE" \ + SMTP_SERVER="$SMTP_SERVER" \ + SMTP_PORT=$SMTP_PORT \ + SMTP_USER="$SMTP_USER" \ + SMTP_PASSWORD="$SMTP_PASSWORD" \ + SMTP_SSL="$SMTP_SSL" \ + EMAIL_FROM="$EMAIL_FROM" \ + WITHOUT_DEMO="$WITHOUT_DEMO" +ONBUILD ARG LOCAL_CUSTOM_DIR=./custom +ONBUILD COPY --chown=root:odoo $LOCAL_CUSTOM_DIR /opt/odoo/custom + +# https://docs.python.org/3/library/logging.html#levels +ONBUILD ARG LOG_LEVEL=INFO +ONBUILD RUN [ -d ~root/.ssh ] && rm -r ~root/.ssh; \ + mkdir -p /opt/odoo/custom/ssh \ + && ln -s /opt/odoo/custom/ssh ~root/.ssh \ + && chmod -R u=rwX,go= /opt/odoo/custom/ssh \ + && sync +ONBUILD ARG DB_VERSION=latest +ONBUILD RUN /opt/odoo/common/build && sync +ONBUILD VOLUME ["/var/lib/odoo"] +ONBUILD USER odoo diff --git a/18.0.Dockerfile b/18.0.Dockerfile new file mode 100644 index 00000000..9cf13c18 --- /dev/null +++ b/18.0.Dockerfile @@ -0,0 +1,261 @@ +FROM python:3.10-slim-bookworm AS base + +EXPOSE 8069 8072 + +ARG TARGETARCH +ARG GEOIP_UPDATER_VERSION=6.0.0 +ARG WKHTMLTOPDF_VERSION=0.12.6.1 +ARG WKHTMLTOPDF_AMD64_CHECKSUM='98ba0d157b50d36f23bd0dedf4c0aa28c7b0c50fcdcdc54aa5b6bbba81a3941d' +ARG WKHTMLTOPDF_ARM64_CHECKSUM="b6606157b27c13e044d0abbe670301f88de4e1782afca4f9c06a5817f3e03a9c" +ARG WKHTMLTOPDF_URL="https://github.com/wkhtmltopdf/packaging/releases/download/${WKHTMLTOPDF_VERSION}-3/wkhtmltox_${WKHTMLTOPDF_VERSION}-3.bookworm_${TARGETARCH}.deb" +ARG LAST_SYSTEM_UID=499 +ARG LAST_SYSTEM_GID=499 +ARG FIRST_UID=500 +ARG FIRST_GID=500 +ENV DB_FILTER=.* \ + DEPTH_DEFAULT=1 \ + DEPTH_MERGE=100 \ + EMAIL=https://hub.docker.com/r/tecnativa/odoo \ + GEOIP_ACCOUNT_ID="" \ + GEOIP_LICENSE_KEY="" \ + GIT_AUTHOR_NAME=docker-odoo \ + INITIAL_LANG="" \ + LC_ALL=C.UTF-8 \ + LIST_DB=false \ + NODE_PATH=/usr/local/lib/node_modules:/usr/lib/node_modules \ + OPENERP_SERVER=/opt/odoo/auto/odoo.conf \ + PATH="/home/odoo/.local/bin:$PATH" \ + PIP_NO_CACHE_DIR=0 \ + DEBUGPY_ARGS="--listen 0.0.0.0:6899 --wait-for-client" \ + DEBUGPY_ENABLE=0 \ + PUDB_RDB_HOST=0.0.0.0 \ + PUDB_RDB_PORT=6899 \ + PYTHONOPTIMIZE="" \ + UNACCENT=true \ + WAIT_DB=true \ + WDB_NO_BROWSER_AUTO_OPEN=True \ + WDB_SOCKET_SERVER=wdb \ + WDB_WEB_PORT=1984 \ + WDB_WEB_SERVER=localhost + +# Other requirements and recommendations +# See https://github.com/$ODOO_SOURCE/blob/$ODOO_VERSION/debian/control +RUN echo "LAST_SYSTEM_UID=$LAST_SYSTEM_UID\nLAST_SYSTEM_GID=$LAST_SYSTEM_GID\nFIRST_UID=$FIRST_UID\nFIRST_GID=$FIRST_GID" >> /etc/adduser.conf \ + && echo "SYS_UID_MAX $LAST_SYSTEM_UID\nSYS_GID_MAX $LAST_SYSTEM_GID" >> /etc/login.defs \ + && sed -i -E "s/^UID_MIN\s+[0-9]+.*/UID_MIN $FIRST_UID/;s/^GID_MIN\s+[0-9]+.*/GID_MIN $FIRST_GID/" /etc/login.defs \ + && useradd --system -u $LAST_SYSTEM_UID -s /usr/sbin/nologin -d / systemd-network \ + && apt-get -qq update \ + && apt-get install -yqq --no-install-recommends \ + curl \ + && if [ "$TARGETARCH" = "arm64" ]; then \ + WKHTMLTOPDF_CHECKSUM=$WKHTMLTOPDF_ARM64_CHECKSUM; \ + elif [ "$TARGETARCH" = "amd64" ]; then \ + WKHTMLTOPDF_CHECKSUM=$WKHTMLTOPDF_AMD64_CHECKSUM; \ + else \ + echo "Unsupported architecture: $TARGETARCH" >&2; \ + exit 1; \ + fi \ + && curl -SLo wkhtmltox.deb ${WKHTMLTOPDF_URL} \ + && echo "Downloading wkhtmltopdf from: ${WKHTMLTOPDF_URL}" \ + && echo "Expected wkhtmltox checksum: ${WKHTMLTOPDF_CHECKSUM}" \ + && echo "Computed wkhtmltox checksum: $(sha256sum wkhtmltox.deb | awk '{ print $1 }')" \ + && echo "${WKHTMLTOPDF_CHECKSUM} wkhtmltox.deb" | sha256sum -c - \ + && apt-get install -yqq --no-install-recommends \ + ./wkhtmltox.deb \ + chromium \ + ffmpeg \ + fonts-liberation2 \ + gettext \ + git \ + gnupg2 \ + locales-all \ + nano \ + npm \ + openssh-client \ + telnet \ + vim \ + && echo 'deb https://apt.postgresql.org/pub/repos/apt/ bookworm-pgdg main' >> /etc/apt/sources.list.d/postgresql.list \ + && curl -SL https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - \ + && apt-get update \ + && curl --silent -L --output geoipupdate_${GEOIP_UPDATER_VERSION}_linux_${TARGETARCH}.deb https://github.com/maxmind/geoipupdate/releases/download/v${GEOIP_UPDATER_VERSION}/geoipupdate_${GEOIP_UPDATER_VERSION}_linux_${TARGETARCH}.deb \ + && dpkg -i geoipupdate_${GEOIP_UPDATER_VERSION}_linux_${TARGETARCH}.deb \ + && rm geoipupdate_${GEOIP_UPDATER_VERSION}_linux_${TARGETARCH}.deb \ + && apt-get autopurge -yqq \ + && rm -Rf wkhtmltox.deb /var/lib/apt/lists/* /tmp/* \ + && sync + +WORKDIR /opt/odoo +COPY bin/* /usr/local/bin/ +COPY lib/doodbalib /usr/local/lib/python3.10/site-packages/doodbalib +COPY build.d common/build.d +COPY conf.d common/conf.d +COPY entrypoint.d common/entrypoint.d +RUN rm -f /opt/odoo/common/conf.d/60-geoip-lt17.conf \ + && mv /opt/odoo/common/conf.d/60-geoip-ge17.conf /opt/odoo/common/conf.d/60-geoip.conf +RUN mkdir -p auto/addons auto/geoip custom/src/private \ + && ln /usr/local/bin/direxec common/entrypoint \ + && ln /usr/local/bin/direxec common/build \ + && chmod -R a+rx common/entrypoint* common/build* /usr/local/bin \ + && chmod -R a+rX /usr/local/lib/python3.10/site-packages/doodbalib \ + && cp -a /etc/GeoIP.conf /etc/GeoIP.conf.orig \ + && mv /etc/GeoIP.conf /opt/odoo/auto/geoip/GeoIP.conf \ + && ln -s /opt/odoo/auto/geoip/GeoIP.conf /etc/GeoIP.conf \ + && sed -i 's/.*DatabaseDirectory .*$/DatabaseDirectory \/opt\/odoo\/auto\/geoip\//g' /opt/odoo/auto/geoip/GeoIP.conf \ + && sync + +# Doodba-QA dependencies in a separate virtualenv +COPY qa /qa +RUN python -m venv --system-site-packages /qa/venv \ + && . /qa/venv/bin/activate \ + && pip install \ + click \ + coverage \ + && deactivate \ + && mkdir -p /qa/artifacts + +ARG ODOO_SOURCE=OCA/OCB +ARG ODOO_VERSION=18.0 +ENV ODOO_VERSION="$ODOO_VERSION" + +# Install Odoo hard & soft dependencies, and Doodba utilities +RUN build_deps=" \ + build-essential \ + libfreetype6-dev \ + libfribidi-dev \ + libghc-zlib-dev \ + libharfbuzz-dev \ + libjpeg-dev \ + liblcms2-dev \ + libldap2-dev \ + libopenjp2-7-dev \ + libpq-dev \ + libsasl2-dev \ + libtiff5-dev \ + libwebp-dev \ + libxml2-dev \ + libxslt-dev \ + tcl-dev \ + tk-dev \ + zlib1g-dev \ + " \ + && apt-get update \ + && apt-get install -yqq --no-install-recommends $build_deps \ + && curl -o requirements.txt https://raw.githubusercontent.com/$ODOO_SOURCE/$ODOO_VERSION/requirements.txt \ + # disable gevent version recommendation from odoo and use 22.10.2 used in debian bookworm as python3-gevent + && sed -i -E "s/(gevent==)21\.8\.0( ; sys_platform != 'win32' and python_version == '3.10')/\122.10.2\2/;s/(greenlet==)1.1.2( ; sys_platform != 'win32' and python_version == '3.10')/\12.0.2\2/" requirements.txt \ + # need to upgrade setuptools, since the fixes for CVE-2024-6345 rolled out in base images we get errors "error: invalid command 'bdist_wheel'" + && pip install --upgrade setuptools \ + && pip install -r requirements.txt \ + 'websocket-client~=0.56' \ + astor \ + click-odoo-contrib \ + debugpy \ + pydevd-odoo \ + git+https://github.com/mailgun/flanker.git@v0.9.15#egg=flanker[validator] \ + geoip2 \ + "git-aggregator==4.0" \ + inotify \ + pdfminer.six \ + pg_activity \ + phonenumbers \ + plumbum \ + pudb \ + pyOpenSSL \ + python-magic \ + watchdog \ + wdb \ + && (python3 -m compileall -q /usr/local/lib/python3.10/ || true) \ + # generate flanker cached tables during install when /usr/local/lib/ is still intended to be written to + # https://github.com/Tecnativa/doodba/issues/486 + && python3 -c 'from flanker.addresslib import address' >/dev/null 2>&1 \ + && apt-get purge -yqq $build_deps \ + && apt-get autopurge -yqq \ + && rm -Rf /var/lib/apt/lists/* /tmp/* + +# Metadata +ARG VCS_REF +ARG BUILD_DATE +ARG VERSION +LABEL org.label-schema.schema-version="$VERSION" \ + org.label-schema.vendor=Tecnativa \ + org.label-schema.license=Apache-2.0 \ + org.label-schema.build-date="$BUILD_DATE" \ + org.label-schema.vcs-ref="$VCS_REF" \ + org.label-schema.vcs-url="https://github.com/Tecnativa/doodba" + +# Onbuild version, with all the magic +FROM base AS onbuild + +# Enable setting custom uids for odoo user during build of scaffolds +ONBUILD ARG UID=1000 +ONBUILD ARG GID=1000 + +# Enable Odoo user and filestore +ONBUILD RUN groupadd -g $GID odoo -o \ + && useradd -l -md /home/odoo -s /bin/false -u $UID -g $GID odoo \ + && mkdir -p /var/lib/odoo \ + && chown -R odoo:odoo /var/lib/odoo /qa/artifacts \ + && chmod a=rwX /qa/artifacts \ + && sync + +# Subimage triggers +ONBUILD ENTRYPOINT ["/opt/odoo/common/entrypoint"] +ONBUILD CMD ["/usr/local/bin/odoo"] +ONBUILD ARG AGGREGATE=true +ONBUILD ARG DEFAULT_REPO_PATTERN="https://github.com/OCA/{}.git" +ONBUILD ARG DEFAULT_REPO_PATTERN_ODOO="https://github.com/OCA/OCB.git" +ONBUILD ARG DEPTH_DEFAULT=1 +ONBUILD ARG DEPTH_MERGE=100 +ONBUILD ARG CLEAN=true +ONBUILD ARG COMPILE=true +ONBUILD ARG FONT_MONO="Liberation Mono" +ONBUILD ARG FONT_SANS="Liberation Sans" +ONBUILD ARG FONT_SERIF="Liberation Serif" +ONBUILD ARG PIP_INSTALL_ODOO=true +ONBUILD ARG ADMIN_PASSWORD=admin +ONBUILD ARG SMTP_SERVER=smtp +ONBUILD ARG SMTP_PORT=25 +ONBUILD ARG SMTP_USER=false +ONBUILD ARG SMTP_PASSWORD=false +ONBUILD ARG SMTP_SSL=false +ONBUILD ARG EMAIL_FROM="" +ONBUILD ARG PROXY_MODE=false +ONBUILD ARG WITHOUT_DEMO=all +ONBUILD ARG PGUSER=odoo +ONBUILD ARG PGPASSWORD=odoopassword +ONBUILD ARG PGHOST=db +ONBUILD ARG PGPORT=5432 +ONBUILD ARG PGDATABASE=prod + +# Config variables +ONBUILD ENV ADMIN_PASSWORD="$ADMIN_PASSWORD" \ + DEFAULT_REPO_PATTERN="$DEFAULT_REPO_PATTERN" \ + DEFAULT_REPO_PATTERN_ODOO="$DEFAULT_REPO_PATTERN_ODOO" \ + UNACCENT="$UNACCENT" \ + PGUSER="$PGUSER" \ + PGPASSWORD="$PGPASSWORD" \ + PGHOST="$PGHOST" \ + PGPORT=$PGPORT \ + PGDATABASE="$PGDATABASE" \ + PROXY_MODE="$PROXY_MODE" \ + SMTP_SERVER="$SMTP_SERVER" \ + SMTP_PORT=$SMTP_PORT \ + SMTP_USER="$SMTP_USER" \ + SMTP_PASSWORD="$SMTP_PASSWORD" \ + SMTP_SSL="$SMTP_SSL" \ + EMAIL_FROM="$EMAIL_FROM" \ + WITHOUT_DEMO="$WITHOUT_DEMO" +ONBUILD ARG LOCAL_CUSTOM_DIR=./custom +ONBUILD COPY --chown=root:odoo $LOCAL_CUSTOM_DIR /opt/odoo/custom + +# https://docs.python.org/3/library/logging.html#levels +ONBUILD ARG LOG_LEVEL=INFO +ONBUILD RUN [ -d ~root/.ssh ] && rm -r ~root/.ssh; \ + mkdir -p /opt/odoo/custom/ssh \ + && ln -s /opt/odoo/custom/ssh ~root/.ssh \ + && chmod -R u=rwX,go= /opt/odoo/custom/ssh \ + && sync +ONBUILD ARG DB_VERSION=latest +ONBUILD RUN /opt/odoo/common/build && sync +ONBUILD VOLUME ["/var/lib/odoo"] +ONBUILD USER odoo diff --git a/19.0.Dockerfile b/19.0.Dockerfile new file mode 100644 index 00000000..f3982476 --- /dev/null +++ b/19.0.Dockerfile @@ -0,0 +1,259 @@ +FROM python:3.12-slim-bookworm AS base + +EXPOSE 8069 8072 + +ARG TARGETARCH +ARG GEOIP_UPDATER_VERSION=6.0.0 +ARG WKHTMLTOPDF_VERSION=0.12.6.1 +ARG WKHTMLTOPDF_AMD64_CHECKSUM='98ba0d157b50d36f23bd0dedf4c0aa28c7b0c50fcdcdc54aa5b6bbba81a3941d' +ARG WKHTMLTOPDF_ARM64_CHECKSUM="b6606157b27c13e044d0abbe670301f88de4e1782afca4f9c06a5817f3e03a9c" +ARG WKHTMLTOPDF_URL="https://github.com/wkhtmltopdf/packaging/releases/download/${WKHTMLTOPDF_VERSION}-3/wkhtmltox_${WKHTMLTOPDF_VERSION}-3.bookworm_${TARGETARCH}.deb" +ARG LAST_SYSTEM_UID=499 +ARG LAST_SYSTEM_GID=499 +ARG FIRST_UID=500 +ARG FIRST_GID=500 +ENV DB_FILTER=.* \ + DEPTH_DEFAULT=1 \ + DEPTH_MERGE=100 \ + EMAIL=https://hub.docker.com/r/tecnativa/odoo \ + GEOIP_ACCOUNT_ID="" \ + GEOIP_LICENSE_KEY="" \ + GIT_AUTHOR_NAME=docker-odoo \ + INITIAL_LANG="" \ + LC_ALL=C.UTF-8 \ + LIST_DB=false \ + NODE_PATH=/usr/local/lib/node_modules:/usr/lib/node_modules \ + ODOO_RC=/opt/odoo/auto/odoo.conf \ + PATH="/home/odoo/.local/bin:$PATH" \ + PIP_NO_CACHE_DIR=0 \ + DEBUGPY_ARGS="--listen 0.0.0.0:6899 --wait-for-client" \ + DEBUGPY_ENABLE=0 \ + PUDB_RDB_HOST=0.0.0.0 \ + PUDB_RDB_PORT=6899 \ + PYTHONOPTIMIZE="" \ + UNACCENT=true \ + WAIT_DB=true \ + WDB_NO_BROWSER_AUTO_OPEN=True \ + WDB_SOCKET_SERVER=wdb \ + WDB_WEB_PORT=1984 \ + WDB_WEB_SERVER=localhost + +# Other requirements and recommendations +# See https://github.com/$ODOO_SOURCE/blob/$ODOO_VERSION/debian/control +RUN echo "LAST_SYSTEM_UID=$LAST_SYSTEM_UID\nLAST_SYSTEM_GID=$LAST_SYSTEM_GID\nFIRST_UID=$FIRST_UID\nFIRST_GID=$FIRST_GID" >> /etc/adduser.conf \ + && echo "SYS_UID_MAX $LAST_SYSTEM_UID\nSYS_GID_MAX $LAST_SYSTEM_GID" >> /etc/login.defs \ + && sed -i -E "s/^UID_MIN\s+[0-9]+.*/UID_MIN $FIRST_UID/;s/^GID_MIN\s+[0-9]+.*/GID_MIN $FIRST_GID/" /etc/login.defs \ + && useradd --system -u $LAST_SYSTEM_UID -s /usr/sbin/nologin -d / systemd-network \ + && apt-get -qq update \ + && apt-get install -yqq --no-install-recommends \ + curl \ + && if [ "$TARGETARCH" = "arm64" ]; then \ + WKHTMLTOPDF_CHECKSUM=$WKHTMLTOPDF_ARM64_CHECKSUM; \ + elif [ "$TARGETARCH" = "amd64" ]; then \ + WKHTMLTOPDF_CHECKSUM=$WKHTMLTOPDF_AMD64_CHECKSUM; \ + else \ + echo "Unsupported architecture: $TARGETARCH" >&2; \ + exit 1; \ + fi \ + && curl -SLo wkhtmltox.deb ${WKHTMLTOPDF_URL} \ + && echo "Downloading wkhtmltopdf from: ${WKHTMLTOPDF_URL}" \ + && echo "Expected wkhtmltox checksum: ${WKHTMLTOPDF_CHECKSUM}" \ + && echo "Computed wkhtmltox checksum: $(sha256sum wkhtmltox.deb | awk '{ print $1 }')" \ + && echo "${WKHTMLTOPDF_CHECKSUM} wkhtmltox.deb" | sha256sum -c - \ + && apt-get install -yqq --no-install-recommends \ + ./wkhtmltox.deb \ + chromium \ + ffmpeg \ + fonts-liberation2 \ + gettext \ + git \ + gnupg2 \ + locales-all \ + nano \ + npm \ + openssh-client \ + telnet \ + vim \ + && echo 'deb https://apt.postgresql.org/pub/repos/apt/ bookworm-pgdg main' >> /etc/apt/sources.list.d/postgresql.list \ + && curl -SL https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - \ + && apt-get update \ + && curl --silent -L --output geoipupdate_${GEOIP_UPDATER_VERSION}_linux_${TARGETARCH}.deb https://github.com/maxmind/geoipupdate/releases/download/v${GEOIP_UPDATER_VERSION}/geoipupdate_${GEOIP_UPDATER_VERSION}_linux_${TARGETARCH}.deb \ + && dpkg -i geoipupdate_${GEOIP_UPDATER_VERSION}_linux_${TARGETARCH}.deb \ + && rm geoipupdate_${GEOIP_UPDATER_VERSION}_linux_${TARGETARCH}.deb \ + && apt-get autopurge -yqq \ + && rm -Rf wkhtmltox.deb /var/lib/apt/lists/* /tmp/* \ + && sync + +WORKDIR /opt/odoo +COPY bin/* /usr/local/bin/ +COPY lib/doodbalib /usr/local/lib/python3.12/site-packages/doodbalib +COPY build.d common/build.d +COPY conf.d common/conf.d +COPY entrypoint.d common/entrypoint.d +RUN rm -f /opt/odoo/common/conf.d/60-geoip-lt17.conf \ + && mv /opt/odoo/common/conf.d/60-geoip-ge17.conf /opt/odoo/common/conf.d/60-geoip.conf +RUN mkdir -p auto/addons auto/geoip custom/src/private \ + && ln /usr/local/bin/direxec common/entrypoint \ + && ln /usr/local/bin/direxec common/build \ + && chmod -R a+rx common/entrypoint* common/build* /usr/local/bin \ + && chmod -R a+rX /usr/local/lib/python3.12/site-packages/doodbalib \ + && cp -a /etc/GeoIP.conf /etc/GeoIP.conf.orig \ + && mv /etc/GeoIP.conf /opt/odoo/auto/geoip/GeoIP.conf \ + && ln -s /opt/odoo/auto/geoip/GeoIP.conf /etc/GeoIP.conf \ + && sed -i 's/.*DatabaseDirectory .*$/DatabaseDirectory \/opt\/odoo\/auto\/geoip\//g' /opt/odoo/auto/geoip/GeoIP.conf \ + && sync + +# Doodba-QA dependencies in a separate virtualenv +COPY qa /qa +RUN python -m venv --system-site-packages /qa/venv \ + && . /qa/venv/bin/activate \ + && pip install \ + click \ + coverage \ + && deactivate \ + && mkdir -p /qa/artifacts + +ARG ODOO_SOURCE=OCA/OCB +ARG ODOO_VERSION=19.0 +ENV ODOO_VERSION="$ODOO_VERSION" + +# Install Odoo hard & soft dependencies, and Doodba utilities +RUN build_deps=" \ + build-essential \ + libfreetype6-dev \ + libfribidi-dev \ + libghc-zlib-dev \ + libharfbuzz-dev \ + libjpeg-dev \ + liblcms2-dev \ + libldap2-dev \ + libopenjp2-7-dev \ + libpq-dev \ + libsasl2-dev \ + libtiff5-dev \ + libwebp-dev \ + libxml2-dev \ + libxslt-dev \ + tcl-dev \ + tk-dev \ + zlib1g-dev \ + " \ + && apt-get update \ + && apt-get install -yqq --no-install-recommends $build_deps \ + && curl -o requirements.txt https://raw.githubusercontent.com/$ODOO_SOURCE/$ODOO_VERSION/requirements.txt \ + # need to upgrade setuptools, since the fixes for CVE-2024-6345 rolled out in base images we get errors "error: invalid command 'bdist_wheel'" + && pip install --upgrade setuptools \ + && pip install -r requirements.txt \ + 'websocket-client~=0.56' \ + astor \ + click-odoo-contrib \ + debugpy \ + pydevd-odoo \ + git+https://github.com/mailgun/flanker.git@v0.9.15#egg=flanker[validator] \ + geoip2 \ + "git-aggregator==4.0" \ + inotify \ + pdfminer.six \ + pg_activity \ + phonenumbers \ + plumbum \ + pudb \ + pyOpenSSL \ + python-magic \ + watchdog \ + wdb \ + && (python3 -m compileall -q /usr/local/lib/python3.12/ || true) \ + # generate flanker cached tables during install when /usr/local/lib/ is still intended to be written to + # https://github.com/Tecnativa/doodba/issues/486 + && python3 -c 'from flanker.addresslib import address' >/dev/null 2>&1 \ + && apt-get purge -yqq $build_deps \ + && apt-get autopurge -yqq \ + && rm -Rf /var/lib/apt/lists/* /tmp/* + +# Metadata +ARG VCS_REF +ARG BUILD_DATE +ARG VERSION +LABEL org.label-schema.schema-version="$VERSION" \ + org.label-schema.vendor=Tecnativa \ + org.label-schema.license=Apache-2.0 \ + org.label-schema.build-date="$BUILD_DATE" \ + org.label-schema.vcs-ref="$VCS_REF" \ + org.label-schema.vcs-url="https://github.com/Tecnativa/doodba" + +# Onbuild version, with all the magic +FROM base AS onbuild + +# Enable setting custom uids for odoo user during build of scaffolds +ONBUILD ARG UID=1000 +ONBUILD ARG GID=1000 + +# Enable Odoo user and filestore +ONBUILD RUN groupadd -g $GID odoo -o \ + && useradd -l -md /home/odoo -s /bin/false -u $UID -g $GID odoo \ + && mkdir -p /var/lib/odoo \ + && chown -R odoo:odoo /var/lib/odoo /qa/artifacts \ + && chmod a=rwX /qa/artifacts \ + && sync + +# Subimage triggers +ONBUILD ENTRYPOINT ["/opt/odoo/common/entrypoint"] +ONBUILD CMD ["/usr/local/bin/odoo"] +ONBUILD ARG AGGREGATE=true +ONBUILD ARG DEFAULT_REPO_PATTERN="https://github.com/OCA/{}.git" +ONBUILD ARG DEFAULT_REPO_PATTERN_ODOO="https://github.com/OCA/OCB.git" +ONBUILD ARG DEPTH_DEFAULT=1 +ONBUILD ARG DEPTH_MERGE=100 +ONBUILD ARG CLEAN=true +ONBUILD ARG COMPILE=true +ONBUILD ARG FONT_MONO="Liberation Mono" +ONBUILD ARG FONT_SANS="Liberation Sans" +ONBUILD ARG FONT_SERIF="Liberation Serif" +ONBUILD ARG PIP_INSTALL_ODOO=true +ONBUILD ARG ADMIN_PASSWORD=admin +ONBUILD ARG SMTP_SERVER=smtp +ONBUILD ARG SMTP_PORT=25 +ONBUILD ARG SMTP_USER=false +ONBUILD ARG SMTP_PASSWORD=false +ONBUILD ARG SMTP_SSL=false +ONBUILD ARG EMAIL_FROM="" +ONBUILD ARG PROXY_MODE=false +ONBUILD ARG WITHOUT_DEMO=all +ONBUILD ARG PGUSER=odoo +ONBUILD ARG PGPASSWORD=odoopassword +ONBUILD ARG PGHOST=db +ONBUILD ARG PGPORT=5432 +ONBUILD ARG PGDATABASE=prod + +# Config variables +ONBUILD ENV ADMIN_PASSWORD="$ADMIN_PASSWORD" \ + DEFAULT_REPO_PATTERN="$DEFAULT_REPO_PATTERN" \ + DEFAULT_REPO_PATTERN_ODOO="$DEFAULT_REPO_PATTERN_ODOO" \ + UNACCENT="$UNACCENT" \ + PGUSER="$PGUSER" \ + PGPASSWORD="$PGPASSWORD" \ + PGHOST="$PGHOST" \ + PGPORT=$PGPORT \ + PGDATABASE="$PGDATABASE" \ + PROXY_MODE="$PROXY_MODE" \ + SMTP_SERVER="$SMTP_SERVER" \ + SMTP_PORT=$SMTP_PORT \ + SMTP_USER="$SMTP_USER" \ + SMTP_PASSWORD="$SMTP_PASSWORD" \ + SMTP_SSL="$SMTP_SSL" \ + EMAIL_FROM="$EMAIL_FROM" \ + WITHOUT_DEMO="$WITHOUT_DEMO" +ONBUILD ARG LOCAL_CUSTOM_DIR=./custom +ONBUILD COPY --chown=root:odoo $LOCAL_CUSTOM_DIR /opt/odoo/custom + +# https://docs.python.org/3/library/logging.html#levels +ONBUILD ARG LOG_LEVEL=INFO +ONBUILD RUN [ -d ~root/.ssh ] && rm -r ~root/.ssh; \ + mkdir -p /opt/odoo/custom/ssh \ + && ln -s /opt/odoo/custom/ssh ~root/.ssh \ + && chmod -R u=rwX,go= /opt/odoo/custom/ssh \ + && sync +ONBUILD ARG DB_VERSION=latest +ONBUILD RUN /opt/odoo/common/build && sync +ONBUILD VOLUME ["/var/lib/odoo"] +ONBUILD USER odoo diff --git a/8.0.Dockerfile b/8.0.Dockerfile deleted file mode 100644 index 27b75e60..00000000 --- a/8.0.Dockerfile +++ /dev/null @@ -1,166 +0,0 @@ -FROM debian:8 AS base - -# Enable Odoo user and filestore -RUN useradd -md /home/odoo -s /bin/false odoo \ - && mkdir -p /var/lib/odoo \ - && chown -R odoo:odoo /var/lib/odoo \ - && sync -VOLUME ["/var/lib/odoo"] -EXPOSE 8069 8072 - -ARG WKHTMLTOPDF_VERSION=0.12.5 -ARG WKHTMLTOPDF_CHECKSUM='2583399a865d7604726da166ee7cec656b87ae0a6016e6bce7571dcd3045f98b' -ENV DB_FILTER=.* \ - DEPTH_DEFAULT=1 \ - DEPTH_MERGE=100 \ - EMAIL=https://hub.docker.com/r/tecnativa/odoo \ - GIT_AUTHOR_NAME=docker-odoo \ - INITIAL_LANG="" \ - LC_ALL=C.UTF-8 \ - NODE_PATH=/usr/local/lib/node_modules:/usr/lib/node_modules \ - OPENERP_SERVER=/opt/odoo/auto/odoo.conf \ - PATH="/home/odoo/.local/bin:$PATH" \ - PIP_NO_CACHE_DIR=0 \ - PUDB_RDB_HOST=0.0.0.0 \ - PUDB_RDB_PORT=6899 \ - PYTHONOPTIMIZE=1 \ - UNACCENT=true \ - WAIT_DB=true \ - WDB_NO_BROWSER_AUTO_OPEN=True \ - WDB_SOCKET_SERVER=wdb \ - WDB_WEB_PORT=1984 \ - WDB_WEB_SERVER=localhost - -# Other requirements and recommendations to run Odoo -# See https://github.com/$ODOO_SOURCE/blob/$ODOO_VERSION/debian/control -RUN apt-get update \ - && apt-get -y upgrade \ - && apt-get install -y --no-install-recommends \ - python ruby-compass \ - fontconfig libfreetype6 libxml2 libxslt1.1 libjpeg62-turbo zlib1g \ - libfreetype6 liblcms2-2 libopenjpeg5 libtiff5 tk tcl libpq5 \ - libldap-2.4-2 libsasl2-2 libx11-6 libxext6 libxrender1 \ - locales-all zlibc \ - bzip2 ca-certificates curl gettext-base git nano \ - openssh-client telnet xz-utils \ - && curl https://bootstrap.pypa.io/get-pip.py | python /dev/stdin \ - && curl -sL https://deb.nodesource.com/setup_6.x | bash - \ - && apt-get install -yqq nodejs \ - && curl -SLo wkhtmltox.deb https://github.com/wkhtmltopdf/wkhtmltopdf/releases/download/${WKHTMLTOPDF_VERSION}/wkhtmltox_${WKHTMLTOPDF_VERSION}-1.jessie_amd64.deb \ - && echo "${WKHTMLTOPDF_CHECKSUM} wkhtmltox.deb" | sha256sum -c - \ - && (dpkg --install wkhtmltox.deb || true) \ - && apt-get install -yqq --no-install-recommends --fix-broken \ - && rm wkhtmltox.deb \ - && wkhtmltopdf --version \ - && rm -Rf /var/lib/apt/lists/* - -# Special case to get latest PostgreSQL client -RUN echo 'deb http://apt.postgresql.org/pub/repos/apt/ jessie-pgdg main' >> /etc/apt/sources.list.d/postgresql.list \ - && curl -SL https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - \ - && apt-get update \ - && apt-get install -y --no-install-recommends postgresql-client \ - && rm -Rf /var/lib/apt/lists/* /tmp/* - -# Special case to get latest Less and PhantomJS -RUN ln -s /usr/bin/nodejs /usr/local/bin/node \ - && npm install -g less@2 less-plugin-clean-css@1 phantomjs-prebuilt@2 \ - && rm -Rf ~/.npm /tmp/* - -# Special case to get bootstrap-sass, required by Odoo for Sass assets -RUN gem install --no-rdoc --no-ri --no-update-sources bootstrap-sass --version '<4' \ - && rm -Rf ~/.gem /var/lib/gems/*/cache/ - -# Other facilities -WORKDIR /opt/odoo -RUN pip install \ - astor git-aggregator openupgradelib ptvsd==3.0.0 pudb wdb -COPY bin/* /usr/local/bin/ -COPY lib/odoobaselib /usr/local/lib/python2.7/dist-packages/odoobaselib -COPY build.d common/build.d -COPY conf.d common/conf.d -COPY entrypoint.d common/entrypoint.d -RUN mkdir -p auto/addons custom/src/private \ - && ln /usr/local/bin/direxec common/entrypoint \ - && ln /usr/local/bin/direxec common/build \ - && chmod -R a+rx common/entrypoint* common/build* /usr/local/bin \ - && chmod -R a+rX /usr/local/lib/python2.7/dist-packages/odoobaselib \ - && sync - -# Execute installation script by Odoo version -# This is at the end to benefit from cache at build time -# https://docs.docker.com/engine/reference/builder/#/impact-on-build-caching -ARG ODOO_SOURCE=OCA/OCB -ARG ODOO_VERSION=10.0 -ENV ODOO_VERSION="$ODOO_VERSION" -RUN install.sh -RUN pip install pg_activity - -# HACK Special case for Werkzeug -USER odoo -RUN pip install --user Werkzeug==0.14.1 - -# Metadata -ARG VCS_REF -ARG BUILD_DATE -ARG VERSION -LABEL org.label-schema.schema-version="$VERSION" \ - org.label-schema.vendor=Tecnativa \ - org.label-schema.license=Apache-2.0 \ - org.label-schema.build-date="$BUILD_DATE" \ - org.label-schema.vcs-ref="$VCS_REF" \ - org.label-schema.vcs-url="https://github.com/Tecnativa/doodba" - -# Onbuild version, with all the magic -FROM base AS onbuild - -# Subimage triggers -ONBUILD USER root -ONBUILD ENTRYPOINT ["/opt/odoo/common/entrypoint"] -ONBUILD CMD ["/usr/local/bin/odoo"] -ONBUILD ARG AGGREGATE=true -ONBUILD ARG AUTO_REQUIREMENTS=false -ONBUILD ARG DEPTH_DEFAULT=1 -ONBUILD ARG DEPTH_MERGE=100 -ONBUILD ARG CLEAN=true -ONBUILD ARG COMPILE=true -ONBUILD ARG PIP_INSTALL_ODOO=true -ONBUILD ARG ADMIN_PASSWORD=admin -ONBUILD ARG SMTP_SERVER=smtp -ONBUILD ARG SMTP_PORT=25 -ONBUILD ARG SMTP_USER=false -ONBUILD ARG SMTP_PASSWORD=false -ONBUILD ARG SMTP_SSL=false -ONBUILD ARG EMAIL_FROM="" -ONBUILD ARG PROXY_MODE=false -ONBUILD ARG WITHOUT_DEMO=all -ONBUILD ARG PGUSER=odoo -ONBUILD ARG PGPASSWORD=odoopassword -ONBUILD ARG PGHOST=db -ONBUILD ARG PGPORT=5432 -ONBUILD ARG PGDATABASE=prod -# Config variables -ONBUILD ENV ADMIN_PASSWORD="$ADMIN_PASSWORD" \ - UNACCENT="$UNACCENT" \ - PGUSER="$PGUSER" \ - PGPASSWORD="$PGPASSWORD" \ - PGHOST="$PGHOST" \ - PGPORT=$PGPORT \ - PGDATABASE="$PGDATABASE" \ - PROXY_MODE="$PROXY_MODE" \ - SMTP_SERVER="$SMTP_SERVER" \ - SMTP_PORT=$SMTP_PORT \ - SMTP_USER="$SMTP_USER" \ - SMTP_PASSWORD="$SMTP_PASSWORD" \ - SMTP_SSL="$SMTP_SSL" \ - EMAIL_FROM="$EMAIL_FROM" \ - WITHOUT_DEMO="$WITHOUT_DEMO" -ONBUILD ARG LOCAL_CUSTOM_DIR=./custom -ONBUILD COPY $LOCAL_CUSTOM_DIR /opt/odoo/custom -# https://docs.python.org/2.7/library/logging.html#levels -ONBUILD ARG LOG_LEVEL=INFO -ONBUILD RUN mkdir -p /opt/odoo/custom/ssh \ - && ln -s /opt/odoo/custom/ssh ~root/.ssh \ - && chmod -R u=rwX,go= /opt/odoo/custom/ssh \ - && sync -ONBUILD RUN /opt/odoo/common/build && sync -ONBUILD USER odoo diff --git a/9.0.Dockerfile b/9.0.Dockerfile deleted file mode 120000 index 04c2b0a4..00000000 --- a/9.0.Dockerfile +++ /dev/null @@ -1 +0,0 @@ -8.0.Dockerfile \ No newline at end of file diff --git a/README.md b/README.md index 6c5cd7ad..c686059c 100644 --- a/README.md +++ b/README.md @@ -1,45 +1,92 @@ # [Doodba](https://hub.docker.com/r/tecnativa/doodba) +![ci](https://github.com/Tecnativa/doodba/workflows/ci/badge.svg) [![](https://images.microbadger.com/badges/version/tecnativa/doodba:latest.svg)](https://microbadger.com/images/tecnativa/doodba:latest "Get your own version badge on microbadger.com") [![](https://images.microbadger.com/badges/image/tecnativa/doodba:latest.svg)](https://microbadger.com/images/tecnativa/doodba:latest "Get your own image badge on microbadger.com") [![](https://images.microbadger.com/badges/commit/tecnativa/doodba:latest.svg)](https://microbadger.com/images/tecnativa/doodba:latest "Get your own commit badge on microbadger.com") [![](https://images.microbadger.com/badges/license/tecnativa/doodba.svg)](https://microbadger.com/images/tecnativa/doodba "Get your own license badge on microbadger.com") -[![](https://api.travis-ci.org/Tecnativa/doodba.svg)](https://travis-ci.org/Tecnativa/doodba) - -**Doodba** stands for **Do**cker **Od**oo **Ba**se, and it is a -highly opinionated image ready to put [Odoo](https://www.odoo.com) inside it, -but **without Odoo**. +**Doodba** stands for **Do**cker **Od**oo **Ba**se, and it is a highly opinionated image +ready to put [Odoo](https://www.odoo.com) inside it, but **without Odoo**. ## What? -Yes, the purpose of this is to serve as a base for you to build your own Odoo -project, because most of them end up requiring a big amount of custom patches, -merges, repositories, etc. With this image, you have a collection of good -practices and tools to enable your team to have a standard Odoo project -structure. +Yes, the purpose of this is to serve as a base for you to build your own Odoo project, +because most of them end up requiring a big amount of custom patches, merges, +repositories, etc. With this image, you have a collection of good practices and tools to +enable your team to have a standard Odoo project structure. BTW, we use [Debian][]. I hope you like that. - [Debian]: https://debian.org/ +[debian]: https://debian.org/ ## Why? -Because developing Odoo is hard. You need lots of customizations, dependencies, -and if you want to move from one version to another, it's a pain. +Because developing Odoo is hard. You need lots of customizations, dependencies, and if +you want to move from one version to another, it's a pain. -Also because nobody wants Odoo as it comes from upstream, you most likely will -need to add custom patches and addons, at least, so we need a way to put all -together and make it work anywhere quickly. +Also because nobody wants Odoo as it comes from upstream, you most likely will need to +add custom patches and addons, at least, so we need a way to put all together and make +it work anywhere quickly. ## How? -You can start working with this straight away with our [scaffolding][]. +You can start working with this straight away with our [template][]. + + + + + + +- [Image usage](#image-usage) + - [`/opt/odoo/custom`: The important one](#optodoocustom-the-important-one) + - [`/opt/odoo/custom/entrypoint.d`](#optodoocustomentrypointd) + - [`/opt/odoo/custom/build.d`](#optodoocustombuildd) + - [`/opt/odoo/custom/conf.d`](#optodoocustomconfd) + - [`/opt/odoo/custom/ssh`](#optodoocustomssh) + - [`/opt/odoo/custom/src`](#optodoocustomsrc) + - [`/opt/odoo/custom/src/odoo`](#optodoocustomsrcodoo) + - [`/opt/odoo/custom/src/private`](#optodoocustomsrcprivate) + - [`/opt/odoo/custom/src/repos.yaml`](#optodoocustomsrcreposyaml) + - [Automatic download of repos](#automatic-download-of-repos) + - [`/opt/odoo/custom/src/addons.yaml`](#optodoocustomsrcaddonsyaml) + - [`/opt/odoo/custom/dependencies/*.txt`](#optodoocustomdependenciestxt) + - [`/opt/odoo/common`: The useful one](#optodoocommon-the-useful-one) + - [`/opt/odoo/auto`: The automatic one](#optodooauto-the-automatic-one) + - [`/opt/odoo/auto/addons`](#optodooautoaddons) + - [`/opt/odoo/auto/odoo.conf`](#optodooautoodooconf) +- [The `Dockerfile`](#the-dockerfile) +- [Bundled tools](#bundled-tools) + - [`addons`](#addons) + - [`click-odoo` and related scripts](#click-odoo-and-related-scripts) + - [`nano`](#nano) + - [`log`](#log) + - [`pot`](#pot) + - [`psql`](#psql) + - [`inotify`](#inotify) + - [`debugpy`](#debugpy) + - [`pudb`](#pudb) + - [`git-aggregator`](#git-aggregator) + - [`autoaggregate`](#autoaggregate) + - [Example `repos.yaml` file](#example-reposyaml-file) + - [`odoo`](#odoo) +- [Subproject template](#subproject-template) +- [FAQ](#faq) + - [Will there be not retrocompatible changes on the image?](#will-there-be-not-retrocompatible-changes-on-the-image) + - [This project is too opinionated, but can I question any of those opinions?](#this-project-is-too-opinionated-but-can-i-question-any-of-those-opinions) + - [What's this `hooks` folder here?](#whats-this-hooks-folder-here) + - [How can I pin an image version?](#how-can-i-pin-an-image-version) + - [How can I help?](#how-can-i-help) +- [Related Projects](#related-projects) + + + + ## Image usage -Basically, every directory you have to worry about is found inside `/opt/odoo`. -This is its structure: +Basically, every directory you have to worry about is found inside `/opt/odoo`. This is +its structure: custom/ entrypoint.d/ @@ -79,59 +126,57 @@ Here you will put everything related to your project. #### `/opt/odoo/custom/entrypoint.d` -Any executables found here will be run when you launch your container, before -running the command you ask. +Any executables found here will be run when you launch your container, before running +the command you ask. #### `/opt/odoo/custom/build.d` Executables here will be aggregated with those in `/opt/odoo/common/build.d`. -The resulting set of executables will then be sorted alphabetically (ascending) -and then subsequently run. +The resulting set of executables will then be sorted alphabetically (ascending) and then +subsequently run. #### `/opt/odoo/custom/conf.d` Files here will be environment-variable-expanded and concatenated in -`/opt/odoo/auto/odoo.conf` at build time. +`/opt/odoo/auto/odoo.conf` in the entrypoint. #### `/opt/odoo/custom/ssh` -It must follow the same structure as a standard `~/.ssh` directory, including -`config` and `known_hosts` files. In fact, it is completely equivalent to -`~root/.ssh`. +It must follow the same structure as a standard `~/.ssh` directory, including `config` +and `known_hosts` files. In fact, it is completely equivalent to `~root/.ssh`. -The `config` file can contain `IdentityFile` keys to represent the private -key that should be used for that host. Unless specified otherwise, this -defaults to `identity[.pub]`, `id_rsa[.pub]` or `id_dsa[.pub]` files found in -this same directory. +The `config` file can contain `IdentityFile` keys to represent the private key that +should be used for that host. Unless specified otherwise, this defaults to +`identity[.pub]`, `id_rsa[.pub]` or `id_dsa[.pub]` files found in this same directory. -This is very useful **to use deployment keys** that grant git access to your -private repositories. +This is very useful **to use deployment keys** that grant git access to your private +repositories. -Example - a private key file in the `ssh` folder named `my_private_key` for -the host `repo.example.com` would have a `config` entry similar to the below: +Example - a private key file in the `ssh` folder named `my_private_key` for the host +`repo.example.com` would have a `config` entry similar to the below: ``` Host repo.example.com IdentityFile ~/.ssh/my_private_key ``` -Or you could just drop the key in `id_rsa` and `id_rsa.pub` files and it should -work by default without the need of adding a `config` file. +Or you could just drop the key in `id_rsa` and `id_rsa.pub` files and it should work by +default without the need of adding a `config` file. -Host key checking is enabled by default, which means that you also need to -provide a `known_hosts` file for any repos that you wish to access via SSH. +Host key checking is enabled by default, which means that you also need to provide a +`known_hosts` file for any repos that you wish to access via SSH. -In order to disable host key checks for a repo, your config would look something -like this: +In order to disable host key checks for a repo, your config would look something like +this: ``` Host repo.example.com StrictHostKeyChecking no ``` -For additional information regarding this directory, take a look at this -[Digital Ocean Article][ssh-conf]. +For additional information regarding this directory, take a look at this [Digital Ocean +Article][ssh-conf]. #### `/opt/odoo/custom/src` @@ -142,9 +187,9 @@ When putting code here, you can either: - Use [`repos.yaml`][], that will fill anything at build time. - Directly copy all there. -Recommendation: use [`repos.yaml`][] for everything except for [`private`][], -and ignore in your `.gitignore` and `.dockerignore` files every folder here -except [`private`][], with rules like these: +Recommendation: use [`repos.yaml`][] for everything except for [`private`][], and ignore +in your `.gitignore` and `.dockerignore` files every folder here except [`private`][], +with rules like these: odoo/custom/src/* !odoo/custom/src/private @@ -159,11 +204,11 @@ You can choose your Odoo version, and even merge PRs from many of them using - [Original Odoo][], by [Odoo S.A.][]. -- [OCB][] (Odoo Community Backports), by [OCA][]. - The original + some features - some stability strictness. +- [OCB][] (Odoo Community Backports), by [OCA][]. The original + some features - some + stability strictness. -- [OpenUpgrade][], by [OCA][]. - The original, frozen at new version launch time + migration scripts. +- [OpenUpgrade][], by [OCA][]. The original, frozen at new version launch time + + migration scripts. ##### `/opt/odoo/custom/src/private` @@ -173,43 +218,150 @@ You can choose your Odoo version, and even merge PRs from many of them using A [git-aggregator](#git-aggregator) configuration file. +It should look similar to this: + +```yaml +# Odoo must be in the `odoo` folder for Doodba to work +odoo: + defaults: + # This will use git shallow clones. + # $DEPTH_DEFAULT is 1 in test and prod, but 100 in devel. + # $DEPTH_MERGE is always 100. + # You can use any integer value, OTOH. + depth: $DEPTH_MERGE + remotes: + origin: https://github.com/OCA/OCB.git + odoo: https://github.com/odoo/odoo.git + openupgrade: https://github.com/OCA/OpenUpgrade.git + # $ODOO_VERSION is... the Odoo version! "11.0" or similar + target: origin $ODOO_VERSION + merges: + - origin $ODOO_VERSION + - odoo refs/pull/25594/head # Expose `Field` from search_filters.js + +web: + defaults: + depth: $DEPTH_MERGE + remotes: + origin: https://github.com/OCA/web.git + tecnativa: https://github.com/Tecnativa/partner-contact.git + target: origin $ODOO_VERSION + merges: + - origin $ODOO_VERSION + - origin refs/pull/1007/head # web_responsive search + - tecnativa 11.0-some_addon-custom # Branch for this customer only +``` + +###### Automatic download of repos + +Doodba is smart enough to download automatically git repositories even if they are +missing in `repos.yaml`. It will happen if it is used in [`addons.yaml`][], except for +the special [`private`][] repo. This will help you keep your deployment definitions DRY. + +You can configure this behavior with these environment variables (default values shown): + +- `DEFAULT_REPO_PATTERN="https://github.com/OCA/{}.git"` +- `DEFAULT_REPO_PATTERN_ODOO="https://github.com/OCA/OCB.git"` + +As you probably guessed, we use something like `str.format(repo_basename)` on top of +those variables to compute the default remote origin. If, i.e., you want to use your own +repositories as default remotes, just add these build arguments to your +`docker-compose.yaml` file: + +```yaml +# [...] +services: + odoo: + build: + args: + DEFAULT_REPO_PATTERN: &origin "https://github.com/Tecnativa/{}.git" + DEFAULT_REPO_PATTERN_ODOO: *origin +# [...] +``` + +So, for example, if your [`repos.yaml`][] file is empty and your [`addons.yaml`][] +contains this: + +```yaml +server-tools: + - module_auto_update +``` + +A `/opt/odoo/auto/repos.yaml` file with this will be generated and used to download git +code: + +```yaml +/opt/odoo/custom/src/odoo: + defaults: + depth: $DEPTH_DEFAULT + remotes: + origin: https://github.com/OCA/OCB.git + target: origin $ODOO_VERSION + merges: + - origin $ODOO_VERSION +/opt/odoo/custom/src/server-tools: + defaults: + depth: $DEPTH_DEFAULT + remotes: + origin: https://github.com/OCA/server-tools.git + target: origin $ODOO_VERSION + merges: + - origin $ODOO_VERSION +``` + +All of this means that, you only need to define the git aggregator spec in +[`repos.yaml`][] if anything diverges from the standard: + +- You need special merges. +- You need a special origin. +- The folder name does not match the origin pattern. +- The branch name does not match `$ODOO_VERSION`. +- Etc. + ##### `/opt/odoo/custom/src/addons.yaml` One entry per repo and addon you want to activate in your project. Like this: ```yaml website: - - website_cookie_notice - - website_legal_page + - website_cookie_notice + - website_legal_page web: - - web_responsive + - web_responsive ``` Advanced features: -- You can bundle [several YAML documents][] if you want to logically group your - addons and some repos are repeated among groups, by separating each document - with `---`. +- You can bundle [several YAML documents][] if you want to logically group your addons + and some repos are repeated among groups, by separating each document with `---`. -- Addons under `private` and `odoo/addons` are linked automatically unless you - specify them. +- Addons under `private` and `odoo/addons` are linked automatically unless you specify + them. -- You can use `ONLY` to supply a dictionary of environment variables and a - list of possible values to enable that document in the matching environments. +- You can use `ONLY` to supply a dictionary of environment variables and a list of + possible values to enable that document in the matching environments. -- If an addon is found in several places at the same time, it will get linked - according to this priority table: +- You can use `ENV` to supply a dictionary of environment variables to be used on + downloading repositories. Following variables are supported: + + - `DEFAULT_REPO_PATTERN` + - `DEFAULT_REPO_PATTERN_ODOO` + - `DEPTH_DEFAULT` + - `ODOO_VERSION` - can be used as repository branch + +- If an addon is found in several places at the same time, it will get linked according + to this priority table: 1. Addons in [`private`][]. - 2. Addons in other repositories (in case one is matched in several, it will - be random, BEWARE!). Better have no duplicated names if possible. + 2. Addons in other repositories (in case one is matched in several, it will be random, + BEWARE!). Better have no duplicated names if possible. 3. Core Odoo addons from [`odoo/addons`][`odoo`]. - If an addon is specified but not available at runtime, it will fail silently. - You can use any wildcards supported by [Python's glob module][glob]. -This example shows these advanced features: +The following example shows these advanced features: ```yaml # Spanish Localization @@ -217,7 +369,7 @@ l10n-spain: - l10n_es # Overrides built-in l10n_es under odoo/addons server-tools: - "*date*" # All modules that contain "date" in their name - - module_auto_update # Makes `autoupdate` script actually autoupdate addons + - auditlog web: - "*" # All web addons --- @@ -225,7 +377,7 @@ web: website: - website_blog_excertp_img server-tools: # Here we repeat server-tools, but no problem because it's a - # different document + # different document - html_image_url_extractor - html_text --- @@ -243,31 +395,39 @@ ONLY: - prod server-tools: - auth_* +--- +# Custom repositories +ENV: + DEFAULT_REPO_PATTERN: https://github.com/Tecnativa/{}.git + ODOO_VERSION: 16.0-new-feature +some-repo: # Cloned from https://github.com/Tecnativa/some-repo.git branch 15.0-new-feature + - some_custom_module ``` ##### `/opt/odoo/custom/dependencies/*.txt` -Files to indicate dependencies of your subimage, one for each of the supported -package managers: +Files to indicate dependencies of your subimage, one for each of the supported package +managers: -- `apt_build.txt`: build-time dependencies, installed before any others and - removed after all the others too. Usually these would include Debian packages - such as `build-essential` or `python-dev`. +- `apt_build.txt`: build-time dependencies, installed before any others and removed + after all the others too. Usually these would include Debian packages such as + `build-essential` or `python-dev`. From Doodba 11.0, this is most likely not needed, + as build dependencies are shipped with the image, and local python develpment headers + should be used instead of those downloaded from apt. - `apt.txt`: run-time dependencies installed by apt. - `gem.txt`: run-time dependencies installed by gem. - `npm.txt`: run-time dependencies installed by npm. -- `pip.txt`: a normal [pip `requirements.txt`][] file, for run-time - dependencies too. It will get executed with `--update` flag, just in case - you want to overwrite any of the pre-bundled dependencies. +- `pip.txt`: a normal [pip `requirements.txt`][] file, for run-time dependencies too. It + will get executed with `--update` flag, just in case you want to overwrite any of the + pre-bundled dependencies. ### `/opt/odoo/common`: The useful one -This folder is full of magic. I'll document it some day. For now, just look at -the code. +This folder is full of magic. I'll document it some day. For now, just look at the code. Only some notes: -- Will compile your code with [`PYTHONOPTIMIZE=1`][] by default. +- Will compile your code with [`PYTHONOPTIMIZE=""`][] by default. - Will remove all code not used from the image by default (not listed in `/opt/odoo/custom/src/addons.yaml`), to keep it thin. @@ -287,132 +447,129 @@ It will have the result of merging all configurations under ## The `Dockerfile` -I will document all build arguments and environment variables some day, but for -now keep this in mind: +I will document all build arguments and environment variables some day, but for now keep +this in mind: -- This is just a base image, full of tools. **You need to build your project - subimage** from this one, even if your project's `Dockerfile` only contains - these 2 lines: +- This is just a base image, full of tools. **You need to build your project subimage** + from this one, even if your project's `Dockerfile` only contains these 2 lines: FROM tecnativa/doodba MAINTAINER Me -- The above sentence becomes true because we have a lot of `ONBUILD` sentences - here, so at least **your project must have a `./custom` folder** along with - its `Dockerfile` for it to work. +- The above sentence becomes true because we have a lot of `ONBUILD` sentences here, so + at least **your project must have a `./custom` folder** along with its `Dockerfile` + for it to work. -- All should be magic if you adhere to our opinions here. Just put the code - where it should go, and relax. +- All should be magic if you adhere to our opinions here. Just put the code where it + should go, and relax. ## Bundled tools -There is a good collections of tools available in the image that help dealing -with Odoo and its peculiarities: +There is a good collections of tools available in the image that help dealing with Odoo +and its peculiarities: ### `addons` -A handy CLI tool to automate addon management based on the current environment. -It allows you to install, update, test and/or list private, extra and/or core -addons available to current container, based on current [`addons.yaml`][] -configuration. +A handy CLI tool to automate addon management based on the current environment. It +allows you to install, update, test and/or list private, extra and/or core addons +available to current container, based on current [`addons.yaml`][] configuration. Call `addons --help` for usage instructions. -### [`nano`][] +### `click-odoo` and related scripts -The CLI text editor we all know, just in case you need to inspect some bug in -hot deployments. +The great [`click-odoo`][] scripting framework and the collection of scripts found in +[`click-odoo-contrib`][] are included. Refer to their sites to know how to use them. + +\* Note: This replaces the deprecated `python-odoo-shell` binary. + +### [`nano`](https://www.nano-editor.org/) + +The CLI text editor we all know, just in case you need to inspect some bug in hot +deployments. ### `log` -Just a little shell script that you can use to add logs to your build or -entrypoint scripts: +Just a little shell script that you can use to add logs to your build or entrypoint +scripts: log INFO I'm informing ### `pot` -Little shell shortcut for exporting a translation template from any addon(s). -Usage: +Little shell shortcut for exporting a translation template from any addon(s). Usage: pot my_addon,my_other_addon -### `python-odoo-shell` +### [`psql`](https://www.postgresql.org/docs/current/app-psql.html) -Little shortcut to make your `odoo shell` scripts executable. +Environment variables are there so that if you need to connect with the database, you +just need to execute: -For example, create this file in your scaffolding-based project: -`odoo/custom/shell-scripts/whoami.py`. Fill it with: - -```python -#!/usr/local/bin/python-odoo-shell -from __future__ import print_function -print(env.user.name) -print(env.context) -``` + docker-compose run -l traefik.enable=false --rm odoo psql -Now run it: - -```bash -$ chmod a+x odoo/custom/shell-scripts/whoami.py # Make it executable -$ docker-compose build --pull # Rebuild the image, unless in devel -$ docker-compose run --rm odoo custom/shell-scripts/whoami.py -``` - -### `unittest` +The same is true for any other [Postgres client applications][]. -Another little shell script, useful for debugging. Just run it like this and -Odoo will execute unit tests in its default database: +### [`inotify`](https://github.com/dsoprea/PyInotify) - unittest my_addon,my_other_addon +Enables hot code reloading when odoo is started with `--dev` and passed `reload` or +`all` as an argument. -Note that the addon must be installed for it to work. Otherwise, you should run -it as: +[copier template](https://github.com/Tecnativa/doodba-copier-template) enables this by +default in the development environment. - unittest my_addon,my_other_addon -i my_addon,my_other_addon +Doodba supports this feature under versions 11.0 and later. Check +[CLI docs](https://www.odoo.com/documentation/13.0/reference/cmdline.html#developer-features) +for details. -### [`psql`](https://www.postgresql.org/docs/9.5/static/app-psql.html) +### [`debugpy`](https://github.com/microsoft/vscode-python) -Environment variables are there so that if you need to connect with the -database, you just need to execute: +[VSCode][] debugger. If you use this editor with its python module, you will find it +useful. - docker exec -it your_container psql +To debug at a certain point of the code, add this Python code somewhere: -The same is true for any other [Postgres client applications][]. - -### [`ptvsd`](https://github.com/DonJayamanne/pythonVSCode) +```python +import debugpy +debugpy.listen(6899) +print("Waiting for debugger attach") +debugpy.wait_for_client() +debugpy.breakpoint() +print('break on this line') +``` -[VSCode][] debugger. If you use this editor with its python module, you will -find it useful. +To start Odoo within a debugpy environment, which will obey the breakpoints established +in your IDE (but will work slowly), just add `-e DEBUGPY_ENABLE=1` to your odoo +container. -To debug, add this Python code somewhere: +If you use the official [template][], you can boot it in debugpy mode with: -```python -import ptvsd -ptvsd.enable_attach("my_secret", address=("0.0.0.0", 6899)) -print("ptvsd waiting...") -ptvsd.wait_for_attach() +```bash +export DOODBA_DEBUGPY_ENABLE=1 +docker-compose -f devel.yaml up -d ``` -Of course, you need to have properly configured your [VSCode][]. To do so, make -sure in your project there is a `.vscode/launch.json` file with these minimal -contents: +Of course, you need to have properly configured your [VSCode][]. To do so, make sure in +your project there is a `.vscode/launch.json` file with these minimal contents: ```json { - "version": "0.2.0", - "configurations": [ + "version": "0.2.0", + "configurations": [ + { + "name": "Attach to debug in devel.yaml", + "type": "python", + "request": "attach", + "pathMappings": [ { - "name": "Attach to debug in devel.yaml", - "type": "python", - "request": "attach", - "localRoot": "${workspaceRoot}/odoo", - "remoteRoot": "/opt/odoo", - "port": 6899, - "secret": "my_secret", - "host": "localhost" + "localRoot": "${workspaceRoot}/odoo", + "remoteRoot": "/opt/odoo" } - ] + ], + "port": 6899, + "host": "localhost" + } + ] } ``` @@ -420,8 +577,8 @@ Then, execute that configuration as usual. ### [`pudb`](https://github.com/inducer/pudb) -This is another great debugger that includes remote debugging via telnet, which -can be useful for some cases, or for people that prefer it over [wdb](#wdb). +This is another great debugger that includes remote debugging via telnet, which can be +useful for some cases, or for people that prefer it over [wdb](#wdb). To use it, inject this in any Python script: @@ -432,444 +589,70 @@ pudb.remote.set_trace(term_size=(80, 24)) Then open a telnet connection to it (running in `0.0.0.0:6899` by default). -It is safe to use in [production][] environments **if you know what you are -doing and do not expose the debugging port to attackers**. Usage: +It is safe to use in [production][] environments **if you know what you are doing and do +not expose the debugging port to attackers**. Usage: docker-compose exec odoo telnet localhost 6899 ### [`git-aggregator`](https://pypi.python.org/pypi/git-aggregator) -We found this one to be the most useful tool for downlading code, merging it -and placing it somewhere. +We found this one to be the most useful tool for downloading code, merging it and +placing it somewhere. ### `autoaggregate` -This little script wraps `git-aggregator` to make it work fine and -automatically with this image. Used in the [scaffolding][]'s `setup-devel.yaml` -step. +This little script wraps `git-aggregator` to make it work fine and automatically with +this image. Used in the [template][]'s `setup-devel.yaml` step. -#### Example [`repos.yaml`][] file +#### Example `repos.yaml` file -This example merges [several sources][`odoo`]: +This [`repos.yaml`][] example merges [several sources][`odoo`]: ```yaml ./odoo: - defaults: - # Shallow repositores are faster & thinner. You better use - # $DEPTH_DEFAULT here when you need no merges. - depth: $DEPTH_MERGE - remotes: - ocb: https://github.com/OCA/OCB.git - odoo: https://github.com/odoo/odoo.git - target: - ocb $ODOO_VERSION - merges: - - ocb $ODOO_VERSION - - odoo refs/pull/13635/head + defaults: + # Shallow repositores are faster & thinner. You better use + # $DEPTH_DEFAULT here when you need no merges. + depth: $DEPTH_MERGE + remotes: + ocb: https://github.com/OCA/OCB.git + odoo: https://github.com/odoo/odoo.git + target: ocb $ODOO_VERSION + merges: + - ocb $ODOO_VERSION + - odoo refs/pull/13635/head + shell_command_after: + # Useful to merge a diff when there's no git history correlation + - curl -sSL https://github.com/odoo/odoo/pull/37187.diff | patch -fp1 ``` ### [`odoo`](https://www.odoo.com/documentation/10.0/reference/cmdline.html) -We set an `$OPENERP_SERVER` environment variable pointing to [the autogenerated -configuration file](#optodooautoodooconf) so you don't have to worry about -it. Just execute `odoo` and it will work fine. - -Note that version 9.0 has an `odoo` binary to provide forward compatibility -(but it has the `odoo.py` one too). - -## Scaffolding - -Get up and running quickly with the provided -[scaffolding](https://github.com/Tecnativa/doodba-scaffolding). - -### Skip the boring parts - -I will assume you know how to use Git, Docker and Docker Compose. - - git clone https://github.com/Tecnativa/doodba-scaffolding.git myproject - cd myproject - ln -s devel.yaml docker-compose.yml - chown -R $USER:1000 odoo/auto - chmod -R ug+rwX odoo/auto - export UID GID="$(id -g $USER)" UMASK="$(umask)" - docker-compose build --pull - docker-compose -f setup-devel.yaml run --rm odoo - docker-compose up - -And if you don't want to have a chance to do a `git merge` and get possible -future scaffolding updates merged in your project's `git log`: - - rm -Rf .git - git init - -### Tell me the boring parts - -The scaffolding provides you a boilerplate-ready project to start developing -Odoo in no time. - -#### Environments - -This scaffolding comes with some environment configurations, ready for you to -extend them. Each of them is a [Docker Compose -file](https://docs.docker.com/compose/compose-file/) almost ready to work out -of the box (or almost), but that will assume that you understand it and will -modify it. - -After you clone the scaffolding, **search for `XXX` comments**, they will help -you on making it work. - -##### Development - -Set it up with: - - export UID GID="$(id -g $USER)" UMASK="$(umask)" - docker-compose -f setup-devel.yaml run --rm odoo - -Once finished, you can start using Odoo with: - - docker-compose -f devel.yaml up --build - -This allows you to track only what Git needs to track and provides faster -Docker builds. - -You might consider adding this line to your `~/.bashrc`: - - export UID GID="$(id -g $USER)" UMASK="$(umask)" - -To browse Odoo go to `http://localhost:${ODOO_MAJOR}069` -(i.e. for Odoo 11.0 this would be `http://localhost:11069`). - -This environment has several special features: - -###### [`wdb`](https://github.com/Kozea/wdb/) - -This is one of the greatest Python debugger available, and even more for -Docker-based development, so here you have it preinstalled. - -I told you, this image is opinionated. :wink: - -To use it, write this in any Python script: - -```python -import wdb -wdb.set_trace() -``` - -It's available by default on the [development][] environment, -where you can browse http://localhost:1984 to use it. - -**DO NOT USE IT IN PRODUCTION ENVIRONMENTS.** (I had to say it). - -###### [MailHog](https://github.com/mailhog/MailHog) - -It provides a fake SMTP server that intercepts all mail sent by Odoo and -displays a simple interface that lets you see and debug all that mail -comfortably, including headers sent, attachments, etc. - -- For [development][], it's in http://localhost:8025 -- For [testing][], it's in http://$DOMAIN_TEST/smtpfake/ -- For [production][], it's not used. - -All environments are configured by default to use the bundled SMTP relay. -They are configured by these environment variables: - -- `SMTP_SERVER` -- `SMTP_PORT` -- `SMTP_USER` -- `SMTP_PASSWORD` -- `SMTP_SSL` -- `EMAIL_FROM` - -For them to be useful, you need to remove any `ir.mail_server` records in your -database. - -###### Network isolation - -The Docker network is in `--internal` mode, which means that it has -no access to the Internet. This feature protects you in cases where -a [production][] database is restored and Odoo tries to connect to -SMTP/IMAP/POP3 servers to send or receive emails. Also when you are -using [connectors](https://github.com/OCA/connector), -[mail trackers](https://www.odoo.com/apps/modules/browse?search=mail_tracking) -or any API sync/calls. - -If you still need to have public access, set `internal: false` in the -environment file, detach all containers from that network, remove the network, -reatach all containers to it, and possibly restart them. You can also just do: - - docker-compose down - docker-compose up -d - -Usually a better option is -[whitelisting](#how-can-i-whitelist-a-service-and-allow-external-access-to-it). - -##### Production - -This environment is just a template. **It is not production-ready**. You must -change many things inside it, it's just a guideline. - -It includes pluggable `smtp` and `backup` services. +We set an `$OPENERP_SERVER` or `$ODOO_RC` environment variable pointing to +[the autogenerated configuration file](#optodooautoodooconf), so you don't have to worry +about it. Just execute `odoo` and it will work fine. -Once you fixed everything needed, run it with: +Note that version 9.0 has an `odoo` binary to provide forward compatibility (but it has +the `odoo.py` one too). - docker-compose -f prod.yaml up --build --remove-orphans +## Subproject template -Remember that you will want to backup the filestore in `/var/lib/odoo` volume. +That's a big structure! Get it up and running quickly using the +[copier template](https://github.com/Tecnativa/doodba-copier-template) we provide to +help you generate your subproject. -###### Global inverse proxy - -For [production][] and [test][] templates to work fine, you need to have a -working [Traefik][] inverse proxy in each node. - -To have it, use this `inverseproxy.yaml` file: - -```yaml -version: "2.1" - -services: - proxy: - image: traefik:1.6-alpine - networks: - shared: - private: - public: - volumes: - - acme:/etc/traefik/acme:rw,Z - ports: - - "80:80" - - "443:443" - depends_on: - - dockersocket - restart: unless-stopped - privileged: true - tty: true - command: - - --ACME.ACMELogging - - --ACME.Email=you@example.com - - --ACME.EntryPoint=https - - --ACME.HTTPChallenge.entryPoint=http - - --ACME.OnHostRule - - --ACME.Storage=/etc/traefik/acme/acme.json - - --DefaultEntryPoints=http,https - - --EntryPoints=Name:http Address::80 Redirect.EntryPoint:https - - --EntryPoints=Name:https Address::443 TLS - - --LogLevel=INFO - - --Docker - - --Docker.EndPoint=http://dockersocket:2375 - - --Docker.ExposedByDefault=false - - --Docker.Watch - - dockersocket: - image: tecnativa/docker-socket-proxy - privileged: true - networks: - private: - volumes: - - /var/run/docker.sock:/var/run/docker.sock - environment: - CONTAINERS: 1 - NETWORKS: 1 - SERVICES: 1 - SWARM: 1 - TASKS: 1 - restart: unless-stopped - -networks: - shared: - internal: true - driver_opts: - encrypted: 1 - - private: - internal: true - driver_opts: - encrypted: 1 - - public: - -volumes: - acme: -``` - -Then boot it up with: - - docker-compose -p inverseproxy -f inverseproxy.yaml up -d - -This will intercept all requests coming from port 80 (`http`) and redirect them -to port 443 (`https`), it will download and install required SSL certificates -from [Let's Encrypt][] whenever you boot a new [production][] instance, add the -required proxy headers to the request, and then redirect all traffic to/from -odoo automatically. - -It includes [a security-enhaced proxy][docker-socket-proxy] to reduce attack -surface when listening to the Docker socket. - -This allows you to: - -* Have multiple domains for each Odoo instance. -* Have multiple Odoo instances in each node. -* Add an SSL layer automatically and for free. - -##### Testing - -A good rule of thumb is test in testing before uploading to production, so this -environment tries to imitate the [production][] one in everything, -but *removing possible pollution points*: - -- It has a fake `smtp` service based on [MailHog][]. - -- It has no `backup` service. - -- It is [isolated](#network-isolation). - -Test it in your machine with: - - docker-compose -f test.yaml up --build - -This environment also needs a [global inverse proxy](#global-inverse-proxy). - -#### Other usage scenarios - -In examples below I will skip the `-f .yaml` part and assume you -know which environment you want to use. - -Also, we recommend to use `run` subcommand to create a new container with same -settings and volumes. Sometimes you may prefer to use `exec` instead, to -execute an arbitrary command in a running container. - -##### Inspect the database - - docker-compose run --rm odoo psql - -##### Restart Odoo - -You will need to restart it whenever any Python code changes, so to do that: - - docker-compose restart -t0 odoo - -In production: - - docker-compose restart odoo https - -##### Run unit tests for some addon - - docker-compose run --rm odoo odoo --stop-after-init --init addon1,addon2 - docker-compose run --rm odoo unittest addon1,addon2 - -##### Reading the logs - -For all services in the environment: - - docker-compose logs -f --tail 10 - -Only Odoo's: - - docker-compose logs -f --tail 10 odoo - -##### Install some addon without stopping current running process - - docker-compose run --rm odoo odoo -i addon1,addon2 --stop-after-init - -##### Update some addon without stopping current running process - - docker-compose run --rm odoo odoo -u addon1,addon2 --stop-after-init - -##### Update changed addons only - -Add `module_auto_update` from https://github.com/OCA/server-tools to your -installation following the standard methods of `repos.yaml` + `addons.yaml`. - -Now we will install the addon: - - docker-compose up -d - docker-compose run --rm odoo --stop-after-init -u base - docker-compose run --rm odoo --stop-after-init -i module_auto_update - docker-compose restart odoo - -It will automatically update addons that got updated every night. -To force that automatic update now in a separate container: - - docker-compose up -d - docker-compose run --rm odoo autoupdate - docker-compose restart odoo - -##### Export some addon's translations to stdout - - docker-compose run --rm odoo pot addon1[,addon2] - -Now copy the relevant parts to your `addon1.pot` file. - -##### Open an odoo shell - - docker-compose run --rm odoo odoo shell - -##### Open another UI instance linked to same filestore and database - - docker-compose run --rm -p 127.0.0.1:$SomeFreePort:8069 odoo - -Then open `http://localhost:$SomeFreePort`. +Check its docs to know how to use it. ## FAQ ### Will there be not retrocompatible changes on the image? -This image is production-ready, but it is constantly evolving too, so some new -features can break some old ones, or conflict with them, and some old features -might get deprecated and removed at some point. - -The best you can do is to [subscribe to the compatibility breakage -announcements issue][retrobreak]. - -### I need to force addition or removal of `www.` prefix in production - -These instructions assume you use the official [scaffolding][]. -To **remove** the `www.` prefix, set these params in the `.env` file: - - DOMAIN_PROD=example.com - DOMAIN_PROD_ALT=www.example.com - -To **add** the `www.` prefix, it is almost the same: - - DOMAIN_PROD=www.example.com - DOMAIN_PROD_ALT=example.com - -Of course, both domains should point to the same machine before booting, or -Let's Encrypt might ban your server for some time. - -### How to allow access from several host names? - -In `.env`, set `DOMAIN_PROD` to `host1.com,host2.com,www.host1.com`, etc. - -### How to choose initial DB creation language? - -This image includes a hack that will set the initial language to load when -Odoo creates its database for the first time. These conditions must match: - -- `$PGDATABASE` is set. -- That database does not yet exist. -- `$INITIAL_LANG` is set to any Odoo lang code. I.e. `es_ES`. -- Odoo is booted. - -### I use [Fish][], how to export needed variables? +This image is production-ready, but it is constantly evolving too, so some new features +can break some old ones, or conflict with them, and some old features might get +deprecated and removed at some point. -Do: - - set -x UID (id -u $USER) - set -x GID (id -g $USER) - set -x UMASK (umask) - -You can make those variables universal (available in all terminals you open -from now on) by using `set -Ux` instead of `set -x`. - -### When I boot `devel.yaml` for the first time, Odoo crashes - -Most likely you are using versions `8.0` or `9.0` of the image. If so: - -1. Edit `devel.yaml`. -2. Search for the line that starts with `command:` in the `odoo` service. -3. Change it for a command that actually works with your version: - - `odoo --workers 0` for Odoo 8.0. - - `odoo --workers 0 --dev` for Odoo 9.0. +The best you can do is to [subscribe to the compatibility breakage announcements +issue][retrobreak]. ### This project is too opinionated, but can I question any of those opinions? @@ -880,49 +663,22 @@ Of course. There's no guarantee that we will like it, but please do it. :wink: It runs triggers when doing the automatic build in the Docker Hub. [Check this](https://hub.docker.com/r/thibaultdelor/testautobuildhooks/). -### Can I have my own [scaffolding][]? - -You probably **should**, and rebase on our updates. However, if you are -planning on a general update to it that you find interesting for the -general-purpose one, please send us a pull request. - -### Can I skip the `-f .yaml` part for `docker-compose` commands? - -Let's suppose you want to use [`test.yaml`][testing] environment by default, -no matter where you clone the project: - - ln -s test.yaml docker-compose.yaml - git add docker-compose.yaml - git commit - -Let's suppose you only want to use `devel.yaml` in your local development -machine by default: - - ln -s devel.yaml docker-compose.yml - -Notice the difference in the prefix (`.yaml` vs. `.yml`). Docker Compose will -use the `.yml` one if both are found, so that's the one we considered you -should use in your local clones, and that's the one that will be git-ignored by -default by the scaffolding `.gitignore` file. - -As a design choice, the scaffolding defaults to being explicit. - ### How can I pin an image version? -Version-pinning is a good idea to keep your code from differing among image -updates. It's the best way to ensure no updates got in between the last time -you checked the image and the time you deploy it to production. +Version-pinning is a good idea to keep your code from differing among image updates. +It's the best way to ensure no updates got in between the last time you checked the +image and the time you deploy it to production. You can do it through **its sha256 code**. -Get any image's code through inspect, running from a computer where the correct -image version is downloaded: +Get any image's code through inspect, running from a computer where the correct image +version is downloaded: docker image inspect --format='{{.RepoDigests}}' tecnativa/doodba:10.0-onbuild -Alternatively, you can browse [this image's builds][builds], click on the one -you know it works fine for you, and search for the `digest` word using your -browser's *search in page* system (Ctrl+F usually). +Alternatively, you can browse [this image's builds][builds], click on the one you know +it works fine for you, and search for the `digest` word using your browser's _search in +page_ system (Ctrl+F usually). You will find lines similar to: @@ -934,83 +690,62 @@ You will find lines similar to: 9.0: digest: sha256:33a540eca6441b950d633d3edc77d2cc46586717410f03d51c054ce348b2e977 size: 4508 [...] -Once you find them, you can use that pinned version in your builds, using a -Dockerfile similar to this one: +Once you find them, you can use that pinned version in your builds, using a Dockerfile +similar to this one: ```Dockerfile # Hash-pinned version of tecnativa/doodba:10.0-onbuild FROM tecnativa/doodba@sha256:fba69478f9b0616561aa3aba4d18e4bcc2f728c9568057946c98d5d3817699e1 ``` -### How to get proper assets when printing reports? - -Make sure there's a `ir.config_parameter` called `report.url` with the value -`http://localhost:8069`. - -### How can I whitelist a service and allow external access to it? - -This can become useful when you have isolated environments -(like in `devel.yaml` and `test.yaml` by default) but you need to allow -some external API access for them. I.e., you could use -Google Fonts API for your customer's reports, and those reports -would take forever and end up rendering badly in staging environments. - -In such case, we recommend using the -[tecnativa/whitelist](https://hub.docker.com/r/tecnativa/whitelist/) image. -Read its docs there. - ### How can I help? -Just [head to our project](https://github.com/Tecnativa/doodba) and -open an issue or pull request. - -If you plan to open a pull request, remember that you will usually have to open -two of them: - -1. Targeting the `master` branch, from which the main images are built. - This pull request must include tests. -2. Targeting the `scaffolding` branch, which serves as the base for projects - using this base image. This one is not always required. - -If you need to add a feature or fix for `scaffolding`, before merging that PR, -we need tests that ensure that backwards compatibility with previous -scaffolding versions is preserved. +Just [head to our project](https://github.com/Tecnativa/doodba) and open a discussion, +issue or pull request. ## Related Projects -- [QA tools for Doodba-based projects](https://github.com/Tecnativa/doodba-qa) +- Of course, + [the Doodba Copier Template](https://github.com/Tecnativa/doodba-copier-template). +- [QA tools for Doodba-based projects][doodba-qa] - [Ansible role for automated deployment / update from Le Filament](https://github.com/remi-filament/ansible_role_odoo_docker) -- Find others by searching [GitHub projects tagged with `#doodba`](https://github.com/topics/doodba) - +- Find others by searching + [GitHub projects tagged with `#doodba`](https://github.com/topics/doodba) [`/opt/odoo/auto/addons`]: #optodooautoaddons -[`addons.yaml`]: #optodoocustomsrcaddonstxt -[`COMPOSE_FILE` environment variable]: https://docs.docker.com/compose/reference/envvars/#/composefile -[`nano`]: https://www.nano-editor.org/ +[`addons.yaml`]: #optodoocustomsrcaddonsyaml +[`compose_file` environment variable]: + https://docs.docker.com/compose/reference/envvars/#/composefile [`odoo.conf`]: #optodooautoodooconf [`odoo`]: #optodoocustomsrcodoo [`private`]: #optodoocustomsrcprivate -[`PYTHONOPTIMIZE=1`]: https://docs.python.org/3/using/cmdline.html#envvar-PYTHONOPTIMIZE +[`pythonoptimize=1`]: https://docs.python.org/3/using/cmdline.html#envvar-PYTHONOPTIMIZE [`repos.yaml`]: #optodoocustomsrcreposyaml +[`click-odoo`]: https://github.com/acsone/click-odoo +[`click-odoo-contrib`]: https://github.com/acsone/click-odoo-contrib +[build.d]: #optodoocustombuildd [builds]: https://hub.docker.com/r/tecnativa/doodba/builds/ +[dependencies]: #optodoocustomdependenciestxt [development]: #development -[docker-socket-proxy]: https://hub.docker.com/r/tecnativa/docker-socket-proxy/ -[Fish]: http://fishshell.com/ +[doodba-qa]: https://github.com/Tecnativa/doodba-qa +[fish]: http://fishshell.com/ [glob]: https://docs.python.org/3/library/glob.html -[Let's Encrypt]: https://letsencrypt.org/ -[MailHog]: #mailhog -[OCA]: https://odoo-community.org/ -[OCB]: https://github.com/OCA/OCB -[Odoo S.A.]: https://www.odoo.com -[OpenUpgrade]: https://github.com/OCA/OpenUpgrade/ -[Original Odoo]: https://github.com/odoo/odoo -[pip `requirements.txt`]: https://pip.readthedocs.io/en/latest/user_guide/#requirements-files -[Postgres client applications]: https://www.postgresql.org/docs/current/static/reference-client.html +[mailhog]: #mailhog +[oca]: https://odoo-community.org/ +[ocb]: https://github.com/OCA/OCB +[odoo s.a.]: https://www.odoo.com +[openupgrade]: https://github.com/OCA/OpenUpgrade/ +[original odoo]: https://github.com/odoo/odoo +[pip `requirements.txt`]: + https://pip.readthedocs.io/en/latest/user_guide/#requirements-files +[postgres client applications]: + https://www.postgresql.org/docs/current/static/reference-client.html [production]: #production [retrobreak]: https://github.com/Tecnativa/doodba/issues/67 -[scaffolding]: #scaffolding -[several YAML documents]: http://www.yaml.org/spec/1.2/spec.html#id2760395 -[ssh-conf]: https://www.digitalocean.com/community/tutorials/how-to-configure-custom-connection-options-for-your-ssh-client +[template]: #subproject-template +[several yaml documents]: http://www.yaml.org/spec/1.2/spec.html#id2760395 +[ssh-conf]: + https://www.digitalocean.com/community/tutorials/how-to-configure-custom-connection-options-for-your-ssh-client [testing]: #testing -[Traefik]: https://traefik.io/ -[VSCode]: https://code.visualstudio.com/ +[traefik]: https://traefik.io/ +[vscode]: https://code.visualstudio.com/ diff --git a/bin/autoupdate b/bin-deprecated/autoupdate similarity index 72% rename from bin/autoupdate rename to bin-deprecated/autoupdate index 41f0102c..51f36777 100755 --- a/bin/autoupdate +++ b/bin-deprecated/autoupdate @@ -1,6 +1,14 @@ #!/usr/local/bin/python-odoo-shell +import logging import os +_logger = logging.getLogger("autoupdate") + +# TODO Delete this script at some point +_logger.warning( + "`autoupdate` is DEPRECATED and will be removed in Doodba 13.0, " + "use instead: click-odoo-update" +) # Note: ``module_auto_update`` must be installed in Odoo for this to work. try: diff --git a/bin/python-odoo-shell b/bin-deprecated/python-odoo-shell similarity index 50% rename from bin/python-odoo-shell rename to bin-deprecated/python-odoo-shell index 31f3c4cc..9f2ac550 100755 --- a/bin/python-odoo-shell +++ b/bin-deprecated/python-odoo-shell @@ -1,3 +1,5 @@ #!/usr/bin/env bash export PYTHONOPTIMIZE="" # You'll want to `assert` in your scripts +log WARNING python-odoo-shell is deprecated and will be removed in \ + Doodba 13.0, use instead: click-odoo exec odoo shell < "$1" diff --git a/bin/unittest b/bin-deprecated/unittest similarity index 71% rename from bin/unittest rename to bin-deprecated/unittest index 866b8a23..f4017d92 100755 --- a/bin/unittest +++ b/bin-deprecated/unittest @@ -1,4 +1,6 @@ #!/bin/bash +log WARNING unittest is deprecated and will be removed in Doodba 13.0, \ + use instead: addons update --test $@ # Shortcut to run Odoo in unit testing mode set -e addons=$1 diff --git a/bin/addons b/bin/addons index 7c88ee24..9e82492f 100755 --- a/bin/addons +++ b/bin/addons @@ -1,98 +1,145 @@ #!/usr/bin/env python +# -*- coding: utf-8 -*- from __future__ import print_function + import ast import os import sys from argparse import ArgumentParser from subprocess import check_call -from odoobaselib import ( - addons_config, - AddonsConfigError, + +from doodbalib import ( CORE, - logger, + ENTERPRISE, MANIFESTS, PRIVATE, SRC_DIR, + AddonsConfigError, + addons_config, + logger, ) +# Exit codes +EXIT_NO_ADDONS = 0x4 + # Define CLI options parser = ArgumentParser(description="Install addons in current environment") parser.add_argument( - "action", choices=("init", "update", "list"), - help="What to do with the matched addons.") + "action", + choices=("init", "update", "list"), + help="What to do with the matched addons.", +) parser.add_argument( - "-c", "--core", action="store_true", - help="Use all Odoo core addons") + "-c", "--core", action="store_true", help="Use all Odoo core addons" +) parser.add_argument( - "-e", "--extra", action="store_true", - help="Use all extra addons") + "-d", + "--dependencies", + action="store_true", + help="Use only dependencies of selected addons", +) +parser.add_argument("-e", "--extra", action="store_true", help="Use all extra addons") parser.add_argument( - "-f", "--fullpath", action="store_true", - help="Print addon's full path, only useful with list mode") + "-f", + "--fullpath", + action="store_true", + help="Print addon's full path, only useful with list mode", +) parser.add_argument( - "-i", "--installable", action="store_true", - help="Include only installable addons") + "-i", "--installable", action="store_true", help="Include only installable addons" +) +parser.add_argument( + "-n", "--enterprise", action="store_true", help="Use all enterprise addons" +) parser.add_argument( - "-p", "--private", action="store_true", - help="Use all private addons") + "-p", "--private", action="store_true", help="Use all private addons" +) +parser.add_argument( + "-s", + "--separator", + type=str, + default=",", + help="String that separates addons only useful with list mode", +) parser.add_argument( - "-s", "--separator", type=str, default=",", - help="String that separates addons only useful with list mode") + "-t", + "--test", + action="store_true", + help="Run unit tests for these addons, usually combined with update", +) parser.add_argument( - "-t", "--test", action="store_true", - help="Run unit tests for these addons, usually combined with update") + "-x", + "--explicit", + action="store_true", + help="Fail if any addon is explicitly declared but not found", +) parser.add_argument( - "-x", "--explicit", action="store_true", - help="Fail if any addon is explicitly declared but not found") + "-w", + "--with", + action="append", + dest="with_", + default=[], + help="Addons to include always.", +) parser.add_argument( - "-w", "--with", action="append", dest="with_", default=[], - help="Addons to include always.") + "--force-with", + action="append", + dest="force_with", + default=[], + help="Addons to enforce on dependencies.", +) parser.add_argument( - "-W", "--without", action="append", default=[], - help="Addons to exclude always.") + "-W", "--without", action="append", default=[], help="Addons to exclude always." +) # Generate the matching addons set args = parser.parse_args() +dependencies = {"base"} addons = set(args.with_) without = set(args.without) if addons & without: sys.exit("Cannot include and exclude the same addon!") +if args.dependencies and args.fullpath: + sys.exit("Unsupported combination of --dependencies and --fullpath") +if args.force_with and not args.dependencies: + sys.exit("Force With only makes sense combined with --dependencies") try: for addon, repo in addons_config(strict=args.explicit): if addon in without: continue core_ok = args.core and repo == CORE - extra_ok = args.extra and repo not in {CORE, PRIVATE} + enterprise_ok = args.enterprise and repo == ENTERPRISE + extra_ok = args.extra and repo not in {CORE, ENTERPRISE, PRIVATE} private_ok = args.private and repo == PRIVATE - if private_ok or core_ok or extra_ok: + manual_ok = addon in addons + if private_ok or core_ok or extra_ok or enterprise_ok or manual_ok: addon_path = os.path.join(SRC_DIR, repo, addon) - if args.installable: - installable = False - manifests = list(MANIFESTS) - while True: - try: - manifest = os.path.join(addon_path, manifests.pop()) - with open(manifest, "r") as code: - manifest = ast.literal_eval(code.read()) - except IndexError: - break - except IOError: - continue - else: - installable = manifest.get("installable", True) + manifest = {} + for manifest_name in MANIFESTS: + try: + manifest_path = os.path.join(addon_path, manifest_name) + with open(manifest_path, "r") as code: + manifest = ast.literal_eval(code.read()) break - if not installable: + except IOError: continue + if args.installable and not manifest.get("installable", True): + continue + dependencies.update(manifest.get("depends", [])) if args.fullpath and args.action == "list": addon = addon_path addons.add(addon) except AddonsConfigError as error: sys.exit(error.message) +# Use dependencies instead, if requested +if args.dependencies: + addons = (dependencies - addons).union(set(args.force_with)) +addons -= without # Do the required action if not addons: print("No addons found", file=sys.stderr) - sys.exit(2) + sys.exit(EXIT_NO_ADDONS) addons = args.separator.join(sorted(addons)) if args.action == "list": print(addons) @@ -100,5 +147,7 @@ else: command = ["odoo", "--stop-after-init", "--{}".format(args.action), addons] if args.test: command += ["--test-enable", "--workers", "0"] + if os.environ.get("PGDATABASE"): + command += ["--db-filter", "^{}$".format(os.environ.get("PGDATABASE"))] logger.info("Executing %s", " ".join(command)) check_call(command) diff --git a/bin/autoaggregate b/bin/autoaggregate index 46728ca6..a1a3c05d 100755 --- a/bin/autoaggregate +++ b/bin/autoaggregate @@ -1,37 +1,177 @@ -#!/bin/bash -set -e - -conf=/opt/odoo/custom/src/repos - -if [ -f "${conf}.yaml" ]; then - conf="${conf}.yaml" -elif [ -f "${conf}.yml" ]; then - conf="${conf}.yml" -fi - -# Update linked repositories, if the `repos.yaml` file is found -if [ -f $conf ]; then - log INFO Aggregating repositories from $conf - cd $(dirname $conf) - - # Avoid wrong umask in aggregated files - if [ -n "$UMASK" ]; then - umask "$UMASK" - fi - - # Perform aggregation with environment variables expansion - set +e - gitaggregate --expand-env -c $conf - code=$? - set -e - - # Avoid wrong user/group in aggregated files - if [ -n "$GID" -a -n "$UID" ]; then - chown -R "$UID:$GID" . - fi - - [ $code -eq 0 ] || exit $code -else - log ERROR Cannot aggregate repositories: $conf not found - exit 1 -fi +#!/usr/bin/env python +# -*- coding: utf-8 -*- +import os +import sys +from multiprocessing import cpu_count +from subprocess import check_call + +import yaml +from doodbalib import ( + ADDONS_YAML, + AUTO_REPOS_YAML, + CORE, + ODOO_DIR, + PRIVATE, + REPOS_YAML, + SRC_DIR, + logger, +) + +# if the umask matches the `chmod -R u+rwX,g+rX-w,o= /opt/odoo` command the build is faster as we don't need to fix as +# many permissions after auto aggregation +UMASK = os.environ.get("UMASK") or "0027" +UID = int(os.environ.get("UID") or -1) +GID = int(os.environ.get("GID") or -1) +DEFAULT_REPO_PATTERN = os.environ.get("DEFAULT_REPO_PATTERN") +DEFAULT_REPO_PATTERN_ODOO = os.environ.get("DEFAULT_REPO_PATTERN_ODOO") +log_level = os.environ.get("LOG_LEVEL", "INFO") + + +def aggregate(config): + """Execute git aggregator to pull git code. + + :param str config: + Path where to find the ``repos.yaml`` file. + """ + logger.info("Running gitaggregate with %s", config) + + def pre_exec_umask(): + # Download git code with the specified umask, if set, otherwise use "0027" + os.umask(int(UMASK, 8)) + + pre_execs = [pre_exec_umask] + + def pre_exec(): + for _exec in pre_execs: + try: + _exec() + except Exception as err: + logger.error("Error in %s: %s" % (_exec, err)) + logger.exception(err) + raise + + if ~GID: + + def pre_exec_gid(): + # execute git with GID + os.setgid(GID) + + pre_execs.append(pre_exec_gid) + + if ~UID: + + def pre_exec_uid(): + # execute git with UID + os.setuid(UID) + # set odoo home directory + # (git checks if user has a config in $HOME, and we cannot read /root as odoo user) + os.environ["HOME"] = "/home/odoo" + + pre_execs.append(pre_exec_uid) + + check_call( + [ + "gitaggregate", + "--expand-env", + "--config", + config, + "--log-level", + log_level, + "--jobs", + str(cpu_count() or 1), + "aggregate", + ], + cwd=SRC_DIR, + stderr=sys.stderr, + stdout=sys.stdout, + preexec_fn=pre_exec, + ) + + +def origin_for( + folder, + default_repo_pattern=DEFAULT_REPO_PATTERN, + odoo_repo_pattern=DEFAULT_REPO_PATTERN_ODOO, +): + """Guess the default git origin for that folder. + + :param str folder: + Normally an absolute path to an expected git repo, whose name should + match the git repository where it comes from, using the env-supplied + pattern. + """ + base = os.path.basename(folder) + pattern = default_repo_pattern + if base == "odoo": + pattern = odoo_repo_pattern + return pattern.format(base) + + +def missing_repos_config(): + """Find the undefined repositories and return their default configuration. + + :return dict: + git-aggregator-ready configuration dict for undefined repositories. + """ + defined, expected = set(), {ODOO_DIR} + # Find the repositories defined by hand + try: + with open(REPOS_YAML) as yaml_file: + for doc in yaml.safe_load_all(yaml_file): + for repo in doc: + defined.add(os.path.abspath(os.path.join(SRC_DIR, repo))) + except (IOError, AttributeError): + logger.debug("No repositories defined by hand") + addons_env = {} + # Find the repositories that should be present + try: + with open(ADDONS_YAML) as yaml_file: + for doc in yaml.safe_load_all(yaml_file): + env = dict(os.environ, **doc.get("ENV", {})) + for repo in doc: + if repo in {PRIVATE, "ONLY", "ENV"}: + continue + if repo == CORE: + repo_path = ODOO_DIR + else: + repo_path = os.path.abspath(os.path.join(SRC_DIR, repo)) + if not os.path.exists(repo_path) or os.path.isdir( + os.path.join(repo_path, ".git") + ): + expected.add(repo_path) + addons_env[repo_path] = env + except (IOError, AttributeError): + logger.debug("No addons are expected to be present") + # Find the undefined repositories and generate a config for them + missing = expected - defined + config = {} + for repo_path in missing: + env = addons_env.get(repo_path, os.environ) + depth = env["DEPTH_DEFAULT"] + origin_version = "origin %s" % env["ODOO_VERSION"] + config[repo_path] = { + "defaults": {"depth": depth}, + "merges": [origin_version], + "remotes": { + "origin": origin_for( + repo_path, + env["DEFAULT_REPO_PATTERN"], + env["DEFAULT_REPO_PATTERN_ODOO"], + ) + }, + "target": origin_version, + } + logger.debug("Generated missing repos config %r", config) + return config + + +# Aggregate user-specified repos +if os.path.isfile(REPOS_YAML): + aggregate(REPOS_YAML) + +# Aggregate unspecified repos +missing_config = missing_repos_config() +if missing_config: + with open(AUTO_REPOS_YAML, "w") as autorepos: + yaml.dump(missing_config, autorepos) + aggregate(AUTO_REPOS_YAML) diff --git a/bin/config-generate b/bin/config-generate index c41d370f..7865890d 100755 --- a/bin/config-generate +++ b/bin/config-generate @@ -1,9 +1,52 @@ -#!/bin/bash -# Generate Odoo server configuration from templates -set -e -src="/opt/odoo/common/conf.d/* /opt/odoo/custom/conf.d/*" -log INFO Merging $(ls $src | wc -l) configuration files in $OPENERP_SERVER -conf=$(cat $src | envsubst) -log DEBUG "Resulting configuration: -$conf" -echo "$conf" > $OPENERP_SERVER +#!/usr/bin/env python +# -*- coding: utf-8 -*- +"""Generate Odoo server configuration from templates""" + +import os +from contextlib import closing +from string import Template + +from doodbalib import logger + +try: + # Python 2, where io.StringIO fails because it is unicode-only + from StringIO import StringIO +except ImportError: + from io import StringIO + +try: + from configparser import RawConfigParser + + parser = RawConfigParser(strict=False) +except ImportError: + # Python 2, where strict=True doesn't exist + from ConfigParser import RawConfigParser + + parser = RawConfigParser() + +ODOO_VERSION = os.environ.get("ODOO_VERSION") +TARGET_FILE = os.environ.get("ODOO_RC", "/opt/odoo/auto/odoo.conf") +CONFIG_DIRS = ("/opt/odoo/common/conf.d", "/opt/odoo/custom/conf.d") +CONFIG_FILES = [] + +# Read all configuraiton files found in those folders +logger.info("Merging found configuration files in %s", TARGET_FILE) +for dir_ in CONFIG_DIRS: + try: + for file_ in sorted(os.listdir(dir_)): + parser.read(os.path.join(dir_, file_)) + except OSError: # TODO Use FileNotFoundError when we drop python 2 + continue + +# Write it to a memory string object +with closing(StringIO()) as resultfp: + parser.write(resultfp) + resultfp.seek(0) + # Obtain the config string + result = resultfp.read() + # Expand environment variables found within + result = Template(result).substitute(os.environ) + logger.debug("Resulting configuration:\n%s", result) + # Write it to destination + with open(TARGET_FILE, "w") as targetfp: + targetfp.write(result) diff --git a/bin/direxec b/bin/direxec index 7560b756..ca84efdd 100755 --- a/bin/direxec +++ b/bin/direxec @@ -1,19 +1,19 @@ #!/usr/bin/env python +# -*- coding: utf-8 -*- import os import subprocess import sys +from logging import DEBUG, INFO, WARNING -from psycopg2 import connect, OperationalError - -from odoobaselib import logger +from doodbalib import logger, which # Call this file linked from another file called `build` or `entrypoint` mode = os.path.basename(__file__) -dir_odoo = '/opt/odoo' -dir_common = os.path.join(dir_odoo, 'common', '%s.d' % mode) -dir_custom = os.path.join(dir_odoo, 'custom', '%s.d' % mode) +dir_odoo = "/opt/odoo" +dir_common = os.path.join(dir_odoo, "common", "%s.d" % mode) +dir_custom = os.path.join(dir_odoo, "custom", "%s.d" % mode) # Find scripts files = [(d, dir_common) for d in os.listdir(dir_common)] @@ -25,23 +25,51 @@ except OSError: # Run scripts for executable, folder in sorted(files): command = os.path.join(folder, executable) - if os.access(command, os.X_OK): + if os.access(command, os.X_OK) and not os.path.isdir(command): logger.debug("Executing %s", command) subprocess.check_call(command) # Allow to omit 1st command and default to `odoo` extra_command = sys.argv[1:] if extra_command: - if extra_command[0] == 'shell' or extra_command[0].startswith("-"): + if extra_command[0] == "shell" or extra_command[0].startswith("-"): extra_command.insert(0, "odoo") # Set the DB creation language, if needed - if (extra_command[0] in {"odoo", "/usr/local/bin/odoo"} and - os.environ.get("INITIAL_LANG")): - try: - connection = connect(dbname=os.environ.get("PGDATABASE")) - connection.close() - except OperationalError: - # No DB exists, set initial language - extra_command += ["--load-language", os.environ["INITIAL_LANG"]] - logger.info("Executing %s", " ".join(extra_command)) + if extra_command[0] in {"odoo", "/usr/local/bin/odoo"}: + if os.environ.get("INITIAL_LANG"): + from psycopg2 import OperationalError, connect + + try: + connection = connect(dbname=os.environ.get("PGDATABASE")) + connection.close() + except OperationalError: + # No DB exists, set initial language + extra_command += ["--load-language", os.environ["INITIAL_LANG"]] + if os.environ.get("PTVSD_ENABLE") == "1": + # Warn deprecation + logger.log( + WARNING, + "ptvsd has beed deprecated for python debugging. " + "Please use debugpy (see https://github.com/Tecnativa/doodba#debugpy)", + ) + # See `python -m ptvsd -h` to understand this + extra_command[0] = os.path.realpath(which(extra_command[0])) + extra_command = ( + ["python", "-m", "ptvsd"] + + os.environ.get("PTVSD_ARGS", "").split() + + extra_command + ) + elif os.environ["DEBUGPY_ENABLE"] == "1": + # See `python -m debugpy -h` to understand this + extra_command[0] = os.path.realpath(which(extra_command[0])) + extra_command = ( + ["python", "-m", "debugpy"] + + os.environ["DEBUGPY_ARGS"].split() + + extra_command + ) + logger.log( + DEBUG if extra_command[0] == "/qa/insider" else INFO, + "Executing %s", + " ".join(extra_command), + ) os.execvp(extra_command[0], extra_command) diff --git a/bin/install.sh b/bin/install.sh deleted file mode 100755 index 295acc61..00000000 --- a/bin/install.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/bash -set -ex - -reqs=https://raw.githubusercontent.com/$ODOO_SOURCE/$ODOO_VERSION/requirements.txt -apt_deps="python-dev build-essential" -apt-get update - -# lxml -apt_deps="$apt_deps libxml2-dev libxslt1-dev" -# Pillow -apt_deps="$apt_deps libjpeg-dev libfreetype6-dev - liblcms2-dev libopenjpeg-dev libtiff5-dev tk-dev tcl-dev" -# psutil -apt_deps="$apt_deps linux-headers-amd64" -# psycopg2 -apt_deps="$apt_deps libpq-dev" -# python-ldap -apt_deps="$apt_deps libldap2-dev libsasl2-dev" - -apt-get install -y --no-install-recommends $apt_deps - -# Download requirements file to be able to patch it -curl -SLo /tmp/requirements.txt $reqs -reqs=/tmp/requirements.txt - -if [ "$ODOO_VERSION" == "8.0" ]; then - # Packages already installed that conflict with others - sed -ir 's/pyparsing|six/#\0/' $reqs - # Extra dependencies for Odoo at runtime - apt-get install -y --no-install-recommends file -fi - -# Build and install Odoo dependencies with pip -pip install --requirement $reqs - -# Remove all installed garbage -apt-get -y purge $apt_deps -apt-get -y autoremove -rm -Rf /var/lib/apt/lists/* /tmp/* || true diff --git a/bin/log b/bin/log index 00fafb27..ebc8d394 100755 --- a/bin/log +++ b/bin/log @@ -1,10 +1,11 @@ #!/usr/bin/env python +# -*- coding: utf-8 -*- from __future__ import unicode_literals import argparse import logging -from odoobaselib import LOG_LEVELS, logger +from doodbalib import LOG_LEVELS, logger parser = argparse.ArgumentParser(description="Easy logging for scripts") parser.add_argument("level", choices=LOG_LEVELS) diff --git a/bin/preparedb b/bin/preparedb new file mode 100755 index 00000000..f0421fc6 --- /dev/null +++ b/bin/preparedb @@ -0,0 +1,21 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Script to prepare the database with initial data + +import click +import click_odoo + + +@click.command() +@click_odoo.env_options(default_log_level="info", database_must_exist=True) +def main(env): + """Set report.url in the database to be pointing at localhost.""" + env["ir.config_parameter"].set_param("report.url", "http://localhost:8069") + env["ir.config_parameter"].set_param( + "database.expiration_date", "3000-01-30 00:00:00" + ) + env.cr.commit() + + +if __name__ == "__main__": + main() diff --git a/build.d/100-repos-aggregate b/build.d/100-repos-aggregate index d7f41c01..67508d2a 100755 --- a/build.d/100-repos-aggregate +++ b/build.d/100-repos-aggregate @@ -1,9 +1,21 @@ #!/bin/bash set -e +# make sure odoo has a user.name configured, as merges would not succeed otherwise +# (even if GIT_AUTHOR_NAME and EMAIL are set and should be used, it seems gitaggregate is not passing them to git) +su --shell="$SHELL" odoo -c 'git config user.name 1>/dev/null || git config --global user.name "'"$GIT_AUTHOR_NAME"'"' + +# copy ssh directory to odoo user as well (gitaggregate may also be run as odoo user) +if [[ ! -e ~odoo/.ssh ]] ; then + cp -a /opt/odoo/custom/ssh ~odoo/.ssh +fi + if [ "$AGGREGATE" != true ]; then log WARNING Not aggregating code repositories exit 0 fi +# during build checkout sources for root:odoo +# to checkout sources as odoo:odoo set AGGREGATE to false for build and execute autoaggregate during runtime +export UID=0 GID=$GID UMASK=0027 exec autoaggregate diff --git a/build.d/200-dependencies b/build.d/200-dependencies index aff68406..3a1dab65 100755 --- a/build.d/200-dependencies +++ b/build.d/200-dependencies @@ -1,37 +1,29 @@ #!/usr/bin/env python +# -*- coding: utf-8 -*- # Copyright 2017 LasLabs Inc. -from os.path import basename, join, splitext from glob import glob +from os.path import basename, join, splitext -from odoobaselib import ( - AUTO_REQUIREMENTS, - CUSTOM_DIR, - FILE_APT_BUILD, - SRC_DIR, -) -from odoobaselib.installer import install, INSTALLERS, logger - +from doodbalib import CUSTOM_DIR, FILE_APT_BUILD, SRC_DIR +from doodbalib.installer import INSTALLERS, install, logger # Build dependencies installed before any others install("apt", FILE_APT_BUILD) for name in INSTALLERS: req_files = [] - # pip `requirements.txt` files found in repositories - if name == "pip" and AUTO_REQUIREMENTS: - req_files += glob(join(SRC_DIR, "*", "requirements.txt")) # Normal dependency installation - req_files.append(join(CUSTOM_DIR, 'dependencies', '%s.txt' % name)) + req_files.append(join(CUSTOM_DIR, "dependencies", "%s.txt" % name)) for req_file in req_files: install(name, req_file) # Sorted dependencies installation -dep_files = sorted(glob(join(CUSTOM_DIR, 'dependencies', '[0-9]*-*'))) +dep_files = sorted(glob(join(CUSTOM_DIR, "dependencies", "[0-9]*-*"))) for dep_file in dep_files: root, ext = splitext(basename(dep_file)) # Get the installer (xxx-installer[-description][.ext]) - installer = root.split('-', 2)[1] + installer = root.split("-", 2)[1] if installer not in INSTALLERS: logger.error("Unknown installer: %s", installer) raise Exception diff --git a/build.d/250-postgres-client b/build.d/250-postgres-client new file mode 100755 index 00000000..b96f7bec --- /dev/null +++ b/build.d/250-postgres-client @@ -0,0 +1,9 @@ +#!/bin/bash +set -e + +apt-get update +if [[ "$DB_VERSION" != "latest" ]] ; then + apt-get install -yqq postgresql-client-$DB_VERSION +else + apt-get install -yqq postgresql-client +fi diff --git a/build.d/300-fontconfig b/build.d/300-fontconfig new file mode 100755 index 00000000..e22bdcab --- /dev/null +++ b/build.d/300-fontconfig @@ -0,0 +1,31 @@ +#!/bin/bash +set -e + +mkdir -p ~odoo/.config/fontconfig/conf.d +cat < ~odoo/.config/fontconfig/conf.d/100-doodba.conf + + + + + + monospace + + $FONT_MONO + + + + sans-serif + + $FONT_SANS + + + + serif + + $FONT_SERIF + + + +END + +chown odoo:odoo ~odoo/.config diff --git a/build.d/400-clean b/build.d/400-clean index 39e20771..274893fd 100755 --- a/build.d/400-clean +++ b/build.d/400-clean @@ -4,37 +4,48 @@ import os import shutil import sys -from odoobaselib import addons_config, CORE, CLEAN, logger, PRIVATE, SRC_DIR +from doodbalib import CLEAN, ODOO_DIR, PRIVATE_DIR, SRC_DIR, addons_config, logger if not CLEAN: logger.warning("Not cleaning garbage") sys.exit() -addons = set(addons_config(False)) -repos = {addon[1] for addon in addons} | {CORE, PRIVATE} -for directory in os.listdir(SRC_DIR): - # Special directories must be preserved - if directory == "odoo": - directory = CORE +# Get the enabled paths +repos_addons = {} +for addon, repo in addons_config(filtered=False): + repo_path = os.path.realpath(os.path.join(SRC_DIR, repo)) + repos_addons.setdefault(repo_path, set()) + repos_addons[repo_path].add(addon) +logger.debug("Addon paths enabled: %s", repos_addons) - # Skip regular files - full = os.path.join(SRC_DIR, directory) - if not os.path.isdir(full): +# Traverse src dir and remove anything not explicitly enabled +for directory, subdirectories, subfiles in os.walk(SRC_DIR): + logger.debug("Checking for cleanup directory %s", directory) + # Skip main src directory + if directory == SRC_DIR: continue - - # Remove directories not listed in addons.yaml - if directory not in repos: - logger.info("Removing directory %s", full) - shutil.rmtree(full) + # Always skip private/* + if directory == PRIVATE_DIR: + subdirectories[:] = [] continue - - # Traverse addons - for subdirectory in os.listdir(full): - subfull = os.path.join(full, subdirectory) - # Skip regular files - if not os.path.isdir(subfull): + # Inside the odoo dir, skip all but addons dir + if directory == ODOO_DIR: + subdirectories[:] = ["addons"] + continue + try: + # Get addons enalbed in current directory + enabled_addons = repos_addons[directory] + except KeyError: + # This isn't a repo; is there anything inside to preserve? + directory += os.path.sep + if any(repo.startswith(directory) for repo in repos_addons): + # Then, let's walk in; we'll remove later if needed continue - # Remove addon if not used - if (subdirectory, directory) not in addons: - logger.info("Removing subdirectory %s", subfull) - shutil.rmtree(subfull) + else: + # This is an addons repo; do not walk into the enabled ones + for addon in enabled_addons: + subdirectories.remove(addon) + continue + # Remove every other directory + logger.info("Removing directory %s", directory) + shutil.rmtree(directory) diff --git a/build.d/700-odoo-install b/build.d/700-odoo-install index cfc44067..b895a35a 100755 --- a/build.d/700-odoo-install +++ b/build.d/700-odoo-install @@ -7,22 +7,11 @@ log INFO Installing Odoo from $src # For development you could want to avoid installing Odoo to speed up build if [ "$PIP_INSTALL_ODOO" == true ]; then args="--no-cache-dir" - # Odoo v8 dependencies could crash at install, so we don't use them - if [ "$ODOO_VERSION" == "8.0" ]; then - args="$args --no-deps" - fi pip install $args --editable $src - - # Make version 8.0 and 9.0 have an `odoo` executable - if [ "$ODOO_VERSION" == "8.0" -o "$ODOO_VERSION" == "9.0" ]; then - ln -s $dst.py $dst - fi else log WARNING Blindly symlinking odoo executable bin=$src/odoo-bin - if [ "$ODOO_VERSION" == "8.0" -o "$ODOO_VERSION" == "9.0" ]; then - bin=$src/odoo.py - ln -s /opt/odoo/custom/src/odoo/openerp-{gevent,server} /usr/local/bin/ - fi + # Cannot check for scripts existence and link all: they probably do not + # exist yet at build time! Just check Odoo version and act properly. ln -s $bin $dst fi diff --git a/build.d/800-permissions b/build.d/800-permissions index 3e5f1713..312ab845 100755 --- a/build.d/800-permissions +++ b/build.d/800-permissions @@ -1,8 +1,72 @@ -#!/bin/bash -set -e -chown -R root:odoo /opt/odoo -chmod -R u+rwX,g+rX-w,o= /opt/odoo -chmod -R g+w /opt/odoo/auto -if [ -d /opt/odoo/custom/ssh ]; then - chmod -R u=rwX,go= /opt/odoo/custom/ssh -fi +#!/usr/bin/env python +# -*- coding: utf-8 -*- +import os.path + +from doodbalib import AUTO_DIR, CUSTOM_DIR +from plumbum import FG, local + +find, xargs, chmod, chown = ( + local.cmd.find, + local.cmd.xargs, + local.cmd.chmod, + local.cmd.chown, +) + +# find all files where group or user are not odoo that are not a symlink, and fix permissions for those +# we use find and xargs because chown -R can be very slow on certain systems: https://github.com/docker/for-linux/issues/388 +( + find[ + "/opt/odoo", + "(", + "-not", + "-user", + "root", + "-or", + "-not", + "-group", + "odoo", + ")", + "-and", + "-not", + "-type", + "l", + "-print0", + ] + | xargs["-0", "--no-run-if-empty", "chown", "root:odoo"] +) & FG +( + find[ + "/opt/odoo", + "(", + "-type", + "d", + "-not", + "-perm", + "u=rwx,g=rx,o=", + ")", + "-o", + "(", + "-type", + "f", + "-not", + "-perm", + "u=rw,g=r,o=", + "-not", + "-perm", + "u=rwx,g=rx,o=", + ")", + "-print0", + ] + | xargs["-0", "--no-run-if-empty", "chmod", "u+rwX,g+rX-w,o="] +) & FG + +chmod["-R", "g+w", AUTO_DIR] & FG + +custom_ssh_dir = os.path.join(CUSTOM_DIR, "ssh") +if os.path.isdir(custom_ssh_dir): + chmod["-R", "u=rwx,go=", custom_ssh_dir] & FG + +odoo_ssh_dir = "/home/odoo/.ssh" +if os.path.isdir(odoo_ssh_dir): + chown["-R", "odoo:odoo", odoo_ssh_dir] & FG + chmod["-R", "u=rwx,go=", odoo_ssh_dir] & FG diff --git a/build.d/900-dependencies-cleanup b/build.d/900-dependencies-cleanup index f0e8fedf..467ea0bc 100755 --- a/build.d/900-dependencies-cleanup +++ b/build.d/900-dependencies-cleanup @@ -1,23 +1,21 @@ #!/usr/bin/env python +# -*- coding: utf-8 -*- # Copyright 2017 LasLabs Inc. import os -from odoobaselib import CUSTOM_DIR, FILE_APT_BUILD -from odoobaselib.installer import INSTALLERS - +from doodbalib import CUSTOM_DIR, FILE_APT_BUILD +from doodbalib.installer import INSTALLERS # Build-time dependencies must be removed when finishing build if os.path.isfile(FILE_APT_BUILD): - installer = INSTALLERS['apt'](FILE_APT_BUILD) + installer = INSTALLERS["apt"](FILE_APT_BUILD) installer.remove() installer.cleanup() # Clean up garbage generated by respective package managers for name, class_ in INSTALLERS.items(): - req_file = os.path.join( - CUSTOM_DIR, 'dependencies', '%s.txt' % name, - ) + req_file = os.path.join(CUSTOM_DIR, "dependencies", "%s.txt" % name) if os.path.isfile(req_file): class_(req_file).cleanup() diff --git a/conf.d/00-base.conf b/conf.d/00-base.conf index f3dcbe04..5f59459b 100644 --- a/conf.d/00-base.conf +++ b/conf.d/00-base.conf @@ -3,3 +3,7 @@ admin_passwd = $ADMIN_PASSWORD data_dir = /var/lib/odoo unaccent = $UNACCENT + +; Used in v13+ devel mode only +screencasts = /opt/odoo/auto/test-artifacts +screenshots = /opt/odoo/auto/test-artifacts diff --git a/conf.d/10-addons.conf b/conf.d/10-addons.conf index d7ad1445..56393e80 100644 --- a/conf.d/10-addons.conf +++ b/conf.d/10-addons.conf @@ -1,2 +1,3 @@ +[options] ; Addons in priority order: private, then other repos, then base Odoo addons_path = /opt/odoo/auto/addons diff --git a/conf.d/20-database.conf b/conf.d/20-database.conf index dd6074e9..e6fe35df 100644 --- a/conf.d/20-database.conf +++ b/conf.d/20-database.conf @@ -1,3 +1,4 @@ +[options] ; Database settings, matching defaults when you execute `psql` db_user = $PGUSER db_password = $PGPASSWORD @@ -5,3 +6,4 @@ db_host = $PGHOST db_port = $PGPORT db_name = $PGDATABASE dbfilter = $DB_FILTER +list_db = $LIST_DB diff --git a/conf.d/30-proxy-mode.conf b/conf.d/30-proxy-mode.conf index 31ce6027..ab33311a 100644 --- a/conf.d/30-proxy-mode.conf +++ b/conf.d/30-proxy-mode.conf @@ -1,2 +1,3 @@ +[options] ; Normally Odoo should run behind a proxy proxy_mode = $PROXY_MODE diff --git a/conf.d/40-smtp.conf b/conf.d/40-smtp.conf index 2befcf4e..91d268c9 100644 --- a/conf.d/40-smtp.conf +++ b/conf.d/40-smtp.conf @@ -1,3 +1,4 @@ +[options] ; Prepared to link with https://hub.docker.com/r/tecnativa/postfix-relay smtp_server = $SMTP_SERVER smtp_port = $SMTP_PORT diff --git a/conf.d/50-demo-data.conf b/conf.d/50-demo-data.conf index 421d4018..90e90581 100644 --- a/conf.d/50-demo-data.conf +++ b/conf.d/50-demo-data.conf @@ -1,2 +1,3 @@ +[options] ; Useful for testing, useless for production, disabled by default without_demo = $WITHOUT_DEMO diff --git a/conf.d/60-geoip-ge17.conf b/conf.d/60-geoip-ge17.conf new file mode 100644 index 00000000..c624c604 --- /dev/null +++ b/conf.d/60-geoip-ge17.conf @@ -0,0 +1,3 @@ +[options] +geoip_city_db = /opt/odoo/auto/geoip/GeoLite2-City.mmdb +geoip_country_db = /opt/odoo/auto/geoip/GeoLite2-Country.mmdb diff --git a/conf.d/60-geoip-lt17.conf b/conf.d/60-geoip-lt17.conf new file mode 100644 index 00000000..1665f2c0 --- /dev/null +++ b/conf.d/60-geoip-lt17.conf @@ -0,0 +1,2 @@ +[options] +geoip_database = /opt/odoo/auto/geoip/GeoLite2-City.mmdb diff --git a/entrypoint.d/20-postgres-wait b/entrypoint.d/20-postgres-wait index 55ee402b..cca4d52d 100755 --- a/entrypoint.d/20-postgres-wait +++ b/entrypoint.d/20-postgres-wait @@ -6,6 +6,16 @@ fi log INFO Waiting until postgres is listening at $PGHOST... while true; do - psql --list > /dev/null 2>&1 && break + # If your postgres connection has minimal permissions, you should + # have at least an empty PGDATABASE and rights on this + # databases. The following will then succeed: + [ -n "$PGDATABASE" ] && echo "SELECT 1;" | psql "$PGDATABASE" > /dev/null 2>&1 && break + + # if previous check failed (if PGDATABASE is set, but not yet + # created), you are in a more common scenario where odoo is + # expected to manage databases, and it should have the permissions + # to create it and will attempt to do it. In that case, you'll + # probably also have the permissions to list the databases. + psql -l > /dev/null 2>&1 && break sleep 1 done diff --git a/entrypoint.d/40-addons-link b/entrypoint.d/40-addons-link index e6849af5..626e3523 100755 --- a/entrypoint.d/40-addons-link +++ b/entrypoint.d/40-addons-link @@ -3,18 +3,9 @@ import os from glob import iglob -from odoobaselib import ( - addons_config, - ADDONS_DIR, - ADDONS_YAML, - logger, - SRC_DIR, -) +from doodbalib import ADDONS_DIR, ADDONS_YAML, SRC_DIR, addons_config, logger -logger.info( - "Linking all addons from %s in %s", - ADDONS_YAML, - ADDONS_DIR) +logger.info("Linking all addons from %s in %s", ADDONS_YAML, ADDONS_DIR) # Remove all links in addons dir for link in iglob(os.path.join(ADDONS_DIR, "*")): diff --git a/entrypoint.d/45-geoip b/entrypoint.d/45-geoip new file mode 100755 index 00000000..4035e27a --- /dev/null +++ b/entrypoint.d/45-geoip @@ -0,0 +1,50 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +import os.path +import re +import sys + +from doodbalib import logger +from plumbum import BG, local +from plumbum.cmd import geoipupdate + +GEOIP_ACCOUNT_ID = local.env["GEOIP_ACCOUNT_ID"] +GEOIP_LICENSE_KEY = local.env["GEOIP_LICENSE_KEY"] + +if GEOIP_ACCOUNT_ID not in {"", "0"} and GEOIP_LICENSE_KEY not in {"", "0"}: + # see https://dev.maxmind.com/geoip/geoipupdate/ + logger.info("Activating GeoIP/GeoLite2 updates") + logger.info( + "This product includes GeoLite2 data created by MaxMind, " + "available from https://www.maxmind.com" + ) + + # copy geoip conf to an inspectable dir (devel mode) if they do not exist yet and keep them up to date + os.makedirs("/opt/odoo/auto/geoip/", exist_ok=True) + if not os.path.exists("/opt/odoo/auto/geoip/GeoIP.conf"): + with open("/etc/GeoIP.conf.orig") as fpr, open( + "/opt/odoo/auto/geoip/GeoIP.conf", "w" + ) as fpw: + for line in fpr.readlines(): + if "DatabaseDirectory " in line: + # save databases in /opt/odoo/auto/geoip/ + line = "DatabaseDirectory /opt/odoo/auto/geoip/" + fpw.write(line) + + # Obtain current GeoIP configuration + geoip_file = local.path("/opt/odoo/auto/geoip/GeoIP.conf") + geoip_conf = geoip_file.read() + # Patch it with provided account and license keys + geoip_conf = re.sub( + r"(^|\n)AccountID\s*[^\n]*(\n|$)", + "\\1AccountID {}\\2".format(GEOIP_ACCOUNT_ID), + geoip_conf, + ) + geoip_conf = re.sub( + r"(^|\n)LicenseKey\s*[^\n]*(\n|$)", + "\\1LicenseKey {}\\2".format(GEOIP_LICENSE_KEY), + geoip_conf, + ) + geoip_file.write(geoip_conf) + # run geoip update in background to make sure it doesn't block odoo startup + geoipupdate & BG(stdout=sys.stdout, stderr=sys.stderr) diff --git a/entrypoint.d/50-config-generate b/entrypoint.d/50-config-generate index d7f8f89a..12c66944 100755 --- a/entrypoint.d/50-config-generate +++ b/entrypoint.d/50-config-generate @@ -1,8 +1,5 @@ #!/bin/bash -if [ -f "${OPENERP_SERVER}" ]; then - log INFO File $OPENERP_SERVER exists, skipping config generation - exit 0 -fi +log INFO "Generating ${OPENERP_SERVER:-$ODOO_RC} file. Overriding any existing..." config-generate diff --git a/hooks/build b/hooks/build deleted file mode 100755 index 3ed0146c..00000000 --- a/hooks/build +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash -set -ex - -# Get Odoo version -version="$DOCKER_TAG" -if [ "$version" == latest ]; then - version=11.0 -fi - -if [ -z "$IMAGE_NAME" ]; then - IMAGE_NAME="$DOCKER_REPO:$DOCKER_TAG" -fi - -# See http://label-schema.org/rc1/#build-time-labels -for target in base onbuild; do - suffix='' - if [ "$target" == onbuild ]; then - suffix="-$target" - fi - time docker image build \ - --build-arg VCS_REF="$GIT_SHA1" \ - --build-arg BUILD_DATE="$(date --rfc-3339 ns)" \ - --build-arg ODOO_VERSION="$version" \ - --file "$version.Dockerfile" \ - --tag "$IMAGE_NAME$suffix" \ - --target $target \ - . -done diff --git a/hooks/post_push b/hooks/post_push deleted file mode 100755 index 306545d2..00000000 --- a/hooks/post_push +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash -set -ex - -# Get Odoo version -version="$DOCKER_TAG" -if [ "$version" == latest ]; then - version=11.0 -fi - -if [ -z "$IMAGE_NAME" ]; then - IMAGE_NAME="$DOCKER_REPO:$DOCKER_TAG" -fi - -docker image push "$IMAGE_NAME-onbuild" diff --git a/lib/doodbalib/__init__.py b/lib/doodbalib/__init__.py new file mode 100644 index 00000000..6da810b9 --- /dev/null +++ b/lib/doodbalib/__init__.py @@ -0,0 +1,173 @@ +# -*- coding: utf-8 -*- +import logging +import os +from glob import glob +from pprint import pformat +from subprocess import check_output + +import yaml + +# Constants needed in scripts +CUSTOM_DIR = "/opt/odoo/custom" +AUTO_DIR = "/opt/odoo/auto" +ADDONS_DIR = os.path.join(AUTO_DIR, "addons") +SRC_DIR = os.path.join(CUSTOM_DIR, "src") + +ADDONS_YAML = os.path.join(SRC_DIR, "addons") +if os.path.isfile("%s.yaml" % ADDONS_YAML): + ADDONS_YAML = "%s.yaml" % ADDONS_YAML +else: + ADDONS_YAML = "%s.yml" % ADDONS_YAML + +REPOS_YAML = os.path.join(SRC_DIR, "repos") +if os.path.isfile("%s.yaml" % REPOS_YAML): + REPOS_YAML = "%s.yaml" % REPOS_YAML +else: + REPOS_YAML = "%s.yml" % REPOS_YAML + +AUTO_REPOS_YAML = os.path.join(AUTO_DIR, "repos") +if os.path.isfile("%s.yml" % AUTO_REPOS_YAML): + AUTO_REPOS_YAML = "%s.yml" % AUTO_REPOS_YAML +else: + AUTO_REPOS_YAML = "%s.yaml" % AUTO_REPOS_YAML + +CLEAN = os.environ.get("CLEAN") == "true" +LOG_LEVELS = frozenset({"DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"}) +FILE_APT_BUILD = os.path.join(CUSTOM_DIR, "dependencies", "apt_build.txt") +PRIVATE = "private" +CORE = "odoo/addons" +ENTERPRISE = "enterprise" +PRIVATE_DIR = os.path.join(SRC_DIR, PRIVATE) +CORE_DIR = os.path.join(SRC_DIR, CORE) +ODOO_DIR = os.path.join(SRC_DIR, "odoo") +ODOO_VERSION = os.environ["ODOO_VERSION"] +MANIFESTS = ("__manifest__.py", "__openerp__.py") + +# Customize logging for build +logger = logging.getLogger("doodba") +log_handler = logging.StreamHandler() +log_formatter = logging.Formatter("%(name)s %(levelname)s: %(message)s") +log_handler.setFormatter(log_formatter) +logger.addHandler(log_handler) +_log_level = os.environ.get("LOG_LEVEL", "") +if _log_level.isdigit(): + _log_level = int(_log_level) +elif _log_level in LOG_LEVELS: + _log_level = getattr(logging, _log_level) +else: + if _log_level: + logger.warning("Wrong value in $LOG_LEVEL, falling back to INFO") + _log_level = logging.INFO +logger.setLevel(_log_level) + + +class AddonsConfigError(Exception): + def __init__(self, message, *args): + super(AddonsConfigError, self).__init__(message, *args) + self.message = message + + +def addons_config(filtered=True, strict=False): + """Yield addon name and path from ``ADDONS_YAML``. + + :param bool filtered: + Use ``False`` to include all addon definitions. Use ``True`` (default) + to include only those matched by ``ONLY`` clauses, if any. + + :param bool strict: + Use ``True`` to raise an exception if any declared addon is not found. + + :return Iterator[str, str]: + A generator that yields ``(addon, repo)`` pairs. + """ + config = dict() + missing_glob = set() + missing_manifest = set() + all_globs = {} + try: + with open(ADDONS_YAML) as addons_file: + for doc in yaml.safe_load_all(addons_file): + # Skip sections with ONLY and that don't match + only = doc.pop("ONLY", {}) + if not filtered: + doc.setdefault(CORE, ["*"]) + doc.setdefault(PRIVATE, ["*"]) + elif any( + os.environ.get(key) not in values for key, values in only.items() + ): + logger.debug("Skipping section with ONLY %s", only) + continue + # Flatten all sections in a single dict + for repo, partial_globs in doc.items(): + if repo == "ENV": + continue + logger.debug("Processing %s repo", repo) + all_globs.setdefault(repo, set()) + all_globs[repo].update(partial_globs) + except IOError: + logger.debug("Could not find addons configuration yaml.") + # Add default values for special sections + for repo in (CORE, PRIVATE): + all_globs.setdefault(repo, {"*"}) + logger.debug("Merged addons definition before expanding: %r", all_globs) + # Expand all globs and store config + for repo, partial_globs in all_globs.items(): + for partial_glob in partial_globs: + logger.debug("Expanding in repo %s glob %s", repo, partial_glob) + full_glob = os.path.join(SRC_DIR, repo, partial_glob) + found = glob(full_glob) + if not found: + # Projects without private addons should never fail + if (repo, partial_glob) != (PRIVATE, "*"): + missing_glob.add(full_glob) + logger.debug("Skipping unexpandable glob '%s'", full_glob) + continue + for addon in found: + if not os.path.isdir(addon): + continue + manifests = (os.path.join(addon, m) for m in MANIFESTS) + if not any(os.path.isfile(m) for m in manifests): + missing_manifest.add(addon) + logger.debug( + "Skipping '%s' as it is not a valid Odoo " "module", addon + ) + continue + logger.debug("Registering addon %s", addon) + addon = os.path.basename(addon) + config.setdefault(addon, set()) + config[addon].add(repo) + # Fail now if running in strict mode + if strict: + error = [] + if missing_glob: + error += ["Addons not found:", pformat(missing_glob)] + if missing_manifest: + error += ["Addons without manifest:", pformat(missing_manifest)] + if error: + raise AddonsConfigError("\n".join(error), missing_glob, missing_manifest) + logger.debug("Resulting configuration after expanding: %r", config) + for addon, repos in config.items(): + # Private addons are most important + if PRIVATE in repos: + yield addon, PRIVATE + continue + # Odoo core addons are least important + if repos == {CORE}: + yield addon, CORE + continue + repos.discard(CORE) + # Other addons fall in between + if filtered and len(repos) != 1: + raise AddonsConfigError( + "Addon {} defined in several repos {}".format(addon, repos) + ) + for repo in repos: + yield addon, repo + + +try: + from shutil import which +except ImportError: + # Custom which implementation for Python 2 + def which(binary): + return check_output(["which", binary]).strip() diff --git a/lib/odoobaselib/installer.py b/lib/doodbalib/installer.py similarity index 69% rename from lib/odoobaselib/installer.py rename to lib/doodbalib/installer.py index 745d5695..2f926cc8 100644 --- a/lib/odoobaselib/installer.py +++ b/lib/doodbalib/installer.py @@ -2,11 +2,13 @@ from collections import OrderedDict from os.path import exists from subprocess import check_call -from odoobaselib import logger + +from doodbalib import logger class Installer(object): """Base class to install packages with some package system.""" + _cleanup_commands = [] _install_command = None _remove_command = None @@ -27,11 +29,9 @@ def cleanup(self): def install(self): """Install the requirements from the given file.""" if self._requirements: - return not self._run_command( - self._install_command + self._requirements) + return not self._run_command(self._install_command + self._requirements) else: - logger.info("No installable requirements found in %s", - self.file_path) + logger.info("No installable requirements found in %s", self.file_path) return False def remove(self): @@ -41,17 +41,16 @@ def remove(self): if self._requirements: self._run_command(self._remove_command + self._requirements) else: - logger.info("No removable requirements found in %s", - self.file_path) + logger.info("No removable requirements found in %s", self.file_path) def requirements(self): """Get a list of requirements from the given file.""" requirements = [] try: - with open(self.file_path, 'r') as fh: + with open(self.file_path, "r") as fh: for line in fh: line = line.strip() - if not line or line.startswith('#'): + if not line or line.startswith("#"): continue requirements += line.split() except IOError: @@ -61,15 +60,16 @@ def requirements(self): class AptInstaller(Installer): - _cleanup_commands = [ - ['apt-get', '-y', 'autoremove'], - 'rm -Rf /var/lib/apt/lists/*', - ] + _cleanup_commands = [["apt-get", "-y", "autoremove"], "rm -Rf /var/lib/apt/lists/*"] _install_command = [ - 'apt-get', - '-o', 'Dpkg::Options::=--force-confdef', - '-o', 'Dpkg::Options::=--force-confold', - '-y', '--no-install-recommends', 'install', + "apt-get", + "-o", + "Dpkg::Options::=--force-confdef", + "-o", + "Dpkg::Options::=--force-confold", + "-y", + "--no-install-recommends", + "install", ] _remove_command = ["apt-get", "purge", "-y"] @@ -82,38 +82,36 @@ def cleanup(self): def install(self): if not self._dirty() and self._requirements: - self._run_command(['apt-get', 'update']) + self._run_command(["apt-get", "update"]) return super(AptInstaller, self).install() class GemInstaller(Installer): - _cleanup_commands = [ - 'rm -Rf ~/.gem /var/lib/gems/*/cache/', - ] - _install_command = [ - "gem", "install", "--no-rdoc", "--no-ri", "--no-update-sources", - ] + _cleanup_commands = ["rm -Rf ~/.gem /var/lib/gems/*/cache/"] + _install_command = ["gem", "install", "--no-document", "--no-update-sources"] class NpmInstaller(Installer): - _cleanup_commands = ['rm -Rf ~/.npm /tmp/*'] + _cleanup_commands = ["rm -Rf ~/.npm /tmp/*"] _install_command = ["npm", "install", "-g"] class PipInstaller(Installer): - _install_command = ["pip", "install", "--upgrade", "--no-cache-dir", "-r"] + _install_command = ["pip", "install", "--no-cache-dir", "-r"] def requirements(self): """Pip will use its ``--requirements`` feature.""" return [self.file_path] if exists(self.file_path) else [] -INSTALLERS = OrderedDict([ - ("apt", AptInstaller), - ("gem", GemInstaller), - ("npm", NpmInstaller), - ("pip", PipInstaller), -]) +INSTALLERS = OrderedDict( + [ + ("apt", AptInstaller), + ("gem", GemInstaller), + ("npm", NpmInstaller), + ("pip", PipInstaller), + ] +) def install(installer, file_path): diff --git a/lib/odoobaselib/__init__.py b/lib/odoobaselib/__init__.py deleted file mode 100644 index 2d979f6c..00000000 --- a/lib/odoobaselib/__init__.py +++ /dev/null @@ -1,154 +0,0 @@ -# -*- coding: utf-8 -*- -import logging -import os - -from glob import glob -from pprint import pformat - -import yaml - -# Constants needed in scripts -CUSTOM_DIR = "/opt/odoo/custom" -SRC_DIR = os.path.join(CUSTOM_DIR, 'src') -ADDONS_YAML = os.path.join(SRC_DIR, 'addons') -if os.path.isfile('%s.yaml' % ADDONS_YAML): - ADDONS_YAML = '%s.yaml' % ADDONS_YAML -else: - ADDONS_YAML = '%s.yml' % ADDONS_YAML -ADDONS_DIR = "/opt/odoo/auto/addons" -CLEAN = os.environ.get("CLEAN") == "true" -AUTO_REQUIREMENTS = os.environ.get("AUTO_REQUIREMENTS") == "true" -LOG_LEVELS = ("DEBUG", "INFO", "WARNING", "ERROR") -FILE_APT_BUILD = os.path.join( - CUSTOM_DIR, 'dependencies', 'apt_build.txt', -) -PRIVATE = "private" -CORE = "odoo/addons" -PRIVATE_DIR = os.path.join(SRC_DIR, PRIVATE) -CORE_DIR = os.path.join(SRC_DIR, CORE) -ODOO_VERSION = float(os.environ["ODOO_VERSION"]) -MANIFESTS = ("__manifest__.py", "__openerp__.py") -if ODOO_VERSION < 10: - MANIFESTS = MANIFESTS[1:] - -# Customize logging for build -logger = logging.getLogger("doodba") -log_handler = logging.StreamHandler() -log_formatter = logging.Formatter("%(name)s %(levelname)s: %(message)s") -log_handler.setFormatter(log_formatter) -logger.addHandler(log_handler) -_log_level = os.environ.get("LOG_LEVEL", "") -if _log_level.isdigit(): - _log_level = int(_log_level) -elif _log_level in LOG_LEVELS: - _log_level = getattr(logging, _log_level) -else: - if _log_level: - logger.warning("Wrong value in $LOG_LEVEL, falling back to INFO") - _log_level = logging.INFO -logger.setLevel(_log_level) - - -class AddonsConfigError(Exception): - def __init__(self, message, *args): - super(AddonsConfigError, self).__init__(message, *args) - self.message = message - - -def addons_config(filtered=True, strict=False): - """Yield addon name and path from ``ADDONS_YAML``. - - :param bool filtered: - Use ``False`` to include all addon definitions. Use ``True`` (default) - to include only those matched by ``ONLY`` clauses, if any. - - :param bool strict: - Use ``True`` to raise an exception if any declared addon is not found. - """ - config = dict() - missing_glob = set() - missing_manifest = set() - special_missing = {PRIVATE, CORE} - try: - with open(ADDONS_YAML) as addons_file: - for doc in yaml.load_all(addons_file): - # When not filtering, private and core addons should be either - # defined under every doc, or defaulted to `*` in the - # ones where it is missing - if not filtered: - doc.setdefault(CORE, ["*"]) - doc.setdefault(PRIVATE, ["*"]) - # Skip sections with ONLY and that don't match - elif any(os.environ.get(key) not in values - for key, values in doc.get("ONLY", dict()).items()): - logger.debug("Skipping section with ONLY %s", doc["ONLY"]) - continue - # Flatten all sections in a single dict - for repo, addons in doc.items(): - if repo == "ONLY": - continue - logger.debug("Processing %s repo", repo) - special_missing.discard(repo) - for partial_glob in addons: - logger.debug("Expanding glob %s", partial_glob) - full_glob = os.path.join(SRC_DIR, repo, partial_glob) - found = glob(full_glob) - if not found: - missing_glob.add(full_glob) - logger.debug( - "Skipping unexpandable glob '%s'", - full_glob) - continue - for addon in found: - manifests = ( - os.path.join(addon, m) for m in MANIFESTS - ) - if not any(os.path.isfile(m) for m in manifests): - missing_manifest.add(addon) - logger.debug( - "Skipping '%s' as it is not a valid Odoo " - "module", addon) - continue - logger.debug("Registering addon %s", addon) - addon = os.path.basename(addon) - config.setdefault(addon, set()) - config[addon].add(repo) - except IOError: - logger.debug('Could not find addons configuration yaml.') - # Fail now if running in strict mode - if strict: - error = [] - if missing_glob: - error += ["Addons not found:", pformat(missing_glob)] - if missing_manifest: - error += ["Addons without manifest:", pformat(missing_manifest)] - if error: - raise AddonsConfigError( - "\n".join(error), - missing_glob, - missing_manifest, - ) - # By default, all private and core addons are enabled - for repo in special_missing: - logger.debug("Auto-adding all addons from %s", repo) - for addon in glob(os.path.join(SRC_DIR, repo, "*")): - addon = os.path.basename(addon) - config.setdefault(addon, set()) - config[addon].add(repo) - logger.debug("Resulting configuration: %r", config) - for addon, repos in config.items(): - # Private addons are most important - if PRIVATE in repos: - yield addon, PRIVATE - continue - # Odoo core addons are least important - if repos == {CORE}: - yield addon, CORE - continue - repos.discard(CORE) - # Other addons fall in between - if len(repos) != 1: - raise AddonsConfigError( - u"Addon {} defined in several repos {}".format(addon, repos), - ) - yield addon, repos.pop() diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 00000000..bc3083f6 --- /dev/null +++ b/poetry.lock @@ -0,0 +1,242 @@ +# This file is automatically @generated by Poetry 2.1.2 and should not be changed by hand. + +[[package]] +name = "cfgv" +version = "3.4.0" +description = "Validate configuration and produce human readable error messages." +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"}, + {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"}, +] + +[[package]] +name = "distlib" +version = "0.3.9" +description = "Distribution utilities" +optional = false +python-versions = "*" +groups = ["dev"] +files = [ + {file = "distlib-0.3.9-py2.py3-none-any.whl", hash = "sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87"}, + {file = "distlib-0.3.9.tar.gz", hash = "sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403"}, +] + +[[package]] +name = "filelock" +version = "3.18.0" +description = "A platform independent file lock." +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "filelock-3.18.0-py3-none-any.whl", hash = "sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de"}, + {file = "filelock-3.18.0.tar.gz", hash = "sha256:adbc88eabb99d2fec8c9c1b229b171f18afa655400173ddc653d5d01501fb9f2"}, +] + +[package.extras] +docs = ["furo (>=2024.8.6)", "sphinx (>=8.1.3)", "sphinx-autodoc-typehints (>=3)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.6.10)", "diff-cover (>=9.2.1)", "pytest (>=8.3.4)", "pytest-asyncio (>=0.25.2)", "pytest-cov (>=6)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.28.1)"] +typing = ["typing-extensions (>=4.12.2) ; python_version < \"3.11\""] + +[[package]] +name = "identify" +version = "2.6.10" +description = "File identification library for Python" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "identify-2.6.10-py2.py3-none-any.whl", hash = "sha256:5f34248f54136beed1a7ba6a6b5c4b6cf21ff495aac7c359e1ef831ae3b8ab25"}, + {file = "identify-2.6.10.tar.gz", hash = "sha256:45e92fd704f3da71cc3880036633f48b4b7265fd4de2b57627cb157216eb7eb8"}, +] + +[package.extras] +license = ["ukkonen"] + +[[package]] +name = "nodeenv" +version = "1.9.1" +description = "Node.js virtual environment builder" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +groups = ["dev"] +files = [ + {file = "nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9"}, + {file = "nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f"}, +] + +[[package]] +name = "platformdirs" +version = "4.3.8" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4"}, + {file = "platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc"}, +] + +[package.extras] +docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.1.3)", "sphinx-autodoc-typehints (>=3)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.4)", "pytest-cov (>=6)", "pytest-mock (>=3.14)"] +type = ["mypy (>=1.14.1)"] + +[[package]] +name = "plumbum" +version = "1.9.0" +description = "Plumbum: shell combinators library" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "plumbum-1.9.0-py3-none-any.whl", hash = "sha256:9fd0d3b0e8d86e4b581af36edf3f3bbe9d1ae15b45b8caab28de1bcb27aaa7f5"}, + {file = "plumbum-1.9.0.tar.gz", hash = "sha256:e640062b72642c3873bd5bdc3effed75ba4d3c70ef6b6a7b907357a84d909219"}, +] + +[package.dependencies] +pywin32 = {version = "*", markers = "platform_system == \"Windows\" and platform_python_implementation != \"PyPy\""} + +[package.extras] +dev = ["coverage[toml]", "paramiko", "psutil", "pytest (>=6.0)", "pytest-cov", "pytest-mock", "pytest-timeout"] +docs = ["sphinx (>=4.0.0)", "sphinx-rtd-theme (>=1.0.0)"] +ssh = ["paramiko"] +test = ["coverage[toml]", "paramiko", "psutil", "pytest (>=6.0)", "pytest-cov", "pytest-mock", "pytest-timeout"] + +[[package]] +name = "pre-commit" +version = "2.21.0" +description = "A framework for managing and maintaining multi-language pre-commit hooks." +optional = false +python-versions = ">=3.7" +groups = ["dev"] +files = [ + {file = "pre_commit-2.21.0-py2.py3-none-any.whl", hash = "sha256:e2f91727039fc39a92f58a588a25b87f936de6567eed4f0e673e0507edc75bad"}, + {file = "pre_commit-2.21.0.tar.gz", hash = "sha256:31ef31af7e474a8d8995027fefdfcf509b5c913ff31f2015b4ec4beb26a6f658"}, +] + +[package.dependencies] +cfgv = ">=2.0.0" +identify = ">=1.0.0" +nodeenv = ">=0.11.1" +pyyaml = ">=5.1" +virtualenv = ">=20.10.0" + +[[package]] +name = "pywin32" +version = "310" +description = "Python for Window Extensions" +optional = false +python-versions = "*" +groups = ["dev"] +markers = "platform_system == \"Windows\" and platform_python_implementation != \"PyPy\"" +files = [ + {file = "pywin32-310-cp310-cp310-win32.whl", hash = "sha256:6dd97011efc8bf51d6793a82292419eba2c71cf8e7250cfac03bba284454abc1"}, + {file = "pywin32-310-cp310-cp310-win_amd64.whl", hash = "sha256:c3e78706e4229b915a0821941a84e7ef420bf2b77e08c9dae3c76fd03fd2ae3d"}, + {file = "pywin32-310-cp310-cp310-win_arm64.whl", hash = "sha256:33babed0cf0c92a6f94cc6cc13546ab24ee13e3e800e61ed87609ab91e4c8213"}, + {file = "pywin32-310-cp311-cp311-win32.whl", hash = "sha256:1e765f9564e83011a63321bb9d27ec456a0ed90d3732c4b2e312b855365ed8bd"}, + {file = "pywin32-310-cp311-cp311-win_amd64.whl", hash = "sha256:126298077a9d7c95c53823934f000599f66ec9296b09167810eb24875f32689c"}, + {file = "pywin32-310-cp311-cp311-win_arm64.whl", hash = "sha256:19ec5fc9b1d51c4350be7bb00760ffce46e6c95eaf2f0b2f1150657b1a43c582"}, + {file = "pywin32-310-cp312-cp312-win32.whl", hash = "sha256:8a75a5cc3893e83a108c05d82198880704c44bbaee4d06e442e471d3c9ea4f3d"}, + {file = "pywin32-310-cp312-cp312-win_amd64.whl", hash = "sha256:bf5c397c9a9a19a6f62f3fb821fbf36cac08f03770056711f765ec1503972060"}, + {file = "pywin32-310-cp312-cp312-win_arm64.whl", hash = "sha256:2349cc906eae872d0663d4d6290d13b90621eaf78964bb1578632ff20e152966"}, + {file = "pywin32-310-cp313-cp313-win32.whl", hash = "sha256:5d241a659c496ada3253cd01cfaa779b048e90ce4b2b38cd44168ad555ce74ab"}, + {file = "pywin32-310-cp313-cp313-win_amd64.whl", hash = "sha256:667827eb3a90208ddbdcc9e860c81bde63a135710e21e4cb3348968e4bd5249e"}, + {file = "pywin32-310-cp313-cp313-win_arm64.whl", hash = "sha256:e308f831de771482b7cf692a1f308f8fca701b2d8f9dde6cc440c7da17e47b33"}, + {file = "pywin32-310-cp38-cp38-win32.whl", hash = "sha256:0867beb8addefa2e3979d4084352e4ac6e991ca45373390775f7084cc0209b9c"}, + {file = "pywin32-310-cp38-cp38-win_amd64.whl", hash = "sha256:30f0a9b3138fb5e07eb4973b7077e1883f558e40c578c6925acc7a94c34eaa36"}, + {file = "pywin32-310-cp39-cp39-win32.whl", hash = "sha256:851c8d927af0d879221e616ae1f66145253537bbdd321a77e8ef701b443a9a1a"}, + {file = "pywin32-310-cp39-cp39-win_amd64.whl", hash = "sha256:96867217335559ac619f00ad70e513c0fcf84b8a3af9fc2bba3b59b97da70475"}, +] + +[[package]] +name = "pyyaml" +version = "6.0.2" +description = "YAML parser and emitter for Python" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, + {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed"}, + {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180"}, + {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68"}, + {file = "PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99"}, + {file = "PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e"}, + {file = "PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774"}, + {file = "PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85"}, + {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"}, + {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e"}, + {file = "PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5"}, + {file = "PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44"}, + {file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"}, + {file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"}, + {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"}, + {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"}, + {file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"}, + {file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"}, + {file = "PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba"}, + {file = "PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5"}, + {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc"}, + {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652"}, + {file = "PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183"}, + {file = "PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563"}, + {file = "PyYAML-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083"}, + {file = "PyYAML-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706"}, + {file = "PyYAML-6.0.2-cp38-cp38-win32.whl", hash = "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a"}, + {file = "PyYAML-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff"}, + {file = "PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d"}, + {file = "PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19"}, + {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e"}, + {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725"}, + {file = "PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631"}, + {file = "PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8"}, + {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"}, +] + +[[package]] +name = "virtualenv" +version = "20.31.2" +description = "Virtual Python Environment builder" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "virtualenv-20.31.2-py3-none-any.whl", hash = "sha256:36efd0d9650ee985f0cad72065001e66d49a6f24eb44d98980f630686243cf11"}, + {file = "virtualenv-20.31.2.tar.gz", hash = "sha256:e10c0a9d02835e592521be48b332b6caee6887f332c111aa79a09b9e79efc2af"}, +] + +[package.dependencies] +distlib = ">=0.3.7,<1" +filelock = ">=3.12.2,<4" +platformdirs = ">=3.9.1,<5" + +[package.extras] +docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] +test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8) ; platform_python_implementation == \"PyPy\" or platform_python_implementation == \"GraalVM\" or platform_python_implementation == \"CPython\" and sys_platform == \"win32\" and python_version >= \"3.13\"", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10) ; platform_python_implementation == \"CPython\""] + +[metadata] +lock-version = "2.1" +python-versions = "^3.9" +content-hash = "4e323a4a9e17ff1a3a4038e5c65bfa6562caad1b578404c97503461017324860" diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..2380115e --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,17 @@ +[tool.poetry] +name = "doodba" +version = "0.0.0" +package-mode = false +description = "Docker Odoo Base, a highly opinionated image ready to put Odoo inside it, but without Odoo" +authors = ["Tecnativa"] + +[tool.poetry.dependencies] +python = "^3.9" + +[tool.poetry.group.dev.dependencies] +plumbum = "^1.6.9" +pre-commit = "^2.9.3" + +[build-system] +requires = ["poetry-core>=1.0.0"] +build-backend = "poetry.core.masonry.api" diff --git a/qa/insider b/qa/insider new file mode 100755 index 00000000..a217466e --- /dev/null +++ b/qa/insider @@ -0,0 +1,73 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +from __future__ import print_function + +import os +import shutil +import stat +import subprocess +import sys +from argparse import ArgumentParser +from tempfile import NamedTemporaryFile, mkstemp + +from doodbalib import logger + +# Define CLI options +parser = ArgumentParser( + description="Execute some code in this container's QA environment." +) +parser.add_argument( + "script", + help="The source code that will be executed. It should start with a shebang.", +) +parser.add_argument( + "arguments", nargs="*", help="Additional arguments passed to the script." +) +args = parser.parse_args() + +# Copy the source code to an executable file +executable = NamedTemporaryFile(mode="w+", delete=False) +with executable as tmp: + logger.debug("Insider script source code:\n%s", args.script) + tmp.write(args.script) +os.chmod( + executable.name, + stat.S_IRWXU | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH, +) + +# Execute the script +cmd = [executable.name] + args.arguments +returncode = 0 +try: + logger.debug("Executing %r", cmd) + subprocess.check_call( + cmd, + stdout=sys.stderr, + # TODO Change to text=True when we support Python 3.7+ only + universal_newlines=True, + ) +except subprocess.CalledProcessError as error: + logger.debug("Subcommand exception:", exc_info=True) + returncode = error.returncode +finally: + logger.debug("Deleting %s", executable.name) + os.unlink(executable.name) + + artifacts_zip_path = mkstemp()[1] + logger.debug("Zipping /qa/artifacts in %s.zip", artifacts_zip_path) + shutil.make_archive(artifacts_zip_path, "zip", "/qa/artifacts") + artifacts_zip_path += ".zip" + with open(artifacts_zip_path, "rb") as zip_fd: + if sys.version_info >= (3,): + with os.fdopen(sys.stdout.fileno(), "wb", closefd=False) as stdout: + stdout.write(zip_fd.read()) + stdout.flush() + # TODO Delete when dropping Python 2 (Odoo 10.0 and lower) support, + # as this is a less safe and idiomatic way of doing the same as above + else: + os.write(sys.stdout.fileno(), zip_fd.read()) + + logger.debug("Deleting %s", artifacts_zip_path) + os.unlink(artifacts_zip_path) + +sys.exit(returncode) diff --git a/requirements-ci.txt b/requirements-ci.txt index e41f7569..ccc6abca 100644 --- a/requirements-ci.txt +++ b/requirements-ci.txt @@ -1 +1,3 @@ docker-compose +plumbum +pre-commit diff --git a/tests/__init__.py b/tests/__init__.py index 97bf23c0..ecd462b9 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,32 +1,43 @@ -#!/usr/bin/env python3 +# -*- coding: utf-8 -*- """Run tests for this base image. Each test must be a valid docker-compose.yaml file with a ``odoo`` service. """ import logging -import tempfile +import os import unittest - from itertools import product -from os import environ, getlogin +from os import environ from os.path import dirname, join -from pwd import getpwnam from subprocess import Popen logging.basicConfig(level=logging.DEBUG) -MAIN_SCAFFOLDING_VERSION = "11.0" DIR = dirname(__file__) ODOO_PREFIX = ("odoo", "--stop-after-init", "--workers=0") -ODOO_VERSIONS = frozenset(environ.get( - "DOCKER_TAG", "8.0 9.0 10.0 11.0").split()) -PG_VERSIONS = frozenset(environ.get( - "PG_VERSIONS", "9.6").split()) +ODOO_VERSIONS = frozenset(environ.get("ODOO_MINOR", "19.0").split()) +PG_VERSIONS = frozenset(environ.get("PG_VERSIONS", "17").split()) SCAFFOLDINGS_DIR = join(DIR, "scaffoldings") +GEIOP_CREDENTIALS_PROVIDED = environ.get("GEOIP_LICENSE_KEY", False) and environ.get( + "GEOIP_ACCOUNT_ID", False +) + + +# This decorator skips tests that will fail until some branches and/or addons +# are migrated to the next release. It is used in situations where Doodba is +# preparing the pre-release for the next version of Odoo, which hasn't been +# released yet. +# prerelease_skip = unittest.skipIf( +# ODOO_VERSIONS & {"16.0"}, "Tests not supported in pre-release" +# ) +prerelease_skip = unittest.skipIf( + False, "Tests not supported in pre-release" +) # No pre-releases to test -def matrix(odoo=ODOO_VERSIONS, pg=PG_VERSIONS, - odoo_skip=frozenset(), pg_skip=frozenset()): +def matrix( + odoo=ODOO_VERSIONS, pg=PG_VERSIONS, odoo_skip=frozenset(), pg_skip=frozenset() +): """All possible combinations. We compute the variable matrix here instead of in ``.travis.yml`` because @@ -38,14 +49,57 @@ def matrix(odoo=ODOO_VERSIONS, pg=PG_VERSIONS, product( product(("ODOO_MINOR",), ODOO_VERSIONS & odoo - odoo_skip), product(("DB_VERSION",), PG_VERSIONS & pg - pg_skip), - ) + ), ) class ScaffoldingCase(unittest.TestCase): + @classmethod + def build_base_image(cls, tag, file): + assert ( + Popen( + ( + "docker", + "build", + "-t", + tag, + "-f", + file, + "--target", + "onbuild", + ".", + ), + cwd=os.getcwd(), + ).wait() + == 0 + ), "Building image for tests failed" + + @classmethod + def setUpClass(cls): + use_prebuilt_images = ( + os.environ.get("USE_PREBUILT_IMAGES", "false").lower() == "true" + ) + if "DOCKER_TAG" in os.environ and not use_prebuilt_images: + print(f"Building {os.environ['DOCKER_TAG']}-onbuild image...") + cls.build_base_image( + f"tecnativa/doodba:{os.environ['DOCKER_TAG']}-onbuild", + f"{os.environ['ODOO_MINOR']}.Dockerfile", + ) + elif not use_prebuilt_images: + # We build the “onbuild” images with the latest changes for + # testing instead of relying on the latest published ones. + for ODOO_VER in ODOO_VERSIONS: + print(f"Building {ODOO_VER}-onbuild image...") + cls.build_base_image( + f"tecnativa/doodba:{ODOO_VER}-onbuild", + f"{ODOO_VER}.Dockerfile", + ) + else: + logging.info("using prebuilt images") + def setUp(self): super().setUp() - self.compose_run = ("docker-compose", "run", "--rm", "odoo") + self.compose_run = ("docker", "compose", "run", "--rm", "odoo") def popen(self, *args, **kwargs): """Shortcut to open a subprocess and ensure it works.""" @@ -53,7 +107,7 @@ def popen(self, *args, **kwargs): self.assertFalse(Popen(*args, **kwargs).wait()) def compose_test(self, workdir, sub_env, *commands): - """Execute commands in a docker-compose environment. + """Execute commands in a docker compose environment. :param workdir: Path where the docker compose commands will be executed. It should @@ -61,10 +115,10 @@ def compose_test(self, workdir, sub_env, *commands): :param dict sub_env: Specific environment variables that will be appended to current - ones to execute the ``docker-compose`` tests. + ones to execute the ``docker compose`` tests. You can set in this dict a ``COMPOSE_FILE`` key to choose different - docker-compose files in the same directory. + docker compose files in the same directory. :param tuple()... commands: List of commands to be tested in the odoo container. @@ -72,65 +126,92 @@ def compose_test(self, workdir, sub_env, *commands): full_env = dict(environ, **sub_env) with self.subTest(PWD=workdir, **sub_env): try: + build_arg = f"ODOO_VERSION={full_env.get('DOCKER_TAG', full_env.get('ODOO_MINOR', '19.0'))}" self.popen( - ("docker-compose", "build"), + ("docker", "compose", "build", "--build-arg", build_arg), cwd=workdir, env=full_env, ) for command in commands: with self.subTest(command=command): self.popen( - self.compose_run + command, - cwd=workdir, - env=full_env, + self.compose_run + command, cwd=workdir, env=full_env ) finally: self.popen( - ("docker-compose", "down", "-v"), - cwd=workdir, - env=full_env, + ("docker", "compose", "down", "-v"), cwd=workdir, env=full_env ) - def test_addons_filtered(self): - """Test addons filtering with ``ONLY`` keyword in ``addons.yaml``.""" - project_dir = join(SCAFFOLDINGS_DIR, "dotd") - for sub_env in matrix(): + def _check_addons(self, scaffolding_dir, odoo_skip): + project_dir = join(SCAFFOLDINGS_DIR, scaffolding_dir) + for sub_env in matrix(odoo_skip=odoo_skip): self.compose_test( project_dir, dict(sub_env, DBNAME="prod"), - ("test", "-e", "auto/addons/website"), + ("test", "-e", "auto/addons/web"), ("test", "-e", "auto/addons/private_addon"), - ("bash", "-c", - 'test "$(addons list -p)" == disabled_addon,private_addon'), - ("bash", "-c", 'test "$(addons list -ip)" == private_addon'), - ("bash", "-c", 'addons list -c | grep ,crm,'), + ( + "bash", + "-xc", + 'test "$(addons list -p)" == disabled_addon,private_addon', + ), + ("bash", "-xc", 'test "$(addons list -ip)" == private_addon'), + ("bash", "-xc", "addons list -c | grep ,crm,"), # absent_addon is missing and should fail - ("bash", "-c", "! addons list -px"), + ("bash", "-xc", "! addons list -px"), + # Test addon inclusion, exclusion, dependencies... + ( + "bash", + "-xc", + 'test "$(addons list -dw private_addon)" == base,dummy_addon,website', + ), + ( + "bash", + "-xc", + 'test "$(addons list -dwprivate_addon -Wwebsite)" == base,dummy_addon', + ), + ( + "bash", + "-xc", + 'test "$(addons list -dw private_addon -W dummy_addon)" == base,website', + ), + ( + "bash", + "-xc", + 'test "$(addons list -nd)" == base,iap', + ), + ( + "bash", + "-xc", + 'test "$(addons list --enterprise)" == make_odoo_rich', + ), ) self.compose_test( project_dir, dict(sub_env, DBNAME="limited_private"), - ("test", "-e", "auto/addons/website"), + ("test", "-e", "auto/addons/web"), ("test", "!", "-e", "auto/addons/private_addon"), - ("bash", "-c", 'test -z "$(addons list -p)"'), - ("bash", "-c", - '[ "$(addons list -s. -pwfake1 -wfake2)" == fake1.fake2 ]'), - ("bash", "-c", "! addons list -wrepeat -Wrepeat"), - ("bash", "-c", 'addons list -c | grep ,crm,'), + ("bash", "-xc", 'test -z "$(addons list -p)"'), + ( + "bash", + "-xc", + '[ "$(addons list -s. -pwfake1 -wfake2)" == fake1.fake2 ]', + ), + ("bash", "-xc", "! addons list -wrepeat -Wrepeat"), + ("bash", "-xc", "addons list -c | grep ,crm,"), ) self.compose_test( project_dir, dict(sub_env, DBNAME="limited_core"), - ("test", "!", "-e", "auto/addons/website"), + ("test", "!", "-e", "auto/addons/web"), ("test", "!", "-e", "auto/addons/private_addon"), - ("bash", "-c", 'test -z "$(addons list -p)"'), - ("bash", "-c", 'test "$(addons list -c)" == crm,sale'), + ("bash", "-xc", 'test -z "$(addons list -p)"'), + ("bash", "-xc", 'test "$(addons list -c)" == crm,sale'), ) - # Skip Odoo versions that don't support __manifest__.py files - for sub_env in matrix(odoo_skip={"8.0", "9.0"}): self.compose_test( project_dir, dict(sub_env, DBNAME="prod"), + ("bash", "-xc", 'test "$(addons list -ped)" == base,web,website'), # ``dummy_addon`` and ``private_addon`` exist ("test", "-d", "auto/addons/dummy_addon"), ("test", "-h", "auto/addons/dummy_addon"), @@ -138,30 +219,63 @@ def test_addons_filtered(self): ("test", "-e", "auto/addons/dummy_addon"), # Addon from extra repo takes higher priority than core version ("realpath", "auto/addons/product"), - ("bash", "-c", 'test "$(realpath auto/addons/product)" == ' - '/opt/odoo/custom/src/dummy_repo/product'), - ("bash", "-c", - 'test "$(addons list -e)" == dummy_addon,product'), + ( + "bash", + "-xc", + 'test "$(realpath auto/addons/product)" == ' + "/opt/odoo/custom/src/other-doodba/odoo/src/private/product", + ), + ("bash", "-xc", 'test "$(addons list -e)" == dummy_addon,product'), ) self.compose_test( project_dir, dict(sub_env, DBNAME="limited_private"), ("test", "-e", "auto/addons/dummy_addon"), - ("bash", "-c", - 'test "$(addons list -e)" == dummy_addon,product'), + ("bash", "-xc", 'test "$(addons list -e)" == dummy_addon,product'), ) self.compose_test( project_dir, dict(sub_env, DBNAME="limited_core"), ("test", "-e", "auto/addons/dummy_addon"), - ("bash", "-c", - '[ "$(addons list -s. -pwfake1 -wfake2)" == fake1.fake2 ]'), - ("bash", "-c", - 'test "$(addons list -e)" == dummy_addon,product'), - ("bash", "-c", 'test "$(addons list -c)" == crm,sale'), - ("bash", "-c", 'test "$(addons list -cWsale)" == crm'), + ( + "bash", + "-xc", + '[ "$(addons list -s. -pwfake1 -wfake2)" == fake1.fake2 ]', + ), + ("bash", "-xc", 'test "$(addons list -e)" == dummy_addon,product'), + ("bash", "-xc", 'test "$(addons list -c)" == crm,sale'), + ("bash", "-xc", 'test "$(addons list -cWsale)" == crm'), ) + def test_addons_filtered_lt_16(self): + """Test addons filtering with ``ONLY`` keyword in ``addons.yaml`` for versions < 16""" + self._check_addons("dotd", {"16.0", "17.0", "18.0", "19.0"}) + + def test_addons_filtered_ge_16(self): + """Test addons filtering with ``ONLY`` keyword in ``addons.yaml`` for versions >= 16""" + self._check_addons("dotd_ge_16", {"11.0", "12.0", "13.0", "14.0", "15.0"}) + + def test_qa(self): + """Test that QA tools are in place and work as expected.""" + folder = join(SCAFFOLDINGS_DIR, "settings") + commands = (("./custom/scripts/qa-insider-test",),) + for sub_env in matrix(): + # Images up to v12 (inclusive) still had QA/NodeJS dependencies. + # Check if they are correctly installed. + if float(sub_env["ODOO_MINOR"]) < 13: + commands += ( + ("/qa/node_modules/.bin/eslint", "--version"), + ("/qa/venv/bin/flake8", "--version"), + ("/qa/venv/bin/pylint", "--version"), + ("/qa/venv/bin/python", "-c", "import pylint_odoo"), + ) + if sub_env["ODOO_MINOR"] != "11.0": + commands += (("/qa/node_modules/.bin/eslint", "--env-info"),) + commands += (("/qa/venv/bin/python", "--version"),) + if float(sub_env["ODOO_MINOR"]) < 14: + commands += (("test", "-d", "/qa/mqt"),) + self.compose_test(folder, sub_env, *commands) + def test_settings(self): """Test settings are filled OK""" folder = join(SCAFFOLDINGS_DIR, "settings") @@ -171,49 +285,150 @@ def test_settings(self): # Odoo settings work ("./custom/scripts/test_settings.py",), ) - # Odoo 8.0 has no shell, and --load-language doesn't work fine in 9.0 - for sub_env in matrix(odoo={"9.0"}): - self.compose_test(folder, sub_env, *commands) - # Extra tests for versions >= 10.0, that support --load-language fine + if "11.0" in ODOO_VERSIONS: + commands += ( + # Check Odoo settings using python-odoo-shell, which is available + # only for Odoo 9-11 (for 8 too, but it had no built-in shell) + ("./custom/scripts/test_settings_python_odoo_shell.py",), + ) commands += ( # DB was created with the correct language - ("bash", "-c", - """test "$(psql -Atqc "SELECT code FROM res_lang - WHERE active = TRUE")" == es_ES"""), + ( + "bash", + "-xc", + """test "$(psql -Atqc "SELECT code FROM res_lang + WHERE active = TRUE")" == es_ES""", + ), + # If `preparedb` is executed, we should have `report.url` set + ("preparedb",), + ("./custom/scripts/test_ir_config_parameters.py",), ) - for sub_env in matrix(odoo_skip={"8.0", "9.0"}): + for sub_env in matrix(): self.compose_test(folder, sub_env, *commands) def test_smallest(self): """Tests for the smallest possible environment.""" + liberation = 'Liberation{0}-Regular.ttf: "Liberation {0}" "Regular"' commands = ( # Must generate a configuration file ("test", "-f", "/opt/odoo/auto/odoo.conf"), ("test", "-d", "/opt/odoo/custom/src/private"), ("test", "-d", "/opt/odoo/custom/ssh"), - ("test", "-x", "/usr/local/bin/unittest"), + ("addons", "list", "-cpix"), ("pg_activity", "--version"), + # Default fonts must be liberation + ( + "bash", + "-xc", + """test "$(fc-match monospace)" == '{}'""".format( + liberation.format("Mono") + ), + ), + ( + "bash", + "-xc", + """test "$(fc-match sans-serif)" == '{}'""".format( + liberation.format("Sans") + ), + ), + ( + "bash", + "-xc", + """test "$(fc-match serif)" == '{}'""".format( + liberation.format("Serif") + ), + ), # Must be able to install base addon ODOO_PREFIX + ("--init", "base"), # Auto updater must work - ("autoupdate",), + ("click-odoo-update",), + # Auto updater must work, ignoring core addons + ("click-odoo-update", "--ignore-core-addons"), + # Needed tools exist + ("curl", "--version"), + ("git", "--version"), + ("pg_activity", "--version"), + ("psql", "--version"), + ("msgmerge", "--version"), + ("ssh", "-V"), + ("python", "-c", "import plumbum"), + # We are able to dump + ("pg_dump", "-f/var/lib/odoo/prod.sql", "prod"), + # Geoip should not be activated + ("bash", "-xc", 'test "$(which geoipupdate)" != ""'), + ("test", "!", "-e", "/usr/share/GeoIP/GeoLite2-City.mmdb"), + ("bash", "-xc", "! geoipupdate"), + # Ensure /root/.ssh/ has not been mangled + ("bash", "-c", "[[ ! -d ~root/.ssh/ssh ]]"), ) smallest_dir = join(SCAFFOLDINGS_DIR, "smallest") - for sub_env in matrix(odoo_skip={"8.0"}): - self.compose_test(smallest_dir, sub_env, *commands) - for sub_env in matrix(odoo={"8.0"}): + for sub_env in matrix(): self.compose_test( - smallest_dir, sub_env, - # Odoo 8.0 does not autocreate the database - ("psql", "-d", "postgres", "-c", "create database prod"), - *commands + smallest_dir, sub_env, *commands, ("python", "-c", "import watchdog") ) - def test_dotd(self): - """Test environment with common ``*.d`` directories.""" + def test_addons_env(self): + """Test environment variables in addons.yaml""" + # The test is hacking ODOO_VERSION to pin a commit + # It uses OCA/OpenUpgrade as base for Odoo, which won't work from v14 + # and onwards as it no longer is a fork from Odoo + for sub_env in matrix(odoo={"11.0", "12.0", "13.0"}): + self.compose_test( + join(SCAFFOLDINGS_DIR, "addons_env"), + sub_env, + # check module from custom repo pattern + ("test", "-d", "custom/src/misc-addons"), + ("test", "-d", "custom/src/misc-addons/web_debranding"), + ("test", "-e", "auto/addons/web_debranding"), + # Migrations folder is only in OpenUpgrade + ("test", "-e", "auto/addons/crm"), + ("test", "-d", "auto/addons/crm/migrations"), + ) + # TODO: Review error on 19.0 + for sub_env in matrix(odoo_skip={"11.0", "12.0", "13.0", "19.0"}): + self.compose_test( + join(SCAFFOLDINGS_DIR, "addons_env_ou"), + sub_env, + # check module from custom repo pattern + ("test", "-d", "custom/src/misc-addons"), + ("test", "-d", "custom/src/misc-addons/web_debranding"), + ("test", "-e", "auto/addons/web_debranding"), + # Migrations folder + ("test", "-e", "auto/addons/openupgrade_scripts"), + ("test", "-d", "auto/addons/openupgrade_scripts/scripts"), + ) + + # HACK https://github.com/itpp-labs/misc-addons/issues/1014 + def test_addons_env_double(self): + """Test double addon reference in addons.yaml""" + common_tests = ( + ("test", "-d", "custom/src/rma-old/rma"), + ("test", "!", "-d", "custom/src/rma-old/rma_sale"), + ("test", "-d", "custom/src/rma-new/rma"), + ("test", "!", "-d", "custom/src/rma-new/rma_sale"), + ) + # The test is hacking ODOO_VERSION to pin a commit for sub_env in matrix(): self.compose_test( - join(SCAFFOLDINGS_DIR, "dotd"), sub_env, + join(SCAFFOLDINGS_DIR, "addons_env_double"), + dict(sub_env, DOODBA_ENVIRONMENT="test"), + *common_tests, + # Check version is 12.0.1.6.1 + ("grep", "-q", "12.0.1.6.1", "auto/addons/rma/__manifest__.py"), + ) + self.compose_test( + join(SCAFFOLDINGS_DIR, "addons_env_double"), + dict(sub_env, DOODBA_ENVIRONMENT="prod"), + *common_tests, + # Check version is 12.0.2.0.0 + ("grep", "-q", "12.0.2.0.0", "auto/addons/rma/__manifest__.py"), + ) + + def _check_dotd(self, scaffolding_dir, odoo_skip): + for sub_env in matrix(odoo_skip=odoo_skip): + self.compose_test( + join(SCAFFOLDINGS_DIR, scaffolding_dir), + sub_env, # ``custom/build.d`` was properly executed ("test", "-f", "/home/odoo/created-at-build"), # ``custom/entrypoint.d`` was properly executed @@ -221,19 +436,25 @@ def test_dotd(self): # ``custom/conf.d`` was properly concatenated ("grep", "test-conf", "auto/odoo.conf"), # ``custom/dependencies`` were installed - ("test", "!", "-e", "/usr/bin/gcc"), + ("test", "!", "-e", "/usr/sbin/sshd"), ("test", "!", "-e", "/var/lib/apt/lists/lock"), ("busybox", "whoami"), - ("bash", "-c", "echo $NODE_PATH"), + ("bash", "-xc", "echo $NODE_PATH"), ("node", "-e", "require('test-npm-install')"), - ("aloha_world",), - ("python", "-c", "import Crypto; print(Crypto.__version__)"), - ("sh", "-c", "rst2html.py --version | grep 'Docutils 0.14'"), + ("hello-world",), + ( + "bash", + "-c", + 'test "$(hello-world)" == "this is executable hello-world"', + ), + ("python", "-xc", "import Crypto; print(Crypto.__version__)"), # ``requirements.txt`` from addon repos were processed - ("python", "-c", "import cfssl"), + ("python", "-c", "import numpy"), # Local executable binaries found in $PATH - ("sh", "-c", "pip install --user -q flake8 && which flake8"), + ("sh", "-xc", "pip install --user -q flake8 && which flake8"), + # Addon cleanup works correctly ("test", "!", "-e", "custom/src/private/dummy_addon"), + ("test", "!", "-e", "custom/src/dummy_repo/dummy_link"), ("test", "-d", "custom/src/private/private_addon"), ("test", "-f", "custom/src/private/private_addon/__init__.py"), ("test", "-e", "auto/addons/private_addon"), @@ -243,22 +464,27 @@ def test_dotd(self): ("--version",), ) - def test_dependencies(self): - """Test dependencies installation.""" - dependencies_dir = join(SCAFFOLDINGS_DIR, "dependencies") - for sub_env in matrix(): + def test_dotd_lt_16(self): + """Test environment with common ``*.d`` directories for versions < 16.""" + self._check_dotd("dotd", {"16.0", "17.0", "18.0", "19.0"}) + + def test_dotd_ge_16(self): + """Test environment with common ``*.d`` directories for versions >= 16.""" + self._check_dotd("dotd_ge_16", {"11.0", "12.0", "13.0", "14.0", "15.0"}) + + def _check_dependencies(self, scaffolding_dir, odoo_skip): + dependencies_dir = join(SCAFFOLDINGS_DIR, scaffolding_dir) + for sub_env in matrix(odoo_skip=odoo_skip): self.compose_test( - dependencies_dir, sub_env, + dependencies_dir, + sub_env, ("test", "!", "-f", "custom/dependencies/apt.txt"), ("test", "!", "-f", "custom/dependencies/gem.txt"), ("test", "!", "-f", "custom/dependencies/npm.txt"), ("test", "!", "-f", "custom/dependencies/pip.txt"), - # Patched Werkzeug version - ("bash", "-c", ('test "$(python -c "import werkzeug; ' - 'print(werkzeug.__version__)")" == 0.14.1')), # apt_build.txt ("test", "-f", "custom/dependencies/apt_build.txt"), - ("test", "!", "-e", "/usr/bin/gcc"), + ("test", "!", "-e", "/usr/sbin/sshd"), # apt-without-sequence.txt ("test", "-f", "custom/dependencies/apt-without-sequence.txt"), ("test", "!", "-e", "/bin/busybox"), @@ -266,67 +492,391 @@ def test_dependencies(self): ("test", "-f", "custom/dependencies/070-apt-bc.txt"), ("test", "-e", "/usr/bin/bc"), # 150-npm-aloha_world-install.txt - ("test", "-f", ("custom/dependencies/" - "150-npm-aloha_world-install.txt")), + ("test", "-f", "custom/dependencies/150-npm-aloha_world-install.txt"), ("node", "-e", "require('test-npm-install')"), # 200-pip-without-ext ("test", "-f", "custom/dependencies/200-pip-without-ext"), ("python", "-c", "import Crypto; print(Crypto.__version__)"), - ("sh", "-c", "rst2html.py --version | grep 'Docutils 0.14'"), # 270-gem.txt ("test", "-f", "custom/dependencies/270-gem.txt"), - ("aloha_world",), + ("hello-world",), + ) + if float(sub_env["ODOO_MINOR"]) < 14: + self.compose_test( + dependencies_dir, + sub_env, + # For odoo versions < 14.0 we make sure we have a patched Werkzeug version + ( + "bash", + "-xc", + ( + 'test "$(python -c "import werkzeug; ' + 'print(werkzeug.__version__)")" == 0.14.1' + ), + ), + ) + + def test_dependencies_lt_16(self): + """Test dependencies installation for versions < 16""" + self._check_dependencies("dependencies", {"16.0", "17.0", "18.0", "19.0"}) + + def test_dependencies_ge_16(self): + """Test dependencies installation for versions >= 16""" + self._check_dependencies( + "dependencies_ge_16", {"11.0", "12.0", "13.0", "14.0", "15.0"} + ) + + def test_dependencies_base_search_fuzzy(self): + """Test dependencies installation.""" + dependencies_dir = join(SCAFFOLDINGS_DIR, "dependencies_base_search_fuzzy") + # TODO: Remove 19.0 from the matrix skip when 'base_search_fuzzy' + # is available for that version + for sub_env in matrix(odoo_skip={"19.0"}): + self.compose_test( + dependencies_dir, + sub_env, + # It should have base_search_fuzzy available + ("test", "-d", "custom/src/server-tools/base_search_fuzzy"), ) - @unittest.skipUnless( - MAIN_SCAFFOLDING_VERSION in ODOO_VERSIONS, - "Main scaffolding version is not being tested") - def test_main_scaffolding(self): - """Test the official scaffolding.""" - with tempfile.TemporaryDirectory() as tmpdirname: - # Clone main scaffolding - self.popen( - ("git", "clone", "--depth", "1", - "https://github.com/Tecnativa/doodba-scaffolding.git"), - cwd=tmpdirname, + def test_modified_uids(self): + """tests if we can build an image with a custom uid and gid of odoo""" + for expected_uid, expected_gid, uids_dir in [ + (1001, 1002, join(SCAFFOLDINGS_DIR, "uids_1001")), + (998, 998, join(SCAFFOLDINGS_DIR, "uids_998")), + ]: + for sub_env in matrix(): + self.compose_test( + uids_dir, + sub_env, + # verify that odoo user has the given ids + ("bash", "-xc", 'test "$(id -u)" == "%s"' % expected_uid), + ("bash", "-xc", 'test "$(id -g)" == "%s"' % expected_gid), + ("bash", "-xc", 'test "$(id -u -n)" == "odoo"'), + # all those directories need to belong to odoo (user or group odoo) + ( + "bash", + "-xc", + 'test "$(stat -c \'%U:%G\' /var/lib/odoo)" == "odoo:odoo"', + ), + ( + "bash", + "-xc", + 'test "$(stat -c \'%U:%G\' /opt/odoo/auto/addons)" == "root:odoo"', + ), + ( + "bash", + "-xc", + 'test "$(stat -c \'%U:%G\' /opt/odoo/custom/src)" == "root:odoo"', + ), + ) + + def test_uids_mac_os(self): + """tests if we can build an image with a custom uid and gid of odoo""" + uids_dir = join(SCAFFOLDINGS_DIR, "uids_mac_os") + for sub_env in matrix(): + self.compose_test( + uids_dir, + sub_env, + # verify that odoo user has the given ids + ("bash", "-c", 'test "$(id -u)" == "501"'), + ("bash", "-c", 'test "$(id -g)" == "20"'), + ("bash", "-c", 'test "$(id -u -n)" == "odoo"'), + # all those directories need to belong to odoo (user or group odoo/dialout) + ( + "bash", + "-c", + 'test "$(stat -c \'%U:%g\' /var/lib/odoo)" == "odoo:20"', + ), + ( + "bash", + "-c", + 'test "$(stat -c \'%U:%g\' /opt/odoo/auto/addons)" == "root:20"', + ), + ( + "bash", + "-c", + 'test "$(stat -c \'%U:%g\' /opt/odoo/custom/src)" == "root:20"', + ), ) - # Create inverseproxy_shared network - self.popen( - ("docker", "network", "create", "inverseproxy_shared") + + def test_default_uids(self): + uids_dir = join(SCAFFOLDINGS_DIR, "uids_default") + for sub_env in matrix(): + self.compose_test( + uids_dir, + sub_env, + # verify that odoo user has the given ids + ("bash", "-xc", 'test "$(id -u)" == "1000"'), + ("bash", "-xc", 'test "$(id -g)" == "1000"'), + ("bash", "-xc", 'test "$(id -u -n)" == "odoo"'), + # all those directories need to belong to odoo (user or group odoo) + ( + "bash", + "-xc", + 'test "$(stat -c \'%U:%G\' /var/lib/odoo)" == "odoo:odoo"', + ), + ( + "bash", + "-xc", + 'test "$(stat -c \'%U:%G\' /opt/odoo/auto/addons)" == "root:odoo"', + ), + ( + "bash", + "-xc", + 'test "$(stat -c \'%U:%G\' /opt/odoo/custom/src)" == "root:odoo"', + ), ) - tmpdirname = join(tmpdirname, "doodba") - # Special env keys for setup-devel - pwdata = getpwnam(environ["USER"]) - setup_env = { - "COMPOSE_FILE": "setup-devel.yaml", - # Avoid unlink permission errors - "UID": str(pwdata.pw_uid), - "GID": str(pwdata.pw_gid), - } - # TODO Test all supported versions - for sub_env in matrix(odoo={"10.0"}): - # Setup the devel environment - self.compose_test(tmpdirname, dict(sub_env, **setup_env), ()) - # Travis seems to have a different UID than 1000 - if environ.get("TRAVIS"): - self.popen( - ("sudo", "chown", "1000:1000", - join(tmpdirname, "odoo", "auto", "addons")), + + @unittest.skipIf( + not GEIOP_CREDENTIALS_PROVIDED, "GeoIP credentials missing in environment" + ) + def test_geoip(self): + for geoip_dir in ( + join(SCAFFOLDINGS_DIR, "geoip"), + join(SCAFFOLDINGS_DIR, "geoip_devel"), + ): + for sub_env in matrix(): + if float(sub_env.get("ODOO_MINOR")) < 17.0: + # in Odoo versions lower than 17.0 we have only one GeoIP database config parameter + expected_geoip_config_lines = ( + "geoip_database = /opt/odoo/auto/geoip/GeoLite2-City.mmdb", ) - # Test all 3 official environments - for dcfile in ("devel", "test", "prod"): - sub_env["COMPOSE_FILE"] = "{}.yaml".format(dcfile) - self.compose_test( - tmpdirname, sub_env, - # ``odoo`` command works - ("odoo", "--version"), + else: + # starting with Odoo 17.0 we expect GeoIP city db and country db to be configured + expected_geoip_config_lines = ( + "geoip_city_db = /opt/odoo/auto/geoip/GeoLite2-City.mmdb", + "geoip_country_db = /opt/odoo/auto/geoip/GeoLite2-Country.mmdb", ) - # Restore owner in Travis so directory can be removed - if environ.get("TRAVIS"): - self.popen( - ("sudo", "chown", "-R", "{0}:{0}".format(getlogin()), - join(tmpdirname, "odoo", "auto", "addons")), + test_config_lines = ( + ( + "grep", + "-R", + line, + "/opt/odoo/auto/odoo.conf", ) + for line in expected_geoip_config_lines + ) + self.compose_test( + geoip_dir, + dict( + sub_env, + UID=str(os.getuid()), + GID=str(os.getgid()), + ), + # verify that geoipupdate works after waiting for entrypoint to finish its update + ( + "bash", + "-c", + "timeout 60s bash -c 'while (ls -l /proc/*/exe 2>&1 | grep geoipupdate); do sleep 1; done' &&" + " geoipupdate", + ), + # verify that geoip database exists after entrypoint finished its update + # using ls and /proc because ps is missing in image for 13.0 + ( + "bash", + "-c", + "timeout 60s bash -c 'while (ls -l /proc/*/exe 2>&1 | grep geoipupdate); do sleep 1; done' &&" + " test -e /opt/odoo/auto/geoip/GeoLite2-City.mmdb", + ), + # verify that geoip database is configured + *test_config_lines, + ) + + def test_postgres_client_version(self): + postgres_client_version_dir = join(SCAFFOLDINGS_DIR, "postgres_client_version") + for sub_env in matrix(): + self.compose_test( + postgres_client_version_dir, + sub_env, + ("psql", "--version"), + # verify that psql --version is as expected + ( + "bash", + "-c", + '[[ "$(psql --version)" == "psql (PostgreSQL) %s."* ]]' + % sub_env["DB_VERSION"], + ), + ("pg_dump", "--version"), + # verify that pg_dump --version is as expected + ( + "bash", + "-c", + '[[ "$(pg_dump --version)" == "pg_dump (PostgreSQL) %s."* ]]' + % sub_env["DB_VERSION"], + ), + ("pg_restore", "--version"), + # verify that pg_restore --version is as expected + ( + "bash", + "-c", + '[[ "$(pg_restore --version)" == "pg_restore (PostgreSQL) %s."* ]]' + % sub_env["DB_VERSION"], + ), + ) + + def test_symlinks(self): + symlink_dir = join(SCAFFOLDINGS_DIR, "symlinks") + for sub_env in matrix(): + self.compose_test( + symlink_dir, + sub_env, + # there should be no addon for broken symlinks + ("test", "!", "-e", "/opt/odoo/auto/addons/broken_addon_link"), + # there should be an addon for working symlinks + ("test", "-e", "/opt/odoo/auto/addons/addon_alias"), + # and the addon should have a manifest (this addon link would probably not work in odoo, + # we are just testing filesystem here) + ( + "test", + "-e", + "/opt/odoo/auto/addons/addon_alias/__manifest__.py", + "-o", + "-e", + "/opt/odoo/auto/addons/addon_alias/__openerp__.py", + ), + # verify that symlinking outside the src directory doesn't enable changing permission of important stuff + ( + "bash", + "-c", + '[[ "$(stat -c %U:%G /bin/date)" == "root:root" ]]', + ), + # verify that everything in src dir (except symlinks) is accessible by odoo + ( + "bash", + "-c", + "files=$(find /opt/odoo/custom/src -not -group odoo -and -not -type l " + " | wc -l) &&" + " [[ $files == 0 ]]", + ), + ) + + def test_repo_merge(self): + symlink_dir = join(SCAFFOLDINGS_DIR, "repo_merge") + for sub_env in matrix(): + self.compose_test( + symlink_dir, + sub_env, + ( + "git", + "--git-dir=/opt/odoo/custom/src/odoo/.git", + "--no-pager", + "log", + "-n", + "2", + ), + # make sure the git log contains a merge commit signed by $GIT_AUTHOR_NAME (otherwise ff was enabled + # and we did not test the merge commits) + ( + "bash", + "-c", + "git --git-dir=/opt/odoo/custom/src/odoo/.git log -n 1" + " | grep 'docker-odoo '", + ), + ) + + def test_repo_merge_aggregate_permissions(self): + symlink_dir = join(SCAFFOLDINGS_DIR, "repo_merge") + for sub_env in matrix(): + self.compose_test( + symlink_dir, + dict( + sub_env, + COMPOSE_FILE="setup-devel.yaml", + UID=str(os.getuid()), + GID=str(os.getgid()), + ), + # create a fake odoo git repo to ensure a merge commit is created + ("/opt/odoo/custom/build.d/099-create-fake-odoo",), + # autoaggregate as odoo:odoo to check if merges also work + ("autoaggregate",), + ( + "git", + "--git-dir=/opt/odoo/custom/src/odoo/.git", + "--no-pager", + "log", + "-n", + "2", + ), + # make sure the git log contains a merge commit signed by $GIT_AUTHOR_NAME (otherwise ff was enabled + # and we did not test the merge commits) + ( + "bash", + "-c", + "git --git-dir=/opt/odoo/custom/src/odoo/.git log -n 1" + " | grep 'docker-odoo '", + ), + ) + + def test_aggregate_permissions(self): + symlink_dir = join(SCAFFOLDINGS_DIR, "aggregate_permissions") + for sub_env in matrix(): + self.compose_test( + symlink_dir, + dict(sub_env, UID=str(os.getuid()), GID=str(os.getgid())), + ("autoaggregate",), + # test that permissions are set in a way that enables a second autoaggregation after the first one + # e.g. when used in dev we update the source code sometimes/daily + ("autoaggregate",), + ) + + def test_entrypoint_python(self): + symlink_dir = join(SCAFFOLDINGS_DIR, "entrypoint") + for sub_env in matrix(): + self.compose_test( + symlink_dir, + dict(sub_env, UID=str(os.getuid()), GID=str(os.getgid())), + # we verify that customizing entrypoint with python files work by writing to + # /tmp/customize_entrypoint.mark.txt with 60-customize_entrypoint.py + ( + "cat", + "/tmp/customize_entrypoint.mark.txt", + ), + ) + + def test_screencasts(self): + test_artifacts_dir = join(SCAFFOLDINGS_DIR, "test_artifacts") + for sub_env in matrix(odoo_skip={"11.0", "12.0", "13.0", "14.0"}): + self.compose_test( + test_artifacts_dir, + dict(sub_env, UID=str(os.getuid()), GID=str(os.getgid())), + # remove artifacts from previous tests (ignores .gitkeep) + ( + "find", + "/opt/odoo/auto/test-artifacts", + "-type", + "f", + "!", + "-name", + ".gitkeep", + "-exec", + "rm", + "-v", + "{}", + ";", + ), + # install odoo base module + ( + "odoo", + "-i", + "base", + "--stop-after-init", + ), + # run odoo test for screencast + ( + "odoo", + "--test-tags", + ".test_screencasts", + "--stop-after-init", + ), + # verify screencast is saved in container + ( + "grep", + "-Rl", + ".", + "/opt/odoo/auto/test-artifacts", + ), + ) if __name__ == "__main__": diff --git a/tests/scaffoldings/addons_env/Dockerfile b/tests/scaffoldings/addons_env/Dockerfile new file mode 100644 index 00000000..4916c47a --- /dev/null +++ b/tests/scaffoldings/addons_env/Dockerfile @@ -0,0 +1,2 @@ +ARG ODOO_VERSION +FROM tecnativa/doodba:${ODOO_VERSION}-onbuild diff --git a/tests/scaffoldings/addons_env/custom/src/addons.yaml b/tests/scaffoldings/addons_env/custom/src/addons.yaml new file mode 100644 index 00000000..50e07c04 --- /dev/null +++ b/tests/scaffoldings/addons_env/custom/src/addons.yaml @@ -0,0 +1,14 @@ +server-tools: + - module_auto_update +--- +ENV: + DEFAULT_REPO_PATTERN_ODOO: https://github.com/OCA/OpenUpgrade.git +odoo/addons: + - crm + - sale +--- +ENV: + DEFAULT_REPO_PATTERN: https://github.com/itpp-labs/{}.git + ODOO_VERSION: 554222498d5101ef59fc4d3e1059e2b407dffd6f +misc-addons: + - web_debranding diff --git a/tests/scaffoldings/addons_env/docker-compose.yaml b/tests/scaffoldings/addons_env/docker-compose.yaml new file mode 100644 index 00000000..e75ddf87 --- /dev/null +++ b/tests/scaffoldings/addons_env/docker-compose.yaml @@ -0,0 +1,28 @@ +services: + odoo: + build: + context: ./ + args: + COMPILE: "false" + ODOO_VERSION: $ODOO_MINOR + WITHOUT_DEMO: "false" + tty: true + depends_on: + - db + environment: + PYTHONOPTIMIZE: "" + UNACCENT: "false" + volumes: + - filestore:/var/lib/odoo + + db: + image: postgres:${DB_VERSION}-alpine + environment: + POSTGRES_USER: odoo + POSTGRES_PASSWORD: odoopassword + volumes: + - db:/var/lib/postgresql/data + +volumes: + db: + filestore: diff --git a/tests/scaffoldings/addons_env_double/Dockerfile b/tests/scaffoldings/addons_env_double/Dockerfile new file mode 100644 index 00000000..4916c47a --- /dev/null +++ b/tests/scaffoldings/addons_env_double/Dockerfile @@ -0,0 +1,2 @@ +ARG ODOO_VERSION +FROM tecnativa/doodba:${ODOO_VERSION}-onbuild diff --git a/tests/scaffoldings/addons_env_double/custom/src/addons.yaml b/tests/scaffoldings/addons_env_double/custom/src/addons.yaml new file mode 100644 index 00000000..226028fc --- /dev/null +++ b/tests/scaffoldings/addons_env_double/custom/src/addons.yaml @@ -0,0 +1,12 @@ +--- +ONLY: + DOODBA_ENVIRONMENT: + - test +rma-old: # rma should have version 12.0.1.6.1 + - rma +--- +ONLY: + DOODBA_ENVIRONMENT: + - prod +rma-new: # rma should have version 12.0.2.0.0 + - rma diff --git a/tests/scaffoldings/addons_env_double/custom/src/repos.yaml b/tests/scaffoldings/addons_env_double/custom/src/repos.yaml new file mode 100644 index 00000000..e3c00dac --- /dev/null +++ b/tests/scaffoldings/addons_env_double/custom/src/repos.yaml @@ -0,0 +1,25 @@ +# Odoo is always required +./odoo: + defaults: + # Shallow repositores are faster & thinner + depth: $DEPTH_DEFAULT + remotes: + ocb: https://github.com/OCA/OCB.git + odoo: https://github.com/odoo/odoo.git + target: ocb $ODOO_VERSION + merges: + - ocb $ODOO_VERSION + +rma-old: + remotes: + origin: https://github.com/OCA/rma.git + target: origin _merged_branch + merges: + - origin 242b7e21a174e48f713459f836794560e68290de # rma v12.0.1.6.1 + +rma-new: + remotes: + origin: https://github.com/OCA/rma.git + target: origin _merged_branch + merges: + - origin 96d2081987292ae02efda9826cbe5ba1ad84d6c3 # rma v12.0.2.0.0 diff --git a/tests/scaffoldings/addons_env_double/docker-compose.yaml b/tests/scaffoldings/addons_env_double/docker-compose.yaml new file mode 100644 index 00000000..ff30cf7e --- /dev/null +++ b/tests/scaffoldings/addons_env_double/docker-compose.yaml @@ -0,0 +1,29 @@ +services: + odoo: + build: + context: ./ + args: + COMPILE: "false" + ODOO_VERSION: $ODOO_MINOR + WITHOUT_DEMO: "false" + tty: true + depends_on: + - db + environment: + DOODBA_ENVIRONMENT: "$DOODBA_ENVIRONMENT" + PYTHONOPTIMIZE: "" + UNACCENT: "false" + volumes: + - filestore:/var/lib/odoo + + db: + image: postgres:${DB_VERSION}-alpine + environment: + POSTGRES_USER: odoo + POSTGRES_PASSWORD: odoopassword + volumes: + - db:/var/lib/postgresql/data + +volumes: + db: + filestore: diff --git a/tests/scaffoldings/addons_env_ou/Dockerfile b/tests/scaffoldings/addons_env_ou/Dockerfile new file mode 100644 index 00000000..4916c47a --- /dev/null +++ b/tests/scaffoldings/addons_env_ou/Dockerfile @@ -0,0 +1,2 @@ +ARG ODOO_VERSION +FROM tecnativa/doodba:${ODOO_VERSION}-onbuild diff --git a/tests/scaffoldings/addons_env_ou/custom/src/addons.yaml b/tests/scaffoldings/addons_env_ou/custom/src/addons.yaml new file mode 100644 index 00000000..874250c3 --- /dev/null +++ b/tests/scaffoldings/addons_env_ou/custom/src/addons.yaml @@ -0,0 +1,16 @@ +server-tools: + - module_auto_update +OpenUpgrade: + - openupgrade_scripts +--- +ENV: + DEFAULT_REPO_PATTERN_ODOO: https://github.com/OCA/OCB.git +odoo/addons: + - crm + - sale +--- +ENV: + DEFAULT_REPO_PATTERN: https://github.com/itpp-labs/{}.git + ODOO_VERSION: 554222498d5101ef59fc4d3e1059e2b407dffd6f +misc-addons: + - web_debranding diff --git a/tests/scaffoldings/addons_env_ou/docker-compose.yaml b/tests/scaffoldings/addons_env_ou/docker-compose.yaml new file mode 100644 index 00000000..e75ddf87 --- /dev/null +++ b/tests/scaffoldings/addons_env_ou/docker-compose.yaml @@ -0,0 +1,28 @@ +services: + odoo: + build: + context: ./ + args: + COMPILE: "false" + ODOO_VERSION: $ODOO_MINOR + WITHOUT_DEMO: "false" + tty: true + depends_on: + - db + environment: + PYTHONOPTIMIZE: "" + UNACCENT: "false" + volumes: + - filestore:/var/lib/odoo + + db: + image: postgres:${DB_VERSION}-alpine + environment: + POSTGRES_USER: odoo + POSTGRES_PASSWORD: odoopassword + volumes: + - db:/var/lib/postgresql/data + +volumes: + db: + filestore: diff --git a/tests/scaffoldings/aggregate_permissions/.dockerignore b/tests/scaffoldings/aggregate_permissions/.dockerignore new file mode 100644 index 00000000..a0d46fd2 --- /dev/null +++ b/tests/scaffoldings/aggregate_permissions/.dockerignore @@ -0,0 +1 @@ +custom/src/odoo diff --git a/tests/scaffoldings/aggregate_permissions/.gitignore b/tests/scaffoldings/aggregate_permissions/.gitignore new file mode 100644 index 00000000..a0d46fd2 --- /dev/null +++ b/tests/scaffoldings/aggregate_permissions/.gitignore @@ -0,0 +1 @@ +custom/src/odoo diff --git a/tests/scaffoldings/aggregate_permissions/Dockerfile b/tests/scaffoldings/aggregate_permissions/Dockerfile new file mode 100644 index 00000000..4916c47a --- /dev/null +++ b/tests/scaffoldings/aggregate_permissions/Dockerfile @@ -0,0 +1,2 @@ +ARG ODOO_VERSION +FROM tecnativa/doodba:${ODOO_VERSION}-onbuild diff --git a/tests/scaffoldings/dotd/custom/src/dummy_repo/dummy_addon/__init__.py b/tests/scaffoldings/aggregate_permissions/custom/src/addons.yaml similarity index 100% rename from tests/scaffoldings/dotd/custom/src/dummy_repo/dummy_addon/__init__.py rename to tests/scaffoldings/aggregate_permissions/custom/src/addons.yaml diff --git a/tests/scaffoldings/aggregate_permissions/docker-compose.yaml b/tests/scaffoldings/aggregate_permissions/docker-compose.yaml new file mode 100644 index 00000000..fd52ee3b --- /dev/null +++ b/tests/scaffoldings/aggregate_permissions/docker-compose.yaml @@ -0,0 +1,24 @@ +services: + odoo: + build: + context: ./ + args: + AGGREGATE: "false" + CLEAN: "false" + COMPILE: "false" + ODOO_VERSION: $ODOO_MINOR + PIP_INSTALL_ODOO: "false" + environment: + PYTHONOPTIMIZE: "" + UNACCENT: "false" + UID: "${UID:-1000}" + GID: "${GID:-1000}" + UMASK: "$UMASK" + user: root + entrypoint: "" # we are calling autoaggregate inside the tests + volumes: + - ./custom/src/:/opt/odoo/custom/src:rw,z + - filestore:/var/lib/odoo + +volumes: + filestore: diff --git a/tests/scaffoldings/dependencies/custom/build.d/150-conditional-ruby b/tests/scaffoldings/dependencies/custom/build.d/150-conditional-ruby new file mode 100755 index 00000000..e9959230 --- /dev/null +++ b/tests/scaffoldings/dependencies/custom/build.d/150-conditional-ruby @@ -0,0 +1,14 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +"""Add ruby as a conditional dependency.""" + +import os + +from doodbalib import ODOO_VERSION + +if float(ODOO_VERSION) >= 13: + # These Doodba versions still can use the ruby gem autoinstaller, but + # need ruby to be manually installed because it is not in the base image + # by default (it was until Odoo 12.0) + with open("/opt/odoo/custom/dependencies/000-apt-ruby.txt", "w") as fd: + fd.writelines(["ruby"]) diff --git a/tests/scaffoldings/dependencies/custom/dependencies/200-pip-without-ext b/tests/scaffoldings/dependencies/custom/dependencies/200-pip-without-ext index 5b9322ed..86ae918c 100644 --- a/tests/scaffoldings/dependencies/custom/dependencies/200-pip-without-ext +++ b/tests/scaffoldings/dependencies/custom/dependencies/200-pip-without-ext @@ -1,4 +1,2 @@ # Compiled locally, which would fail if `apt_build.txt` fails pycrypto==2.6.1 --no-binary :all: -# Odoo pins docutils==0.12, so let's check it gets upgraded -docutils==0.14 diff --git a/tests/scaffoldings/dependencies/custom/dependencies/270-gem.txt b/tests/scaffoldings/dependencies/custom/dependencies/270-gem.txt index fd48e218..ce51ab87 100644 --- a/tests/scaffoldings/dependencies/custom/dependencies/270-gem.txt +++ b/tests/scaffoldings/dependencies/custom/dependencies/270-gem.txt @@ -1,2 +1,2 @@ # This line should be ignored -aloha_world +hello-world diff --git a/tests/scaffoldings/dependencies/custom/dependencies/apt_build.txt b/tests/scaffoldings/dependencies/custom/dependencies/apt_build.txt index a06f5b92..0b02fdcb 100644 --- a/tests/scaffoldings/dependencies/custom/dependencies/apt_build.txt +++ b/tests/scaffoldings/dependencies/custom/dependencies/apt_build.txt @@ -1,5 +1,7 @@ # This installs gcc among other things build-essential -# This is the basic need to build any python extensions +# This is the basic need to build any python extensions in v11- python-dev python3-dev +# Just to test it is removed later +openssh-server diff --git a/tests/scaffoldings/dependencies/custom/src/repos.yaml b/tests/scaffoldings/dependencies/custom/src/repos.yaml deleted file mode 100644 index 1eddc934..00000000 --- a/tests/scaffoldings/dependencies/custom/src/repos.yaml +++ /dev/null @@ -1,12 +0,0 @@ -# Odoo is always required -./odoo: - defaults: - # Shallow repositores are faster & thinner - depth: $DEPTH_DEFAULT - remotes: - ocb: https://github.com/OCA/OCB.git - odoo: https://github.com/odoo/odoo.git - target: - ocb $ODOO_VERSION - merges: - - ocb $ODOO_VERSION diff --git a/tests/scaffoldings/dependencies/docker-compose.yaml b/tests/scaffoldings/dependencies/docker-compose.yaml index 5cb154cd..e75ddf87 100644 --- a/tests/scaffoldings/dependencies/docker-compose.yaml +++ b/tests/scaffoldings/dependencies/docker-compose.yaml @@ -1,4 +1,3 @@ -version: "2.1" services: odoo: build: @@ -14,7 +13,7 @@ services: PYTHONOPTIMIZE: "" UNACCENT: "false" volumes: - - filestore:/var/lib/odoo:z + - filestore:/var/lib/odoo db: image: postgres:${DB_VERSION}-alpine @@ -22,7 +21,7 @@ services: POSTGRES_USER: odoo POSTGRES_PASSWORD: odoopassword volumes: - - db:/var/lib/postgresql/data:z + - db:/var/lib/postgresql/data volumes: db: diff --git a/tests/scaffoldings/dependencies_base_search_fuzzy/Dockerfile b/tests/scaffoldings/dependencies_base_search_fuzzy/Dockerfile new file mode 100644 index 00000000..4916c47a --- /dev/null +++ b/tests/scaffoldings/dependencies_base_search_fuzzy/Dockerfile @@ -0,0 +1,2 @@ +ARG ODOO_VERSION +FROM tecnativa/doodba:${ODOO_VERSION}-onbuild diff --git a/tests/scaffoldings/dependencies_base_search_fuzzy/custom/src/addons.yaml b/tests/scaffoldings/dependencies_base_search_fuzzy/custom/src/addons.yaml new file mode 100644 index 00000000..1c8ff89e --- /dev/null +++ b/tests/scaffoldings/dependencies_base_search_fuzzy/custom/src/addons.yaml @@ -0,0 +1,2 @@ +server-tools: + - base_search_fuzzy diff --git a/tests/scaffoldings/dependencies_base_search_fuzzy/docker-compose.yaml b/tests/scaffoldings/dependencies_base_search_fuzzy/docker-compose.yaml new file mode 100644 index 00000000..e75ddf87 --- /dev/null +++ b/tests/scaffoldings/dependencies_base_search_fuzzy/docker-compose.yaml @@ -0,0 +1,28 @@ +services: + odoo: + build: + context: ./ + args: + COMPILE: "false" + ODOO_VERSION: $ODOO_MINOR + WITHOUT_DEMO: "false" + tty: true + depends_on: + - db + environment: + PYTHONOPTIMIZE: "" + UNACCENT: "false" + volumes: + - filestore:/var/lib/odoo + + db: + image: postgres:${DB_VERSION}-alpine + environment: + POSTGRES_USER: odoo + POSTGRES_PASSWORD: odoopassword + volumes: + - db:/var/lib/postgresql/data + +volumes: + db: + filestore: diff --git a/tests/scaffoldings/dependencies_ge_16/Dockerfile b/tests/scaffoldings/dependencies_ge_16/Dockerfile new file mode 100644 index 00000000..4916c47a --- /dev/null +++ b/tests/scaffoldings/dependencies_ge_16/Dockerfile @@ -0,0 +1,2 @@ +ARG ODOO_VERSION +FROM tecnativa/doodba:${ODOO_VERSION}-onbuild diff --git a/tests/scaffoldings/dependencies_ge_16/custom/build.d/150-conditional-ruby b/tests/scaffoldings/dependencies_ge_16/custom/build.d/150-conditional-ruby new file mode 100755 index 00000000..e9959230 --- /dev/null +++ b/tests/scaffoldings/dependencies_ge_16/custom/build.d/150-conditional-ruby @@ -0,0 +1,14 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +"""Add ruby as a conditional dependency.""" + +import os + +from doodbalib import ODOO_VERSION + +if float(ODOO_VERSION) >= 13: + # These Doodba versions still can use the ruby gem autoinstaller, but + # need ruby to be manually installed because it is not in the base image + # by default (it was until Odoo 12.0) + with open("/opt/odoo/custom/dependencies/000-apt-ruby.txt", "w") as fd: + fd.writelines(["ruby"]) diff --git a/tests/scaffoldings/dependencies_ge_16/custom/dependencies/070-apt-bc.txt b/tests/scaffoldings/dependencies_ge_16/custom/dependencies/070-apt-bc.txt new file mode 100644 index 00000000..4aef3ad0 --- /dev/null +++ b/tests/scaffoldings/dependencies_ge_16/custom/dependencies/070-apt-bc.txt @@ -0,0 +1,2 @@ +# This line should be ignored +bc diff --git a/tests/scaffoldings/dependencies_ge_16/custom/dependencies/150-npm-aloha_world-install.txt b/tests/scaffoldings/dependencies_ge_16/custom/dependencies/150-npm-aloha_world-install.txt new file mode 100644 index 00000000..d822001c --- /dev/null +++ b/tests/scaffoldings/dependencies_ge_16/custom/dependencies/150-npm-aloha_world-install.txt @@ -0,0 +1,2 @@ +# This line should be ignored +test-npm-install diff --git a/tests/scaffoldings/dependencies_ge_16/custom/dependencies/200-pip-without-ext b/tests/scaffoldings/dependencies_ge_16/custom/dependencies/200-pip-without-ext new file mode 100644 index 00000000..86ae918c --- /dev/null +++ b/tests/scaffoldings/dependencies_ge_16/custom/dependencies/200-pip-without-ext @@ -0,0 +1,2 @@ +# Compiled locally, which would fail if `apt_build.txt` fails +pycrypto==2.6.1 --no-binary :all: diff --git a/tests/scaffoldings/dependencies_ge_16/custom/dependencies/270-gem.txt b/tests/scaffoldings/dependencies_ge_16/custom/dependencies/270-gem.txt new file mode 100644 index 00000000..ce51ab87 --- /dev/null +++ b/tests/scaffoldings/dependencies_ge_16/custom/dependencies/270-gem.txt @@ -0,0 +1,2 @@ +# This line should be ignored +hello-world diff --git a/tests/scaffoldings/dependencies_ge_16/custom/dependencies/apt-without-sequence.txt b/tests/scaffoldings/dependencies_ge_16/custom/dependencies/apt-without-sequence.txt new file mode 100644 index 00000000..2100ebc6 --- /dev/null +++ b/tests/scaffoldings/dependencies_ge_16/custom/dependencies/apt-without-sequence.txt @@ -0,0 +1,2 @@ +# This package WON'T be installed +busybox diff --git a/tests/scaffoldings/dependencies_ge_16/custom/dependencies/apt_build.txt b/tests/scaffoldings/dependencies_ge_16/custom/dependencies/apt_build.txt new file mode 100644 index 00000000..2068bd87 --- /dev/null +++ b/tests/scaffoldings/dependencies_ge_16/custom/dependencies/apt_build.txt @@ -0,0 +1,6 @@ +# This installs gcc among other things +build-essential +# This is the basic need to build any python extensions in v11- +python3-dev +# Just to test it is removed later +openssh-server diff --git a/tests/scaffoldings/dotd/custom/src/dummy_repo/product/__init__.py b/tests/scaffoldings/dependencies_ge_16/custom/src/addons.yaml similarity index 100% rename from tests/scaffoldings/dotd/custom/src/dummy_repo/product/__init__.py rename to tests/scaffoldings/dependencies_ge_16/custom/src/addons.yaml diff --git a/tests/scaffoldings/dependencies_ge_16/docker-compose.yaml b/tests/scaffoldings/dependencies_ge_16/docker-compose.yaml new file mode 100644 index 00000000..e75ddf87 --- /dev/null +++ b/tests/scaffoldings/dependencies_ge_16/docker-compose.yaml @@ -0,0 +1,28 @@ +services: + odoo: + build: + context: ./ + args: + COMPILE: "false" + ODOO_VERSION: $ODOO_MINOR + WITHOUT_DEMO: "false" + tty: true + depends_on: + - db + environment: + PYTHONOPTIMIZE: "" + UNACCENT: "false" + volumes: + - filestore:/var/lib/odoo + + db: + image: postgres:${DB_VERSION}-alpine + environment: + POSTGRES_USER: odoo + POSTGRES_PASSWORD: odoopassword + volumes: + - db:/var/lib/postgresql/data + +volumes: + db: + filestore: diff --git a/tests/scaffoldings/dotd/custom/build.d/201-assert-dependencies b/tests/scaffoldings/dotd/custom/build.d/201-assert-dependencies index c4a56a52..04d2692d 100755 --- a/tests/scaffoldings/dotd/custom/build.d/201-assert-dependencies +++ b/tests/scaffoldings/dotd/custom/build.d/201-assert-dependencies @@ -2,6 +2,6 @@ # Dependencies are processed at step 200 set -ex which busybox -aloha_world +hello-world node -e "require('test-npm-install')" -python -c "import cfssl, Crypto" +python -c "import numpy, Crypto" diff --git a/tests/scaffoldings/dotd/custom/dependencies/apt.txt b/tests/scaffoldings/dotd/custom/dependencies/apt.txt index ce054159..5b76ceb3 100644 --- a/tests/scaffoldings/dotd/custom/dependencies/apt.txt +++ b/tests/scaffoldings/dotd/custom/dependencies/apt.txt @@ -1,2 +1,5 @@ # This line should be ignored busybox +ruby +ninja-build +patchelf diff --git a/tests/scaffoldings/dotd/custom/dependencies/apt_build.txt b/tests/scaffoldings/dotd/custom/dependencies/apt_build.txt index a06f5b92..ddb98b39 100644 --- a/tests/scaffoldings/dotd/custom/dependencies/apt_build.txt +++ b/tests/scaffoldings/dotd/custom/dependencies/apt_build.txt @@ -1,5 +1,7 @@ # This installs gcc among other things build-essential -# This is the basic need to build any python extensions +# This is the basic need to build any python extensions on v11- python-dev python3-dev +# Just to test it is removed after building +openssh-server diff --git a/tests/scaffoldings/dotd/custom/dependencies/gem.txt b/tests/scaffoldings/dotd/custom/dependencies/gem.txt index fd48e218..ce51ab87 100644 --- a/tests/scaffoldings/dotd/custom/dependencies/gem.txt +++ b/tests/scaffoldings/dotd/custom/dependencies/gem.txt @@ -1,2 +1,2 @@ # This line should be ignored -aloha_world +hello-world diff --git a/tests/scaffoldings/dotd/custom/dependencies/pip.txt b/tests/scaffoldings/dotd/custom/dependencies/pip.txt index 5b9322ed..e9d91282 100644 --- a/tests/scaffoldings/dotd/custom/dependencies/pip.txt +++ b/tests/scaffoldings/dotd/custom/dependencies/pip.txt @@ -1,4 +1,4 @@ # Compiled locally, which would fail if `apt_build.txt` fails pycrypto==2.6.1 --no-binary :all: -# Odoo pins docutils==0.12, so let's check it gets upgraded -docutils==0.14 +# External dependency files can be included too; example: numpy +-r https://raw.githubusercontent.com/Tecnativa/doodba/6cec8ea6eefa9d8de8cff103cfca6e373f8fe910/tests/scaffoldings/dotd/custom/src/dummy_repo/requirements.txt diff --git a/tests/scaffoldings/dotd/custom/entrypoint.d/check-requirements b/tests/scaffoldings/dotd/custom/entrypoint.d/check-requirements index f71069e8..a2aedbeb 100755 --- a/tests/scaffoldings/dotd/custom/entrypoint.d/check-requirements +++ b/tests/scaffoldings/dotd/custom/entrypoint.d/check-requirements @@ -1,2 +1,3 @@ #!/usr/bin/env python -from cfssl import CFSSL +# -*- coding: utf-8 -*- +import numpy diff --git a/tests/scaffoldings/dotd/custom/src/addons.yaml b/tests/scaffoldings/dotd/custom/src/addons.yaml index f4689cb2..10da6de1 100644 --- a/tests/scaffoldings/dotd/custom/src/addons.yaml +++ b/tests/scaffoldings/dotd/custom/src/addons.yaml @@ -1,8 +1,9 @@ -dummy_repo: +other-doodba/odoo/src/private: - absent_addon - dummy_addon - product - +enterprise: + - make_odoo_rich --- ONLY: PGDATABASE: diff --git a/tests/scaffoldings/dotd/custom/src/dummy_repo/dummy_addon/__manifest__.py b/tests/scaffoldings/dotd/custom/src/dummy_repo/dummy_addon/__manifest__.py deleted file mode 100644 index d7bb944e..00000000 --- a/tests/scaffoldings/dotd/custom/src/dummy_repo/dummy_addon/__manifest__.py +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "dummy_addon", - "installable": True, -} diff --git a/tests/scaffoldings/dotd/custom/src/dummy_repo/dummy_link b/tests/scaffoldings/dotd/custom/src/dummy_repo/dummy_link new file mode 120000 index 00000000..abb95d99 --- /dev/null +++ b/tests/scaffoldings/dotd/custom/src/dummy_repo/dummy_link @@ -0,0 +1 @@ +dummy_addon \ No newline at end of file diff --git a/tests/scaffoldings/dotd/custom/src/dummy_repo/product/__manifest__.py b/tests/scaffoldings/dotd/custom/src/dummy_repo/product/__manifest__.py deleted file mode 100644 index a77ba4fd..00000000 --- a/tests/scaffoldings/dotd/custom/src/dummy_repo/product/__manifest__.py +++ /dev/null @@ -1,3 +0,0 @@ -{ - "name": "dummy_repo/product", -} diff --git a/tests/scaffoldings/dotd/custom/src/dummy_repo/requirements.txt b/tests/scaffoldings/dotd/custom/src/dummy_repo/requirements.txt index 0139cd0a..24ce15ab 100644 --- a/tests/scaffoldings/dotd/custom/src/dummy_repo/requirements.txt +++ b/tests/scaffoldings/dotd/custom/src/dummy_repo/requirements.txt @@ -1 +1 @@ -cfssl +numpy diff --git a/tests/scaffoldings/dotd/custom/src/enterprise/make_odoo_rich/__openerp__.py b/tests/scaffoldings/dotd/custom/src/enterprise/make_odoo_rich/__openerp__.py new file mode 100644 index 00000000..cc1ba263 --- /dev/null +++ b/tests/scaffoldings/dotd/custom/src/enterprise/make_odoo_rich/__openerp__.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- +{"name": "make_odoo_rich", "depends": ["iap"]} diff --git a/tests/scaffoldings/dotd/custom/src/other-doodba/odoo/src/private/dummy_addon/__init__.py b/tests/scaffoldings/dotd/custom/src/other-doodba/odoo/src/private/dummy_addon/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/scaffoldings/dotd/custom/src/other-doodba/odoo/src/private/dummy_addon/__manifest__.py b/tests/scaffoldings/dotd/custom/src/other-doodba/odoo/src/private/dummy_addon/__manifest__.py new file mode 100644 index 00000000..7a4cc997 --- /dev/null +++ b/tests/scaffoldings/dotd/custom/src/other-doodba/odoo/src/private/dummy_addon/__manifest__.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- +{"name": "dummy_addon", "depends": ["web"], "installable": True} diff --git a/tests/scaffoldings/dotd/custom/src/other-doodba/odoo/src/private/product/__init__.py b/tests/scaffoldings/dotd/custom/src/other-doodba/odoo/src/private/product/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/scaffoldings/dotd/custom/src/other-doodba/odoo/src/private/product/__manifest__.py b/tests/scaffoldings/dotd/custom/src/other-doodba/odoo/src/private/product/__manifest__.py new file mode 100644 index 00000000..4e285873 --- /dev/null +++ b/tests/scaffoldings/dotd/custom/src/other-doodba/odoo/src/private/product/__manifest__.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- +{"name": "other-doodba/product"} diff --git a/tests/scaffoldings/dotd/custom/src/other-doodba/odoo/src/private/some_random_evil_file.txt b/tests/scaffoldings/dotd/custom/src/other-doodba/odoo/src/private/some_random_evil_file.txt new file mode 100644 index 00000000..e69de29b diff --git a/tests/scaffoldings/dotd/custom/src/private/disabled_addon/__openerp__.py b/tests/scaffoldings/dotd/custom/src/private/disabled_addon/__openerp__.py index 0776a71a..32114e6b 100644 --- a/tests/scaffoldings/dotd/custom/src/private/disabled_addon/__openerp__.py +++ b/tests/scaffoldings/dotd/custom/src/private/disabled_addon/__openerp__.py @@ -1,4 +1,2 @@ -{ - "name": "disabled_addon", - "installable": False, -} +# -*- coding: utf-8 -*- +{"name": "disabled_addon", "installable": False} diff --git a/tests/scaffoldings/dotd/custom/src/private/private_addon/__openerp__.py b/tests/scaffoldings/dotd/custom/src/private/private_addon/__openerp__.py index 24035e9a..a9c52e7d 100644 --- a/tests/scaffoldings/dotd/custom/src/private/private_addon/__openerp__.py +++ b/tests/scaffoldings/dotd/custom/src/private/private_addon/__openerp__.py @@ -1,3 +1,2 @@ -{ - "name": "private_addon", -} +# -*- coding: utf-8 -*- +{"name": "private_addon", "depends": ["dummy_addon", "website"]} diff --git a/tests/scaffoldings/dotd/custom/src/private/some_random_evil_file.txt b/tests/scaffoldings/dotd/custom/src/private/some_random_evil_file.txt new file mode 100644 index 00000000..e69de29b diff --git a/tests/scaffoldings/dotd/custom/src/repos.yaml b/tests/scaffoldings/dotd/custom/src/repos.yaml deleted file mode 100644 index 1eddc934..00000000 --- a/tests/scaffoldings/dotd/custom/src/repos.yaml +++ /dev/null @@ -1,12 +0,0 @@ -# Odoo is always required -./odoo: - defaults: - # Shallow repositores are faster & thinner - depth: $DEPTH_DEFAULT - remotes: - ocb: https://github.com/OCA/OCB.git - odoo: https://github.com/odoo/odoo.git - target: - ocb $ODOO_VERSION - merges: - - ocb $ODOO_VERSION diff --git a/tests/scaffoldings/dotd/docker-compose.yaml b/tests/scaffoldings/dotd/docker-compose.yaml index 75ebd8d5..06cdb3d5 100644 --- a/tests/scaffoldings/dotd/docker-compose.yaml +++ b/tests/scaffoldings/dotd/docker-compose.yaml @@ -1,10 +1,8 @@ -version: "2.1" services: odoo: build: context: ./ args: - AUTO_REQUIREMENTS: "true" LOG_LEVEL: DEBUG ODOO_VERSION: $ODOO_MINOR tty: true @@ -16,15 +14,15 @@ services: depends_on: - postgresql volumes: - - filestore:/var/lib/odoo:z + - filestore:/var/lib/odoo postgresql: - image: postgres:${DB_VERSION}-alpine + image: tecnativa/postgres-autoconf:${DB_VERSION}-alpine environment: POSTGRES_USER: another_odoo POSTGRES_PASSWORD: anotherodoopassword volumes: - - db:/var/lib/postgresql/data:z + - db:/var/lib/postgresql/data volumes: db: diff --git a/tests/scaffoldings/dotd_ge_16/Dockerfile b/tests/scaffoldings/dotd_ge_16/Dockerfile new file mode 100644 index 00000000..4916c47a --- /dev/null +++ b/tests/scaffoldings/dotd_ge_16/Dockerfile @@ -0,0 +1,2 @@ +ARG ODOO_VERSION +FROM tecnativa/doodba:${ODOO_VERSION}-onbuild diff --git a/tests/scaffoldings/dotd_ge_16/custom/build.d/10-touch-build b/tests/scaffoldings/dotd_ge_16/custom/build.d/10-touch-build new file mode 100755 index 00000000..953a11f0 --- /dev/null +++ b/tests/scaffoldings/dotd_ge_16/custom/build.d/10-touch-build @@ -0,0 +1,3 @@ +#!/bin/bash +set -ex +touch /home/odoo/created-at-build diff --git a/tests/scaffoldings/dotd_ge_16/custom/build.d/100-assert-touched b/tests/scaffoldings/dotd_ge_16/custom/build.d/100-assert-touched new file mode 100755 index 00000000..4f905cdd --- /dev/null +++ b/tests/scaffoldings/dotd_ge_16/custom/build.d/100-assert-touched @@ -0,0 +1,3 @@ +#!/bin/bash +set -ex +test -f /home/odoo/created-at-build diff --git a/tests/scaffoldings/dotd_ge_16/custom/build.d/101-assert-aggregation b/tests/scaffoldings/dotd_ge_16/custom/build.d/101-assert-aggregation new file mode 100755 index 00000000..a8c07a2e --- /dev/null +++ b/tests/scaffoldings/dotd_ge_16/custom/build.d/101-assert-aggregation @@ -0,0 +1,4 @@ +#!/bin/bash +# Git aggregation is performed at step 100 +set -ex +test -d /opt/odoo/custom/src/odoo diff --git a/tests/scaffoldings/dotd_ge_16/custom/build.d/15-broken-link b/tests/scaffoldings/dotd_ge_16/custom/build.d/15-broken-link new file mode 100755 index 00000000..684810f2 --- /dev/null +++ b/tests/scaffoldings/dotd_ge_16/custom/build.d/15-broken-link @@ -0,0 +1,3 @@ +#!/bin/bash +set -ex +ln -s brokenpath auto/addons/dummy_addon diff --git a/tests/scaffoldings/dotd_ge_16/custom/build.d/201-assert-dependencies b/tests/scaffoldings/dotd_ge_16/custom/build.d/201-assert-dependencies new file mode 100755 index 00000000..04d2692d --- /dev/null +++ b/tests/scaffoldings/dotd_ge_16/custom/build.d/201-assert-dependencies @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +# Dependencies are processed at step 200 +set -ex +which busybox +hello-world +node -e "require('test-npm-install')" +python -c "import numpy, Crypto" diff --git a/tests/scaffoldings/dotd_ge_16/custom/conf.d/test-conf b/tests/scaffoldings/dotd_ge_16/custom/conf.d/test-conf new file mode 100644 index 00000000..21c748da --- /dev/null +++ b/tests/scaffoldings/dotd_ge_16/custom/conf.d/test-conf @@ -0,0 +1 @@ +[test-conf] diff --git a/tests/scaffoldings/dotd_ge_16/custom/dependencies/apt.txt b/tests/scaffoldings/dotd_ge_16/custom/dependencies/apt.txt new file mode 100644 index 00000000..5b76ceb3 --- /dev/null +++ b/tests/scaffoldings/dotd_ge_16/custom/dependencies/apt.txt @@ -0,0 +1,5 @@ +# This line should be ignored +busybox +ruby +ninja-build +patchelf diff --git a/tests/scaffoldings/dotd_ge_16/custom/dependencies/apt_build.txt b/tests/scaffoldings/dotd_ge_16/custom/dependencies/apt_build.txt new file mode 100644 index 00000000..b74d8115 --- /dev/null +++ b/tests/scaffoldings/dotd_ge_16/custom/dependencies/apt_build.txt @@ -0,0 +1,6 @@ +# This installs gcc among other things +build-essential +# This is the basic need to build any python extensions on v11- +python3-dev +# Just to test it is removed after building +openssh-server diff --git a/tests/scaffoldings/dotd_ge_16/custom/dependencies/gem.txt b/tests/scaffoldings/dotd_ge_16/custom/dependencies/gem.txt new file mode 100644 index 00000000..ce51ab87 --- /dev/null +++ b/tests/scaffoldings/dotd_ge_16/custom/dependencies/gem.txt @@ -0,0 +1,2 @@ +# This line should be ignored +hello-world diff --git a/tests/scaffoldings/dotd_ge_16/custom/dependencies/npm.txt b/tests/scaffoldings/dotd_ge_16/custom/dependencies/npm.txt new file mode 100644 index 00000000..d822001c --- /dev/null +++ b/tests/scaffoldings/dotd_ge_16/custom/dependencies/npm.txt @@ -0,0 +1,2 @@ +# This line should be ignored +test-npm-install diff --git a/tests/scaffoldings/dotd_ge_16/custom/dependencies/pip.txt b/tests/scaffoldings/dotd_ge_16/custom/dependencies/pip.txt new file mode 100644 index 00000000..e9d91282 --- /dev/null +++ b/tests/scaffoldings/dotd_ge_16/custom/dependencies/pip.txt @@ -0,0 +1,4 @@ +# Compiled locally, which would fail if `apt_build.txt` fails +pycrypto==2.6.1 --no-binary :all: +# External dependency files can be included too; example: numpy +-r https://raw.githubusercontent.com/Tecnativa/doodba/6cec8ea6eefa9d8de8cff103cfca6e373f8fe910/tests/scaffoldings/dotd/custom/src/dummy_repo/requirements.txt diff --git a/tests/scaffoldings/dotd_ge_16/custom/entrypoint.d/check-requirements b/tests/scaffoldings/dotd_ge_16/custom/entrypoint.d/check-requirements new file mode 100755 index 00000000..a2aedbeb --- /dev/null +++ b/tests/scaffoldings/dotd_ge_16/custom/entrypoint.d/check-requirements @@ -0,0 +1,3 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +import numpy diff --git a/tests/scaffoldings/dotd_ge_16/custom/entrypoint.d/pip-install-user b/tests/scaffoldings/dotd_ge_16/custom/entrypoint.d/pip-install-user new file mode 100755 index 00000000..b82411e1 --- /dev/null +++ b/tests/scaffoldings/dotd_ge_16/custom/entrypoint.d/pip-install-user @@ -0,0 +1,8 @@ +#!/bin/bash +set -ex + +# Check that --user installations work +pip install --user pg_activity + +# Binary must be in $PATH +pg_activity --version diff --git a/tests/scaffoldings/dotd_ge_16/custom/entrypoint.d/touch-entrypoint b/tests/scaffoldings/dotd_ge_16/custom/entrypoint.d/touch-entrypoint new file mode 100755 index 00000000..3ce7311b --- /dev/null +++ b/tests/scaffoldings/dotd_ge_16/custom/entrypoint.d/touch-entrypoint @@ -0,0 +1,3 @@ +#!/bin/bash +set -ex +touch /home/odoo/created-at-entrypoint diff --git a/tests/scaffoldings/dotd_ge_16/custom/src/addons.yaml b/tests/scaffoldings/dotd_ge_16/custom/src/addons.yaml new file mode 100644 index 00000000..10da6de1 --- /dev/null +++ b/tests/scaffoldings/dotd_ge_16/custom/src/addons.yaml @@ -0,0 +1,20 @@ +other-doodba/odoo/src/private: + - absent_addon + - dummy_addon + - product +enterprise: + - make_odoo_rich +--- +ONLY: + PGDATABASE: + - limited_core +odoo/addons: + - crm + - sale + +--- +ONLY: + PGDATABASE: + - limited_private + - limited_core +private: [] diff --git a/tests/scaffoldings/dotd_ge_16/custom/src/dummy_repo/dummy_link b/tests/scaffoldings/dotd_ge_16/custom/src/dummy_repo/dummy_link new file mode 120000 index 00000000..abb95d99 --- /dev/null +++ b/tests/scaffoldings/dotd_ge_16/custom/src/dummy_repo/dummy_link @@ -0,0 +1 @@ +dummy_addon \ No newline at end of file diff --git a/tests/scaffoldings/dotd_ge_16/custom/src/dummy_repo/requirements.txt b/tests/scaffoldings/dotd_ge_16/custom/src/dummy_repo/requirements.txt new file mode 100644 index 00000000..24ce15ab --- /dev/null +++ b/tests/scaffoldings/dotd_ge_16/custom/src/dummy_repo/requirements.txt @@ -0,0 +1 @@ +numpy diff --git a/tests/scaffoldings/dotd_ge_16/custom/src/enterprise/make_odoo_rich/__openerp__.py b/tests/scaffoldings/dotd_ge_16/custom/src/enterprise/make_odoo_rich/__openerp__.py new file mode 100644 index 00000000..cc1ba263 --- /dev/null +++ b/tests/scaffoldings/dotd_ge_16/custom/src/enterprise/make_odoo_rich/__openerp__.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- +{"name": "make_odoo_rich", "depends": ["iap"]} diff --git a/tests/scaffoldings/dotd_ge_16/custom/src/other-doodba/odoo/src/private/dummy_addon/__init__.py b/tests/scaffoldings/dotd_ge_16/custom/src/other-doodba/odoo/src/private/dummy_addon/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/scaffoldings/dotd_ge_16/custom/src/other-doodba/odoo/src/private/dummy_addon/__manifest__.py b/tests/scaffoldings/dotd_ge_16/custom/src/other-doodba/odoo/src/private/dummy_addon/__manifest__.py new file mode 100644 index 00000000..7a4cc997 --- /dev/null +++ b/tests/scaffoldings/dotd_ge_16/custom/src/other-doodba/odoo/src/private/dummy_addon/__manifest__.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- +{"name": "dummy_addon", "depends": ["web"], "installable": True} diff --git a/tests/scaffoldings/dotd_ge_16/custom/src/other-doodba/odoo/src/private/product/__init__.py b/tests/scaffoldings/dotd_ge_16/custom/src/other-doodba/odoo/src/private/product/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/scaffoldings/dotd_ge_16/custom/src/other-doodba/odoo/src/private/product/__manifest__.py b/tests/scaffoldings/dotd_ge_16/custom/src/other-doodba/odoo/src/private/product/__manifest__.py new file mode 100644 index 00000000..4e285873 --- /dev/null +++ b/tests/scaffoldings/dotd_ge_16/custom/src/other-doodba/odoo/src/private/product/__manifest__.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- +{"name": "other-doodba/product"} diff --git a/tests/scaffoldings/dotd_ge_16/custom/src/other-doodba/odoo/src/private/some_random_evil_file.txt b/tests/scaffoldings/dotd_ge_16/custom/src/other-doodba/odoo/src/private/some_random_evil_file.txt new file mode 100644 index 00000000..e69de29b diff --git a/tests/scaffoldings/dotd_ge_16/custom/src/private/.empty b/tests/scaffoldings/dotd_ge_16/custom/src/private/.empty new file mode 100644 index 00000000..e69de29b diff --git a/tests/scaffoldings/dotd_ge_16/custom/src/private/disabled_addon/__init__.py b/tests/scaffoldings/dotd_ge_16/custom/src/private/disabled_addon/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/scaffoldings/dotd_ge_16/custom/src/private/disabled_addon/__openerp__.py b/tests/scaffoldings/dotd_ge_16/custom/src/private/disabled_addon/__openerp__.py new file mode 100644 index 00000000..32114e6b --- /dev/null +++ b/tests/scaffoldings/dotd_ge_16/custom/src/private/disabled_addon/__openerp__.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- +{"name": "disabled_addon", "installable": False} diff --git a/tests/scaffoldings/dotd_ge_16/custom/src/private/private_addon/__init__.py b/tests/scaffoldings/dotd_ge_16/custom/src/private/private_addon/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/scaffoldings/dotd_ge_16/custom/src/private/private_addon/__openerp__.py b/tests/scaffoldings/dotd_ge_16/custom/src/private/private_addon/__openerp__.py new file mode 100644 index 00000000..a9c52e7d --- /dev/null +++ b/tests/scaffoldings/dotd_ge_16/custom/src/private/private_addon/__openerp__.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- +{"name": "private_addon", "depends": ["dummy_addon", "website"]} diff --git a/tests/scaffoldings/dotd_ge_16/custom/src/private/some_random_evil_file.txt b/tests/scaffoldings/dotd_ge_16/custom/src/private/some_random_evil_file.txt new file mode 100644 index 00000000..e69de29b diff --git a/tests/scaffoldings/dotd_ge_16/docker-compose.yaml b/tests/scaffoldings/dotd_ge_16/docker-compose.yaml new file mode 100644 index 00000000..06cdb3d5 --- /dev/null +++ b/tests/scaffoldings/dotd_ge_16/docker-compose.yaml @@ -0,0 +1,29 @@ +services: + odoo: + build: + context: ./ + args: + LOG_LEVEL: DEBUG + ODOO_VERSION: $ODOO_MINOR + tty: true + environment: + PGUSER: another_odoo + PGPASSWORD: anotherodoopassword + PGHOST: postgresql + PGDATABASE: ${DBNAME:-prod} + depends_on: + - postgresql + volumes: + - filestore:/var/lib/odoo + + postgresql: + image: tecnativa/postgres-autoconf:${DB_VERSION}-alpine + environment: + POSTGRES_USER: another_odoo + POSTGRES_PASSWORD: anotherodoopassword + volumes: + - db:/var/lib/postgresql/data + +volumes: + db: + filestore: diff --git a/tests/scaffoldings/entrypoint/Dockerfile b/tests/scaffoldings/entrypoint/Dockerfile new file mode 100644 index 00000000..4916c47a --- /dev/null +++ b/tests/scaffoldings/entrypoint/Dockerfile @@ -0,0 +1,2 @@ +ARG ODOO_VERSION +FROM tecnativa/doodba:${ODOO_VERSION}-onbuild diff --git a/tests/scaffoldings/entrypoint/custom/entrypoint.d/60-customize_entrypoint.py b/tests/scaffoldings/entrypoint/custom/entrypoint.d/60-customize_entrypoint.py new file mode 100755 index 00000000..c2054ffa --- /dev/null +++ b/tests/scaffoldings/entrypoint/custom/entrypoint.d/60-customize_entrypoint.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +import doodbalib + +doodbalib.logger.info("custom entrypoint running") +with open("/tmp/customize_entrypoint.mark.txt", "w") as fp: + fp.write("ok\n") +doodbalib.logger.info("custom created /tmp/customize_entrypoint.mark.txt") diff --git a/tests/scaffoldings/entrypoint/custom/src/addons.yaml b/tests/scaffoldings/entrypoint/custom/src/addons.yaml new file mode 100644 index 00000000..e69de29b diff --git a/tests/scaffoldings/entrypoint/docker-compose.yaml b/tests/scaffoldings/entrypoint/docker-compose.yaml new file mode 100644 index 00000000..cd626716 --- /dev/null +++ b/tests/scaffoldings/entrypoint/docker-compose.yaml @@ -0,0 +1,29 @@ +services: + odoo: + build: + context: ./ + args: + # compile causes the creation of __pycache__ in entrypoint.d for this test + COMPILE: "true" + ODOO_VERSION: $ODOO_MINOR + WITHOUT_DEMO: "false" + tty: true + depends_on: + - db + environment: + PYTHONOPTIMIZE: "" + UNACCENT: "false" + volumes: + - filestore:/var/lib/odoo + + db: + image: postgres:${DB_VERSION}-alpine + environment: + POSTGRES_USER: odoo + POSTGRES_PASSWORD: odoopassword + volumes: + - db:/var/lib/postgresql/data + +volumes: + db: + filestore: diff --git a/tests/scaffoldings/geoip/Dockerfile b/tests/scaffoldings/geoip/Dockerfile new file mode 100644 index 00000000..4916c47a --- /dev/null +++ b/tests/scaffoldings/geoip/Dockerfile @@ -0,0 +1,2 @@ +ARG ODOO_VERSION +FROM tecnativa/doodba:${ODOO_VERSION}-onbuild diff --git a/tests/scaffoldings/geoip/custom/src/addons.yaml b/tests/scaffoldings/geoip/custom/src/addons.yaml new file mode 100644 index 00000000..e69de29b diff --git a/tests/scaffoldings/geoip/docker-compose.yaml b/tests/scaffoldings/geoip/docker-compose.yaml new file mode 100644 index 00000000..607fa85f --- /dev/null +++ b/tests/scaffoldings/geoip/docker-compose.yaml @@ -0,0 +1,34 @@ +services: + odoo: + build: + context: ./ + args: + COMPILE: "false" + ODOO_VERSION: $ODOO_MINOR + PIP_INSTALL_ODOO: "false" + WITHOUT_DEMO: "false" + + tty: true + depends_on: + - db + environment: + PYTHONOPTIMIZE: "" + UNACCENT: "false" + + # This product includes GeoLite2 data created by MaxMind, available from https://www.maxmind.com + GEOIP_ACCOUNT_ID: $GEOIP_ACCOUNT_ID + GEOIP_LICENSE_KEY: $GEOIP_LICENSE_KEY + volumes: + - filestore:/var/lib/odoo + + db: + image: postgres:${DB_VERSION}-alpine + environment: + POSTGRES_USER: odoo + POSTGRES_PASSWORD: odoopassword + volumes: + - db:/var/lib/postgresql/data + +volumes: + db: + filestore: diff --git a/tests/scaffoldings/geoip_devel/Dockerfile b/tests/scaffoldings/geoip_devel/Dockerfile new file mode 100644 index 00000000..4916c47a --- /dev/null +++ b/tests/scaffoldings/geoip_devel/Dockerfile @@ -0,0 +1,2 @@ +ARG ODOO_VERSION +FROM tecnativa/doodba:${ODOO_VERSION}-onbuild diff --git a/tests/scaffoldings/geoip_devel/custom/src/addons.yaml b/tests/scaffoldings/geoip_devel/custom/src/addons.yaml new file mode 100644 index 00000000..e69de29b diff --git a/tests/scaffoldings/geoip_devel/docker-compose.yaml b/tests/scaffoldings/geoip_devel/docker-compose.yaml new file mode 100644 index 00000000..402222ef --- /dev/null +++ b/tests/scaffoldings/geoip_devel/docker-compose.yaml @@ -0,0 +1,41 @@ +services: + odoo: + build: + context: ./ + args: + COMPILE: "false" + ODOO_VERSION: $ODOO_MINOR + PIP_INSTALL_ODOO: "false" + WITHOUT_DEMO: "false" + + # enable creating geoip directories with correct permissions + UID: "${UID:-1000}" + GID: "${GID:-1000}" + tty: true + depends_on: + - db + environment: + PYTHONOPTIMIZE: "" + UNACCENT: "false" + + # This product includes GeoLite2 data created by MaxMind, available from https://www.maxmind.com + GEOIP_ACCOUNT_ID: $GEOIP_ACCOUNT_ID + GEOIP_LICENSE_KEY: $GEOIP_LICENSE_KEY + volumes: + - filestore:/var/lib/odoo + # also use mappings from https://github.com/Tecnativa/doodba-copier-template/blob/main/devel.yaml.jinja to + # simulate devel.yaml + - ./odoo/custom:/opt/odoo/custom:ro,z + - ./odoo/auto:/opt/odoo/auto:rw,z + + db: + image: postgres:${DB_VERSION}-alpine + environment: + POSTGRES_USER: odoo + POSTGRES_PASSWORD: odoopassword + volumes: + - db:/var/lib/postgresql/data + +volumes: + db: + filestore: diff --git a/tests/scaffoldings/geoip_devel/odoo/auto/.gitkeep b/tests/scaffoldings/geoip_devel/odoo/auto/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/tests/scaffoldings/geoip_devel/odoo/custom/.gitkeep b/tests/scaffoldings/geoip_devel/odoo/custom/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/tests/scaffoldings/postgres_client_version/Dockerfile b/tests/scaffoldings/postgres_client_version/Dockerfile new file mode 100644 index 00000000..4916c47a --- /dev/null +++ b/tests/scaffoldings/postgres_client_version/Dockerfile @@ -0,0 +1,2 @@ +ARG ODOO_VERSION +FROM tecnativa/doodba:${ODOO_VERSION}-onbuild diff --git a/tests/scaffoldings/postgres_client_version/custom/src/addons.yaml b/tests/scaffoldings/postgres_client_version/custom/src/addons.yaml new file mode 100644 index 00000000..e69de29b diff --git a/tests/scaffoldings/postgres_client_version/docker-compose.yaml b/tests/scaffoldings/postgres_client_version/docker-compose.yaml new file mode 100644 index 00000000..195fbccb --- /dev/null +++ b/tests/scaffoldings/postgres_client_version/docker-compose.yaml @@ -0,0 +1,30 @@ +services: + odoo: + build: + context: ./ + args: + COMPILE: "false" + ODOO_VERSION: $ODOO_MINOR + PIP_INSTALL_ODOO: "false" + WITHOUT_DEMO: "false" + DB_VERSION: ${DB_VERSION} + tty: true + depends_on: + - db + environment: + PYTHONOPTIMIZE: "" + UNACCENT: "false" + volumes: + - filestore:/var/lib/odoo + + db: + image: postgres:${DB_VERSION}-alpine + environment: + POSTGRES_USER: odoo + POSTGRES_PASSWORD: odoopassword + volumes: + - db:/var/lib/postgresql/data + +volumes: + db: + filestore: diff --git a/tests/scaffoldings/repo_merge/Dockerfile b/tests/scaffoldings/repo_merge/Dockerfile new file mode 100644 index 00000000..4916c47a --- /dev/null +++ b/tests/scaffoldings/repo_merge/Dockerfile @@ -0,0 +1,2 @@ +ARG ODOO_VERSION +FROM tecnativa/doodba:${ODOO_VERSION}-onbuild diff --git a/tests/scaffoldings/repo_merge/custom/build.d/099-create-fake-odoo b/tests/scaffoldings/repo_merge/custom/build.d/099-create-fake-odoo new file mode 100755 index 00000000..c81c6d2a --- /dev/null +++ b/tests/scaffoldings/repo_merge/custom/build.d/099-create-fake-odoo @@ -0,0 +1,20 @@ +#!/bin/bash +rm -rf /tmp/fake-odoo +mkdir /tmp/fake-odoo +cd /tmp/fake-odoo + +git init +git config --system --add safe.directory /tmp/fake-odoo/.git +touch odoo-bin +git add odoo-bin +git commit -m odoo-bin + +git checkout -b branch1 +touch 1.txt +git add 1.txt +git commit -m 1.txt + +git checkout -b branch2 HEAD~1 +touch 2.txt +git add 2.txt +git commit -m 2.txt diff --git a/tests/scaffoldings/repo_merge/custom/src/addons.yaml b/tests/scaffoldings/repo_merge/custom/src/addons.yaml new file mode 100644 index 00000000..e69de29b diff --git a/tests/scaffoldings/repo_merge/custom/src/repos.yaml b/tests/scaffoldings/repo_merge/custom/src/repos.yaml new file mode 100644 index 00000000..fcb83956 --- /dev/null +++ b/tests/scaffoldings/repo_merge/custom/src/repos.yaml @@ -0,0 +1,9 @@ +# Odoo is always required +./odoo: + defaults: + depth: $DEPTH_MERGE + remotes: + local: /tmp/fake-odoo + merges: + - local branch1 + - local branch2 diff --git a/tests/scaffoldings/repo_merge/docker-compose.yaml b/tests/scaffoldings/repo_merge/docker-compose.yaml new file mode 100644 index 00000000..b50f76d4 --- /dev/null +++ b/tests/scaffoldings/repo_merge/docker-compose.yaml @@ -0,0 +1,18 @@ +services: + odoo: + build: + context: ./ + args: + COMPILE: "false" + ODOO_VERSION: $ODOO_MINOR + PIP_INSTALL_ODOO: "false" # ensure build.d/700-odoo-install does not fail + WITHOUT_DEMO: "false" + environment: + PYTHONOPTIMIZE: "" + UNACCENT: "false" + entrypoint: "" # we are not using odoo but only checking the repo state here, this skips starting the db + volumes: + - filestore:/var/lib/odoo + +volumes: + filestore: diff --git a/tests/scaffoldings/repo_merge/setup-devel.yaml b/tests/scaffoldings/repo_merge/setup-devel.yaml new file mode 100644 index 00000000..50620cc1 --- /dev/null +++ b/tests/scaffoldings/repo_merge/setup-devel.yaml @@ -0,0 +1,25 @@ +version: "2.1" +services: + odoo: + build: + context: ./ + args: + AGGREGATE: "false" + CLEAN: "false" + COMPILE: "false" + ODOO_VERSION: $ODOO_MINOR + PIP_INSTALL_ODOO: "false" + environment: + PYTHONOPTIMIZE: "" + UNACCENT: "false" + UID: "${UID:-1000}" + GID: "${GID:-1000}" + UMASK: "$UMASK" + user: root + entrypoint: "" # we are only calling autoaggregate inside the tests + volumes: + - ./custom/src/:/opt/odoo/custom/src:rw,z + - filestore:/var/lib/odoo:z + +volumes: + filestore: diff --git a/tests/scaffoldings/settings/custom/conf.d/00-defaults.conf b/tests/scaffoldings/settings/custom/conf.d/00-defaults.conf new file mode 100644 index 00000000..9c9e224c --- /dev/null +++ b/tests/scaffoldings/settings/custom/conf.d/00-defaults.conf @@ -0,0 +1,3 @@ +[options] +# Simulate a default value of 1000 MiB +limit_memory_soft = 1048576000 diff --git a/tests/scaffoldings/settings/custom/conf.d/10-custom.conf b/tests/scaffoldings/settings/custom/conf.d/10-custom.conf new file mode 100644 index 00000000..230541e3 --- /dev/null +++ b/tests/scaffoldings/settings/custom/conf.d/10-custom.conf @@ -0,0 +1,3 @@ +[options] +# Customize the default to 2000 MiB +limit_memory_soft = 2097152000 diff --git a/tests/scaffoldings/settings/custom/scripts/qa-insider-test b/tests/scaffoldings/settings/custom/scripts/qa-insider-test new file mode 100755 index 00000000..92cdad3b --- /dev/null +++ b/tests/scaffoldings/settings/custom/scripts/qa-insider-test @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +set -ex + +# Declare some scripts +bash_script='#!/usr/bin/env bash +echo "$@"' +python_script='#!/usr/bin/env python +import sys +with open("/qa/artifacts/python", "w+") as fd: + for arg in sys.argv[1:]: + fd.write(arg)' + +# Test bash script +bash_result="$(/qa/insider "$bash_script" 1 2 3 2>/dev/stdout >/dev/null)" +test "$bash_result" == "1 2 3" + +# Test python script +python_result="$(mktemp --suffix .zip)" +/qa/insider "$python_script" 1 2 > "$python_result" +python_unzipped="$(mktemp -d)" +python -m zipfile -e "$python_result" "$python_unzipped" +ls -lR "$python_unzipped" +test "$(cat "$python_unzipped/python")" == "12" diff --git a/tests/scaffoldings/settings/custom/scripts/test_ir_config_parameters.py b/tests/scaffoldings/settings/custom/scripts/test_ir_config_parameters.py new file mode 100755 index 00000000..ff4a74e7 --- /dev/null +++ b/tests/scaffoldings/settings/custom/scripts/test_ir_config_parameters.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import click +import click_odoo + + +@click.command() +@click_odoo.env_options(default_log_level="error") +def main(env): + """Set report.url in the database to be pointing at localhost.""" + assert env["ir.config_parameter"].get_param("report.url") == "http://localhost:8069" + + +if __name__ == "__main__": + main() diff --git a/tests/scaffoldings/settings/custom/scripts/test_settings.py b/tests/scaffoldings/settings/custom/scripts/test_settings.py index fcebe86a..65e5c195 100755 --- a/tests/scaffoldings/settings/custom/scripts/test_settings.py +++ b/tests/scaffoldings/settings/custom/scripts/test_settings.py @@ -1,14 +1,22 @@ -#!/usr/local/bin/python-odoo-shell -try: - from odoo.tools import config -except ImportError: - from openerp.tools import config - - -assert config.get("email_from") == "test@example.com" -assert config.get("smtp_password") is False -assert config.get("smtp_port") == 1025 -assert config.get("smtp_server") == "mailhog" -assert config.get("smtp_ssl") is False -assert config.get("smtp_user") is False -assert config.get("dbfilter") == ".*" +#!/usr/bin/env python +# -*- coding: utf-8 -*- +from click import command +from click_odoo import env_options, odoo + + +@command() +@env_options(default_log_level="error") +def main(env): + config = odoo.tools.config + assert config.get("email_from") == "test@example.com" + assert config.get("limit_memory_soft") == 2097152000 + assert bool(config.get("smtp_password")) is False + assert config.get("smtp_port") == 1025 + assert config.get("smtp_server") == "mailhog" + assert config.get("smtp_ssl") is False + assert bool(config.get("smtp_user")) is False + assert config.get("dbfilter") == ".*" + + +if __name__ == "__main__": + main() diff --git a/tests/scaffoldings/settings/custom/scripts/test_settings_python_odoo_shell.py b/tests/scaffoldings/settings/custom/scripts/test_settings_python_odoo_shell.py new file mode 100755 index 00000000..6daf0033 --- /dev/null +++ b/tests/scaffoldings/settings/custom/scripts/test_settings_python_odoo_shell.py @@ -0,0 +1,18 @@ +#!/usr/local/bin/python-odoo-shell +# -*- coding: utf-8 -*- + +# python-odoo-shell is deprecated + +try: + from odoo.tools import config +except ImportError: + from openerp.tools import config + +assert config.get("email_from") == "test@example.com" +assert config.get("limit_memory_soft") == 2097152000 +assert config.get("smtp_password") is False +assert config.get("smtp_port") == 1025 +assert config.get("smtp_server") == "mailhog" +assert config.get("smtp_ssl") is False +assert config.get("smtp_user") is False +assert config.get("dbfilter") == ".*" diff --git a/tests/scaffoldings/settings/custom/src/repos.yaml b/tests/scaffoldings/settings/custom/src/repos.yaml index 1eddc934..f07365a3 100644 --- a/tests/scaffoldings/settings/custom/src/repos.yaml +++ b/tests/scaffoldings/settings/custom/src/repos.yaml @@ -1,12 +1,11 @@ # Odoo is always required ./odoo: - defaults: - # Shallow repositores are faster & thinner - depth: $DEPTH_DEFAULT - remotes: - ocb: https://github.com/OCA/OCB.git - odoo: https://github.com/odoo/odoo.git - target: - ocb $ODOO_VERSION - merges: - - ocb $ODOO_VERSION + defaults: + # Shallow repositores are faster & thinner + depth: $DEPTH_DEFAULT + remotes: + ocb: https://github.com/OCA/OCB.git + odoo: https://github.com/odoo/odoo.git + target: ocb $ODOO_VERSION + merges: + - ocb $ODOO_VERSION diff --git a/tests/scaffoldings/settings/docker-compose.yaml b/tests/scaffoldings/settings/docker-compose.yaml index 73d45fc5..fa31b318 100644 --- a/tests/scaffoldings/settings/docker-compose.yaml +++ b/tests/scaffoldings/settings/docker-compose.yaml @@ -1,10 +1,8 @@ -version: "2.1" services: odoo: build: context: ./ args: - AUTO_REQUIREMENTS: "true" LOG_LEVEL: DEBUG ODOO_VERSION: $ODOO_MINOR tty: true @@ -21,7 +19,7 @@ services: depends_on: - postgresql volumes: - - filestore:/var/lib/odoo:z + - filestore:/var/lib/odoo postgresql: image: postgres:${DB_VERSION}-alpine @@ -30,7 +28,7 @@ services: POSTGRES_PASSWORD: anotherodoopassword command: -p 15432 volumes: - - db:/var/lib/postgresql/data:z + - db:/var/lib/postgresql/data mailhog: image: mailhog/mailhog diff --git a/tests/scaffoldings/smallest/custom/src/repos.yaml b/tests/scaffoldings/smallest/custom/src/repos.yaml deleted file mode 100644 index 1eddc934..00000000 --- a/tests/scaffoldings/smallest/custom/src/repos.yaml +++ /dev/null @@ -1,12 +0,0 @@ -# Odoo is always required -./odoo: - defaults: - # Shallow repositores are faster & thinner - depth: $DEPTH_DEFAULT - remotes: - ocb: https://github.com/OCA/OCB.git - odoo: https://github.com/odoo/odoo.git - target: - ocb $ODOO_VERSION - merges: - - ocb $ODOO_VERSION diff --git a/tests/scaffoldings/smallest/docker-compose.yaml b/tests/scaffoldings/smallest/docker-compose.yaml index 5cb154cd..e75ddf87 100644 --- a/tests/scaffoldings/smallest/docker-compose.yaml +++ b/tests/scaffoldings/smallest/docker-compose.yaml @@ -1,4 +1,3 @@ -version: "2.1" services: odoo: build: @@ -14,7 +13,7 @@ services: PYTHONOPTIMIZE: "" UNACCENT: "false" volumes: - - filestore:/var/lib/odoo:z + - filestore:/var/lib/odoo db: image: postgres:${DB_VERSION}-alpine @@ -22,7 +21,7 @@ services: POSTGRES_USER: odoo POSTGRES_PASSWORD: odoopassword volumes: - - db:/var/lib/postgresql/data:z + - db:/var/lib/postgresql/data volumes: db: diff --git a/tests/scaffoldings/symlinks/Dockerfile b/tests/scaffoldings/symlinks/Dockerfile new file mode 100644 index 00000000..4916c47a --- /dev/null +++ b/tests/scaffoldings/symlinks/Dockerfile @@ -0,0 +1,2 @@ +ARG ODOO_VERSION +FROM tecnativa/doodba:${ODOO_VERSION}-onbuild diff --git a/tests/scaffoldings/symlinks/custom/src/addons.yaml b/tests/scaffoldings/symlinks/custom/src/addons.yaml new file mode 100644 index 00000000..38fb777f --- /dev/null +++ b/tests/scaffoldings/symlinks/custom/src/addons.yaml @@ -0,0 +1,2 @@ +./repo_with_links: + - addon_alias diff --git a/tests/scaffoldings/symlinks/custom/src/repo_with_links/addon_alias b/tests/scaffoldings/symlinks/custom/src/repo_with_links/addon_alias new file mode 120000 index 00000000..85ff76ca --- /dev/null +++ b/tests/scaffoldings/symlinks/custom/src/repo_with_links/addon_alias @@ -0,0 +1 @@ +../odoo/addons/web \ No newline at end of file diff --git a/tests/scaffoldings/symlinks/custom/src/repo_with_links/broken_addon_link b/tests/scaffoldings/symlinks/custom/src/repo_with_links/broken_addon_link new file mode 120000 index 00000000..8681f8b8 --- /dev/null +++ b/tests/scaffoldings/symlinks/custom/src/repo_with_links/broken_addon_link @@ -0,0 +1 @@ +base \ No newline at end of file diff --git a/tests/scaffoldings/symlinks/custom/src/repo_with_links/danger/date b/tests/scaffoldings/symlinks/custom/src/repo_with_links/danger/date new file mode 120000 index 00000000..884ba3e7 --- /dev/null +++ b/tests/scaffoldings/symlinks/custom/src/repo_with_links/danger/date @@ -0,0 +1 @@ +/bin/date \ No newline at end of file diff --git a/tests/scaffoldings/symlinks/docker-compose.yaml b/tests/scaffoldings/symlinks/docker-compose.yaml new file mode 100644 index 00000000..e75ddf87 --- /dev/null +++ b/tests/scaffoldings/symlinks/docker-compose.yaml @@ -0,0 +1,28 @@ +services: + odoo: + build: + context: ./ + args: + COMPILE: "false" + ODOO_VERSION: $ODOO_MINOR + WITHOUT_DEMO: "false" + tty: true + depends_on: + - db + environment: + PYTHONOPTIMIZE: "" + UNACCENT: "false" + volumes: + - filestore:/var/lib/odoo + + db: + image: postgres:${DB_VERSION}-alpine + environment: + POSTGRES_USER: odoo + POSTGRES_PASSWORD: odoopassword + volumes: + - db:/var/lib/postgresql/data + +volumes: + db: + filestore: diff --git a/tests/scaffoldings/test_artifacts/Dockerfile b/tests/scaffoldings/test_artifacts/Dockerfile new file mode 100644 index 00000000..4916c47a --- /dev/null +++ b/tests/scaffoldings/test_artifacts/Dockerfile @@ -0,0 +1,2 @@ +ARG ODOO_VERSION +FROM tecnativa/doodba:${ODOO_VERSION}-onbuild diff --git a/tests/scaffoldings/test_artifacts/custom/src/addons.yaml b/tests/scaffoldings/test_artifacts/custom/src/addons.yaml new file mode 100644 index 00000000..e69de29b diff --git a/tests/scaffoldings/test_artifacts/docker-compose.yaml b/tests/scaffoldings/test_artifacts/docker-compose.yaml new file mode 100644 index 00000000..9223a12f --- /dev/null +++ b/tests/scaffoldings/test_artifacts/docker-compose.yaml @@ -0,0 +1,32 @@ +services: + odoo: + build: + context: ./ + args: + COMPILE: "false" + ODOO_VERSION: $ODOO_MINOR + WITHOUT_DEMO: "false" + # enable creating test artifact directories with correct permissions + UID: "${UID:-1000}" + GID: "${GID:-1000}" + tty: true + depends_on: + - db + environment: + PYTHONOPTIMIZE: "" + UNACCENT: "false" + volumes: + - filestore:/var/lib/odoo + - ./test-artifacts:/opt/odoo/auto/test-artifacts:z + + db: + image: postgres:${DB_VERSION}-alpine + environment: + POSTGRES_USER: odoo + POSTGRES_PASSWORD: odoopassword + volumes: + - db:/var/lib/postgresql/data + +volumes: + db: + filestore: diff --git a/tests/scaffoldings/test_artifacts/test-artifacts/.gitkeep b/tests/scaffoldings/test_artifacts/test-artifacts/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/tests/scaffoldings/uids_1001/Dockerfile b/tests/scaffoldings/uids_1001/Dockerfile new file mode 100644 index 00000000..4916c47a --- /dev/null +++ b/tests/scaffoldings/uids_1001/Dockerfile @@ -0,0 +1,2 @@ +ARG ODOO_VERSION +FROM tecnativa/doodba:${ODOO_VERSION}-onbuild diff --git a/tests/scaffoldings/uids_1001/custom/src/addons.yaml b/tests/scaffoldings/uids_1001/custom/src/addons.yaml new file mode 100644 index 00000000..e69de29b diff --git a/tests/scaffoldings/uids_1001/docker-compose.yaml b/tests/scaffoldings/uids_1001/docker-compose.yaml new file mode 100644 index 00000000..216eff24 --- /dev/null +++ b/tests/scaffoldings/uids_1001/docker-compose.yaml @@ -0,0 +1,32 @@ +services: + odoo: + build: + context: ./ + args: + COMPILE: "false" + ODOO_VERSION: $ODOO_MINOR + PIP_INSTALL_ODOO: "false" + WITHOUT_DEMO: "false" + UID: 1001 + GID: 1002 + + tty: true + depends_on: + - db + environment: + PYTHONOPTIMIZE: "" + UNACCENT: "false" + volumes: + - filestore:/var/lib/odoo + + db: + image: postgres:${DB_VERSION}-alpine + environment: + POSTGRES_USER: odoo + POSTGRES_PASSWORD: odoopassword + volumes: + - db:/var/lib/postgresql/data + +volumes: + db: + filestore: diff --git a/tests/scaffoldings/uids_998/Dockerfile b/tests/scaffoldings/uids_998/Dockerfile new file mode 100644 index 00000000..4916c47a --- /dev/null +++ b/tests/scaffoldings/uids_998/Dockerfile @@ -0,0 +1,2 @@ +ARG ODOO_VERSION +FROM tecnativa/doodba:${ODOO_VERSION}-onbuild diff --git a/tests/scaffoldings/uids_998/custom/src/addons.yaml b/tests/scaffoldings/uids_998/custom/src/addons.yaml new file mode 100644 index 00000000..e69de29b diff --git a/tests/scaffoldings/uids_998/docker-compose.yaml b/tests/scaffoldings/uids_998/docker-compose.yaml new file mode 100644 index 00000000..65bb28f4 --- /dev/null +++ b/tests/scaffoldings/uids_998/docker-compose.yaml @@ -0,0 +1,32 @@ +services: + odoo: + build: + context: ./ + args: + COMPILE: "false" + ODOO_VERSION: $ODOO_MINOR + PIP_INSTALL_ODOO: "false" + WITHOUT_DEMO: "false" + UID: 998 + GID: 998 + + tty: true + depends_on: + - db + environment: + PYTHONOPTIMIZE: "" + UNACCENT: "false" + volumes: + - filestore:/var/lib/odoo + + db: + image: postgres:${DB_VERSION}-alpine + environment: + POSTGRES_USER: odoo + POSTGRES_PASSWORD: odoopassword + volumes: + - db:/var/lib/postgresql/data + +volumes: + db: + filestore: diff --git a/tests/scaffoldings/uids_default/Dockerfile b/tests/scaffoldings/uids_default/Dockerfile new file mode 100644 index 00000000..4916c47a --- /dev/null +++ b/tests/scaffoldings/uids_default/Dockerfile @@ -0,0 +1,2 @@ +ARG ODOO_VERSION +FROM tecnativa/doodba:${ODOO_VERSION}-onbuild diff --git a/tests/scaffoldings/uids_default/custom/src/addons.yaml b/tests/scaffoldings/uids_default/custom/src/addons.yaml new file mode 100644 index 00000000..e69de29b diff --git a/tests/scaffoldings/uids_default/docker-compose.yaml b/tests/scaffoldings/uids_default/docker-compose.yaml new file mode 100644 index 00000000..ffbe59b3 --- /dev/null +++ b/tests/scaffoldings/uids_default/docker-compose.yaml @@ -0,0 +1,29 @@ +services: + odoo: + build: + context: ./ + args: + COMPILE: "false" + ODOO_VERSION: $ODOO_MINOR + WITHOUT_DEMO: "false" + + tty: true + depends_on: + - db + environment: + PYTHONOPTIMIZE: "" + UNACCENT: "false" + volumes: + - filestore:/var/lib/odoo + + db: + image: postgres:${DB_VERSION}-alpine + environment: + POSTGRES_USER: odoo + POSTGRES_PASSWORD: odoopassword + volumes: + - db:/var/lib/postgresql/data + +volumes: + db: + filestore: diff --git a/tests/scaffoldings/uids_mac_os/Dockerfile b/tests/scaffoldings/uids_mac_os/Dockerfile new file mode 100644 index 00000000..4916c47a --- /dev/null +++ b/tests/scaffoldings/uids_mac_os/Dockerfile @@ -0,0 +1,2 @@ +ARG ODOO_VERSION +FROM tecnativa/doodba:${ODOO_VERSION}-onbuild diff --git a/tests/scaffoldings/uids_mac_os/custom/src/addons.yaml b/tests/scaffoldings/uids_mac_os/custom/src/addons.yaml new file mode 100644 index 00000000..e69de29b diff --git a/tests/scaffoldings/uids_mac_os/docker-compose.yaml b/tests/scaffoldings/uids_mac_os/docker-compose.yaml new file mode 100644 index 00000000..742d25ba --- /dev/null +++ b/tests/scaffoldings/uids_mac_os/docker-compose.yaml @@ -0,0 +1,32 @@ +services: + odoo: + build: + context: ./ + args: + COMPILE: "false" + ODOO_VERSION: $ODOO_MINOR + PIP_INSTALL_ODOO: "false" + WITHOUT_DEMO: "false" + UID: 501 + GID: 20 + + tty: true + depends_on: + - db + environment: + PYTHONOPTIMIZE: "" + UNACCENT: "false" + volumes: + - filestore:/var/lib/odoo + + db: + image: postgres:${DB_VERSION}-alpine + environment: + POSTGRES_USER: odoo + POSTGRES_PASSWORD: odoopassword + volumes: + - db:/var/lib/postgresql/data + +volumes: + db: + filestore: