Skip to content

Commit a975015

Browse files
committed
Travis CI revamp part 1, refs #2008
Revamping Travis and Docker setup introducing a `Makefile`. The idea is to move the CI complexity from .travis.yml to `Makefile`. That makes a single entry point via `make` command and reproducible builds via Docker. It makes it easy to run some commands outside docker, such as: ```sh make testapps/python3/armeabi-v7a ``` Or the same command inside docker: ```sh make docker/run/make/testapps/python3/armeabi-v7a ``` This pull request also starts introducing some docker layer cache optimization as needed by #2009 to speed up docker pull/push and rebuilds from cache. It also introduces other Docker images good practices like ordering dependencies alphabetically or always enforcing `apt update` prior install, refs: https://docs.docker.com/develop/develop-images/dockerfile_best-practices/ Subsequent pull requests would simplify the process furthermore and leverage the cache to speed up builds.
1 parent 080ac01 commit a975015

File tree

4 files changed

+156
-80
lines changed

4 files changed

+156
-80
lines changed

.env

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# used by coveralls.io, refs:
2+
# https://coveralls-python.readthedocs.io/en/latest/usage/tox.html#travisci
3+
CI
4+
TRAVIS
5+
TRAVIS_BRANCH
6+
TRAVIS_JOB_ID
7+
TRAVIS_PULL_REQUEST
8+
# used for running UI tests
9+
DISPLAY

.travis.yml

Lines changed: 15 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
sudo: required
22

3-
dist: xenial # needed for more recent python 3 and python3-venv
4-
53
language: generic
64

75
stages:
8-
- lint
9-
- test
6+
- unit tests
7+
- build apps
108

119
services:
1210
- docker
@@ -18,8 +16,8 @@ before_install:
1816

1917
jobs:
2018
include:
21-
- &linting
22-
stage: lint
19+
- &unittests
20+
stage: unit tests
2321
language: python
2422
python: 3.7
2523
before_script:
@@ -36,46 +34,26 @@ jobs:
3634
- pip3.7 install pyOpenSSL
3735
- pip3.7 install coveralls
3836
script:
39-
# we want to fail fast on tox errors without having to `docker build` first
37+
# ignores test_pythonpackage.py since it runs for too long
4038
- tox -- tests/ --ignore tests/test_pythonpackage.py
41-
# (we ignore test_pythonpackage.py since these run way too long!!
42-
# test_pythonpackage_basic.py will still be run.)
4339
name: "Tox Pep8"
4440
env: TOXENV=pep8
45-
- <<: *linting
41+
- <<: *unittests
4642
name: "Tox Python 2"
4743
env: TOXENV=py27
48-
- <<: *linting
44+
- <<: *unittests
4945
name: "Tox Python 3 & Coverage"
5046
env: TOXENV=py3
5147
after_success:
5248
- coveralls
53-
5449
- &testing
55-
stage: test
50+
stage: build apps
5651
before_script:
57-
# build docker image
58-
- docker build --tag=p4a --file Dockerfile.py3 .
59-
# Run a background process to make sure that travis will not kill our tests in
60-
# case that the travis log doesn't produce any output for more than 10 minutes
61-
- while sleep 540; do echo "==== Still running (travis, don't kill me) ===="; done &
62-
script:
63-
- >
64-
docker run
65-
-e CI
66-
-e TRAVIS_JOB_ID
67-
-e TRAVIS_BRANCH
68-
-e ANDROID_SDK_HOME="/home/user/.android/android-sdk"
69-
-e ANDROID_NDK_HOME="/home/user/.android/android-ndk"
70-
p4a /bin/sh -c "$COMMAND"
71-
after_script:
72-
# kill the background process started before run docker
73-
- kill %1
52+
# ideally we would have a stage for that so it's not ran multiple time
53+
# but it seems Travis doesn't share the build cache
54+
- make docker/build
7455
name: Python 3 arm64-v8a
75-
# overrides requirements to skip `peewee` pure python module, see:
76-
# https://github.com/kivy/python-for-android/issues/1263#issuecomment-390421054
77-
env:
78-
COMMAND='. venv/bin/activate && cd testapps/ && python setup_testapp_python3_sqlite_openssl.py apk --sdk-dir $ANDROID_SDK_HOME --ndk-dir $ANDROID_NDK_HOME --requirements libffi,sdl2,pyjnius,kivy,python3,openssl,requests,sqlite3,setuptools --arch=arm64-v8a'
56+
script: make docker/run/make/testapps/python3/arm64-v8a
7957
- <<: *testing
8058
name: Python 3 armeabi-v7a
8159
os: osx
@@ -84,18 +62,10 @@ jobs:
8462
# installs java 1.8, android's SDK/NDK and p4a
8563
- make -f ci/makefiles/osx.mk
8664
- export JAVA_HOME=/Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home
87-
# Run a background process (like we do with linux tests)
88-
- while sleep 540; do echo "==== Still running (travis, don't kill me) ===="; done &
89-
script:
90-
- >
91-
cd testapps && python3 setup_testapp_python3_sqlite_openssl.py apk
92-
--sdk-dir $HOME/.android/android-sdk
93-
--ndk-dir $HOME/.android/android-ndk
94-
--requirements libffi,sdl2,pyjnius,kivy,python3,openssl,requests,sqlite3,setuptools
95-
--arch=armeabi-v7a
65+
script: make testapps/python3/armeabi-v7a PYTHON_WITH_VERSION=python3
9666
- <<: *testing
9767
name: Python 2 armeabi-v7a (with numpy)
98-
env: COMMAND='. venv/bin/activate && cd testapps/ && python setup_testapp_python2_sqlite_openssl.py apk --sdk-dir $ANDROID_SDK_HOME --ndk-dir $ANDROID_NDK_HOME --requirements sdl2,pyjnius,kivy,python2,openssl,requests,sqlite3,setuptools,numpy'
68+
script: make docker/run/make/testapps/python2/armeabi-v7a
9969
- <<: *testing
10070
name: Rebuild updated recipes
101-
env: COMMAND='. venv/bin/activate && ./ci/rebuild_updated_recipes.py'
71+
script: make docker/run/make/rebuild_updated_recipes

