Skip to content

v0.1.0 — zero known bugs (first minor release) #1907

v0.1.0 — zero known bugs (first minor release)

v0.1.0 — zero known bugs (first minor release) #1907

Workflow file for this run

name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
permissions:
contents: read
strategy:
# #848: don't let one failed combo cancel the other 11 — a single
# flaky test cancelled two otherwise-green matrices on PR #846.
# Full per-run results also make real cross-platform breakage
# (one OS red, others green) legible at a glance.
fail-fast: false
matrix:
# Explicit macOS pins (not `macos-latest`) so we don't silently
# migrate when GitHub flips the `-latest` alias. See README §Supported
# platforms for the policy. `macos-15` (Sequoia) is currently
# `macos-latest` (May 2026) and the most common single non-current
# version among real users (~24% of macOS install base per
# https://telemetrydeck.com/survey/apple/macOS/versions/); `macos-26`
# (Tahoe) is current and dominant (~75%).
os: [ubuntu-latest, macos-15, macos-26, windows-latest]
python-version: ["3.11", "3.12", "3.13"]
name: test (${{ matrix.os }}, ${{ matrix.python-version }})${{ matrix.python-version == '3.12' && matrix.os == 'ubuntu-latest' && ' + coverage' || '' }}
runs-on: ${{ matrix.os }}
# No PYTHONUTF8 env: #645 made text I/O UTF-8 without the PEP-540 backstop
# (#641). Every text-mode open()/read_text()/write_text() and every
# subprocess text=True capture passes an explicit encoding="utf-8" (enforced
# by scripts/check_explicit_encoding.py), and the `vera` CLI reconfigures its
# stdout/stderr to UTF-8 at startup — so a Vera program printing `→` / `—` is
# UTF-8 on every runner regardless of locale, cp1252 Windows included.
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: pip install -e ".[dev]"
# Two mutually-exclusive run-test steps so the gating cell
# (3.12 / ubuntu) does coverage in the SAME pytest invocation
# rather than running the full suite twice. -n auto runs tests
# in parallel across CPU cores via pytest-xdist; the coverage
# cell takes the longest because instrumentation adds overhead,
# so it sets the wall time and gets parallelised too.
- name: Run tests
if: ${{ !(matrix.python-version == '3.12' && matrix.os == 'ubuntu-latest') }}
run: pytest -v -n auto
- name: Run tests with coverage
if: matrix.python-version == '3.12' && matrix.os == 'ubuntu-latest'
run: pytest -v -n auto --cov=vera --cov-report=term-missing --cov-report=xml --cov-fail-under=80
- name: Upload coverage to Codecov
if: matrix.python-version == '3.12' && matrix.os == 'ubuntu-latest'
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: coverage.xml
flags: python
fail_ci_if_error: false
typecheck:
permissions:
contents: read
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.12"
- name: Install dependencies
run: pip install -e ".[dev]"
- name: Run mypy
run: mypy vera/
lint:
permissions:
contents: read
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
# Full history so check_changelog_updated.py can diff against
# origin/main. Other lint checks work fine without it.
fetch-depth: 0
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.12"
- name: Install dependencies
run: pip install -e ".[dev]"
- name: Check CHANGELOG updated for substantive changes
# PR-level escape hatch: adding the "skip-changelog" label
# skips this step for PRs that legitimately don't need an entry
# (e.g., a typo fix in a code comment). The step always runs
# for push events on main.
if: github.event_name != 'pull_request' || !contains(github.event.pull_request.labels.*.name, 'skip-changelog')
run: python scripts/check_changelog_updated.py
- name: Check conformance suite
run: python scripts/check_conformance.py
- name: Check all examples type-check and verify cleanly
run: python scripts/check_examples.py
- name: Check vera run commands in examples/README.md are valid
run: python scripts/check_examples_readme.py
- name: Check version numbers are in sync
run: python scripts/check_version_sync.py
- name: Check spec code blocks parse correctly
run: python scripts/check_spec_examples.py
- name: Check README code blocks parse correctly
run: python scripts/check_readme_examples.py
- name: Check SKILL.md code blocks parse correctly
run: python scripts/check_skill_examples.py
- name: Check FAQ code blocks parse correctly
run: python scripts/check_faq_examples.py
- name: Check HTML code blocks parse, check, and verify
run: python scripts/check_html_examples.py
- name: Check no doc example redefines a built-in (E151)
run: python scripts/check_doc_builtin_shadowing.py
- name: Check no unexpected [E602]/[E604] silent skips (Layer 1 of #626)
run: python scripts/check_e602_clean.py
- name: Check every diagnostic carries rationale/fix/spec_ref (#682)
run: python scripts/check_diagnostic_fields.py
- name: Check text-mode file I/O passes explicit encoding (#645)
run: python scripts/check_explicit_encoding.py
- name: Check site assets are up-to-date
run: python scripts/check_site_assets.py
- name: Check license compliance
run: python scripts/check_licenses.py
- name: Check documentation counts are consistent
run: python scripts/check_doc_counts.py
- name: Check limitation tables are in sync
run: python scripts/check_limitations_sync.py
- name: Lint (ruff)
run: ruff check .
- name: Security lint (ruff S rules)
run: ruff check --select S vera/
- name: Verify uv.lock is up to date
run: |
pip install "uv>=0.5,<2"
uv lock --check
security:
permissions:
contents: read
security-events: write
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
persist-credentials: false
- name: Gitleaks
uses: gitleaks/gitleaks-action@v3
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
dependency-audit:
permissions:
contents: read
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.12"
- name: Install dependencies and pip-audit
# `pip install --upgrade pip` first: actions/setup-python@v6 bakes
# pip 26.0.1 into its toolchain, which is flagged for CVE-2026-3219
# (archive-handling, fixed in pip 26.1 via pypa/pip#13870). Without
# the upgrade, pip-audit reports the runner's own pip as vulnerable
# even though the fix is shipped on PyPI. Drop the `--upgrade pip`
# once the runner image picks up pip 26.1 natively. Tracked in #537,
# listed in the "CI workarounds" section of KNOWN_ISSUES.md.
run: pip install --upgrade pip && pip install -e . && pip install pip-audit
- name: Audit dependencies for known CVEs
# --skip-editable: vera itself is a local editable install, not on PyPI
# --ignore-vuln CVE-2026-4539: pygments 2.19.2 (transitive via pytest/rich);
# no fix release exists yet — revisit when pygments >2.19.2 ships
run: pip-audit --skip-editable --ignore-vuln CVE-2026-4539
wheel-preflight:
# Structural backstop for #691-class regressions: if an upstream dep
# bumps its platform-tag baseline (e.g. z3-solver going from
# macosx_13_0_arm64 to macosx_15_0_arm64 between 4.15.4 and 4.15.5),
# this job fails fast in CI rather than letting users discover the
# regression at install time on their machine. Pairs with the
# README §Supported platforms policy; the script enforces what the
# README documents.
permissions:
contents: read
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.12"
- name: Check wheel availability across supported platforms
run: python scripts/check_wheel_availability.py
sbom:
permissions:
contents: read
runs-on: ubuntu-latest
# Generate an SBOM on every push to main (i.e. each release merge).
# PRs get the artifact too, useful for reviewing dependency changes.
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.12"
- name: Install vera and CycloneDX tooling
run: pip install -e . && pip install cyclonedx-bom
- name: Generate CycloneDX SBOM
run: cyclonedx-py environment --of JSON -o sbom.json
- name: Upload SBOM artifact
uses: actions/upload-artifact@v7
with:
name: sbom
path: sbom.json
retention-days: 90
browser-parity:
permissions:
contents: read
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.12"
- name: Set up Node.js
uses: actions/setup-node@v6
with:
node-version: "22"
- name: Install dependencies
run: pip install -e ".[dev]"
- name: Run browser parity tests
run: pytest tests/test_browser.py -v
env:
NODE_V8_COVERAGE: ${{ runner.temp }}/v8-coverage
- name: Generate JS coverage report
if: always()
run: npx c8 report --temp-directory="${{ runner.temp }}/v8-coverage" --reporter=lcov --report-dir=./js-coverage --src=vera/browser/
- name: Upload JS coverage to Codecov
if: always()
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: js-coverage/lcov.info
flags: javascript
fail_ci_if_error: false