Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
627fb59
fix: improve mypy settings such that it collects all package and test…
jenstroeger Jul 26, 2026
dd75570
chore(deps): bump oracle/macaron from 0.24.0 to 0.25.0 (#1263)
dependabot[bot] Jul 29, 2026
823cb93
chore(deps): bump ossf/scorecard-action from 2.4.3 to 2.4.4 (#1261)
dependabot[bot] Jul 29, 2026
9634dac
chore(deps-dev): bump faker from 40.28.1 to 40.36.0 (#1259)
dependabot[bot] Jul 29, 2026
579d257
chore(deps-dev): bump pytest-env from 1.6.0 to 1.7.0 (#1258)
dependabot[bot] Jul 29, 2026
d7b8fa7
chore(deps): bump the pre-commit group across 1 directory with 2 upda…
dependabot[bot] Jul 29, 2026
677ee0c
chore(deps): bump actions/setup-python from 6.3.0 to 7.0.0 (#1241)
dependabot[bot] Jul 29, 2026
96c41f3
chore(deps-dev): update mypy requirement from !=1.20.2,<1.21,>=1.0.0 …
dependabot[bot] Jul 29, 2026
9e45cf6
chore(deps): bump actions/checkout from 7.0.0 to 7.0.1 (#1239)
dependabot[bot] Jul 29, 2026
438bc69
chore(deps-dev): update hypothesis requirement from <6.152.10,>=6.21.…
dependabot[bot] Jul 29, 2026
6e7d0eb
chore(deps-dev): bump commitizen from 4.16.4 to 4.16.5 (#1240)
dependabot[bot] Jul 29, 2026
6b6ee70
refactor: improve Makefile variables used to build artifact names, re…
jenstroeger Jul 29, 2026
3503d17
chore: remove unnecessary cmd line flag from `rm` in a Makefile recip…
jenstroeger Jul 29, 2026
b9cc94b
chore: fix comment in pre-commit config (#1252)
jenstroeger Jul 29, 2026
30c6f9e
docs: mention the “immutable” tagging and remove the (uninteresting) …
jenstroeger Jul 29, 2026
dc2ebdd
chore: rename table names for pylint in pyproject.toml (#1249)
jenstroeger Jul 29, 2026
db08c6f
chore(deps): bump step-security/harden-runner from 2.19.4 to 2.20.0 (…
dependabot[bot] Jul 29, 2026
d9fd0a2
fix: make sure to call the `pre-commit` from the local venv instead o…
jenstroeger Jul 29, 2026
7badefa
refactor: use Dependency Groups (PEP 735) instead of misusing package…
jenstroeger Jul 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/_build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,18 +55,18 @@ jobs:
steps:

- name: Harden Runner
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
disable-sudo: true

- name: Check out repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0

- name: Set up Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: ${{ matrix.python }}

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/_generate-rebase.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ jobs:
steps:

- name: Harden Runner
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs

- name: Check out repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
token: ${{ secrets.REPO_ACCESS_TOKEN }}
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/_wiki-documentation.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,15 @@ jobs:
steps:

- name: Harden Runner
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
disable-sudo: true

# Check out the repository's Wiki repo into the wiki/ folder. The token is required
# only for private repositories.
- name: Check out repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
token: ${{ secrets.REPO_ACCESS_TOKEN }}
repository: ${{ format('{0}.wiki', github.repository) }}
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/codeql-analysis.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,16 @@ jobs:
steps:

- name: Harden Runner
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
disable-sudo: true

- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Set up Python ${{ matrix.python }}
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: ${{ matrix.python }}

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/macaron-analysis.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ jobs:
steps:

- name: Check out repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0

# Check the GitHub Actions workflows in the repository for vulnerabilities.
- name: Run Macaron action
uses: oracle/macaron@4ddb55e3c9ef2c77b548be55c557078c4476fd9c # v0.24.0
uses: oracle/macaron@794eec32782979f577efb5ff71d585f683a3550f # v0.25.0
with:
repo_path: ./
policy_file: check-github-actions
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/pr-conventional-commits.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@
steps:

- name: Check out repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0

- name: Set up Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: '3.14'

Expand All @@ -36,7 +36,7 @@
- name: Set up Commitizen
run: |
pip install --upgrade pip wheel
pip install 'commitizen ==4.16.4'
pip install 'commitizen ==4.16.5'

Check warning

Code scanning / Scorecard

Pinned-Dependencies Medium

score is 6: pipCommand not pinned by hash
Click Remediation section below to solve this issue

# Run Commitizen to check the title of the PR which triggered this workflow, and check
# all commit messages of the PR's branch. If any of the checks fails then this job fails.
Expand Down
20 changes: 10 additions & 10 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,26 +30,26 @@
steps:

- name: Harden Runner
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
disable-sudo: true

- name: Check out repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
token: ${{ secrets.REPO_ACCESS_TOKEN }}

- name: Set up Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: '3.14'

- name: Set up Commitizen
run: |
pip install --upgrade pip wheel
pip install 'commitizen ==4.16.4'
pip install 'commitizen ==4.16.5'

Check warning

Code scanning / Scorecard

Pinned-Dependencies Medium

score is 6: pipCommand not pinned by hash
Click Remediation section below to solve this issue

- name: Set up user
run: |
Expand Down Expand Up @@ -98,13 +98,13 @@
steps:

- name: Harden Runner
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
disable-sudo: true

- name: Check out repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0

Expand All @@ -126,14 +126,14 @@

# Create the Release Notes using commitizen.
- name: Set up Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: '3.14'

- name: Set up Commitizen
run: |
pip install --upgrade pip wheel
pip install 'commitizen ==4.16.4'
pip install 'commitizen ==4.16.5'

Check warning

Code scanning / Scorecard

Pinned-Dependencies Medium

score is 6: pipCommand not pinned by hash
Click Remediation section below to solve this issue

- name: Create Release Notes
run: cz changelog --dry-run "$(cz version --project)" > RELEASE_NOTES.md
Expand Down Expand Up @@ -199,13 +199,13 @@
steps:

- name: Harden Runner
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
disable-sudo: true

- name: Check out repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0

Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/scorecards-analysis.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,18 @@ jobs:
steps:

- name: Harden Runner
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
disable-sudo: true

- name: Check out repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- name: Run analysis
uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
uses: ossf/scorecard-action@2d1146689b8cda280b9bc96326124645441f03bc # v2.4.4
with:
results_file: results.sarif
results_format: sarif
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/sync-with-upstream.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
steps:

- name: Check out template repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
# If you decide to change the upstream template repository to a private one, uncomment
# the following argument to pass the required token to be able to check it out.
Expand All @@ -31,7 +31,7 @@ jobs:
path: template

- name: Check out current repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
token: ${{ secrets.REPO_ACCESS_TOKEN }}
fetch-depth: 0
Expand Down
11 changes: 6 additions & 5 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ repos:

# Commitizen enforces semantic and conventional commit messages.
- repo: https://github.com/commitizen-tools/commitizen
rev: 205e71c26d6dd6a802ca674c9ae4d12f1103a9bb # frozen: v4.16.4
rev: 6afcd8e9560ddf1b9a5032262a0be26540e85fb3 # frozen: v4.16.5
hooks:
- id: commitizen
name: Check conventional commit message
stages: [commit-msg]

# Ruff formats and lints code.
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: c59bba8fb259db0fec2bbb77ad8ba51ea7341b56 # frozen: v0.15.20
rev: cb8c523fd4835aba42af70f4cad5568db4df0b6c # frozen: v0.16.0
hooks:
- id: ruff-format
args: [--config, pyproject.toml]
Expand All @@ -49,9 +49,10 @@ repos:
name: Check typing annotations
entry: mypy
language: python
files: ^src/package/|^tests/
files: ^src/package/|^tests/ # Declare files to run the hook only when necessary.
types: [text, python]
args: [--explicit-package-bases, --config-file, pyproject.toml]
pass_filenames: false
args: [--config-file, pyproject.toml]

# Enable a whole bunch of useful helper hooks, too.
# See https://pre-commit.com/hooks.html for more hooks.
Expand Down Expand Up @@ -111,7 +112,7 @@ repos:
hooks:
- id: actionlint

# On push to the remote, run all tests.
# On push to the remote, run all unit tests.
- repo: local
hooks:
- id: pytest
Expand Down
26 changes: 14 additions & 12 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ PACKAGE_VERSION := $(shell python -c $$'try: import $(PACKAGE_NAME); print($(PAC
# (py3), the ABI tag (none), and the platform tag (any) for the final wheel
# file name.
PACKAGE_BASE_NAME := $(PACKAGE_NAME)-$(PACKAGE_VERSION)
PACKAGE_SDIST_NAME := $(PACKAGE_BASE_NAME).tar.gz
PACKAGE_WHEEL_NAME := $(PACKAGE_BASE_NAME)-py3-none-any.whl
PACKAGE_SDIST_BASE_NAME := $(PACKAGE_BASE_NAME)
PACKAGE_SDIST_NAME := $(PACKAGE_SDIST_BASE_NAME).tar.gz
PACKAGE_WHEEL_BASE_NAME := $(PACKAGE_BASE_NAME)-py3-none-any
PACKAGE_WHEEL_NAME := $(PACKAGE_WHEEL_BASE_NAME).whl

# If a PYTHON environment variable exists then use that, else define it here.
PYTHON ?= python3.14
Expand Down Expand Up @@ -98,7 +100,7 @@ venv:
# See https://packaging.python.org/en/latest/tutorials/packaging-projects/#generating-distribution-archives.
.PHONY: setup
setup: force-upgrade
pre-commit install
python -m pre_commit install
mkdir -p dist

# Install or upgrade an existing virtual environment based on the
Expand All @@ -108,7 +110,7 @@ upgrade: .venv/upgraded-on
.venv/upgraded-on: pyproject.toml
python -m pip install --upgrade pip setuptools
python -m pip install --upgrade wheel
python -m pip install --upgrade --upgrade-strategy eager --editable .[actions,dev,docs,hooks,test]
python -m pip install --upgrade --upgrade-strategy eager --group dev --editable .
$(MAKE) upgrade-quiet
force-upgrade:
rm -f .venv/upgraded-on
Expand Down Expand Up @@ -165,15 +167,15 @@ audit:
.PHONY: check check-code check-ruff check-lint check-mypy check-actionlint
check-code: check-ruff check-lint check-mypy check-actionlint
check-ruff:
pre-commit run ruff --all-files
python -m pre_commit run ruff --all-files
check-lint:
pre-commit run pylint --all-files
python -m pre_commit run pylint --all-files
check-mypy:
pre-commit run mypy --all-files
python -m pre_commit run mypy --all-files
check-actionlint:
pre-commit run actionlint --all-files
python -m pre_commit run actionlint --all-files
check:
pre-commit run --all-files
python -m pre_commit run --all-files

# Run different kinds of tests: unit tests, integration tests, performance tests.
# Note that the default goal 'test' runs the unit tests only, mainly for convenience
Expand All @@ -194,8 +196,8 @@ test-all: test-unit test-integration test-performance
.PHONY: dist
dist: dist/$(PACKAGE_WHEEL_NAME) dist/$(PACKAGE_SDIST_NAME) dist/$(PACKAGE_BASE_NAME)-docs-html.zip dist/$(PACKAGE_BASE_NAME)-docs-md.zip
dist/$(PACKAGE_WHEEL_NAME): check test-all
SOURCE_DATE_EPOCH=$(SOURCE_DATE_EPOCH) python -m flit build --setup-py --format wheel
echo $(SOURCE_DATE_EPOCH) > dist/$(PACKAGE_BASE_NAME)-py3-none-any-build-epoch.txt
SOURCE_DATE_EPOCH=$(SOURCE_DATE_EPOCH) python -m flit build --format wheel
echo $(SOURCE_DATE_EPOCH) > dist/$(PACKAGE_WHEEL_BASE_NAME)-build-epoch.txt
dist/$(PACKAGE_SDIST_NAME): check test-all
SOURCE_DATE_EPOCH=$(SOURCE_DATE_EPOCH) python -m flit build --no-setup-py --format sdist
dist/$(PACKAGE_BASE_NAME)-docs-html.zip: docs-html
Expand Down Expand Up @@ -264,7 +266,7 @@ clean: dist-clean
# Remove code caches, or the entire virtual environment.
.PHONY: nuke-git-hooks nuke-caches nuke
nuke-git-hooks:
find .git/hooks/ -type f ! -name '*.sample' -exec rm -fr {} +
find .git/hooks/ -type f ! -name '*.sample' -exec rm -f {} +
nuke-caches:
find src/ -type d -name __pycache__ -exec rm -fr {} +
find tests/ -type d -name __pycache__ -exec rm -fr {} +
Expand Down
9 changes: 2 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ Documentation is important, and [Sphinx](https://www.sphinx-doc.org/en/master/)

### Versioning and publishing

Automatic package versioning and tagging, publishing to [PyPI](https://pypi.org/), and [Changelog](https://keepachangelog.com/) generation are enabled using Github Actions. Furthermore, an optional [Release Notification](https://github.com/jenstroeger/python-package-template/tree/main/.github/workflows/release-notifications.yaml) Action allows Github to push an update notification to a [Slack bot](https://api.slack.com/bot-users) of your choice. For setup instructions, please see [below](#versioning-publishing-and-changelog).
Automatic and immutable package versioning and tagging, publishing to [PyPI](https://pypi.org/), and [Changelog](https://keepachangelog.com/) generation are enabled using Github Actions. Furthermore, an optional [Release Notification](https://github.com/jenstroeger/python-package-template/tree/main/.github/workflows/release-notifications.yaml) Action allows Github to push an update notification to a [Slack bot](https://api.slack.com/bot-users) of your choice. For setup instructions, please see [below](#versioning-publishing-and-changelog).

### Dependency analysis

Expand Down Expand Up @@ -261,7 +261,7 @@ The [sync-with-upstream.yaml](https://github.com/jenstroeger/python-package-temp

To enable automation for [semantic versioning](https://semver.org/), package publishing, and changelog generation it is important to use meaningful [conventional commit messages](https://www.conventionalcommits.org/)! This package template already has a built-in semantic release support enabled which is set up to take care of all three of these aspects — every time changes are pushed to the `release` branch.

With every package release, a new `bump:` commit is pushed to the `release` branch and tagged with the package’s new version. In addition, the `main` branch (which this repository uses to stage merged pull requests into for the next release) is rebased on top of the updated `release` branch automatically, so that subsequent pull requests can be merged while keeping a [linear history](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches#require-linear-history).
With every package release, a new `bump:` commit is pushed to the `release` branch and tagged with the package’s new version. Tags are immutable for reproducible builds. In addition, the `main` branch (which this repository uses to stage merged pull requests into for the next release) is rebased on top of the updated `release` branch automatically, so that subsequent pull requests can be merged while keeping a [linear history](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches#require-linear-history).

If you’d like to receive Slack notifications whenever a new release is published, follow the comments in the [Release Notification](https://github.com/jenstroeger/python-package-template/tree/main/.github/workflows/_release-notifications.yaml) Action and set up a Slack bot by following [the instructions here](https://github.com/slackapi/slack-github-action#setup-2).

Expand Down Expand Up @@ -338,8 +338,3 @@ On occasion it’s useful (and perhaps necessary) to clean up stale files, cache
- In addition and to **reset everything**, to restore a clean package to start over fresh: `make nuke`

Please be careful when nuking your environment, and make sure you know what you’re doing.

## Frequently asked questions

- **Question**: Why don’t you use tools like [tox](https://github.com/tox-dev/tox) or [nox](https://github.com/theacodes/nox) to orchestrate testing?
**Answer**: We’ve removed `tox` based on a discussion in [issue #100](https://github.com/jenstroeger/python-package-template/issues/100) and [PR #102](https://github.com/jenstroeger/python-package-template/pull/102). In short: we want to run tests inside the development venv using `pytest`, and run more tests using an extensive test matrix using Github Actions.
Loading
Loading