Dockerfile.py3

Lines changed: 54 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,11 @@ ENV LANG="en_US.UTF-8" \
2525
LANGUAGE="en_US.UTF-8" \
2626
LC_ALL="en_US.UTF-8"
2727

28-
RUN apt -y update -qq \
29-
&& apt -y install -qq --no-install-recommends curl unzip ca-certificates \
30-
&& apt -y autoremove
28+
RUN apt -y update -qq > /dev/null && apt -y install -qq --no-install-recommends \
29+
ca-certificates \
30+
curl \
31+
&& apt -y autoremove \
32+
&& apt -y clean
3133

3234
# retry helper script, refs:
3335
# https://github.com/kivy/python-for-android/issues/1306
@@ -37,38 +39,52 @@ RUN curl https://raw.githubusercontent.com/kadwanev/retry/1.0.1/retry \
3739

3840
ENV USER="user"
3941
ENV HOME_DIR="/home/${USER}"
40-
ENV ANDROID_HOME="${HOME_DIR}/.android"
41-
ENV WORK_DIR="${HOME_DIR}" \
42-
PATH="${HOME_DIR}/.local/bin:${PATH}"
42+
ENV WORK_DIR="${HOME_DIR}/app" \
43+
PATH="${HOME_DIR}/.local/bin:${PATH}" \
44+
ANDROID_HOME="${HOME_DIR}/.android" \
45+
JAVA_HOME="/usr/lib/jvm/java-8-openjdk-amd64"
4346

44-
# install system dependencies
45-
RUN ${RETRY} apt -y install -qq --no-install-recommends \
46-
python3 virtualenv python3-pip python3-venv \
47-
wget lbzip2 patch sudo python python-pip \
48-
&& apt -y autoremove
4947

