diff --git a/.travis.yml b/.travis.yml index ca885627..b280a167 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,12 +21,19 @@ env: - DOCKER_REPO=tecnativa/odoo-base - DOCKER_TAG=latest - IMAGE_NAME=$DOCKER_REPO:$DOCKER_TAG + matrix: + - ODOO_VERSIONS=8.0 + - ODOO_VERSIONS=9.0 + - ODOO_VERSIONS=10.0 + - ODOO_VERSIONS=11.0 before_install: - - ./hooks/build + - sudo apt-get update + - sudo apt-get -y -o Dpkg::Options::=--force-confnew install docker-ce + - pip install -r requirements-ci.txt install: - - pip install -r requirements-ci.txt + - ./hooks/build script: - python -m unittest -v tests diff --git a/10.0.Dockerfile b/10.0.Dockerfile new file mode 120000 index 00000000..04c2b0a4 --- /dev/null +++ b/10.0.Dockerfile @@ -0,0 +1 @@ +8.0.Dockerfile \ No newline at end of file diff --git a/11.0.Dockerfile b/11.0.Dockerfile new file mode 100644 index 00000000..98c543a0 --- /dev/null +++ b/11.0.Dockerfile @@ -0,0 +1,154 @@ +FROM debian:9 + +# 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 + +# Subimage triggers +ONBUILD ENTRYPOINT ["/opt/odoo/common/entrypoint"] +ONBUILD CMD ["/usr/local/bin/odoo"] +ONBUILD ARG AGGREGATE=true +ONBUILD ARG DEPTH_DEFAULT=1 +ONBUILD ARG DEPTH_MERGE=100 +ONBUILD ARG CLEAN=true +ONBUILD ARG COMPILE=true +ONBUILD ARG CONFIG_BUILD=true +ONBUILD ARG PIP_INSTALL_ODOO=true +ONBUILD ARG ADMIN_PASSWORD=admin +ONBUILD ARG SMTP_SERVER=smtp +ONBUILD ARG PROXY_MODE=false +ONBUILD ARG WITHOUT_DEMO=all +ONBUILD ARG PGUSER=odoo +ONBUILD ARG PGPASSWORD=odoopassword +ONBUILD ARG PGHOST=db +ONBUILD ARG PGDATABASE=prod +# Config variables +ONBUILD ENV ADMIN_PASSWORD="$ADMIN_PASSWORD" \ + UNACCENT="$UNACCENT" \ + PGUSER="$PGUSER" \ + PGPASSWORD="$PGPASSWORD" \ + PGHOST="$PGHOST" \ + PGDATABASE="$PGDATABASE" \ + PROXY_MODE="$PROXY_MODE" \ + SMTP_SERVER="$SMTP_SERVER" \ + 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"] +ONBUILD USER odoo + +ARG WKHTMLTOPDF_VERSION=0.12.4 +ARG WKHTMLTOPDF_CHECKSUM='049b2cdec9a8254f0ef8ac273afaf54f7e25459a273e27189591edc7d7cf29db' +ENV DEPTH_DEFAULT=1 \ + DEPTH_MERGE=100 \ + EMAIL=https://hub.docker.com/r/tecnativa/odoo \ + GIT_AUTHOR_NAME=docker-odoo \ + LC_ALL=C.UTF-8 \ + NODE_PATH=/usr/local/lib/node_modules:/usr/lib/node_modules \ + OPENERP_SERVER=/opt/odoo/auto/odoo.conf \ + PATH="~/.local/bin:$PATH" \ + PUDB_RDB_HOST=0.0.0.0 \ + PUDB_RDB_PORT=6899 \ + 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 -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 \ + openssh-client postgresql-client telnet xz-utils \ + && curl https://bootstrap.pypa.io/get-pip.py | python3 /dev/stdin --no-cache-dir \ + && curl -sL https://deb.nodesource.com/setup_6.x | bash - \ + && apt-get install -yqq nodejs \ + && apt-get -yqq purge python2.7 \ + && apt-get -yqq autoremove \ + && rm -Rf /var/lib/apt/lists/* + +# Special case to get latest Less and PhantomJS +RUN ln -s /usr/bin/nodejs /usr/local/bin/node \ + && npm install -g less phantomjs-prebuilt \ + && 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/ + +# Special case for wkhtmltox +RUN curl -SLo wkhtmltox.tar.xz https://github.com/wkhtmltopdf/wkhtmltopdf/releases/download/${WKHTMLTOPDF_VERSION}/wkhtmltox-${WKHTMLTOPDF_VERSION}_linux-generic-amd64.tar.xz \ + && echo "${WKHTMLTOPDF_CHECKSUM} wkhtmltox.tar.xz" | sha256sum -c - \ + && tar --strip-components 1 -C /usr/local/ -xf wkhtmltox.tar.xz \ + && rm wkhtmltox.tar.xz \ + && wkhtmltopdf --version + +# Other facilities +WORKDIR /opt/odoo +RUN pip install --no-cache-dir \ + 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 +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/python3.5/dist-packages/odoobaselib \ + && ln -s $(which python3) /usr/local/bin/python \ + && 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=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 --no-cache-dir -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/* + +# 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/docker-odoo-base" diff --git a/Dockerfile b/8.0.Dockerfile similarity index 99% rename from Dockerfile rename to 8.0.Dockerfile index 55a9ba01..dea94c7f 100644 --- a/Dockerfile +++ b/8.0.Dockerfile @@ -1,5 +1,4 @@ FROM debian:8 -MAINTAINER Tecnativa # Enable Odoo user and filestore RUN useradd -md /home/odoo -s /bin/false odoo \ diff --git a/9.0.Dockerfile b/9.0.Dockerfile new file mode 120000 index 00000000..04c2b0a4 --- /dev/null +++ b/9.0.Dockerfile @@ -0,0 +1 @@ +8.0.Dockerfile \ No newline at end of file diff --git a/build.d/500-compile b/build.d/500-compile index 23b7cb98..b60a6f53 100755 --- a/build.d/500-compile +++ b/build.d/500-compile @@ -7,5 +7,5 @@ if [ "$COMPILE" != true ]; then fi log INFO Compiling all Python code in /opt/odoo -log DEBUG PYTHONOPTIMIZE set to $PYTHONOPTIMIZE -python -m compileall -q /opt/odoo +# TODO Remove `|| true` when fixed https://github.com/odoo/odoo/issues/19871 +PYTHONOPTIMIZE=2 python -m compileall -q /opt/odoo || true diff --git a/conf.d/10-addons.conf b/conf.d/10-addons.conf index 56393e80..d7ad1445 100644 --- a/conf.d/10-addons.conf +++ b/conf.d/10-addons.conf @@ -1,3 +1,2 @@ -[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 eebfa912..45d76a46 100644 --- a/conf.d/20-database.conf +++ b/conf.d/20-database.conf @@ -1,4 +1,3 @@ -[options] ; Database settings, matching defaults when you execute `psql` db_user = $PGUSER db_password = $PGPASSWORD diff --git a/conf.d/30-proxy-mode.conf b/conf.d/30-proxy-mode.conf index ab33311a..31ce6027 100644 --- a/conf.d/30-proxy-mode.conf +++ b/conf.d/30-proxy-mode.conf @@ -1,3 +1,2 @@ -[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 923a0547..d4449e6b 100644 --- a/conf.d/40-smtp.conf +++ b/conf.d/40-smtp.conf @@ -1,3 +1,2 @@ -[options] ; Prepared to link with https://hub.docker.com/r/tecnativa/postfix-relay smtp_server = $SMTP_SERVER diff --git a/conf.d/50-demo-data.conf b/conf.d/50-demo-data.conf index 90e90581..421d4018 100644 --- a/conf.d/50-demo-data.conf +++ b/conf.d/50-demo-data.conf @@ -1,3 +1,2 @@ -[options] ; Useful for testing, useless for production, disabled by default without_demo = $WITHOUT_DEMO diff --git a/hooks/build b/hooks/build index 761812ff..b2041cff 100755 --- a/hooks/build +++ b/hooks/build @@ -1,22 +1,50 @@ -#!/bin/bash -set -ex +#!/usr/bin/env python +from __future__ import print_function +import json +import logging +import os +from datetime import datetime +from glob import iglob -build () { - # See http://label-schema.org/rc1/#build-time-labels - time docker build \ - --build-arg VCS_REF="$GIT_SHA1" \ - --build-arg BUILD_DATE="$(date --rfc-3339 ns)" \ - "$@" . -} +import docker -# Build requested tag, probably "latest" -build --tag "$IMAGE_NAME" +CLIENT = docker.client.from_env() +DEFAULT_VERSION = "11.0" +DOCKER_REPO = os.environ.get("DOCKER_REPO", "tecnativa/odoo-base") +GIT_SHA1 = os.environ.get("GIT_SHA1", "") +ODOO_VERSIONS = frozenset(os.environ.get( + "ODOO_VERSIONS", "8.0 9.0 10.0 11.0").split()) -if [ "$DOCKER_TAG" == latest ]; then - # Build other tags, using cache to get it faster - source hooks/variables - docker tag "$IMAGE_NAME" "$DOCKER_REPO:$DEFAULT_VERSION" - for ver in $OTHER_VERSIONS; do - build --build-arg ODOO_VERSION="$ver" --tag "$DOCKER_REPO:$ver" - done -fi +logging.basicConfig(level=logging.INFO) + +# Build version-specific images +for dockerfile in iglob("*.Dockerfile"): + version = dockerfile.replace(".Dockerfile", "") + if version not in ODOO_VERSIONS: + continue + logging.info("Building image for version %s", version) + # Low-level api for building images and streaming output + response = CLIENT.api.build( + path=".", + dockerfile=dockerfile, + tag=u"{}:{}".format(DOCKER_REPO, version), + buildargs={ + "BUILD_DATE": datetime.utcnow().isoformat(), + "ODOO_VERSION": version, + "VCS_REF": GIT_SHA1, + } + ) + status = None + for line in response: + line = json.loads(line) + if line.get("status") not in {status, None}: + status = line["status"] + print(status) + if line.get("stream"): + print(line["stream"], end="") + +# Tag default version +if DEFAULT_VERSION in ODOO_VERSIONS: + logging.info("Tagging latest") + image = CLIENT.images.get(u"{}:{}".format(DOCKER_REPO, DEFAULT_VERSION)) + image.tag(DOCKER_REPO, "latest") diff --git a/hooks/post_push b/hooks/post_push index a9365a44..b4d31ceb 100755 --- a/hooks/post_push +++ b/hooks/post_push @@ -1,9 +1,18 @@ -#!/bin/bash -set -ex -if [ "$DOCKER_TAG" == latest ]; then +#!/usr/bin/env python +import os +from glob import iglob + +import docker + +DEFAULT_VERSION = "11.0" +DOCKER_REPO = os.environ.get("DOCKER_REPO", "tecnativa/odoo-base") +DOCKER_TAG = os.environ.get("DOCKER_TAG") +IMAGE_NAME = os.environ.get("IMAGE_NAME", u"{}:{}") +CLIENT = docker.client.from_env() + +if DOCKER_TAG == "latest": # Push other tags, that should have been built already - source hooks/variables - for ver in $DEFAULT_VERSION $OTHER_VERSIONS; do - docker push "$DOCKER_REPO:$ver" - done -fi + for image in CLIENT.images.list(DOCKER_REPO): + for tag in image.tags: + if tag != IMAGE_NAME: + CLIENT.images.push(tag) diff --git a/hooks/variables b/hooks/variables deleted file mode 100755 index 442e2ecc..00000000 --- a/hooks/variables +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -DEFAULT_VERSION="10.0" -OTHER_VERSIONS="8.0 9.0" diff --git a/tests/__init__.py b/tests/__init__.py index 1ac6e4d3..6a862d64 100755 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -16,20 +16,14 @@ logging.basicConfig(level=logging.DEBUG) -# Common test utilities +MAIN_SCAFFOLDING_VERSION = "10.0" DIR = dirname(__file__) -SCAFFOLDINGS_DIR = join(DIR, "scaffoldings") ODOO_PREFIX = ("odoo", "--stop-after-init", "--workers=0") - -# Variable matrix -ODOO_VERSIONS = frozenset(( - "10.0", - "9.0", - "8.0", -)) -PG_VERSIONS = frozenset(( - "9.6", -)) +ODOO_VERSIONS = frozenset(environ.get( + "ODOO_VERSIONS", "8.0 9.0 10.0 11.0").split()) +PG_VERSIONS = frozenset(environ.get( + "PG_VERSIONS", "9.6").split()) +SCAFFOLDINGS_DIR = join(DIR, "scaffoldings") def matrix(odoo=ODOO_VERSIONS, pg=PG_VERSIONS, @@ -43,8 +37,8 @@ def matrix(odoo=ODOO_VERSIONS, pg=PG_VERSIONS, return map( dict, product( - product(("ODOO_MINOR",), odoo ^ odoo_skip), - product(("DB_VERSION",), pg ^ pg_skip), + product(("ODOO_MINOR",), ODOO_VERSIONS & odoo - odoo_skip), + product(("DB_VERSION",), PG_VERSIONS & pg - pg_skip), ) ) @@ -191,6 +185,9 @@ def test_dotd(self): ("--version",), ) + @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: diff --git a/tests/scaffoldings/dotd/11.0.Dockerfile b/tests/scaffoldings/dotd/11.0.Dockerfile new file mode 100644 index 00000000..dbe72bc8 --- /dev/null +++ b/tests/scaffoldings/dotd/11.0.Dockerfile @@ -0,0 +1 @@ +FROM tecnativa/odoo-base:11.0 diff --git a/tests/scaffoldings/dotd/custom/dependencies/apt_build.txt b/tests/scaffoldings/dotd/custom/dependencies/apt_build.txt index e4328d11..9007ff06 100644 --- a/tests/scaffoldings/dotd/custom/dependencies/apt_build.txt +++ b/tests/scaffoldings/dotd/custom/dependencies/apt_build.txt @@ -2,3 +2,4 @@ build-essential # This is the basic need to build any python extensions, used here for Cython python-dev +python3-dev diff --git a/tests/scaffoldings/smallest/11.0.Dockerfile b/tests/scaffoldings/smallest/11.0.Dockerfile new file mode 100644 index 00000000..dbe72bc8 --- /dev/null +++ b/tests/scaffoldings/smallest/11.0.Dockerfile @@ -0,0 +1 @@ +FROM tecnativa/odoo-base:11.0