-
Notifications
You must be signed in to change notification settings - Fork 0
206 lines (178 loc) · 6.14 KB
/
ci.yml
File metadata and controls
206 lines (178 loc) · 6.14 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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
name: CI
# Trigger CI on pushes to main and all pull requests
# This ensures every code change is validated before merging
on:
push:
branches:
- main
pull_request:
# Run on all PRs regardless of target branch
branches:
- '**'
jobs:
# Job 1: Lint and Format Check
# Runs ruff to check code quality and formatting
lint:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.11'
- name: Install uv
uses: astral-sh/setup-uv@v7
with:
version: "latest"
- name: Install dependencies
# Install the package with uv in system mode
# This installs ruff and other tools defined in dependencies
run: uv pip install --system . --group dev
- name: Run ruff check
run: ruff check --config ./afterpython/ruff.toml .
- name: Run ruff format check
# --check flag ensures it only validates, doesn't reformat
run: ruff format --check --config ./afterpython/ruff.toml .
# Job 2: Detect Test Strategy
# Determines whether to use pixi or uv based on pixi.toml presence
detect-test-strategy:
runs-on: ubuntu-latest
outputs:
use_pixi: ${{ steps.check.outputs.use_pixi }}
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Check for pixi.toml
id: check
run: |
if [ -f "pixi.toml" ]; then
echo "use_pixi=true" >> $GITHUB_OUTPUT
else
echo "use_pixi=false" >> $GITHUB_OUTPUT
fi
# Job 3.1: Test Suite - UV Workflow
# Traditional Python testing with uv for projects without pixi
test-uv:
needs: detect-test-strategy
if: needs.detect-test-strategy.outputs.use_pixi == 'false'
runs-on: ubuntu-latest
strategy:
matrix:
# TODO: support python 3.14
python-version: ['3.11', '3.12', '3.13']
fail-fast: false
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
- name: Install uv
uses: astral-sh/setup-uv@v7
with:
version: "latest"
- name: Install dependencies
run: |
# Install package, main dependencies, and test dependencies
# If no [dependency-groups] test exists, only the package and main dependencies are installed
uv pip install --system . --group test || uv pip install --system .
- name: Run tests with pytest
# Run pytest with verbose output
# Exit code 5 (no tests collected) is treated as success
run: |
pytest -v || if [ $? -eq 5 ]; then exit 0; else exit $?; fi
# Job 3.2: Test Suite - Pixi Workflow
# Pixi-based testing for projects using pixi.toml
test-pixi:
needs: detect-test-strategy
if: needs.detect-test-strategy.outputs.use_pixi == 'true'
runs-on: ubuntu-latest
strategy:
matrix:
# TODO: support python 3.14
environment: ['py311', 'py312', 'py313']
fail-fast: false
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Set up pixi
uses: prefix-dev/setup-pixi@v0.9.4
with:
pixi-version: v0.63.2
cache: true
# Optional: Uncomment if you need prefix.dev authentication
# auth-host: prefix.dev
# auth-token: ${{ secrets.PREFIX_DEV_TOKEN }}
- name: Run tests with pixi
# Runs test in specific Python environment (py311, py312, py313)
# Assumes you have environments defined in pixi.toml with a "test" task
# Example pixi.toml:
# [environments]
# py311 = ["py311", "test"]
# [feature.test.tasks]
# test = "pytest -v"
# Note: Exit code 5 (no tests collected) is treated as success
run: |
pixi run -e ${{ matrix.environment }} test || if [ $? -eq 5 ]; then exit 0; else exit $?; fi
# Job 3.3: Test Suite - Complete
# Unified test status for branch protection
test:
if: always()
needs: [detect-test-strategy, test-uv, test-pixi]
runs-on: ubuntu-latest
steps:
- name: Check test results
run: |
uv_result="${{ needs.test-uv.result }}"
pixi_result="${{ needs.test-pixi.result }}"
# One should succeed, the other should be skipped
if [ "$uv_result" == "success" ] || [ "$uv_result" == "skipped" ]; then
if [ "$pixi_result" == "success" ] || [ "$pixi_result" == "skipped" ]; then
echo "All tests passed!"
exit 0
fi
fi
echo "Tests failed: uv=$uv_result, pixi=$pixi_result"
exit 1
# Job 4: Build Verification
# Ensures the package can be built successfully
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.11'
- name: Install uv
uses: astral-sh/setup-uv@v7
with:
version: "latest"
- name: Build package
run: uv build
- name: List build artifacts
# Show what was built (wheel + sdist)
# Useful for debugging build issues
run: ls -lh dist/
- name: Install built package
# Test that the built wheel can be installed
# This catches packaging issues like missing files
run: uv pip install --system dist/*.whl
- name: Verify installation
# Generic verification: assume project.name maps to import name
# by replacing '-' with '_'. If a project breaks this rule, CI fails.
run: |
PROJECT_NAME="$(python - <<'PY'
import tomllib
with open("pyproject.toml", "rb") as f:
data = tomllib.load(f)
print(data["project"]["name"])
PY
)"
IMPORT_NAME="${PROJECT_NAME//-/_}"
python -c "import ${IMPORT_NAME}"
# Job 5: Type Check
# typecheck: