This repository provides a centralized GitHub Actions workflow designed to orchestrate multiple reusable workflows for
Python projects.
It acts as a single entry point to trigger selected CI jobs like linting, building packages, and generating
documentation.
You need to create the ./.github/workflows/ folder and the ./.github/workflows/ci.yml file in your repository and import this workflow.
name: Python CI
on:
push:
jobs:
ci:
uses: RWTH-EBC/ci_templates/.github/workflows/ci_pipeline.yml@mainThis is a minimal example that does not include any functionality.
- Python project with
setup.pyorpyproject.toml - Optional:
requirements.txtand/ordocs/requirements.txt - This workflow assumes conventional project layouts (e.g., code inside a folder named after the repo or explicitly passed)
- If you want to use the convert_examples workflow, you need a GitLab access token and must add it as a repository
secret
- For information on how to create a repository secret, read this guide
- If you want to use a workflow that pushes code (e.g., github_pages, semantic_release, or convert_examples), you need a
GitHub access token as a repository secret
- For information on how to create a GitHub access token, read this guide
- If you want to use the PyPI release workflow, you need PyPI credentials as repository secrets
- You can use either username/password or API token authentication
- For information on how to create a PyPI API token, read this guide
name: Python CI
on:
push:
jobs:
ci:
uses: RWTH-EBC/ci_templates/.github/workflows/ci_pipeline.yml@main
secrets:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
GITLAB_TOKEN: ${{ secrets.GITLAB_TOKEN }}
PYPI_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
with:
PYTHON_VERSION: "3.13"
USE_PYLINT: true
USE_RUFF: true
BUILD_PACKAGE: true
GENERATE_DOCUMENTATION: true
GH_PAGES: true
EXECUTE_TESTS: true
EXECUTE_COVERAGE_TEST: true
CONVERT_EXAMPLES: true
PYPI_RELEASE: true
EXTRA_REQUIREMENTS: '[dev]'
| Name | Type | Default | Description |
|---|---|---|---|
PYTHON_VERSION |
string | "3.10" |
Python version to use |
USE_PYLINT |
boolean | false |
Run static code analysis using pylint |
USE_RUFF |
boolean | false |
Run static code analysis using ruff |
BUILD_PACKAGE |
boolean | false |
Build and verify the Python package |
GENERATE_DOCUMENTATION |
boolean | false |
Build Sphinx documentation |
PYTHON_PACKAGE_NAME |
string | "" |
The name of your Python package ((needed when the package name is different then the repository)) |
USE_UV |
boolean | false |
Use uv instead of pip for installing dependencies |
INSTALL_REQUIREMENTS |
boolean | true |
Install from requirements.txt if it exists |
EXTRA_REQUIREMENTS |
string | "" |
Extra requirements to pass to pip install (e.g. [dev]) |
EXECUTE_TESTS |
boolean | false |
Run unit tests |
EXECUTE_COVERAGE_TEST |
boolean | false |
Run coverage tests |
COVERAGE_TYPE |
string | "default" |
Coverage mode: default or Dymola |
PYTHON_TEST_MATRIX |
string | '["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]' |
List of Python versions to run tests against as a matrix (e.g. ["3.10", "3.11"]) |
TEST_ENGINE |
string | "PYTEST" |
Test runner engine (PYTEST, unittest, ...) |
TEST_PATH |
string | "tests" |
Path to test folder |
FAIL-FAST |
boolean | false |
If true and one of the jobs in the python test matrix fails, all other jobs are cancelled |
USE_SEMANTIC_RELEASE |
boolean | false |
Use Python Semantic Release for versioning |
DIRECTORY |
string | "." |
Project base directory for semantic release |
COMMIT_SUBJECT |
string | "chore(release): version {version}" |
Commit message format for release |
GH_PAGES |
boolean | false |
Enable GitHub Pages deployment |
GH_PAGES_BRANCH |
string | "gh-pages" |
Target branch for GitHub Pages deployment |
GH_PAGES_DIR |
string | "/tmp/gh-pages" |
Temp directory for Pages workflow |
DOCS_PATH |
string | "docs" |
Path to documentation |
CREATE_PAGES_ON_FAILURE |
boolean | false |
Whether to generate pages even if previous steps failed |
CONVERT_EXAMPLES |
boolean | false |
Enable automatic example conversion into jupyter notebook |
GIT_REPO |
string | "" |
Git repo to push converted files to (only used for example conversion) |
EXAMPLE_CONVERTER_CONFIG |
string | "examples/converter.toml" |
Config file for example converter |
COMMIT_MSG |
string | "chore(examples): Automatic commit of example files in Markdown and Jupyter Notebook format." |
Commit message for example converter |
EXAMPLE_FILE_FOLDER |
string | "converter" |
Folder where the converter repo will be cloned |
PYPI_RELEASE |
boolean | false |
Enable PyPI release (only triggered on main branch with "PYPI-RELEASE" in commit message) |
PYTHON_VERSION_NAME |
string | "__version__" |
Name of the version attribute in your Python package |
| Name | Required | Description |
|---|---|---|
GH_TOKEN |
false | GitHub personal access token (required for releases and pages) |
GITLAB_TOKEN |
false | GitLab access token (required for example conversion) |
PYPI_PASSWORD |
false | PyPI password or API token (required for PyPI releases) |
This CI workflow can trigger the following individual workflows:
- Installs the local repository and its dependencies.
- Optionally uses
uvas the installer. - Builds the package using
python -m build. - Installs the package to verify its integrity.
- Runs
pylinton your codebase. - Auto-detects the module name if not provided.
- Generates a badge and a linting report as artifacts.
- Runs the
rufflinter for fast static code analysis. - Outputs a text report, HTML version, and a badge with issue count.
- Installs documentation dependencies (e.g.
sphinx,sphinx-rtd-theme). - Runs
sphinx-apidocandsphinx-build. - Publishes the generated HTML and a status badge.
- Runs unit tests using
pytestorunittest - Supports specifying a test directory and engine
- Uploads test results as GitHub Actions logs
- Executes tests with
coveragetracking - Generates
HTMLreport andcoverage-badge - Uploads coverage folder as an artifact
- Uses
python-semantic-releaseto automate releases - Requires conventional commits for version bumps
- Can publish to PyPI and update
CHANGELOG.md
- Deploys built documentation (e.g. Sphinx) to GitHub Pages
- Supports dynamic branch folders (e.g. per-branch previews)
- Automatically cleans up outdated previews
- Clones a template repo and converts
.mdand.ipynbexample files. - Commits and pushes the converted files to the current repo or a custom repo.
- Builds and releases your Python package to PyPI
- Creates GitHub releases with built distributions
- Trigger conditions:
- Only runs on commits to the
mainbranch - Only runs when commit message contains
PYPI-RELEASE - Only runs when
PYPI_RELEASEinput is set totrue
- Only runs on commits to the
- Automatically detects package version from your Python module
- Prevents duplicate releases (checks if version already exists on PyPI)
- Supports both PyPI username/password and API token authentication
The PyPI release workflow has special trigger conditions to prevent accidental releases:
- Branch: Must be a push to the
mainbranch - Commit Message: Must contain the text
PYPI-RELEASE - Input Parameter:
PYPI_RELEASEmust be set totrue - Dependencies: All other workflows (build, tests, etc.) must complete successfully
To trigger a PyPI release, make a commit with a message like:
git commit -m "feat: add new feature PYPI-RELEASE"And ensure your workflow configuration includes:
with:
PYPI_RELEASE: true
PYTHON_PACKAGE_NAME: "your-package-name"The workflow automatically detects your package version by:
- First trying to import your package and read the version attribute (default:
__version__) - Falling back to
setup.py --versionif available - Falling back to reading version from
pyproject.toml - Failing if no version can be determined
You can use either traditional username/password or API tokens:
Option 1: Username/Password
secrets:
PYPI_PASSWORD: ${{ secrets.PYPI_PASSWORD }} # Your PyPI passwordOption 2: API Token (Recommended)
secrets:
PYPI_PASSWORD: ${{ secrets.PYPI_PASSWORD }} # Your API tokenFor API token usage:
- Create an API token at https://pypi.org/manage/account/token/
- Set
PYPI_PASSWORDto your API token
Depending on which workflows are enabled, the CI run may upload the following artifacts:
build/— build status badgedist/— built package distributions (from release workflow)pylint/— Pylint output (text, HTML, badge)ruff/— Ruff output (text, HTML, badge)docs/— Sphinx HTML documentationcoverage/— Coverage reports and badges