Repository navigation
161 lines (135 loc) · 6.21 KB
/
Copy pathtests.yml
File metadata and controls
161 lines (135 loc) · 6.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
name: Tests
on:
push:
branches: [main, "v*"] # release branches (v4.0.0, ...) get CI before a PR exists
pull_request:
workflow_dispatch:
schedule:
# Weekly, so a dependency or interpreter change that breaks the suite is
# noticed between releases rather than at the next one.
- cron: "41 6 * * 1"
permissions:
contents: read
# Cancel superseded runs on the same ref (saves CI minutes on rapid pushes).
concurrency:
group: tests-${{ github.ref }}
cancel-in-progress: true
defaults:
run:
# The installable project lives in the tsapython/ subdirectory (the one with
# pyproject.toml, the pytest config, and the `hardware` marker).
working-directory: tsapython
jobs:
test:
name: pytest (${{ matrix.os }}, py${{ matrix.python-version }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
# The library is pyserial-based and developed on Windows, lightly
# tested on Linux -- so both matter; macOS is cheap to include.
os: [windows-latest, ubuntu-latest, macos-latest]
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v5
with:
enable-cache: true
python-version: ${{ matrix.python-version }}
- name: Sync environment (deps + dev group, editable install)
# --locked: fail if uv.lock is stale instead of silently re-resolving
run: uv sync --locked
- name: Run test suite (hardware tests deselected)
run: uv run pytest -m "not hardware" --cov=tsapython --cov-report=xml --cov-report=term-missing --cov-fail-under=85
- name: Upload coverage to Codecov
# Optional: only does anything once the repo is linked at
# https://codecov.io. Tokenless for public repos. Safe to leave in
# before linking -- it soft-fails.
if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.12'
uses: codecov/codecov-action@v5
with:
files: tsapython/coverage.xml
fail_ci_if_error: false
lint:
name: ruff + mypy
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v5
with:
enable-cache: true
python-version: "3.12"
- name: Sync environment
run: uv sync --locked
- name: Ruff lint
# Blocking ruleset is E9 + F only (see [tool.ruff.lint] in
# pyproject.toml); style rules are a planned follow-up cleanup.
run: uv run ruff check .
- name: Mypy
# Blocking. The package ships a py.typed marker, which promises
# downstream type-checkers that these annotations are real; this gate
# is what keeps that promise true.
run: uv run mypy
build:
name: package builds
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v5
- name: Build sdist + wheel
# Catches packaging breakage on every push instead of at release time.
# build-release.yml does the same build for a tag; release.yml publishes
# those files.
run: uv build
- name: Metadata check (twine)
run: uvx twine check dist/*
- name: Install the wheel into a clean environment and import it
# A file missing from the wheel (a new module not picked up, a renamed
# package) passes the editable-install test suite and only fails for a
# user who pip-installs. This catches it on every push.
run: |
uv venv /tmp/wheelcheck
uv pip install --python /tmp/wheelcheck/bin/python dist/*.whl
/tmp/wheelcheck/bin/python -c "import tsapython; from tsapython import tinySA; from tsapython import DeviceProfile, PROFILES; print('tsapython', tsapython.__version__)"
- name: Install the sdist into a clean environment and import it
# The sdist is what a source-only install (and some distro packagers)
# build from; a file the wheel has but the sdist lacks fails only here.
run: |
uv venv /tmp/sdistcheck
uv pip install --python /tmp/sdistcheck/bin/python dist/*.tar.gz
/tmp/sdistcheck/bin/python -c "import tsapython; print('sdist ok', tsapython.__version__)"
- name: pip path the README documents (pip install -e ".[test]") still works
run: |
uv venv /tmp/pipcheck
uv pip install --python /tmp/pipcheck/bin/python -e ".[test]"
/tmp/pipcheck/bin/python -m pytest -q -m "not hardware" -p no:cacheprovider
- name: Examples and helper scripts at least compile
# They need a device to run; this catches a syntax error or a renamed
# import the test suite would never touch.
run: |
uv run python -m compileall -q examples tests/bench_generator.py tests/probe_firmware_returns.py tests/collect_samples.py
uv run python -c "import ast,glob,sys; [ast.parse(open(f).read(), f) for f in glob.glob('examples/*.py')]; print('examples parse')"
metadata:
name: version metadata agrees
runs-on: ubuntu-latest
defaults:
run:
working-directory: .
steps:
- uses: actions/checkout@v4
- name: pyproject.toml, CITATION.cff and zenodo.json carry the same version
# build-release.yml checks the tag against pyproject.toml at release
# time; this catches a half-done bump on the PR instead.
run: |
py="$(python3 -c 'import tomllib; print(tomllib.load(open("tsapython/pyproject.toml","rb"))["project"]["version"])')"
cff="$(sed -n 's/^version: *"\(.*\)"/\1/p' CITATION.cff)"
zen="$(python3 -c 'import json; print(json.load(open("zenodo.json"))["version"])')"
echo "pyproject=$py CITATION.cff=$cff zenodo.json=$zen"
[ "$py" = "$cff" ] && [ "$py" = "$zen" ] || { echo "::error::version mismatch"; exit 1; }
- name: CHANGELOG has a section for this version
run: |
py="$(python3 -c 'import tomllib; print(tomllib.load(open("tsapython/pyproject.toml","rb"))["project"]["version"])')"
grep -q "^## \[$py\]" CHANGELOG.md || { echo "::error::CHANGELOG.md has no '## [$py]' section"; exit 1; }