thompsonson Claude commited on
Commit
d989c27
·
1 Parent(s): a6994a0

feat: add comprehensive CI/CD automation and modern Python tooling

Browse files

- Add pre-commit configuration with ruff (replaces black/isort/flake8), mypy, and bandit
- Add GitHub Actions workflows for CI testing and automated HF Spaces deployment
- Add pyproject.toml with modern Python packaging and centralized tool configuration
- Update requirements.txt with development dependencies including ruff and pytest plugins
- Add comprehensive ruff rule set: pycodestyle, pyflakes, bugbear, comprehensions, pyupgrade
- Configure multi-Python version testing (3.10, 3.11, 3.12) with parallel execution
- Add security scanning with bandit and Trivy vulnerability scanner
- Update README with development workflow and CI/CD pipeline documentation

Performance improvements:
- Ruff provides 10-100x faster linting compared to traditional tools
- pytest-xdist enables parallel test execution
- Single tool replaces multiple separate linters

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

.github/workflows/ci.yml ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [ main, develop ]
6
+ pull_request:
7
+ branches: [ main ]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ python-version: [3.10.x, 3.11.x, 3.12.x]
15
+
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+
19
+ - name: Set up Python ${{ matrix.python-version }}
20
+ uses: actions/setup-python@v4
21
+ with:
22
+ python-version: ${{ matrix.python-version }}
23
+
24
+ - name: Cache pip packages
25
+ uses: actions/cache@v3
26
+ with:
27
+ path: ~/.cache/pip
28
+ key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
29
+ restore-keys: |
30
+ ${{ runner.os }}-pip-
31
+
32
+ - name: Install dependencies
33
+ run: |
34
+ python -m pip install --upgrade pip
35
+ pip install -r requirements.txt
36
+ pip install pytest-cov pytest-xdist
37
+
38
+ - name: Run tests with coverage
39
+ run: |
40
+ python -m pytest tests/ -v --cov=domains --cov=ui --cov-report=xml --cov-report=html -n auto
41
+
42
+ - name: Upload coverage to Codecov
43
+ uses: codecov/codecov-action@v3
44
+ with:
45
+ file: ./coverage.xml
46
+ flags: unittests
47
+ name: codecov-umbrella
48
+
49
+ lint:
50
+ runs-on: ubuntu-latest
51
+
52
+ steps:
53
+ - uses: actions/checkout@v4
54
+
55
+ - name: Set up Python
56
+ uses: actions/setup-python@v4
57
+ with:
58
+ python-version: 3.11.x
59
+
60
+ - name: Install dependencies
61
+ run: |
62
+ python -m pip install --upgrade pip
63
+ pip install ruff mypy bandit
64
+
65
+ - name: Run Ruff linter
66
+ run: ruff check .
67
+
68
+ - name: Run Ruff formatter
69
+ run: ruff format --check .
70
+
71
+ - name: Run mypy
72
+ run: mypy . --ignore-missing-imports
73
+
74
+ - name: Run bandit
75
+ run: bandit -r . -f json -o bandit-report.json || true
76
+
77
+ pre-commit:
78
+ runs-on: ubuntu-latest
79
+
80
+ steps:
81
+ - uses: actions/checkout@v4
82
+
83
+ - name: Set up Python
84
+ uses: actions/setup-python@v4
85
+ with:
86
+ python-version: 3.11.x
87
+
88
+ - name: Install pre-commit
89
+ run: pip install pre-commit
90
+
91
+ - name: Run pre-commit
92
+ run: pre-commit run --all-files
93
+
94
+ security:
95
+ runs-on: ubuntu-latest
96
+
97
+ steps:
98
+ - uses: actions/checkout@v4
99
+
100
+ - name: Run Trivy vulnerability scanner
101
+ uses: aquasecurity/trivy-action@master
102
+ with:
103
+ scan-type: 'fs'
104
+ scan-ref: '.'
105
+ format: 'sarif'
106
+ output: 'trivy-results.sarif'
107
+
108
+ - name: Upload Trivy scan results to GitHub Security tab
109
+ uses: github/codeql-action/upload-sarif@v2
110
+ if: always()
111
+ with:
112
+ sarif_file: 'trivy-results.sarif'
.github/workflows/deploy.yml ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: Deploy to Hugging Face Spaces
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ workflow_dispatch:
7
+
8
+ jobs:
9
+ deploy:
10
+ runs-on: ubuntu-latest
11
+
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+ with:
15
+ fetch-depth: 0
16
+ lfs: true
17
+
18
+ - name: Push to Hugging Face Spaces
19
+ env:
20
+ HF_TOKEN: ${{ secrets.HF_TOKEN }}
21
+ run: |
22
+ git config --global user.email "action@github.com"
23
+ git config --global user.name "GitHub Action"
24
+ git remote add hf https://thompsonson:$HF_TOKEN@hf.co/spaces/thompsonson/bayesian_game
25
+ git push hf main --force
.pre-commit-config.yaml ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ repos:
2
+ - repo: https://github.com/pre-commit/pre-commit-hooks
3
+ rev: v4.4.0
4
+ hooks:
5
+ - id: trailing-whitespace
6
+ - id: end-of-file-fixer
7
+ - id: check-yaml
8
+ - id: check-added-large-files
9
+ - id: check-merge-conflict
10
+ - id: debug-statements
11
+
12
+ - repo: https://github.com/astral-sh/ruff-pre-commit
13
+ rev: v0.1.9
14
+ hooks:
15
+ - id: ruff
16
+ args: [--fix, --exit-non-zero-on-fix]
17
+ - id: ruff-format
18
+
19
+ - repo: https://github.com/pre-commit/mirrors-mypy
20
+ rev: v1.8.0
21
+ hooks:
22
+ - id: mypy
23
+ additional_dependencies: [types-all]
24
+ args: [--ignore-missing-imports]
25
+
26
+ - repo: https://github.com/pycqa/bandit
27
+ rev: 1.7.5
28
+ hooks:
29
+ - id: bandit
30
+ args: [-r, ., -f, json, -o, bandit-report.json]
31
+ exclude: ^tests/
README.md CHANGED
@@ -85,6 +85,11 @@ uv pip install -r requirements.txt
85
  pip install -r requirements.txt
