Skip to content

Commit bfe2a9d

Browse files
author
Akkari
committed
ci: add Quorum self-validation gate for PRs to main
- Runs standard depth on changed files only (auto-detected via git diff) - Max cost cap: $5.00 default (prevents surprise bills) - Manual trigger via workflow_dispatch with configurable depth and budget - Installs ruff + bandit for full pre-screen coverage - Includes pytest run as final check - Requires ANTHROPIC_API_KEY repository secret
1 parent 6d6f47e commit bfe2a9d

1 file changed

Lines changed: 121 additions & 0 deletions

File tree

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
# SPDX-License-Identifier: MIT
2+
# Quorum Self-Validation CI Gate
3+
# Runs standard-depth validation on changed files for every PR to main.
4+
# Requires ANTHROPIC_API_KEY in repository secrets.
5+
6+
name: Quorum Validation
7+
8+
on:
9+
pull_request:
10+
branches: [main]
11+
workflow_dispatch:
12+
inputs:
13+
depth:
14+
description: 'Validation depth (quick/standard/thorough)'
15+
required: false
16+
default: 'standard'
17+
max_cost:
18+
description: 'Maximum cost in USD'
19+
required: false
20+
default: '5.00'
21+
22+
permissions:
23+
contents: read
24+
pull-requests: write
25+
26+
jobs:
27+
validate:
28+
name: Quorum Self-Validation
29+
runs-on: ubuntu-latest
30+
timeout-minutes: 30
31+
32+
steps:
33+
- name: Checkout
34+
uses: actions/checkout@v4
35+
with:
36+
fetch-depth: 0 # Full history for diff
37+
38+
- name: Set up Python
39+
uses: actions/setup-python@v5
40+
with:
41+
python-version: '3.12'
42+
43+
- name: Install Quorum
44+
working-directory: reference-implementation
45+
run: |
46+
pip install -e ".[dev]"
47+
pip install ruff bandit # Optional SAST tools for pre-screen
48+
49+
- name: Detect changed files
50+
id: changes
51+
run: |
52+
if [ "${{ github.event_name }}" = "pull_request" ]; then
53+
BASE="${{ github.event.pull_request.base.sha }}"
54+
else
55+
BASE="HEAD~1"
56+
fi
57+
58+
# Get changed files that Quorum can validate
59+
CHANGED=$(git diff --name-only "$BASE" HEAD -- \
60+
'*.py' '*.md' '*.yaml' '*.yml' '*.json' '*.toml' '*.ps1' \
61+
| grep -v '__pycache__' \
62+
| grep -v '.github/' \
63+
| head -50)
64+
65+
if [ -z "$CHANGED" ]; then
66+
echo "No validatable files changed."
67+
echo "skip=true" >> "$GITHUB_OUTPUT"
68+
else
69+
COUNT=$(echo "$CHANGED" | wc -l | tr -d ' ')
70+
echo "Found $COUNT changed files to validate"
71+
echo "$CHANGED"
72+
# Write to file for quorum to consume
73+
echo "$CHANGED" > /tmp/changed-files.txt
74+
echo "skip=false" >> "$GITHUB_OUTPUT"
75+
echo "count=$COUNT" >> "$GITHUB_OUTPUT"
76+
fi
77+
78+
- name: Run Quorum validation
79+
if: steps.changes.outputs.skip != 'true'
80+
working-directory: reference-implementation
81+
env:
82+
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
83+
run: |
84+
DEPTH="${{ github.event.inputs.depth || 'standard' }}"
85+
MAX_COST="${{ github.event.inputs.max_cost || '5.00' }}"
86+
87+
echo "::group::Quorum validation ($DEPTH depth, max \$$MAX_COST)"
88+
89+
EXIT_CODE=0
90+
while IFS= read -r file; do
91+
[ -f "$file" ] || [ -f "../$file" ] || continue
92+
93+
# Resolve path — files may be relative to repo root
94+
if [ -f "../$file" ]; then
95+
TARGET="../$file"
96+
else
97+
TARGET="$file"
98+
fi
99+
100+
echo "── Validating: $file ──"
101+
python -m quorum run \
102+
--target "$TARGET" \
103+
--depth "$DEPTH" \
104+
--max-cost "$MAX_COST" \
105+
--yes \
106+
--audit-report \
107+
2>&1 || EXIT_CODE=1
108+
109+
done < /tmp/changed-files.txt
110+
111+
echo "::endgroup::"
112+
exit $EXIT_CODE
113+
114+
- name: Skip notice
115+
if: steps.changes.outputs.skip == 'true'
116+
run: echo "No validatable files changed — skipping Quorum validation."
117+
118+
- name: Run tests
119+
working-directory: reference-implementation
120+
run: |
121+
python -m pytest --tb=short -q 2>&1 | tail -5

0 commit comments

Comments
 (0)