Adding QWED to Your CI/CD Pipeline
· 7 min read
As AI-generated code becomes more common, CI/CD pipelines need new verification steps. This guide shows how to integrate QWED into your deployment workflow.
Why Verify AI Outputs in CI/CD?
Modern development increasingly uses AI for:
- Code generation (GitHub Copilot, Cursor)
- SQL query building
- Configuration generation
- Documentation
Problem: AI-generated artifacts can contain errors that slip past traditional tests.
Solution: Add QWED verification as a CI/CD step.
flowchart LR
A[Push Code] --> B[Build]
B --> C[Unit Tests]
C --> D[QWED Verification]
D -->|✅ Pass| E[Deploy]
D -->|❌ Fail| F[Block Deploy]
GitHub Actions Integration
Basic Verification Workflow
.github/workflows/verify.yml
name: QWED Verification
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install QWED
run: pip install qwed
- name: Verify SQL Migrations
run: |
python -c "
from qwed import QWEDClient
import glob
client = QWEDClient()
# Find all SQL files
sql_files = glob.glob('migrations/*.sql')
failed = []
for sql_file in sql_files:
with open(sql_file) as f:
sql = f.read()
result = client.verify_sql(sql, dialect='postgresql')
if not result.verified:
failed.append({
'file': sql_file,
'violations': result.result.get('violations', [])
})
print(f'❌ {sql_file}: {result.status}')
else:
print(f'✅ {sql_file}: VERIFIED')
if failed:
print(f'\\n{len(failed)} files failed verification')
exit(1)
"
- name: Verify Python Code Security
run: |
python -c "
from qwed import QWEDClient
import glob
client = QWEDClient()
# Check AI-generated code files
py_files = glob.glob('src/generated/*.py')
for py_file in py_files:
with open(py_file) as f:
code = f.read()
result = client.verify_code(code, language='python')
if not result.verified:
print(f'⚠️ Security issue in {py_file}')
for vuln in result.result.get('vulnerabilities', []):
print(f' - {vuln}')
exit(1)
print('✅ All code verified safe')
"
Advanced: Multi-Engine Verification
.github/workflows/qwed-full.yml
name: Full QWED Verification Suite
on:
push:
branches: [main]
pull_request:
env:
QWED_API_KEY: ${{ secrets.QWED_API_KEY }}
jobs:
sql-verification:
name: Verify SQL Queries
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with: { python-version: '3.11' }
- run: pip install qwed
- name: Verify migrations
run: python scripts/verify_sql.py migrations/
- name: Verify query files
run: python scripts/verify_sql.py queries/
code-verification:
name: Verify Code Security
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with: { python-version: '3.11' }
- run: pip install qwed
- name: Scan for vulnerabilities
run: python scripts/verify_code.py src/
math-verification:
name: Verify Calculations
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with: { python-version: '3.11' }
- run: pip install qwed pytest
- name: Verify financial calculations
run: python scripts/verify_calculations.py
- name: Run calculation tests
run: pytest tests/calculations/ --qwed-verify
aggregate-results:
name: Aggregate Verification
needs: [sql-verification, code-verification, math-verification]
runs-on: ubuntu-latest
steps:
- name: All verifications passed
run: echo "✅ All QWED verifications passed!"
Verification Scripts
SQL Verification Script
scripts/verify_sql.py
#!/usr/bin/env python3
"""Verify all SQL files in a directory."""
import sys
import glob
from pathlib import Path
from qwed import QWEDClient
def verify_sql_files(directory: str) -> bool:
client = QWEDClient()
sql_files = glob.glob(f"{directory}/**/*.sql", recursive=True)
if not sql_files:
print(f"No SQL files found in {directory}")
return True
print(f"Verifying {len(sql_files)} SQL files...")
failed = []
for sql_file in sql_files:
with open(sql_file) as f:
sql = f.read()
result = client.verify_sql(sql, dialect="postgresql")
if result.verified:
print(f" ✅ {sql_file}")
else:
print(f" ❌ {sql_file}")
violations = result.result.get('violations', [])
for v in violations:
print(f" - {v['type']}: {v.get('message', '')}")
failed.append(sql_file)
print()
if failed:
print(f"FAILED: {len(failed)}/{len(sql_files)} files")
return False
else:
print(f"PASSED: All {len(sql_files)} files verified")
return True
if __name__ == "__main__":
directory = sys.argv[1] if len(sys.argv) > 1 else "."
success = verify_sql_files(directory)
sys.exit(0 if success else 1)
Code Verification Script
scripts/verify_code.py
#!/usr/bin/env python3
"""Verify Python code for security issues."""
import sys
import glob
from qwed import QWEDClient
SKIP_PATTERNS = ["test_", "conftest", "__pycache__"]
def verify_python_files(directory: str) -> bool:
client = QWEDClient()
py_files = glob.glob(f"{directory}/**/*.py", recursive=True)
py_files = [f for f in py_files if not any(p in f for p in SKIP_PATTERNS)]
print(f"Scanning {len(py_files)} Python files for security issues...")
issues = []
for py_file in py_files:
with open(py_file) as f:
code = f.read()
result = client.verify_code(code, language="python")
if not result.verified:
vulns = result.result.get('vulnerabilities', [])
issues.append({
'file': py_file,
'vulnerabilities': vulns
})
if issues:
print("\n⚠️ Security Issues Found:\n")
for issue in issues:
print(f"File: {issue['file']}")
for v in issue['vulnerabilities']:
severity = v.get('severity', 'unknown')
line = v.get('line', '?')
msg = v.get('message', v.get('type', 'Unknown issue'))
print(f" [{severity.upper()}] Line {line}: {msg}")
print()
return False
else:
print("✅ No security issues found")
return True
if __name__ == "__main__":
directory = sys.argv[1] if len(sys.argv) > 1 else "src/"
success = verify_python_files(directory)
sys.exit(0 if success else 1)
Calculation Verification Script
scripts/verify_calculations.py
#!/usr/bin/env python3
"""Verify mathematical calculations in config files."""
import sys
import json
import yaml
from pathlib import Path
from qwed import QWEDClient
def verify_config_calculations():
client = QWEDClient()
# Check pricing calculations
with open("config/pricing.yml") as f:
pricing = yaml.safe_load(f)
issues = []
for tier in pricing.get('tiers', []):
name = tier['name']
base = tier['base_price']
markup = tier['markup_percentage']
final = tier['final_price']
# Verify calculation
expected = base * (1 + markup / 100)
result = client.verify_math(
expression=f"{base} * (1 + {markup}/100)",
expected_result=str(final)
)
if not result.verified:
issues.append({
'tier': name,
'expected': expected,
'actual': final
})
print(f"❌ {name}: {base} * (1 + {markup}%) should be {expected:.2f}, not {final}")
else:
print(f"✅ {name}: Price calculation verified")
return len(issues) == 0
if __name__ == "__main__":
success = verify_config_calculations()
sys.exit(0 if success else 1)
GitLab CI Integration
.gitlab-ci.yml
stages:
- test
- verify
- deploy
qwed-verification:
stage: verify
image: python:3.11
script:
- pip install qwed
- python scripts/verify_sql.py migrations/
- python scripts/verify_code.py src/
- python scripts/verify_calculations.py
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
Pre-commit Hook
Add QWED verification as a pre-commit hook:
.pre-commit-config.yaml
repos:
- repo: local
hooks:
- id: qwed-sql-verify
name: QWED SQL Verification
entry: python scripts/verify_sql.py
language: python
files: \.sql$
additional_dependencies: [qwed]
- id: qwed-code-verify
name: QWED Code Security
entry: python scripts/verify_code.py
language: python
files: \.py$
additional_dependencies: [qwed]
Install:
pip install pre-commit
pre-commit install
Pull Request Comments
Post verification results as PR comments:
.github/workflows/pr-verify.yml
name: PR Verification Report
on:
pull_request:
types: [opened, synchronize]
jobs:
verify-and-comment:
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with: { python-version: '3.11' }
- run: pip install qwed
- name: Run verification
id: verify
run: |
python scripts/full_verification.py > report.md 2>&1 || true
echo "report<<EOF" >> $GITHUB_OUTPUT
cat report.md >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Comment on PR
uses: actions/github-script@v7
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `## 🛡️ QWED Verification Report\n\n${{ steps.verify.outputs.report }}`
})
Monitoring & Alerting
Track verification metrics over time:
scripts/metrics_reporter.py
"""Send verification metrics to monitoring."""
import json
from qwed import QWEDClient
from datetime import datetime
def report_metrics(results: dict):
metrics = {
'timestamp': datetime.utcnow().isoformat(),
'sql_files_verified': results['sql']['total'],
'sql_files_passed': results['sql']['passed'],
'code_files_scanned': results['code']['total'],
'vulnerabilities_found': results['code']['vulnerabilities'],
'calculations_verified': results['math']['total'],
'calculations_passed': results['math']['passed'],
}
# Send to your metrics system
# e.g., Prometheus pushgateway, Datadog, New Relic
print(json.dumps(metrics, indent=2))
# Use in CI workflow
# python scripts/metrics_reporter.py
Best Practices
1. Fail Fast on Critical Issues
- name: Verify (fail on any issue)
run: python scripts/verify.py --strict
2. Allow Warnings in Development
- name: Verify (warn only)
run: python scripts/verify.py --warn-only
if: github.ref != 'refs/heads/main'
3. Cache Verification Results
- name: Cache QWED results
uses: actions/cache@v3
with:
path: ~/.qwed/cache
key: qwed-${{ hashFiles('**/*.sql', '**/*.py') }}
4. Parallel Verification
jobs:
verify:
strategy:
matrix:
engine: [sql, code, math, logic]
steps:
- name: Verify ${{ matrix.engine }}
run: python scripts/verify_${{ matrix.engine }}.py
Conclusion
Adding QWED to your CI/CD pipeline ensures:
- ✅ SQL Safety — No injection vulnerabilities in migrations
- ✅ Code Security — AI-generated code is scanned
- ✅ Calculation Accuracy — Config values are mathematically correct
- ✅ Automated Enforcement — Verification on every push
Don't ship AI-generated artifacts without verification.
Resources
Next up: Formal Verification of Chain-of-Thought Reasoning →
