Skip to content

Commit bb8735d

Browse files
committed
feat: adopt treemapper CI/CD best practices
CI improvements: - Add matrix testing (3 OS × 4 Python versions = 12 jobs) - Separate jobs: pre-commit, lint-type-check, test - Add coverage reporting with 40% threshold - Add mutation testing job (main branch only) - Add complexity checks with radon - Add architecture validation with import-linter pyproject.toml improvements: - Add Python 3.10-3.13 classifiers - Add maintainers field - Expand ruff rules (I, N, S, UP) - Add pytest asyncio_mode and pythonpath - Add ruff.lint.isort with known-first-party CD improvements: - Fix version injection with proper regex - Update PyPI URL to arbitrium-core Pre-commit updates: - Correct isort→black ordering - Update versions (isort 7.0.0, ruff 0.14.0) - Change default Python to 3.12 for stability
1 parent 1f1062e commit bb8735d

File tree

7 files changed

+265
-30
lines changed

7 files changed

+265
-30
lines changed

.github/workflows/cd.yml

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# .github/workflows/cd.yml
2-
name: Arbitrium Framework CD
2+
name: CD
33

44
permissions:
55
contents: write
@@ -43,14 +43,13 @@ jobs:
4343
echo "Setting version to $VERSION"
4444
# Robust version updating using Python
4545
python -c "
46+
import re
47+
ver = '${{ github.event.inputs.version }}'
4648
with open('src/arbitrium/__about__.py', 'r') as f:
4749
content = f.read()
50+
content = re.sub(r'__version__\s*=\s*[\"'\''].*?[\"'\'']', f'__version__ = \"{ver}\"', content, count=1)
4851
with open('src/arbitrium/__about__.py', 'w') as f:
49-
lines = content.split('\n')
50-
for i, line in enumerate(lines):
51-
if line.startswith('__version__'):
52-
lines[i] = f'__version__ = \"$VERSION\"'
53-
f.write('\n'.join(lines))
52+
f.write(content)
5453
"
5554
echo "__about__.py content after change:"
5655
cat src/arbitrium/__about__.py
@@ -168,7 +167,7 @@ jobs:
168167
runs-on: ubuntu-latest
169168
environment:
170169
name: pypi
171-
url: https://pypi.org/p/arbitrium-framework
170+
url: https://pypi.org/p/arbitrium-core
172171
permissions:
173172
id-token: write
174173
steps:

.github/workflows/ci.yml

Lines changed: 204 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
1-
name: Code Quality CI
1+
name: CI
22

33
"on":
44
push:
55
branches: [main]
66
pull_request:
7-
branches: [main]
7+
branches: ['**']
88

99
permissions:
1010
contents: read
11+
security-events: write
1112

1213
jobs:
14+
# ============================================================================
15+
# LAYER 1: Fast feedback (runs first)
16+
# ============================================================================
17+
1318
pre-commit:
1419
name: Pre-commit hooks
1520
runs-on: ubuntu-latest
@@ -19,19 +24,213 @@ jobs:
1924
- name: Set up Python
2025
uses: actions/setup-python@v6
2126
with:
22-
python-version: "3.13"
27+
python-version: "3.12"
2328

2429
- name: Cache pre-commit
2530
uses: actions/cache@v5
2631
with:
2732
path: ~/.cache/pre-commit
2833
key: pre-commit-${{ hashFiles('.pre-commit-config.yaml') }}
2934

30-
- name: Install Python dependencies
35+
- name: Install pre-commit
3136
run: |
3237
python -m pip install --upgrade pip
3338
pip install pre-commit
34-
pip install -e .[dev]
3539
3640
- name: Run pre-commit
3741
run: pre-commit run --all-files
42+
43+
lint-type-check:
44+
name: Lint & Type Check
45+
runs-on: ubuntu-latest
46+
steps:
47+
- uses: actions/checkout@v6
48+
49+
- name: Set up Python
50+
uses: actions/setup-python@v6
51+
with:
52+
python-version: "3.12"
53+
54+
- name: Cache pip
55+
uses: actions/cache@v5
56+
with:
57+
path: ~/.cache/pip
58+
key: ${{ runner.os }}-lint-pip-${{ hashFiles('**/pyproject.toml') }}
59+
restore-keys: |
60+
${{ runner.os }}-lint-pip-
61+
62+
- name: Install dependencies
63+
run: |
64+
python -m pip install --upgrade pip
65+
pip install -e .[dev]
66+
67+
- name: Run ruff
68+
run: ruff check src tests
69+
70+
- name: Run black
71+
run: black --check src tests
72+
73+
- name: Run mypy
74+
run: mypy src
75+
76+
# ============================================================================
77+
# LAYER 2: Tests (depends on Layer 1)
78+
# ============================================================================
79+
80+
test:
81+
name: Test (Python ${{ matrix.python-version }} / ${{ matrix.os }})
82+
needs: [pre-commit, lint-type-check]
83+
runs-on: ${{ matrix.os }}
84+
strategy:
85+
fail-fast: false
86+
matrix:
87+
os: [ubuntu-latest, macos-latest, windows-latest]
88+
python-version: ['3.10', '3.11', '3.12', '3.13']
89+
90+
steps:
91+
- uses: actions/checkout@v6
92+
93+
- name: Set up Python ${{ matrix.python-version }}
94+
uses: actions/setup-python@v6
95+
with:
96+
python-version: ${{ matrix.python-version }}
97+
98+
- name: Cache pip
99+
uses: actions/cache@v5
100+
with:
101+
path: ~/.cache/pip
102+
key: ${{ runner.os }}-pip-${{ matrix.python-version }}-${{ hashFiles('**/pyproject.toml') }}
103+
restore-keys: |
104+
${{ runner.os }}-pip-${{ matrix.python-version }}-
105+
${{ runner.os }}-pip-
106+
107+
- name: Install dependencies
108+
run: |
109+
python -m pip install --upgrade pip
110+
pip install -e .[dev]
111+
112+
- name: Run tests with coverage
113+
run: |
114+
pytest tests/ -v \
115+
--cov=src/arbitrium \
116+
--cov-report=xml \
117+
--cov-report=term-missing \
118+
--cov-branch \
119+
--junitxml=test-results.xml
120+
env:
121+
SKIP_DB_INIT: "true"
122+
123+
- name: Enforce coverage threshold
124+
if: runner.os == 'Linux' && matrix.python-version == '3.12'
125+
run: coverage report --fail-under=40
126+
127+
- name: Upload coverage report
128+
if: runner.os == 'Linux' && matrix.python-version == '3.12'
129+
uses: actions/upload-artifact@v4
130+
with:
131+
name: coverage-report
132+
path: |
133+
coverage.xml
134+
test-results.xml
135+
retention-days: 1
136+
137+
# ============================================================================
138+
# LAYER 3: Quality analysis (parallel, non-blocking on main)
139+
# ============================================================================
140+
141+
mutation-testing:
142+
name: Mutation Testing
143+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
144+
runs-on: ubuntu-latest
145+
continue-on-error: true
146+
steps:
147+
- uses: actions/checkout@v6
148+
149+
- name: Set up Python
150+
uses: actions/setup-python@v6
151+
with:
152+
python-version: "3.12"
153+
154+
- name: Install dependencies
155+
run: |
156+
python -m pip install --upgrade pip
157+
pip install -e .[dev]
158+
159+
- name: Run mutation testing
160+
run: |
161+
mutmut run . || true
162+
mutmut results || true
163+
env:
164+
SKIP_DB_INIT: "true"
165+
166+
complexity-checks:
167+
name: Complexity Analysis
168+
runs-on: ubuntu-latest
169+
steps:
170+
- uses: actions/checkout@v6
171+
172+
- name: Set up Python
173+
uses: actions/setup-python@v6
174+
with:
175+
python-version: "3.12"
176+
177+
- name: Install radon
178+
run: pip install radon
179+
180+
- name: Check cyclomatic complexity
181+
run: |
182+
echo "=== Cyclomatic Complexity ==="
183+
radon cc src/arbitrium/ --min B --total-average
184+
radon cc src/arbitrium/ --min C --total-average || \
185+
(echo "::warning::High complexity detected (grade C or worse)" && exit 0)
186+
187+
- name: Check maintainability index
188+
run: |
189+
echo "=== Maintainability Index ==="
190+
radon mi src/arbitrium/ --min B
191+
192+
architecture-checks:
193+
name: Architecture Validation
194+
runs-on: ubuntu-latest
195+
continue-on-error: true
196+
steps:
197+
- uses: actions/checkout@v6
198+
199+
- name: Set up Python
200+
uses: actions/setup-python@v6
201+
with:
202+
python-version: "3.12"
203+
204+
- name: Install import-linter
205+
run: pip install import-linter
206+
207+
- name: Create import contracts
208+
run: |
209+
cat > .importlinter <<EOF
210+
[importlinter]
211+
root_package = arbitrium
212+
213+
[importlinter:contract:1]
214+
name = CLI should not import core internals directly
215+
type = forbidden
216+
source_modules = arbitrium.cli
217+
forbidden_modules = arbitrium.core.tournament
218+
219+
[importlinter:contract:2]
220+
name = Models should not import CLI
221+
type = forbidden
222+
source_modules = arbitrium.models
223+
forbidden_modules = arbitrium.cli
224+
225+
[importlinter:contract:3]
226+
name = Utils should be independent
227+
type = independence
228+
modules =
229+
arbitrium.utils
230+
EOF
231+
232+
- name: Install package
233+
run: pip install -e .
234+
235+
- name: Validate architecture
236+
run: lint-imports || echo "::warning::Architecture violations detected"

.pre-commit-config.yaml

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
minimum_pre_commit_version: '3.5.0'
22
default_stages: [pre-commit]
33
default_language_version:
4-
python: python3.13
4+
python: python3.12
55
node: system
66

77
fail_fast: false
@@ -44,25 +44,25 @@ repos:
4444
args: ['--verbose']
4545

4646
# ============================================================================
47-
# CODE FORMATTING (minimal - consistency only, not quality)
47+
# CODE FORMATTING (Order matters: isort → black to avoid conflicts)
4848
# ============================================================================
49+
- repo: https://github.com/pycqa/isort
50+
rev: 7.0.0
51+
hooks:
52+
- id: isort
53+
4954
- repo: https://github.com/psf/black
5055
rev: 25.9.0
5156
hooks:
5257
- id: black
5358
language_version: python3
5459

55-
- repo: https://github.com/pycqa/isort
56-
rev: 6.1.0
57-
hooks:
58-
- id: isort
59-
6060
- repo: https://github.com/asottile/pyupgrade
6161
rev: v3.21.1
6262
hooks:
6363
- id: pyupgrade
6464
name: pyupgrade (auto-upgrade Python syntax)
65-
args: ['--py313-plus']
65+
args: ['--py310-plus']
6666
files: ^src/.*\.py$
6767

6868
# ============================================================================
@@ -167,7 +167,7 @@ repos:
167167
# Using Ruff for speed; flake8 removed to avoid redundancy
168168
# ============================================================================
169169
- repo: https://github.com/astral-sh/ruff-pre-commit
170-
rev: v0.13.3
170+
rev: v0.14.0
171171
hooks:
172172
- id: ruff
173173
name: ruff (correctness-focused checks)

0 commit comments

Comments
 (0)