Skip to content

Commit 7422bc2

Browse files
committed
updates to workflows
1 parent 5c5d26e commit 7422bc2

File tree

3 files changed

+69
-70
lines changed

3 files changed

+69
-70
lines changed

.github/dependabot.yml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,3 @@ updates:
88
directory: "/"
99
schedule:
1010
interval: "weekly"
11-
- package-ecosystem: "github-pre-commit"
12-
directory: "/"
13-
schedule:
14-
interval: "weekly"

.github/workflows/ci.yml

Lines changed: 66 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,35 @@ on:
66
pull_request:
77
branches: [ main ]
88

9+
# Cancel redundant runs per-branch/PR
10+
concurrency:
11+
group: ci-${{ github.workflow }}-${{ github.ref }}
12+
cancel-in-progress: true
13+
14+
# Least-privilege for the jobs below
15+
permissions:
16+
contents: read
17+
918
jobs:
1019
test:
1120
name: Test / Lint / Typecheck (uv)
1221
runs-on: ubuntu-latest
22+
# Write perms only where needed
23+
permissions:
24+
contents: read
1325
strategy:
26+
fail-fast: false
1427
matrix:
15-
python-version: ["3.11", "3.12", "3.13", "3.14"]
28+
include:
29+
- python-version: "3.11"
30+
experimental: false
31+
- python-version: "3.12"
32+
experimental: false
33+
- python-version: "3.13"
34+
experimental: false
35+
- python-version: "3.14" # treat 3.14 as experimental so CI doesn't block if it breaks
36+
experimental: true
37+
continue-on-error: ${{ matrix.experimental }}
1638

1739
steps:
1840
- name: Checkout
@@ -23,11 +45,12 @@ jobs:
2345
with:
2446
enable-cache: true
2547

26-
- name: Set up Python ${{ matrix.python-version }}
48+
- name: Set up Python
2749
run: uv python install ${{ matrix.python-version }}
2850

29-
- name: Sync dependencies with uv
30-
run: uv sync --all-extras
51+
# Ensure dev tools (ruff, mypy, pytest, bandit, safety, pytest-cov) are declared in pyproject dev deps.
52+
- name: Sync dependencies
53+
run: uv sync --all-extras --dev
3154

3255
- name: Lint (ruff)
3356
run: uv run ruff check .
@@ -38,14 +61,15 @@ jobs:
3861
- name: Tests (pytest)
3962
run: uv run pytest --cov --cov-report=xml --cov-report=html
4063

41-
- name: Security scan for dangerous APIs
64+
- name: Dangerous API scan (grep)
65+
continue-on-error: true
66+
shell: bash
4267
run: |
4368
set -euo pipefail
44-
if grep -R --line-number -E "\beval\(|\bexec\(|pickle\.loads|yaml\.load|subprocess\.(Popen|call)" src/ tests/ || true; then
45-
echo "⚠️ Potentially dangerous API usage detected. Please review before merging." >&2
69+
if grep -R --line-number -E "\beval\(|\bexec\(|pickle\.loads|yaml\.load(?!_safe)|subprocess\.(Popen|call)" src/ tests/ || true; then
70+
echo "⚠️ Potentially dangerous API usage detected. Please review." >&2
4671
exit 2
4772
fi
48-
continue-on-error: true
4973
5074
- name: Upload coverage.xml
5175
uses: actions/upload-artifact@v4
@@ -59,95 +83,71 @@ jobs:
5983
name: coverage-html-${{ matrix.python-version }}
6084
path: htmlcov
6185

86+
# Upload Codecov once to avoid noisy duplicate uploads
87+
- name: Upload to Codecov
88+
if: matrix.python-version == '3.11'
89+
uses: codecov/codecov-action@v4
90+
with:
91+
files: coverage.xml
92+
flags: unittests
93+
fail_ci_if_error: false
94+
env:
95+
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
96+
6297
security:
63-
name: Security Scan
98+
name: Security Scan (Bandit + Safety)
6499
runs-on: ubuntu-latest
100+
needs: test
101+
# Grant code scanning upload only here
102+
permissions:
103+
contents: read
104+
security-events: write
105+
65106
env:
66107
SECURITY_FAIL_LEVEL: MEDIUM
108+
67109
steps:
68-
- uses: actions/checkout@v4
110+
- name: Checkout
111+
uses: actions/checkout@v4
69112

