Skip to content

ci: add Python 3.14 to test matrix (#109) #377

ci: add Python 3.14 to test matrix (#109)

ci: add Python 3.14 to test matrix (#109) #377

Workflow file for this run

name: CI
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
ci-gate:
name: CI Gate
if: always()
needs: [test, package, install-smoke]
runs-on: ubuntu-latest
steps:
- run: |
if [[ "${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}" == "true" ]]; then
echo "One or more required jobs failed or were cancelled"
exit 1
fi
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.12", "3.13", "3.14"]
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v4
with:
enable-cache: true
cache-dependency-glob: "pyproject.toml"
- name: Set up Python ${{ matrix.python-version }}
run: uv python install ${{ matrix.python-version }}
- name: Install dependencies
run: uv sync --all-extras --dev
- name: Lint
if: matrix.python-version == '3.12'
run: |
uv run ruff check .
uv run ruff format --check .
- name: Add venv to PATH
if: matrix.python-version == '3.12'
run: echo "$PWD/.venv/bin" >> $GITHUB_PATH
- name: Type check
if: matrix.python-version == '3.12'
uses: jakebailey/pyright-action@v3
with:
version: PATH
- name: Run tests
run: |
COV_REPORTS="--cov-report=term-missing"
if [[ "${{ matrix.python-version }}" == "3.12" ]]; then
COV_REPORTS="$COV_REPORTS --cov-report=xml:coverage.xml --cov-report=html:htmlcov"
fi
uv run pytest -v --cov=mpp $COV_REPORTS --cov-fail-under=90
- name: Upload coverage artifacts
if: always() && matrix.python-version == '3.12'
uses: actions/upload-artifact@v4
with:
name: coverage-report
path: |
coverage.xml
htmlcov/
if-no-files-found: ignore
package:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v4
with:
enable-cache: true
cache-dependency-glob: "pyproject.toml"
- name: Set up Python
run: uv python install 3.12
- name: Install dependencies
run: uv sync --dev
- name: Build and validate package
run: |
uv run python -m build
uv run twine check --strict dist/*
- name: Upload package artifacts
uses: actions/upload-artifact@v4
with:
name: package-dist
path: dist/*
if-no-files-found: error
install-smoke:
needs: package
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
profile: [base, tempo, mcp]
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v4
with:
enable-cache: true
cache-dependency-glob: "pyproject.toml"
- name: Set up Python
run: uv python install 3.12
- name: Download package artifacts
uses: actions/download-artifact@v4
with:
name: package-dist
path: dist
- name: Create clean virtualenv
run: uv venv .smoke-venv --python 3.12
- name: Install built wheel
run: |
WHEEL=$(echo dist/*.whl)
case "${{ matrix.profile }}" in
base)
INSTALL_TARGET="$WHEEL"
;;
tempo)
INSTALL_TARGET="${WHEEL}[tempo]"
;;
mcp)
INSTALL_TARGET="${WHEEL}[mcp]"
;;
esac
uv pip install --python .smoke-venv/bin/python "$INSTALL_TARGET"
- name: Smoke test built wheel (base)
if: matrix.profile == 'base'
run: |
.smoke-venv/bin/python - <<'PY'
import mpp
import mpp.extensions.mcp as mcp
import mpp.methods.tempo as tempo
assert tempo.CHAIN_ID == 4217
assert mcp.CODE_PAYMENT_REQUIRED == -32042
for expr, hint in (
("tempo.ChargeIntent", "pympp[tempo]"),
("mcp.PaymentRequiredError", "pympp[mcp]"),
):
try:
eval(expr)
except ImportError as exc:
assert hint in str(exc), str(exc)
else:
raise AssertionError(f"{expr} unexpectedly imported in base install")
print("base install smoke test passed")
PY
- name: Smoke test built wheel (tempo)
if: matrix.profile == 'tempo'
run: |
.smoke-venv/bin/python - <<'PY'
from mpp.methods.tempo import ChargeIntent, TempoAccount
assert ChargeIntent.__name__ == "ChargeIntent"
assert TempoAccount.__name__ == "TempoAccount"
print("tempo install smoke test passed")
PY
- name: Smoke test built wheel (mcp)
if: matrix.profile == 'mcp'
run: |
.smoke-venv/bin/python - <<'PY'
from mpp.extensions.mcp import PaymentRequiredError, pay, verify_or_challenge
assert PaymentRequiredError.__name__ == "PaymentRequiredError"
assert pay.__name__ == "pay"
assert verify_or_challenge.__name__ == "verify_or_challenge"
print("mcp install smoke test passed")
PY