Python Multi-Version Test Template =============================================================================== This template triggers test executions across multiple Python versions using parallel jobs. Useful for libraries or projects that must ensure compatibility between different Python versions. Usage ----- In your project's ``.gitlab-ci.yml``: .. code-block:: yaml include: - project: "bytecode-solutions/core/core-gitlab-templates" file: "tests/run_tests.yml" Advanced Usage with Custom Command ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ You can customize the test command to run: .. code-block:: yaml run-tests: extends: .run_tests variables: cmd: "pytest tests/ -v --cov=mypackage" Installing Additional Extras ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ If your project requires optional dependency groups beyond ``[dev]``, pass them via the ``extras`` input: .. code-block:: yaml include: - project: "bytecode-solutions/core/core-gitlab-templates" file: "templates/tests/run_tests.yml" ref: "release" inputs: extras: "postgres,mongo" This installs ``.[postgres,mongo]`` on top of the base ``.[dev]`` install before running the test command. Custom Python Versions ~~~~~~~~~~~~~~~~~~~~~~ Override the default Python versions: .. code-block:: yaml run-tests: extends: .run_tests variables: versions: - PYTHON_IMAGE: "python:3.11" - PYTHON_IMAGE: "python:3.12" - PYTHON_IMAGE: "python:3.13" Parameters ---------- The template defines the following inputs: ``branch`` Optional: Restrict execution to a specific branch. If empty, the tests will run on all branches. Default: ``""`` (runs on all branches) ``stage`` The pipeline stage in which the test job runs. Default: ``tests`` ``cmd`` Command to execute to run the tests. This allows you to customize how tests are executed for your specific project. Default: ``python manager.py run-coverage`` ``extras`` Optional: additional pip extras to install before running the tests. Accepts a comma-separated string of extra names (e.g. ``all``, ``postgres,mongo``). Installed as ``pip install ".[extras]"`` after the base ``[dev]`` install. When empty, no extra install step is run. Default: ``""`` (no extras installed) ``versions`` Python versions to test. Array of image specifications that determines which Python versions will be tested in parallel. Default: - ``python:3.9`` - ``python:3.10`` - ``python:3.11`` - ``python:3.12`` - ``python:3.13`` - ``python:3.14`` - ``pypy:3.11`` Behavior -------- The job performs the following steps: 1. **PyPy Support**: Automatically detects PyPy images and installs Rust toolchain (required for packages with Rust dependencies) 2. **Environment Setup**: Creates a virtual environment for isolated testing 3. **Package Installation**: Attempts to install the package with ``[dev]`` extras. If the ``[dev]`` extra doesn't exist, falls back to installing the base package 4. **Extras Installation**: If the ``extras`` input is non-empty, installs the specified extras (e.g. ``pip install ".[postgres,mongo]"``) 5. **Test Execution**: Runs the specified test command 5. **Parallel Execution**: Executes tests simultaneously across all specified Python versions using GitLab's matrix feature Special Features ---------------- PyPy Support ~~~~~~~~~~~~ The template automatically detects when running on PyPy and installs the Rust toolchain. This is essential for packages that have dependencies with Rust extensions (like ``cryptography``): .. code-block:: bash if [[ "$PYTHON_IMAGE" == "pypy:3.11" ]]; then apt install -y curl build-essential curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y source "$HOME/.cargo/env" fi Flexible Installation ~~~~~~~~~~~~~~~~~~~~~ The template gracefully handles projects that may or may not define development extras: .. code-block:: bash pip install ".[dev]" || pip install . This ensures the job doesn't fail if your ``pyproject.toml`` or ``setup.py`` doesn't define a ``[dev]`` extra. Extras Installation ~~~~~~~~~~~~~~~~~~~ After the base install, the template conditionally installs any additional extras declared via the ``extras`` input: .. code-block:: bash if [[ -n "postgres,mongo" ]]; then pip install ".[postgres,mongo]" fi When ``extras`` is empty (the default), this step is skipped entirely. Parallel Execution ~~~~~~~~~~~~~~~~~~ Tests run simultaneously across all Python versions using GitLab's matrix feature, significantly reducing total pipeline execution time. Pip Caching ~~~~~~~~~~~ The template caches pip packages in ``.pip_cache`` to speed up subsequent runs. .. tip:: Consider reducing the number of Python versions tested on feature branches and running the full matrix only on main branches or tags to save CI resources. Example: Targeted Testing ~~~~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: yaml # Test only latest versions on feature branches run-tests-quick: extends: .run_tests variables: versions: - PYTHON_IMAGE: "python:3.13" only: - branches except: - main # Full test matrix on main branch run-tests-full: extends: .run_tests only: - main - tags