Metadata-Version: 2.4
Name: desy_fssc_ci_python
Version: 0.1.0a3
Summary: Project to test the GitLab CI components implemented in https://gitlab.desy.de/fs-sc/ci/python
Author: Marc-Olivier Andrez
Maintainer: Marc-Olivier Andrez
License-Expression: MIT
Project-URL: Repository, https://gitlab.desy.de/fs-sc/ci/python
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE.txt
Requires-Dist: requests
Provides-Extra: dev
Requires-Dist: black[d]; extra == "dev"
Requires-Dist: coverage; extra == "dev"
Requires-Dist: pytest; extra == "dev"
Dynamic: license-file

# CI/Python

This project contains GitLab CI templates and
[components](https://docs.gitlab.com/ci/components/) that we can use in GitLab CI
pipelines of Python projects.

[TOC]

## Components

### [build-wheel](templates/build-wheel.yml)

Component that builds a wheel and tarball for the given project (it runs
`python3 -m build`) using the provided `python-version`. In addition, the component
checks that the wheel does not contain the `tests/` directory, and that the files with
the `files-not-in-dist` regex pattern are not present either in the produced wheel or
tarball.

Example:

```yaml
include:
  - component: "gitlab.desy.de/fs-sc/ci/python/build-wheel@main"
    inputs:
      python-version: "3.10"
      files-not-in-dist: "(cspell|etc/|templates/)"
```

### [pre-commit](templates/pre-commit.yml)

Component that runs [pre-commit](https://pre-commit.com/) using the provided
`python-versions`. You can install packages before `pre-commit` runs by providing
`install-commands` a list of commands to execute. Typical install commands are
`python3 -m pip install <package>` and `apt-get install <package>`.

> [!NOTE]
> `pre-commit` requires a configuration file `.pre-commit-config.yaml` in your project,
> see for example [.pre-commit-config.yaml](.pre-commit-config.yaml).

Example:

```yaml
include:
  - component: "gitlab.desy.de/fs-sc/ci/python/pre-commit@main"
    inputs:
      python-versions: ["3.10"]
      install-commands:
        - apt-get install -y --no-install-recommends libatomic1
        - python3 -m pip install mypy
```

### [publish-wheel](templates/publish-wheel.yml)

Component that publishes the wheel and tarball produced by the
[`build-wheel`](#build-wheel) component to PyPI by running the
[`twine upload`](https://twine.readthedocs.io/en/stable/#twine-upload) command with the
provided `python-version` and `twine-options`. The component only runs for Git tags.

Example:

```yaml
include:
  - component: "gitlab.desy.de/fs-sc/ci/python/publish-wheel@main"
    inputs:
      python-version: "3.10"
      # Assuming that you already defined PYPI_API_TOKEN:
      twine-options: --password "$PYPI_API_TOKEN" --skip-existing
```

> [!NOTE]
> In addition to the provided `twine-options`, the `twine` command is executed with the
> options `--verbose` and `--username "__token__"`.

> [!NOTE]
> It is possible to define `PYPI_API_TOKEN` in the
> [CI/CD settings](https://gitlab.desy.de/fs-sc/ci/python/-/settings/ci_cd#js-cicd-variables-settings)
> of the project. If you define this variable as protected, you need to define a pattern
> such as `v*.*.*` for protected tags in the
> [repository settings](https://gitlab.desy.de/fs-sc/ci/python/-/settings/repository#js-protected-tags-settings).

### [pytest](templates/pytest.yml), [pytest-tarball](templates/pytest-tarball.yml), [pytest-wheel](templates/pytest-wheel.yml), [pytest-with-coverage](templates/pytest-with-coverage.yml)

The `pytest` component runs [pytest](https://docs.pytest.org/en/stable/) using the
provided `python-versions` and `pytest-options`. You can install packages before `pytest`
runs by providing `install-commands` a list of commands to execute. Typical install
commands are `python3 -m pip install <package>` and `apt-get install <package>`. You can
also provide the CI job with `services` that will run Docker containers accessible from
the tests.

Example:

```yaml
include:
  - component: "gitlab.desy.de/fs-sc/ci/python/pytest@main"
    inputs:
      python-versions: ["3.10", "3.11", "3.12", "3.13", "3.14"]
      install-commands:
        - python3 -m pip install "${CI_PROJECT_DIR}[asapo,tests,zmq]"
      pytest-options: "-vv --log-cli-level=DEBUG"
      services:
        - name: gitlab.desy.de:5555/asapo/asapo/asapo-standalone-dev:latest
```

Similarly, the components `pytest-tarball` and `pytest-wheel` runs `pytest` respectively
on the tarball and wheel produced by the [`build-wheel`](#build-wheel) component.

The component `pytest-with-coverage` runs `pytest` with coverage and produces a JUnit XML
test report. This component accepts a single `python-version` instead of several
`python-versions` for the other components.

To avoid repeating the code between the includes of these components, we can extract a
[YAML anchor](https://yaml.cc/tutorial/advanced-features.html). For example:

```yaml
.common_test_inputs: &common_test_inputs
  install-commands:
    - python3 -m pip install "${PACKAGE}[asapo,tests,zmq]"
  pytest-options: "-vv --log-cli-level=DEBUG"
  services:
    - name: gitlab.desy.de:5555/asapo/asapo/asapo-standalone-dev:latest

include:
  - component: "gitlab.desy.de/fs-sc/ci/python/build-wheel@main"
  - component: "gitlab.desy.de/fs-sc/ci/python/pytest@main"
    inputs:
      <<: *common_test_inputs
      python-versions: ["3.9"]
  - component: "gitlab.desy.de/fs-sc/ci/python/pytest-with-coverage@main"
    inputs:
      <<: *common_test_inputs
      python-version: "3.9"
  - component: "gitlab.desy.de/fs-sc/ci/python/pytest-wheel@main"
    inputs:
      <<: *common_test_inputs
      python-versions: ["3.9", "3.10", "3.11", "3.12"]
  - component: "gitlab.desy.de/fs-sc/ci/python/pytest-tarball@main"
    inputs:
      <<: *common_test_inputs
      python-versions: ["3.9"]
```

> [!NOTE]
> The first `install-commands` mentions a variable `PACKAGE`. Each component defines the
> value of this variable:
>
> | Component              | Value of $PACKAGE                                                       |
> | ---------------------- | ----------------------------------------------------------------------- |
> | `pytest`               | `$CI_PROJECT_DIR`                                                       |
> | `pytest-with-coverage` | `$CI_PROJECT_DIR`                                                       |
> | `pytest-tarball`       | tarball in the `dist/` directory created by the `build-wheel` component |
> | `pytest-wheel`         | wheel in the `dist/` directory created by the `build-wheel` component   |

## Templates

### [templates/workflows/branch-pipelines.yml](templates/workflows/branch-pipelines.yml)

You can use the `branch-pipelines` workflow template to allow CI pipelines to run only on
branches and tags with the format `v<PEP 440 version>`, see
[`PEP_440_VERSION_REGEX`](templates/workflows/branch-pipelines.yml#L8).

Usage example:

```yaml
include:
  - project: "fs-sc/ci/python"
    ref: "main"
    file:
      - "templates/workflows/branch-pipelines.yml"
```
