-
Notifications
You must be signed in to change notification settings - Fork 0
132 lines (109 loc) · 4.89 KB
/
Copy pathci.yml
File metadata and controls
132 lines (109 loc) · 4.89 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
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
permissions:
contents: read
pull-requests: write
env:
# Fail if type-precision drops below this percentage (mypy --any-exprs-report)
MIN_TYPE_PRECISION: "95"
jobs:
test:
name: Python ${{ matrix.python-version }} on ${{ matrix.os }}
needs: lint
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
python-version: ["3.13"]
steps:
- uses: actions/checkout@v7
- name: Install uv
uses: astral-sh/setup-uv@v10.0.1
- name: Set up Python ${{ matrix.python-version }}
run: uv python install ${{ matrix.python-version }}
- name: Install dependencies
run: uv sync --all-extras --python ${{ matrix.python-version }}
# Windows runs at -n 2 rather than the -n auto in pyproject's addopts.
# The suite spawns real servers and talks to them over loopback, and on
# Windows a connection aborted by the peer is a hard WSAECONNABORTED
# (WinError 10053) where POSIX quietly delivers the response instead. At
# -n auto that shows up as an intermittent failure somewhere in
# TestExternalLocation -- a different test each run, which is the
# signature of contention rather than of a broken test. Halving the
# concurrency keeps the wall-clock win without sitting on that edge.
# A recurrence at -n 2 would mean the race is not purely load-driven and
# is worth chasing on a Windows box rather than papering over here.
- name: Run tests with coverage
run: >
uv run --python ${{ matrix.python-version }} pytest
${{ matrix.os == 'windows-latest' && '-n 2' || '' }}
--cov=vgi_rpc
--cov-report=term-missing
--cov-report=xml:coverage.xml
- name: Upload coverage to Codecov
if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.13'
uses: codecov/codecov-action@v7
with:
files: coverage.xml
flags: python${{ matrix.python-version }}
fail_ci_if_error: false
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Install uv
uses: astral-sh/setup-uv@v10.0.1
- name: Install dependencies
run: uv sync --all-extras
- name: Check formatting
run: uv run ruff format --check .
- name: Check linting
run: uv run ruff check .
# Docstring consistency: documented args/attributes must match the code.
# Config lives in pyproject.toml ([tool.pydoclint]); vgi_rpc/ is fully
# clean with no baseline, so any new violation fails immediately.
# Run isolated via uvx: pydoclint pulls docstring-parser-fork, which
# collides with the canonical docstring-parser in the project venv, so it
# is deliberately not a project dependency (see pyproject.toml). --python
# 3.13 is required so the parser understands the package's 3.13 syntax.
- name: Docstring lint (pydoclint)
run: uvx --python 3.13 --from pydoclint==0.8.7 pydoclint vgi_rpc/
- name: Type check (mypy)
run: uv run mypy vgi_rpc/ --any-exprs-report mypy-type-report
- name: Type precision report
if: always()
shell: bash
run: |
if [ -f mypy-type-report/any-exprs.txt ]; then
echo "## Mypy Type Precision" >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"
# Convert the fixed-width report to a markdown table
echo "| Module | Anys | Exprs | Coverage |" >> "$GITHUB_STEP_SUMMARY"
echo "|--------|-----:|------:|---------:|" >> "$GITHUB_STEP_SUMMARY"
# Skip header (2 lines) and separator, process data lines
awk 'NR > 2 { if (index($0, "---") == 0 && NF >= 4) printf "| %s | %s | %s | %s |\n", $1, $2, $3, $4 }' \
mypy-type-report/any-exprs.txt >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"
# Extract total coverage percentage and check threshold
total_pct=$(awk '/Total/ { gsub(/%/, "", $4); print $4 }' mypy-type-report/any-exprs.txt)
echo "Type precision: **${total_pct}%** (minimum: ${MIN_TYPE_PRECISION}%)" >> "$GITHUB_STEP_SUMMARY"
if [ -n "$total_pct" ]; then
below=$(echo "$total_pct < $MIN_TYPE_PRECISION" | bc -l)
if [ "$below" = "1" ]; then
echo ""
echo "> **Type precision ${total_pct}% is below the ${MIN_TYPE_PRECISION}% threshold.**" >> "$GITHUB_STEP_SUMMARY"
echo "::error::Type precision ${total_pct}% is below the ${MIN_TYPE_PRECISION}% minimum"
exit 1
fi
fi
fi
- name: Type check (ty)
run: uv run ty check vgi_rpc/