From 971841dc948564aff10f5f7441e1cd4e2fe6b263 Mon Sep 17 00:00:00 2001 From: Dave Hunt Date: Wed, 10 Jan 2018 19:39:13 +0000 Subject: [PATCH] Use a docker image to run the tests (#162) * Use a docker image to run the tests * Run against both Python 2 and 3 on Jenkins in parallel * Use Docker in Travis CI * Use Alpine linux for smaller Docker images --- .dockerignore | 8 ++++++ .gitignore | 5 ++-- .travis.yml | 65 +++++++++++++++++-------------------------- Dockerfile | 32 +++++++++++++++++++++ Jenkinsfile | 77 +++++++++++++++++++++++++++++++++++---------------- README.rst | 11 ++++++-- tox.ini | 13 +++++++-- 7 files changed, 140 insertions(+), 71 deletions(-) create mode 100644 .dockerignore create mode 100644 Dockerfile diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..40cf73d --- /dev/null +++ b/.dockerignore @@ -0,0 +1,8 @@ +.cache +.tox +**/__pycache__ +**/*.pyc +build +dist +fxapom.egg-info +results diff --git a/.gitignore b/.gitignore index 1fad098..ea87933 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,10 @@ __pycache__ .cache +.eggs +.idea/ .tox +*.pyc build dist -.idea/ -*.pyc fxapom.egg-info results/ diff --git a/.travis.yml b/.travis.yml index 5dc3f2a..2a0c112 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,47 +1,32 @@ +sudo: required language: python -python: - - 2.7 - - 3.6 -addons: - firefox: latest -env: - global: - - DISPLAY=:99.0 -matrix: +services: + - docker +jobs: include: - - python: 2.7 + - stage: env: TOXENV=flake8 - - python: 2.7 + - stage: env: TOXENV=py27 - - python: 3.6 - env: TOXENV=flake8 - - python: 3.6 + - stage: env: TOXENV=py36 - exclude: - - python: 2.7 - - python: 3.6 -before_install: - - wget -O geckodriver.tar.gz https://github.com/mozilla/geckodriver/releases/download/v0.19.1/geckodriver-v0.19.1-linux64.tar.gz - - gunzip -c geckodriver.tar.gz | tar xopf - - - chmod +x geckodriver && sudo mv geckodriver /usr/local/bin - - firefox --version - - geckodriver --version -install: - - pip install tox -before_script: - - sh -e /etc/init.d/xvfb start -script: - - tox + - stage: deploy + python: 3.6 + before_install: skip + script: skip + deploy: + provider: pypi + user: davehunt + password: + secure: GyTB/x+/F1DNmAWF4K8keaBgwUTq6AVgCfdMzArPSLiHxs4Fi98Y44U6YM4fy5qwZ8oJxYYwdlWoooStIYouV8PEg0GOl+x1m7eb02XXZEufVUqQ4p5sN3HHeUmj2Et0j0o0AkUvAZjY2zCS3hI9U8wH+rLrkyR/1g8a88HLeHo= + distributions: sdist bdist_wheel + on: + tags: true + repo: mozilla/fxapom +cache: + pip: true +before_install: docker build -t mozilla/fxapom . +install: skip +script: docker run -e TOXENV=$TOXENV mozilla/fxapom tox notifications: email: fte-ci@mozilla.com -deploy: - provider: pypi - user: davehunt - password: - secure: GyTB/x+/F1DNmAWF4K8keaBgwUTq6AVgCfdMzArPSLiHxs4Fi98Y44U6YM4fy5qwZ8oJxYYwdlWoooStIYouV8PEg0GOl+x1m7eb02XXZEufVUqQ4p5sN3HHeUmj2Et0j0o0AkUvAZjY2zCS3hI9U8wH+rLrkyR/1g8a88HLeHo= - distributions: sdist bdist_wheel - on: - tags: true - repo: mozilla/fxapom - python: 2.7 - condition: "$TOXENV = py27" diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..aa682d1 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,32 @@ +FROM alpine:latest + +ENV MOZ_HEADLESS=1 + +RUN mkdir /opt +RUN echo @testing http://nl.alpinelinux.org/alpine/edge/testing >> /etc/apk/repositories +RUN apk --no-cache add \ + curl \ + firefox@testing \ + gcc \ + git \ + libffi-dev \ + musl-dev \ + openssl-dev \ + py3-pip \ + python2-dev \ + python3-dev + +ENV GECKODRIVER_VERSION=0.19.1 +RUN curl -fsSLo /tmp/geckodriver.tar.gz https://github.com/mozilla/geckodriver/releases/download/v$GECKODRIVER_VERSION/geckodriver-v$GECKODRIVER_VERSION-linux64.tar.gz \ + && rm -rf /opt/geckodriver \ + && tar -C /opt -zxf /tmp/geckodriver.tar.gz \ + && rm /tmp/geckodriver.tar.gz \ + && mv /opt/geckodriver /opt/geckodriver-$GECKODRIVER_VERSION \ + && chmod 755 /opt/geckodriver-$GECKODRIVER_VERSION \ +&& ln -fs /opt/geckodriver-$GECKODRIVER_VERSION /usr/bin/geckodriver + +ENV TOX_VERSION=2.9.1 +RUN pip3 install tox==$TOX_VERSION + +ADD . /src +WORKDIR /src diff --git a/Jenkinsfile b/Jenkinsfile index 4266b85..ef7a7cf 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -22,52 +22,81 @@ pipeline { "--tb=short " + "--color=yes " + "--driver=SauceLabs " + - "--variables=capabilities.json " + - "--log-raw=results/py27_raw.txt " + - "--log-tbpl=results/py27_tbpl.txt" + "--variables=capabilities.json" PULSE = credentials('PULSE') SAUCELABS = credentials('SAUCELABS') } stages { stage('Lint') { + agent { + dockerfile true + } steps { sh "tox -e flake8" } } stage('Test') { - steps { - writeCapabilities(capabilities, 'capabilities.json') - sh "tox -e py27" - } - post { - always { - archiveArtifacts 'results/*' - junit 'results/*.xml' - submitToActiveData('results/py27_raw.txt') - submitToTreeherder('fxapom', 'T', 'Tests', 'results/*', 'results/py27_tbpl.txt') - publishHTML(target: [ - allowMissing: false, - alwaysLinkToLastBuild: true, - keepAll: true, - reportDir: 'results', - reportFiles: "py27.html", - reportName: 'HTML Report']) + parallel { + stage('py36') { + agent { + dockerfile true + } + steps { + writeCapabilities(capabilities, 'capabilities.json') + sh "tox -e py36" + } + post { + always { + stash includes: 'results/py36.html', name: 'py36' + archiveArtifacts 'results/*' + junit 'results/*.xml' + } + } + } + stage('py27') { + agent { + dockerfile true + } + steps { + writeCapabilities(capabilities, 'capabilities.json') + sh "tox -e py27" + } + post { + always { + stash includes: 'results/py27.html', name: 'py27' + archiveArtifacts 'results/*' + junit 'results/*.xml' + submitToActiveData('results/py27_raw.txt') + submitToTreeherder('fxapom', 'T', 'Tests', 'results/*', 'results/py27_tbpl.txt') + } + } } } } } post { + always { + unstash 'py36' + unstash 'py27' + publishHTML(target: [ + allowMissing: false, + alwaysLinkToLastBuild: true, + keepAll: true, + reportDir: 'results', + reportFiles: "py36.html, py27.html", + reportName: 'HTML Report']) + } + changed { + ircNotification() + } failure { emailext( attachLog: true, - attachmentsPattern: 'results/py27.html', + attachmentsPattern: 'results/*.html', body: '$BUILD_URL\n\n$FAILED_TESTS', replyTo: '$DEFAULT_REPLYTO', subject: '$DEFAULT_SUBJECT', to: '$DEFAULT_RECIPIENTS') } - changed { - ircNotification() - } } } diff --git a/README.rst b/README.rst index 8cad3b3..80ceab5 100644 --- a/README.rst +++ b/README.rst @@ -96,8 +96,15 @@ Contributing ------------ Fork the repository and submit PRs with bug fixes and enhancements, -contributions are very welcome. Tests can be run locally with -`tox `_. +contributions are very welcome. You can run the tests using +`Docker `_: + +.. code-block:: bash + + $ docker build -t fxapom . + $ docker run -it fxapom tox + +Using Resources --------- diff --git a/tox.ini b/tox.ini index ec148b6..8b49482 100644 --- a/tox.ini +++ b/tox.ini @@ -2,9 +2,8 @@ envlist = py{27,36}, flake8 [testenv] -passenv = BUILD_NUMBER DISPLAY GIT_BRANCH GIT_COMMIT GIT_URL JENKINS_URL \ - JOB_NAME PYTEST_ADDOPTS PYTEST_BASE_URL SAUCELABS_USR \ - SAUCELABS_PSW +passenv = HOME DISPLAY MOZ_HEADLESS PYTEST_ADDOPTS PYTEST_BASE_URL \ + SAUCELABS_USR SAUCELABS_PSW JENKINS_URL JOB_NAME BUILD_NUMBER deps = -rrequirements/{envname}-tests.txt commands = pytest \ --junit-xml=results/{envname}.xml \ @@ -16,6 +15,14 @@ skip_install = true deps = -rrequirements/flake8.txt commands = flake8 {posargs:.} +[testenv:py27] +commands = pytest \ + --junit-xml=results/{envname}.xml \ + --html=results/{envname}.html --self-contained-html \ + --log-raw=results/{envname}_raw.txt \ + --log-tbpl=results/{envname}_tbpl.txt \ + {posargs:tests} + [flake8] ignore = E501