diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..94143827e --- /dev/null +++ b/.dockerignore @@ -0,0 +1 @@ +Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..8065d033c --- /dev/null +++ b/Dockerfile @@ -0,0 +1,67 @@ +FROM ubuntu:16.04 +WORKDIR /root +COPY . maintainer-quality-tools +RUN apt-get update -yq \ + && apt-get install -yq \ + # MQT dependencies + git \ + npm \ + python \ + ruby \ + wget \ + # Odoo dependencies + fontconfig \ + libfreetype6 \ + libfreetype6 \ + libjpeg-turbo8 \ + liblcms2-2 \ + libldap-2.4-2 \ + libopenjpeg5 \ + libpq5 \ + libsasl2-2 \ + libtiff5 \ + libx11-6 \ + libxext6 \ + libxml2 \ + libxrender1 \ + libxslt1.1 \ + locales-all \ + phantomjs \ + tcl \ + tk \ + zlib1g \ + zlibc \ + && wget -qO- https://bootstrap.pypa.io/get-pip.py | python \ + && rm -Rf ~/.{cache,npm,gem} /var/lib/{apt/lists/*,gems/*/cache} /tmp/* +ARG VERSION=10.0 +ARG ODOO_REPO=odoo/odoo +ENV ODOO_REPO=$ODOO_REPO \ + PATH=/root/maintainer-quality-tools/travis:$PATH \ + PHANTOMJS_VERSION=OS \ + TRAVIS_BUILD_DIR=/root \ + VERSION=$VERSION +RUN BUILD_DEPENDENCIES=" \ + build-essential \ + libfreetype6-dev \ + libjpeg-turbo8-dev \ + liblcms2-dev \ + libldap2-dev \ + libopenjpeg-dev \ + libpq-dev \ + libsasl2-dev \ + libtiff5-dev \ + libxml2-dev \ + libxslt1-dev \ + linux-headers-virtual \ + python-dev \ + ruby-dev \ + tcl-dev \ + tk-dev" \ + && apt-get update -yq \ + && apt-get install -yq $BUILD_DEPENDENCIES \ + && gem install --no-rdoc --no-ri --no-update-sources compass bootstrap-sass \ + && travis_install_nightly \ + && apt-get -yq purge $BUILD_DEPENDENCIES \ + && apt-get -yq autoremove --purge \ + && rm -Rf ~/.{cache,npm,gem} /var/lib/{apt/lists/*,gems/*/cache} /tmp/* +CMD ["travis_run_tests"] diff --git a/README.md b/README.md index 46c183681..125d2f5b4 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ Names used for the test databases --------------------------------- MQT has a nice feature of organizing your testing databases. -You might want to do that if you want to double them up as +You might want to do that if you want to double them up as staging DBs or if you want to work with an advanced set of templates in order to speed up your CI pipeline. Just specify at will: @@ -84,5 +84,20 @@ Disable test If you want to make a build without tests, you can use the following directive: `TEST_ENABLE="0"` -You will simply get the databases with packages installed, +You will simply get the databases with packages installed, but whithout running any tests. + +Docker image usage +================== + +The instructions are the same as without Docker, except: + +0. No need to run `travis_install_nightly`; all is preinstalled. +0. You should use the correct image version instead of env variables. For + example, `VERSION="10.0" ODOO_REPO="OCA/OCB" travis_run_tests` would become + `docker container run --rm oca/maintainer-quality-tools:OCB-10.0`. +0. Other involved environment variables can be added with `-e KEY=value` to + the above command. +0. You need to mount the addons repositories being tested into + `/root/build/$OWNER/$REPO`, do it with adding something like + `-v (pwd):/root/build/$OWNER/$REPO:ro,z` to the run command. diff --git a/docker/docker_run_tests b/docker/docker_run_tests new file mode 100644 index 000000000..a0f048b49 --- /dev/null +++ b/docker/docker_run_tests @@ -0,0 +1,116 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +"""Run tests using docker image and environment variables. + +Environment Variables +===================== + +Configure this script with these environment variables: + +Required +-------- + +- ``ADDONS_DIR``: Absolute path to host's addons directory to be tested. +- ``OWNER_REPO``: Follow GitHub's convention on ``$OWNER/$REPO``. I.e. + ``OCA/maintainer-quality-tools`` would be a valid value. + +Optional +-------- + +To configure which image to use as base for tests: + +- ``ODOO_REPO``: Currently it can be ``odoo`` or ``ocb``. +- ``ODOO_VERSION``: It can be any version from ``8.0`` to ``10.0`` +- ``DOCKER_TAG``: You can use this variable like in ``ocb-10.0`` instead of + the 2 above (which only build this one). +- ``DOCKER_IMAGE``: Just in case you want to point to another image in the + docker hub. + +To allow committing the container as an image and pushing it to a Docker +Registry: + +- ``DOCKER_PUSH_REPO``: Defaults to ``oca/ci-build``. +- ``DOCKER_PUSH_TAG``: Which tag to use for pushing the build. The convention + is to use i.e. ``maintainer-quality-tools-master`` for branch builds, and + i.e. ``maintainer-quality-tools-pr477`` for pull requests. Use environment + variables supplied by your CI tool to generate this one. +- ``DOCKER_LOGIN_USERNAME`` and ``DOCKER_LOGIN_PASSWORD``: required when you + declare a ``DOCKER_PUSH_TAG``, to log in the registry. **Make sure the + password is protected**. +""" + +from __future__ import unicode_literals, print_function +import os +import sys +import docker +from pprint import pprint + +CONTAINER_VARIABLES = { + "EXCLUDE", + "INCLUDE", + "LINT_CHECK", + "TESTS", + "TRANSIFEX_FILL_UP_RESOURCES", + "TRANSIFEX_ORGANIZATION", + "TRANSIFEX_PASSWORD", + "TRANSIFEX_PROJECT_SLUG", + "TRANSIFEX_TEAM", + "TRANSIFEX_USER", + "TRANSIFEX", + "UNIT_TEST", +} + +# Parse variables to run the container +repo = os.environ.get("ODOO_REPO") +version = os.environ.get("ODOO_VERSION") +tag = os.environ.get( + "DOCKER_TAG", + "{}-{}".format(repo, version).lower() if repo and version else "latest") +image = os.environ.get("DOCKER_IMAGE", "oca/maintainer-quality-tools") +container_env = {key: value for key, value in os.environ.items() + if key in CONTAINER_VARIABLES} +container_env.setdefault( + "TRAVIS_BUILD_DIR", "/root/build/{}".format(os.environ["OWNER_REPO"])) + +# Run container +client = docker.from_env() +run_options = dict( + image="{}:{}".format(image, tag), + detach=True, + remove=True, + environment=container_env, + tty=True, + volumes={ + os.environ["ADDONS_DIR"]: { + "bind": container_env["TRAVIS_BUILD_DIR"], + "mode": "ro,z", + } + }, +) +print("Running MQT container with:") +pprint(run_options) +container = client.containers.run(**run_options) + +# Output logs +for line in container.logs(stdout=True, stderr=True, stream=True, follow=True): + print(line, end="") + +# Store container result +result = container.wait() + +# Commit container and push image +push_repo = os.environ.get("DOCKER_PUSH_REPO", "oca/ci-build") +push_tag = os.environ.get("DOCKER_PUSH_TAG") +if push_tag: + # TODO Support all login parameters (see docs) + login = { + "username": os.environ["DOCKER_LOGIN_USERNAME"], + "password": os.environ["DOCKER_LOGIN_PASSWORD"], + } + client.login(**login) + image = container.commit(push_repo, push_tag) + image.push(push_repo, push_tag) + +# Return container's exit code +sys.exit(result) diff --git a/hooks/_common b/hooks/_common new file mode 100755 index 000000000..667e03cb9 --- /dev/null +++ b/hooks/_common @@ -0,0 +1,10 @@ +#!/bin/bash +env + +REPOS="odoo/odoo OCA/OCB" +VERSIONS="8.0 9.0 10.0" + +# Convert a repo name in a docker image tag name +flavor () { + echo "$(basename $1 | tr '[:upper:]' '[:lower:]')-$2" +} diff --git a/hooks/post_push b/hooks/post_push new file mode 100755 index 000000000..3869d5825 --- /dev/null +++ b/hooks/post_push @@ -0,0 +1,11 @@ +#!/bin/bash +set -ex +if [ "$DOCKER_TAG" == latest ]; then + source hooks/_common + # Push all tags, that should be built already + for repo in $REPOS; do + for version in $VERSIONS; do + docker image push "$DOCKER_REPO:$(flavor $repo $version)" + done + done +fi diff --git a/hooks/pre_build b/hooks/pre_build new file mode 100755 index 000000000..d16c9100c --- /dev/null +++ b/hooks/pre_build @@ -0,0 +1,15 @@ +#!/bin/bash +set -ex +if [ "$DOCKER_TAG" == latest ]; then + source hooks/_common + # Build all tags, using cache to get it faster + for repo in $REPOS; do + for version in $VERSIONS; do + docker image build \ + --build-arg ODOO_REPO="$repo" \ + --build-arg VERSION="$version" \ + --tag "$DOCKER_REPO:$(flavor $repo $version)" \ + . + done + done +fi diff --git a/sample_files/.gitignore b/sample_files/.gitignore index f7f8a408b..7f2da4083 100644 --- a/sample_files/.gitignore +++ b/sample_files/.gitignore @@ -37,8 +37,9 @@ coverage.xml # Translations *.mo -# Pycharm +# Editors .idea +.vscode # Mr Developer .mr.developer.cfg diff --git a/sample_files/.travis.yml b/sample_files/.travis.yml index 53701c655..86e9868bf 100644 --- a/sample_files/.travis.yml +++ b/sample_files/.travis.yml @@ -1,56 +1,20 @@ language: python -sudo: false -cache: - apt: true - directories: - - $HOME/.cache/pip +sudo: required +services: + - docker python: - "2.7" -addons: - apt: -# only add the two lines below if you need wkhtmltopdf for your tests -# sources: -# - pov-wkhtmltopdf -# Search your sources alias here: -# https://github.com/travis-ci/apt-source-whitelist/blob/master/ubuntu.json - packages: - - expect-dev # provides unbuffer utility - - python-lxml # because pip installation is slow - - python-simplejson - - python-serial - - python-yaml -# Search your packages here: -# https://github.com/travis-ci/apt-package-whitelist/blob/master/ubuntu-precise -# - wkhtmltopdf # only add if needed and check the before_install section below - -# set up an X server to run wkhtmltopdf. -#before_install: -# - "export DISPLAY=:99.0" -# - "sh -e /etc/init.d/xvfb start" - -# Sometimes complicated website repos need Compass & SaSS: -#before_install: -# - rvm install ruby --latest -# - gem install bootstrap-sass -# - gem install compass --pre - env: global: - - VERSION="10.0" TESTS="0" LINT_CHECK="0" TRANSIFEX="0" - # - WKHTMLTOPDF_VERSION="0.12.4" - # Set the above to install a `wkhtmltopdf` version that is not the one provided - # by the `pov-wkhtmltopdf` repo. - - PHANTOMJS_VERSION="latest" - # The above line controls the PhantomJS version that is used for JS testing. - # It is not necessary to include this value unless you are altering the default. - # Use `OS` to skip the PhantomJS upgrade & use the system version instead. - - WEBSITE_REPO="1" - # Use the above line to install dependencies that are required for website repos: - # * SASS & Bootstrap-SASS - # * Compass + - ADDONS_DIR="$TRAVIS_BUILD_DIR" + - OWNER_REPO="$TRAVIS_REPO_SLUG" + - LINT_CHECK="0" + - ODOO_VERSION="$TRAVIS_BRANCH" + - TESTS="0" - TRANSIFEX_USER='transbot@odoo-community.org' + - TRANSIFEX="0" # This line contains the encrypted transifex password # To encrypt transifex password, install travis ruby utils with: # $ gem install travis --user-install @@ -71,8 +35,8 @@ env: matrix: - LINT_CHECK="1" - TRANSIFEX="1" - - TESTS="1" ODOO_REPO="odoo/odoo" - - TESTS="1" ODOO_REPO="OCA/OCB" + - TESTS="1" ODOO_REPO="odoo" + - TESTS="1" ODOO_REPO="ocb" # either use the two lines above or the two below. Don't change the default if # it's not necessary (it is only necessary if modules in your repository can't # be installed in the same database. And you get a huge speed penalty in your @@ -80,24 +44,14 @@ env: # - TESTS="1.0" ODOO_REPO="odoo/odoo" UNIT_TEST="1" # - TESTS="1.0" ODOO_REPO="OCA/OCB" UNIT_TEST="1" -virtualenv: - system_site_packages: true - -# Enable this if your repository needs sass command (needed for website related repos) -#before_install: -# - rvm install ruby --latest -# - gem install bootstrap-sass -# - gem install compass --pre - -install: - - git clone --depth=1 https://github.com/OCA/maintainer-quality-tools.git ${HOME}/maintainer-quality-tools - - export PATH=${HOME}/maintainer-quality-tools/travis:${PATH} - - travis_install_nightly -# Use the sentence below to install a specific wkhtmltopdf version -# - export WKHTMLTOPDF_VERSION=0.12.4 +before_script: + - | + if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then + export DOCKER_PUSH_TAG="$(basename $TRAVIS_REPO_SLUG)-$TRAVIS_BRANCH" + else + export DOCKER_PUSH_TAG="$(basename $TRAVIS_REPO_SLUG)-pr$TRAVIS_PULL_REQUEST" + fi script: - - travis_run_tests - -after_success: - - travis_after_tests_success + # TODO Change URL just before merging + - wget -qO- https://raw.githubusercontent.com/Tecnativa/maintainer-quality-tools/dockerfile/docker/docker_run_tests | python diff --git a/travis/travis_install_nightly b/travis/travis_install_nightly index 511cb80db..a14a017a7 100755 --- a/travis/travis_install_nightly +++ b/travis/travis_install_nightly @@ -64,6 +64,7 @@ if [ -z "${REPO_CACHED}" ]; then echo "Installing Odoo $ODOO_URL" wget -nv -O odoo.tar.gz $ODOO_URL tar -xf odoo.tar.gz -C ${HOME} + rm -f odoo.tar.gz else echo "Using Odoo from cache ${REPO_CACHED}" chown `(whoami)`:`(id -gn)` -R ${REPO_CACHED}