70113
- name: Install uv
71114
uses: astral-sh/setup-uv@v4
72115
with:
73116
enable-cache: true
74117

75-
- name: Set up Python 3.11
118+
- name: Set up Python
76119
run: uv python install 3.11
77120

78-
- name: Sync deps and install security tools
79-
run: |
80-
uv sync --all-extras
81-
uv pip install bandit safety
121+
- name: Sync dependencies
122+
run: uv sync --all-extras --dev
82123

83-
- name: Run Bandit and export SARIF
124+
- name: Run Bandit (JSON + SARIF)
84125
run: |
85-
uv run bandit -r src/ -f json -o bandit-report.json
86-
uv run bandit -r src/ -f sarif -o bandit-report.sarif
87-
continue-on-error: true
126+
uv run bandit -r src/ -f json -o bandit-report.json || true
127+
uv run bandit -r src/ -f sarif -o bandit-report.sarif || true
88128
89129
- name: Upload Bandit SARIF to GitHub Code Scanning
90130
uses: github/codeql-action/upload-sarif@v3
91131
with:
92132
sarif_file: bandit-report.sarif
93133
continue-on-error: true
94134

95-
- name: Run Safety (fail on any vulnerability)
96-
run: |
97-
uv run safety check --json > safety-report.json || true
98-
python - <<'PY'
99-
import json,sys,os
100-
try:
101-
data=json.load(open('safety-report.json'))
102-
if data.get('vulnerabilities'):
103-
print('Safety reported vulnerabilities')
104-
sys.exit(2)
105-
print('No safety vulnerabilities')
106-
except Exception as e:
107-
print(f'Error parsing safety output: {e}')
108-
sys.exit(0)
109-
PY
110-
continue-on-error: true
135+
- name: Run Safety (JSON)
136+
run: uv run safety check --json > safety-report.json || true
111137

112138
- name: Apply Bandit threshold
113-
run: |
114-
python - <<'PY'
115-
import json,sys,os
116-
level=os.environ.get('SECURITY_FAIL_LEVEL','MEDIUM').upper()
117-
try:
118-
data=json.load(open('bandit-report.json'))
119-
sevs=[issue.get('issue_severity','') for issue in data.get('results',[])]
120-
if level=='NONE':
121-
print('SECURITY_FAIL_LEVEL=NONE: not failing on bandit issues')
122-
sys.exit(0)
123-
if level=='HIGH':
124-
if 'HIGH' in sevs:
125-
print('Failing on HIGH bandit issues')
126-
sys.exit(2)
127-
else:
128-
print('No HIGH bandit issues')
129-
sys.exit(0)
130-
if level=='MEDIUM':
131-
if any(s in ('HIGH','MEDIUM') for s in sevs):
132-
print('Failing on MEDIUM or HIGH bandit issues')
133-
sys.exit(2)
134-
else:
135-
print('No MEDIUM/HIGH bandit issues')
136-
sys.exit(0)
137-
print('Unknown SECURITY_FAIL_LEVEL:', level)
138-
sys.exit(1)
139-
except Exception as e:
140-
print(f'Error parsing bandit report: {e}')
141-
sys.exit(0)
142-
PY
139+
run: uv run python scripts/security_bandit_check.py
143140
continue-on-error: true
144141

142+
- name: Fail on Safety vulnerabilities
143+
run: uv run python scripts/security_safety_check.py
144+
145145
- name: Upload security reports
146+
if: always()
146147
uses: actions/upload-artifact@v4
147148
with:
148149
name: security-reports
149150
path: |
150151
bandit-report.json
151152
bandit-report.sarif
152153
safety-report.json
153-
if: always()

.github/workflows/docs-pages.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ jobs:
2222
- name: Sync dependencies with uv
2323
run: uv sync --all-extras
2424

25+
- name: Install sphinx
26+
run: uv pip install sphinx sphinx-rtd-theme
27+
2528
- name: Build docs
2629
run: uv run sphinx-build -b html docs docs/_build/html
2730

0 commit comments

Comments
 (0)