50-
# build dependencies
51-
# https://buildozer.readthedocs.io/en/latest/installation.html#android-on-ubuntu-16-04-64bit
48+
# install system dependencies
5249
RUN dpkg --add-architecture i386 \
53-
&& ${RETRY} apt -y update -qq \
50+
&& ${RETRY} apt -y update -qq > /dev/null \
5451
&& ${RETRY} apt -y install -qq --no-install-recommends \
55-
build-essential ccache git python3 python3-dev \
56-
libncurses5:i386 libstdc++6:i386 libgtk2.0-0:i386 \
57-
libpangox-1.0-0:i386 libpangoxft-1.0-0:i386 libidn11:i386 \
58-
zip zlib1g-dev zlib1g:i386 \
59-
&& apt -y autoremove
60-
61-
# specific recipes dependencies (e.g. libffi requires autoreconf binary)
62-
RUN ${RETRY} apt -y install -qq --no-install-recommends \
63-
libffi-dev autoconf automake cmake gettext libltdl-dev libtool pkg-config \
52+
autoconf \
53+
automake \
54+
build-essential \
55+
ccache \
56+
cmake \
57+
gettext \
58+
git \
59+
lbzip2 \
60+
libffi-dev \
61+
libgtk2.0-0:i386 \
62+
libidn11:i386 \
63+
libltdl-dev \
64+
libncurses5:i386 \
65+
libpangox-1.0-0:i386 \
66+
libpangoxft-1.0-0:i386 \
67+
libstdc++6:i386 \
68+
libtool \
69+
openjdk-8-jdk \
70+
patch \
71+
pkg-config \
72+
python \
73+
python-pip \
74+
python3 \
75+
python3-dev \
76+
python3-pip \
77+
python3-venv \
78+
sudo \
79+
unzip \
80+
virtualenv \
81+
wget \
82+
zip \
83+
zlib1g-dev \
84+
zlib1g:i386 \
6485
&& apt -y autoremove \
6586
&& apt -y clean
6687

67-
# Install Java and set JAVA_HOME (to accept android's SDK licenses)
68-
RUN ${RETRY} apt -y install -qq --no-install-recommends openjdk-8-jdk \
69-
&& apt -y autoremove && apt -y clean
70-
ENV JAVA_HOME /usr/lib/jvm/java-8-openjdk-amd64
71-
7288
# prepare non root env
7389
RUN useradd --create-home --shell /bin/bash ${USER}
7490

@@ -80,15 +96,18 @@ RUN echo "%sudo ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
8096
RUN pip2 install --upgrade Cython==0.28.6
8197

8298
WORKDIR ${WORK_DIR}
83-
COPY --chown=user:user . ${WORK_DIR}
84-
RUN mkdir ${ANDROID_HOME} && chown --recursive ${USER} ${ANDROID_HOME}
99+
RUN mkdir ${ANDROID_HOME} && chown --recursive ${USER} ${HOME_DIR} ${ANDROID_HOME}
85100
USER ${USER}
86101

87102
# Download and install android's NDK/SDK
88-
RUN make -f ci/makefiles/android.mk target_os=linux
103+
COPY ci/makefiles/android.mk /tmp/android.mk
104+
RUN make --file /tmp/android.mk target_os=linux \
105+
&& sudo rm /tmp/android.mk
89106

90107
# install python-for-android from current branch
91-
RUN virtualenv --python=python3 venv \
92-
&& . venv/bin/activate \
93-
&& pip3 install --upgrade Cython==0.28.6 \
94-
&& pip3 install -e .
108+
COPY --chown=user:user Makefile README.md setup.py pythonforandroid/__init__.py ${WORK_DIR}/
109+
RUN mkdir pythonforandroid \
110+
&& mv __init__.py pythonforandroid/ \
111+
&& make virtualenv
112+
113+
COPY --chown=user:user . ${WORK_DIR}