86
  ```
87
 
 
 
 
 
 
88
  ### Running the Game
89
 
90
  **Launch the interactive web interface:**
@@ -210,6 +215,32 @@ This implementation demonstrates:
210
  - `numpy`: Numerical computations for Bayesian inference
211
  - `matplotlib`: Belief distribution visualization
212
  - `pytest`: Testing framework
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
213
 
214
  ### Design Principles
215
  1. **Pure Functions**: Domains contain pure, testable functions
 
85
  pip install -r requirements.txt
86
  ```
87
 
88
+ 4. **Set up pre-commit hooks (optional for development):**
89
+ ```bash
90
+ pre-commit install
91
+ ```
92
+
93
  ### Running the Game
94
 
95
  **Launch the interactive web interface:**
 
215
  - `numpy`: Numerical computations for Bayesian inference
216
  - `matplotlib`: Belief distribution visualization
217
  - `pytest`: Testing framework
218
+ - `pre-commit`: Code quality automation
219
+ - `ruff`: Fast Python linter and formatter (replaces Black, isort, flake8)
220
+
221
+ ### Development Workflow
222
+ ```bash
223
+ # Install pre-commit hooks
224
+ pre-commit install
225
+
226
+ # Run pre-commit manually
227
+ pre-commit run --all-files
228
+
229
+ # Run tests with coverage
230
+ python -m pytest tests/ --cov=domains --cov=ui --cov-report=html
231
+
232
+ # Code formatting and linting (automatic with pre-commit)
233
+ ruff check --fix .
234
+ ruff format .
235
+ mypy .
236
+ ```
237
+
238
+ ### CI/CD Pipeline
239
+ - **GitHub Actions**: Automated testing on Python 3.10, 3.11, 3.12
240
+ - **Pre-commit hooks**: Code quality checks (Ruff, mypy, bandit)
241
+ - **Test coverage**: Comprehensive coverage reporting
242
+ - **Security scanning**: Trivy vulnerability scanner
243
+ - **Auto-deployment**: Pushes to Hugging Face Spaces on main branch
244
 
245
  ### Design Principles
246
  1. **Pure Functions**: Domains contain pure, testable functions
