├── .gitignore ├── .gitmodules ├── run_tests.sh ├── LICENSE.txt ├── Dockerfile ├── .github └── workflows │ └── build-and-push.yml └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | example_project/.tox 2 | example_project/__pycache__ 3 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "example_project"] 2 | path = example_project 3 | url = https://github.com/frenzymadness/python-tox-example.git 4 | -------------------------------------------------------------------------------- /run_tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | 3 | # This script will clone project from $GIT_URL (if defined) 4 | # and run tox in project directory 5 | 6 | TEMP_DIR=temp_project_dir 7 | 8 | if [ ! -z $GIT_URL ]; then 9 | git clone $GIT_URL $TEMP_DIR && cd $TEMP_DIR 10 | fi 11 | 12 | if [ ! -z "$DNF_INSTALL" ]; then 13 | echo $DNF_INSTALL | xargs dnf -y --setopt=tsflags=nodocs --setopt=deltarpm=false install 14 | fi 15 | 16 | # Mark the current directory as safe for Git: 17 | git --git-dir=~ config --system --add safe.directory $PWD 18 | 19 | if [ ! -z $WORKDIR ]; then 20 | echo "Changing directory to $WORKDIR" 21 | cd $WORKDIR 22 | fi 23 | 24 | /usr/bin/tox $TOX_PARAMS 25 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017 Lumír Balhar 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM registry.fedoraproject.org/fedora:42 2 | 3 | LABEL maintainer="Lumír 'Frenzy' Balhar " 4 | 5 | RUN dnf update -y \ 6 | && dnf install -y \ 7 | --setopt=tsflags=nodocs \ 8 | --setopt=deltarpm=false \ 9 | findutils \ 10 | pypy2-devel \ 11 | pypy3.10-devel \ 12 | pypy3.11-devel \ 13 | python3.6 \ 14 | python3.9 \ 15 | python3.10-devel \ 16 | python3.10-tkinter \ 17 | python3.11-devel \ 18 | python3.11-tkinter \ 19 | python3.12-devel \ 20 | python3.12-tkinter \ 21 | python3.13-devel \ 22 | python3.13-tkinter \ 23 | python3.14-devel \ 24 | python3.14-tkinter \ 25 | python3.14-freethreading-devel \ 26 | python3.14-freethreading-tkinter \ 27 | python3.15-devel \ 28 | python3.15-tkinter \ 29 | python3.15-freethreading-devel \ 30 | python3.15-freethreading-tkinter \ 31 | python3-pip \ 32 | /usr/bin/tox \ 33 | /usr/bin/virtualenv \ 34 | gcc \ 35 | gcc-c++ \ 36 | git-core \ 37 | make \ 38 | && dnf clean all 39 | 40 | ENV LANG=C.UTF-8 LC_ALL=C.UTF-8 41 | 42 | ADD run_tests.sh / 43 | 44 | CMD ["/run_tests.sh"] 45 | -------------------------------------------------------------------------------- /.github/workflows/build-and-push.yml: -------------------------------------------------------------------------------- 1 | name: Build, test and push container images 2 | 3 | on: 4 | push: 5 | branches: 6 | - 'master' 7 | pull_request: 8 | branches: 9 | - 'master' 10 | schedule: 11 | - cron: '48 23 * * 6' 12 | workflow_dispatch: 13 | 14 | env: 15 | FEDORA_VERSION: 42 16 | 17 | jobs: 18 | build-and-push: 19 | name: Build, test and push 20 | runs-on: ubuntu-latest 21 | strategy: 22 | matrix: 23 | include: 24 | - arch: amd64 25 | toxenv: py36,py39,py310,py311,py312,py313,py314,py315,py314t,py315t,pypy,pypy39,pypy310,pypy311 26 | - arch: arm64 27 | toxenv: py312 28 | - arch: ppc64le 29 | toxenv: py39,py311 30 | - arch: s390x 31 | toxenv: py39,py310,py312 32 | steps: 33 | - name: Checkout 34 | uses: actions/checkout@v2 35 | with: 36 | submodules: true 37 | - name: Set up QEMU 38 | uses: docker/setup-qemu-action@v1 39 | - name: Build 40 | uses: docker/build-push-action@v2 41 | with: 42 | context: . 43 | platforms: linux/${{ matrix.arch }} 44 | load: true 45 | tags: | 46 | fedorapython/fedora-python-tox:${{ matrix.arch }} 47 | fedorapython/fedora-python-tox:${{ matrix.arch }}-f${{ env.FEDORA_VERSION }} 48 | - name: Test local project 49 | env: 50 | TOXENV: ${{ matrix.toxenv }} 51 | run: | 52 | docker run --rm --platform linux/${{ matrix.arch }} -v $PWD/example_project:/src -w /src -e TOXENV fedorapython/fedora-python-tox:${{ matrix.arch }} 53 | - name: Test remote project 54 | env: 55 | TOXENV: ${{ matrix.toxenv }} 56 | run: | 57 | docker run --rm --platform linux/${{ matrix.arch }} -e TOXENV -e GIT_URL=https://github.com/frenzymadness/python-tox-example.git fedorapython/fedora-python-tox:${{ matrix.arch }} 58 | - name: Test parallel run 59 | env: 60 | TOXENV: ${{ matrix.toxenv }} 61 | run: | 62 | docker run --rm --platform linux/${{ matrix.arch }} -v $PWD/example_project:/src -w /src -e TOXENV -e TOX_PARAMS="-p auto" fedorapython/fedora-python-tox:${{ matrix.arch }} 63 | - name: Test dnf install and wheel build 64 | env: 65 | TOXENV: ${{ matrix.toxenv }} 66 | run: | 67 | docker run --rm --platform linux/${{ matrix.arch }} -e DNF_INSTALL="libffi-devel 'pkgconfig(libgit2) >= 1.9' /usr/bin/cowsay" fedorapython/fedora-python-tox:${{ matrix.arch }} sh -c "/run_tests.sh; pip install -I --no-deps --compile --no-binary :all: cffi pygit2~=1.17.0 && cowsay DONE" 68 | - name: Test external project with WORKDIR 69 | run: | 70 | docker run --rm --platform linux/${{ matrix.arch }} -e TOXENV=py3 -e GIT_URL=https://github.com/frenzymadness/nflxprofile.git -e WORKDIR=python fedorapython/fedora-python-tox:${{ matrix.arch }} 71 | - name: Login to DockerHub 72 | uses: docker/login-action@v1 73 | if: github.event_name == 'push' || github.event_name == 'schedule' 74 | with: 75 | username: ${{ secrets.DOCKERHUB_USERNAME }} 76 | password: ${{ secrets.DOCKERHUB_TOKEN }} 77 | - name: Push to Dockerhub 78 | uses: docker/build-push-action@v2 79 | if: github.event_name == 'push' || github.event_name == 'schedule' 80 | with: 81 | context: . 82 | platforms: linux/${{ matrix.arch }} 83 | push: true 84 | tags: | 85 | fedorapython/fedora-python-tox:${{ matrix.arch }} 86 | fedorapython/fedora-python-tox:${{ matrix.arch }}-f${{ env.FEDORA_VERSION }} 87 | 88 | description_update: 89 | name: 'Update Dockerhub description' 90 | if: github.event_name == 'push' 91 | needs: build-and-push 92 | runs-on: ubuntu-latest 93 | steps: 94 | - name: Checkout 95 | uses: actions/checkout@v4 96 | - name: 'Update Dockerhub description' 97 | uses: peter-evans/dockerhub-description@v4 98 | with: 99 | username: ${{ secrets.DOCKERHUB_USERNAME }} 100 | password: ${{ secrets.DOCKERHUB_TOKEN }} 101 | repository: fedorapython/fedora-python-tox 102 | 103 | release: 104 | name: 'Update and test manifests' 105 | if: github.event_name == 'push' || github.event_name == 'schedule' 106 | needs: build-and-push 107 | runs-on: ubuntu-latest 108 | steps: 109 | - name: Login to DockerHub 110 | uses: docker/login-action@v1 111 | with: 112 | username: ${{ secrets.DOCKERHUB_USERNAME }} 113 | password: ${{ secrets.DOCKERHUB_TOKEN }} 114 | - name: Pull all images 115 | run: > 116 | for arch in amd64 arm64 ppc64le s390x; do 117 | docker pull fedorapython/fedora-python-tox:$arch; 118 | docker pull fedorapython/fedora-python-tox:${arch}-f${{ env.FEDORA_VERSION }}; 119 | done 120 | - name: Create and push manifest for the :latest tag 121 | env: 122 | DOCKER_CLI_EXPERIMENTAL: enabled 123 | run: > 124 | docker manifest create fedorapython/fedora-python-tox:latest 125 | fedorapython/fedora-python-tox:amd64 126 | fedorapython/fedora-python-tox:arm64 127 | fedorapython/fedora-python-tox:ppc64le 128 | fedorapython/fedora-python-tox:s390x; 129 | docker manifest push fedorapython/fedora-python-tox:latest; 130 | - name: Test the latest manifest 131 | run: | 132 | docker manifest inspect fedorapython/fedora-python-tox:latest | grep '"architecture":' | grep -Ez '(.*(amd64|arm64|ppc64le|s390x).*){4}' 133 | - name: Create and push manifest for the versioned tag 134 | env: 135 | DOCKER_CLI_EXPERIMENTAL: enabled 136 | run: > 137 | docker manifest create fedorapython/fedora-python-tox:f${{ env.FEDORA_VERSION }} 138 | fedorapython/fedora-python-tox:amd64-f${{ env.FEDORA_VERSION }} 139 | fedorapython/fedora-python-tox:arm64-f${{ env.FEDORA_VERSION }} 140 | fedorapython/fedora-python-tox:ppc64le-f${{ env.FEDORA_VERSION }} 141 | fedorapython/fedora-python-tox:s390x-f${{ env.FEDORA_VERSION }}; 142 | docker manifest push fedorapython/fedora-python-tox:f${{ env.FEDORA_VERSION }}; 143 | - name: Test the versioned manifest 144 | run: | 145 | docker manifest inspect fedorapython/fedora-python-tox:f${{ env.FEDORA_VERSION }} | grep '"architecture":' | grep -Ez '(.*(amd64|arm64|ppc64le|s390x).*){4}' 146 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Fedora + Pythons + Tox in docker image 2 | 3 | ![CI/CD status](https://github.com/fedora-python/fedora-python-tox/actions/workflows/build-and-push.yml/badge.svg) 4 | 5 | This repository contains source code for Docker image designed to help you 6 | run your Tox tests with all available Python versions in Docker container. 7 | 8 | [Docker image is hosted on Docker Hub](https://hub.docker.com/r/fedorapython/fedora-python-tox/) and build automatically after every push to master branch. 9 | 10 | # Fedora base image version 11 | 12 | We usually add the newest Pythons to all supported Fedora releases. We also have to remove the oldest ones 13 | from time to time. These are the reasons why we move this container image from Fedora N to N+1 when 14 | N goes EOL. 15 | 16 | # Installed packages 17 | 18 | On top of stable Fedora, this Docker image contains: 19 | - Python 3.6, 3.9, 3.10, 3.11, 3.12, 3.13, 3.14, 3.15 20 | - Freethreading Python 3.14, 3.15 21 | - Pypy2, Pypy3.10 and Pypy3.11 22 | - python3-pip 23 | - gcc, gcc-c++, git-core and make 24 | - tox 25 | - virtualenv 26 | 27 | # Docker and Podman 28 | 29 | The image works very well with both [Docker](https://www.docker.com/) and [Podman](https://podman.io/) so you can use containers management tool you prefer. 30 | 31 | # Example usage with local source code 32 | 33 | If you want to use this Docker image as environmet for your test, use this command: 34 | 35 | ``` 36 | cd example_project 37 | docker run --rm -it -v $PWD:/src -w /src fedorapython/fedora-python-tox 38 | 39 | py27 create: /src/.tox/py27 40 | py27 installdeps: pytest < 3.3 41 | py27 installed: py==1.5.3,pytest==3.2.5 42 | py27 runtests: PYTHONHASHSEED='85819776' 43 | py27 runtests: commands[0] | pytest 44 | ==== test session starts ==== 45 | platform linux2 -- Python 2.7.18, pytest-3.2.5, py-1.5.3, pluggy-0.4.0 46 | rootdir: /src, inifile: 47 | collected 10 items 48 | 49 | test_fac.py .......... 50 | 51 | ==== 10 passed in 0.02 seconds ==== 52 | 53 | py35 create: /src/.tox/py35 54 | py35 installdeps: pytest < 3.3 55 | py35 installed: py==1.5.3,pytest==3.2.5 56 | py35 runtests: PYTHONHASHSEED='1223497559' 57 | py35 runtests: commands[0] | pytest 58 | ==== test session starts ==== 59 | platform linux -- Python 3.5.10, pytest-3.2.5, py-1.5.3, pluggy-0.4.0 60 | rootdir: /src, inifile: 61 | collected 10 items 62 | 63 | test_fac.py .......... 64 | 65 | ==== 10 passed in 0.04 seconds ==== 66 | ... etc ... 67 | ``` 68 | 69 | This command will download an image from Docker hub for you 70 | 71 | ``` 72 | Unable to find image 'fedorapython/fedora-python-tox:latest' locally 73 | Trying to pull repository docker.io/fedorapython/fedora-python-tox ... 74 | sha256:d4b51931dd86a33552b6a08f39575db336b606f4ccebbc48f390d7f728367a6f: Pulling from docker.io/fedorapython/fedora-python-tox 75 | 76 | ``` 77 | 78 | Command and argument description: 79 | 80 | - `docker run` - run docker image 81 | - `--rm` - automatically remove the container when it exits 82 | - `-i` - keep STDIN open even if not attached 83 | - `-t` - allocate a pseudo-TTY 84 | - `-v $PWD:/src` - mount your current working directory to /src inside container 85 | - `-w` - use /src (mountpoint) as working directory inside container 86 | - `fedorapython/fedora-python-tox` - name of Docker image 87 | 88 | Tox is run automatically with this container. How cool! 89 | 90 | You also can limit Tox tests by passing environment variable to Docker. For example: 91 | 92 | ``` 93 | cd example_project 94 | docker run --rm -it -v $PWD:/src -w /src -e TOXENV=pypy3 fedorapython/fedora-python-tox 95 | pypy3 create: /src/.tox/pypy3 96 | pypy3 installdeps: pytest 97 | pypy3 installed: cffi==1.10.1,greenlet==0.4.12,py==1.4.34,pytest==3.2.2,readline==6.2.4.1 98 | pypy3 runtests: PYTHONHASHSEED='68938415' 99 | pypy3 runtests: commands[0] | pytest 100 | ==== test session starts ==== 101 | platform linux -- Python 3.5.3[pypy-5.8.0-beta], pytest-3.2.2, py-1.4.34, pluggy-0.4.0 102 | rootdir: /src, inifile: 103 | collected 10 items 104 | 105 | test_fac.py .......... 106 | 107 | ==== passed in 0.24 seconds ==== 108 | 109 | pypy3: commands succeeded 110 | congratulations :) 111 | ``` 112 | 113 | ## Parallel run and other tox features 114 | 115 | You can adjust the behavior of tox by setting TOX_PARAMS variable with any combination of CLI parameters. It's useful for example for parallel run of your tests. 116 | 117 | ``` 118 | docker run --rm -it -v $PWD:/src -w /src -e TOX_PARAMS="-p auto" fedorapython/fedora-python-tox 119 | ✔ OK py37 in 1.664 seconds 120 | ✔ OK py35 in 1.893 seconds 121 | ✔ OK py27 in 1.902 seconds 122 | ✔ OK py38 in 1.913 seconds 123 | ✔ OK py36 in 1.987 seconds 124 | ✔ OK pypy in 2.904 seconds 125 | ✔ OK pypy3 in 3.688 seconds 126 | __________________________________________ summary ___________________________________________ 127 | py27: commands succeeded 128 | py35: commands succeeded 129 | py36: commands succeeded 130 | py37: commands succeeded 131 | py38: commands succeeded 132 | pypy: commands succeeded 133 | pypy3: commands succeeded 134 | congratulations :) 135 | ``` 136 | 137 | # Example usage with GIT URL 138 | 139 | Instead of mounting local folder with source code into container, you can 140 | provide HTTPS URL of your GIT repository and it will be cloned automatically. 141 | 142 | For example: 143 | ``` 144 | docker run --rm -it -e GIT_URL=https://github.com/fedora-python/pyp2rpm.git fedorapython/fedora-python-tox 145 | Cloning into 'temp_project_dir'... 146 | remote: Counting objects: 3075, done. 147 | remote: Compressing objects: 100% (5/5), done. 148 | remote: Total 3075 (delta 1), reused 3 (delta 1), pack-reused 3069 149 | Receiving objects: 100% (3075/3075), 2.97 MiB | 2.57 MiB/s, done. 150 | Resolving deltas: 100% (2188/2188), done. 151 | GLOB sdist-make: /temp_project_dir/setup.py 152 | py27 create: /temp_project_dir/.tox/py27 153 | 154 | ... etc ... 155 | ``` 156 | 157 | # Installing RPM packages from Fedora 158 | 159 | Sometimes, your tests need some system packages (such as C libraries). 160 | You can install them via `dnf` by setting the `$DNF_INSTALL` environment variable: 161 | 162 | ``` 163 | docker run --rm -it -v $PWD:/src -w /src -e DNF_INSTALL="libyaml-devel libgit2-devel" fedorapython/fedora-python-tox 164 | ... 165 | Installed: 166 | http-parser-2.9.3-2.fc32.x86_64 libgit2-1.0.1-2.fc32.x86_64 167 | libgit2-devel-1.0.1-2.fc32.x86_64 libssh2-1.9.0-5.fc32.x86_64 168 | libyaml-devel-0.2.2-3.fc32.x86_64 openssl-devel-1:1.1.1g-1.fc32.x86_64 169 | pcre2-devel-10.35-4.fc32.x86_64 pcre2-utf16-10.35-4.fc32.x86_64 170 | pcre2-utf32-10.35-4.fc32.x86_64 zlib-devel-1.2.11-21.fc32.x86_64 171 | 172 | Complete! 173 | py27 create: /src/.tox/py27 174 | ... 175 | ``` 176 | 177 | You can install packages by any RPM *Provides*, for example: 178 | 179 | * Fedora package names, e.g. `libgit2-devel`, 180 | * pkgconfig names, e.g. `pkgconfig(libgit2)`, or 181 | * commands, e.g. `/usr/bin/cowsay`. 182 | 183 | Complex specifications including spaces have to be enclosed in single quotes 184 | inside the double quotes. For example: `-e DNF_INSTALL="libyaml-devel 'pytest > 7'"` 185 | 186 | # WORKDIR 187 | 188 | If your `tox.ini` file is not in the root directory of your project, set `WORKDIR` to the path you want to cd to before the tests are executed. 189 | 190 | ``` 191 | docker run --rm -it -e TOXENV=py310-minimal -e GIT_URL=https://github.com/trezor/trezor-firmware.git -e WORKDIR=python fedora-python-tox 192 | ``` 193 | 194 | # License 195 | 196 | MIT 197 | --------------------------------------------------------------------------------