Makefile

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
VIRTUAL_ENV ?= venv
2+
PIP=$(VIRTUAL_ENV)/bin/pip
3+
TOX=`which tox`
4+
ACTIVATE=$(VIRTUAL_ENV)/bin/activate
5+
PYTHON=$(VIRTUAL_ENV)/bin/python
6+
FLAKE8=$(VIRTUAL_ENV)/bin/flake8
7+
PYTEST=$(VIRTUAL_ENV)/bin/pytest
8+
SOURCES=src/ tests/
9+
PYTHON_MAJOR_VERSION=3
10+
PYTHON_MINOR_VERSION=6
11+
PYTHON_VERSION=$(PYTHON_MAJOR_VERSION).$(PYTHON_MINOR_VERSION)
12+
PYTHON_MAJOR_MINOR=$(PYTHON_MAJOR_VERSION)$(PYTHON_MINOR_VERSION)
13+
PYTHON_WITH_VERSION=python$(PYTHON_VERSION)
14+
DOCKER_IMAGE=kivy/python-for-android
15+
ANDROID_SDK_HOME ?= $(HOME)/.android/android-sdk
16+
ANDROID_NDK_HOME ?= $(HOME)/.android/android-ndk
17+
18+
19+
all: virtualenv
20+
21+
$(VIRTUAL_ENV):
22+
virtualenv --python=$(PYTHON_WITH_VERSION) $(VIRTUAL_ENV)
23+
$(PIP) install Cython==0.28.6
24+
$(PIP) install -e .
25+
26+
virtualenv: $(VIRTUAL_ENV)
27+
28+
# ignores test_pythonpackage.py since it runs for too long
29+
test:
30+
$(TOX) -- tests/ --ignore tests/test_pythonpackage.py
31+
@if test -n "$$CI"; then .tox/py$(PYTHON_MAJOR_MINOR)/bin/coveralls; fi; \
32+
33+
rebuild_updated_recipes: virtualenv
34+
$(PYTHON) ci/rebuild_updated_recipes.py
35+
36+
testapps/python2/armeabi-v7a: virtualenv
37+
. $(ACTIVATE) && cd testapps/ && \
38+
python setup_testapp_python2_sqlite_openssl.py apk --sdk-dir $(ANDROID_SDK_HOME) --ndk-dir $(ANDROID_NDK_HOME) \
39+
--requirements sdl2,pyjnius,kivy,python2,openssl,requests,sqlite3,setuptools,numpy
40+
41+
testapps/python3/arm64-v8a: virtualenv
42+
. $(ACTIVATE) && cd testapps/ && \
43+
python setup_testapp_python3_sqlite_openssl.py apk --sdk-dir $(ANDROID_SDK_HOME) --ndk-dir $(ANDROID_NDK_HOME) \
44+
--arch=arm64-v8a
45+
46+
testapps/python3/armeabi-v7a: virtualenv
47+
. $(ACTIVATE) && cd testapps/ && \
48+
python setup_testapp_python3_sqlite_openssl.py apk --sdk-dir $(ANDROID_SDK_HOME) --ndk-dir $(ANDROID_NDK_HOME) \
49+
--requirements libffi,sdl2,pyjnius,kivy,python3,openssl,requests,sqlite3,setuptools \
50+
--arch=armeabi-v7a
51+
52+
clean:
53+
find . -type d -name "__pycache__" -exec rm -r {} +
54+
find . -type d -name "*.egg-info" -exec rm -r {} +
55+
56+
clean/all: clean
57+
rm -rf $(VIRTUAL_ENV) .tox/
58+
59+
docker/pull:
60+
docker pull $(DOCKER_IMAGE):latest || true
61+
62+
docker/build:
63+
docker build --cache-from=$(DOCKER_IMAGE) --tag=$(DOCKER_IMAGE) --file=Dockerfile.py3 .
64+
65+
docker/push:
66+
docker push $(DOCKER_IMAGE)
67+
68+
docker/run/test: docker/build
69+
docker run --rm --env-file=.env $(DOCKER_IMAGE) 'make test'
70+
71+
docker/run/command: docker/build
72+
docker run --rm --env-file=.env $(DOCKER_IMAGE) /bin/sh -c "$(COMMAND)"
73+
74+
docker/run/make/%: docker/build
75+
docker run --rm --env-file=.env $(DOCKER_IMAGE) make $*
76+
77+
docker/run/shell: docker/build
78+
docker run --rm --env-file=.env -it $(DOCKER_IMAGE)

0 commit comments

Comments
 (0)