pyproject.toml ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [build-system]
2
+ requires = ["setuptools>=45", "wheel", "setuptools_scm[toml]>=6.2"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "bayesian-game"
7
+ description = "Interactive Bayesian inference game with domain-driven design"
8
+ readme = "README.md"
9
+ license = {text = "MIT"}
10
+ authors = [
11
+ {name = "Thompson", email = "thompsonson@example.com"},
12
+ ]
13
+ classifiers = [
14
+ "Development Status :: 4 - Beta",
15
+ "Intended Audience :: Education",
16
+ "License :: OSI Approved :: MIT License",
17
+ "Programming Language :: Python :: 3",
18
+ "Programming Language :: Python :: 3.10",
19
+ "Programming Language :: Python :: 3.11",
20
+ "Programming Language :: Python :: 3.12",
21
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
22
+ "Topic :: Education",
23
+ ]
24
+ requires-python = ">=3.10"
25
+ dependencies = [
26
+ "gradio>=4.0.0",
27
+ "numpy>=1.21.0",
28
+ "matplotlib>=3.5.0",
29
+ ]
30
+ dynamic = ["version"]
31
+
32
+ [project.optional-dependencies]
33
+ dev = [
34
+ "pytest>=7.0.0",
35
+ "pytest-cov>=4.0.0",
36
+ "pytest-xdist>=3.0.0",
37
+ "pre-commit>=3.0.0",
38
+ "ruff>=0.1.0",
39
+ "mypy>=1.0.0",
40
+ "bandit>=1.7.0",
41
+ ]
42
+
43
+ [project.urls]
44
+ Homepage = "https://github.com/thompsonson/bayesian_game"
45
+ Repository = "https://github.com/thompsonson/bayesian_game"
46
+ "Bug Tracker" = "https://github.com/thompsonson/bayesian_game/issues"
47
+ "Hugging Face Space" = "https://huggingface.co/spaces/thompsonson/bayesian_game"
48
+
49
+ [tool.setuptools_scm]
50
+
51
+ [tool.ruff]
52
+ target-version = "py310"
53
+ line-length = 88
54
+ select = [
55
+ "E", # pycodestyle errors
56
+ "W", # pycodestyle warnings
57
+ "F", # pyflakes
58
+ "I", # isort
59
+ "B", # flake8-bugbear
60
+ "C4", # flake8-comprehensions
61
+ "UP", # pyupgrade
62
+ "ARG", # flake8-unused-arguments
63
+ "SIM", # flake8-simplify
64
+ "TCH", # flake8-type-checking
65
+ "PTH", # flake8-use-pathlib
66
+ "ERA", # eradicate
67
+ "PL", # pylint
68
+ "RUF", # ruff-specific rules
69
+ ]
70
+ ignore = [
71
+ "E501", # line too long, handled by formatter
72
+ "B008", # do not perform function calls in argument defaults
73
+ "C901", # too complex
74
+ "PLR0913", # too many arguments
75
+ "PLR0915", # too many statements
76
+ ]
77
+
78
+ [tool.ruff.per-file-ignores]
79
+ "tests/**/*" = ["PLR2004", "S101", "ARG001"]
80
+
81
+ [tool.ruff.format]
82
+ quote-style = "double"
83
+ indent-style = "space"
84
+ skip-magic-trailing-comma = false
85
+ line-ending = "auto"
86
+
87
+ [tool.mypy]
88
+ python_version = "3.10"
89
+ check_untyped_defs = true
90
+ disallow_any_generics = true
91
+ disallow_incomplete_defs = true
92
+ disallow_untyped_defs = true
93
+ no_implicit_optional = true
94
+ warn_redundant_casts = true
95
+ warn_unused_ignores = true
96
+ warn_return_any = true
97
+ strict_equality = true
98
+
99
+ [[tool.mypy.overrides]]
100
+ module = [
101
+ "matplotlib.*",
102
+ "gradio.*",
103
+ ]
104
+ ignore_missing_imports = true
105
+
106
+ [tool.pytest.ini_options]
107
+ minversion = "7.0"
108
+ addopts = "-ra -q --strict-markers --strict-config"
109
+ testpaths = ["tests"]
110
+ python_files = ["test_*.py"]
111
+ python_classes = ["Test*"]
112
+ python_functions = ["test_*"]
113
+ markers = [
114
+ "slow: marks tests as slow",
115
+ "integration: marks tests as integration tests",
116
+ "unit: marks tests as unit tests",
117
+ ]
118
+
119
+ [tool.coverage.run]
120
+ source = ["domains", "ui"]
121
+ omit = [
122
+ "tests/*",
123
+ "app.py",
124
+ ]
125
+
126
+ [tool.coverage.report]
127
+ exclude_lines = [
128
+ "pragma: no cover",
129
+ "def __repr__",
130
+ "raise AssertionError",
131
+ "raise NotImplementedError",
132
+ "if __name__ == .__main__.:",
133
+ "if TYPE_CHECKING:",
134
+ ]
135
+
136
+ [tool.bandit]
137
+ exclude_dirs = ["tests"]
138
+ skips = ["B101", "B601"]
requirements.txt CHANGED
@@ -1,4 +1,10 @@
1
  gradio>=4.0.0
2
  numpy>=1.21.0
3
  matplotlib>=3.5.0
4
- pytest>=7.0.0
 
 
 
 
 
 
 
1
  gradio>=4.0.0
2
  numpy>=1.21.0
3
  matplotlib>=3.5.0
4
+ pytest>=7.0.0
5
+ pytest-cov>=4.0.0
6
+ pytest-xdist>=3.0.0
7
+ pre-commit>=3.0.0
8
+ ruff>=0.1.0
9
+ mypy>=1.0.0
10
+ bandit>=1.7.0