Skip to content

[P0][B3+D1] Harden CI: real coverage enforcement, Ruff, MyPy, pre-commit #10

Description

@POWDER-RANGER

Problem

Current ci.yml is a placeholder with two fatal flaws:

  1. pytest tests/ ... || echo "Tests directory not found..."silently passes when tests don't exist
  2. Only runs flake8 — no type checking, no formatting enforcement, no coverage threshold

This must be completely replaced with a production-grade pipeline that fails hard on any quality regression.

New CI Architecture

Jobs

  1. lint — Ruff + MyPy (fast, runs in parallel with test)
  2. test — pytest + coverage (must hit 100%)
  3. build — pyproject.toml package build verification
  4. smoke — install from wheel and run examples (end-to-end)

New ci.yml

name: CI

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

permissions:
  contents: read

jobs:
  lint:
    name: Lint & Type Check
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@<PIN_SHA>
        with:
          persist-credentials: false

      - uses: actions/setup-python@<PIN_SHA>
        with:
          python-version: "3.11"
          cache: pip

      - name: Install lint tools
        run: pip install ruff mypy 'cryptography>=42.0' pydantic

      - name: Ruff format check
        run: ruff format --check oblisk/ tests/

      - name: Ruff lint
        run: ruff check oblisk/ tests/

      - name: MyPy strict type check
        run: mypy oblisk/ --strict --ignore-missing-imports

  test:
    name: Test (Python ${{ matrix.python-version }})
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ["3.11", "3.12"]
    steps:
      - uses: actions/checkout@<PIN_SHA>
        with:
          persist-credentials: false

      - uses: actions/setup-python@<PIN_SHA>
        with:
          python-version: ${{ matrix.python-version }}
          cache: pip

      - name: Install package + dev deps
        run: pip install -e '.[dev]'

      - name: Run tests with coverage
        run: |
          pytest \
            --cov=oblisk \
            --cov-branch \
            --cov-report=xml:coverage.xml \
            --cov-report=term-missing \
            --cov-fail-under=100 \
            -v

      - name: Upload coverage to Codecov
        uses: codecov/codecov-action@<PIN_SHA>
        with:
          files: coverage.xml
          fail_ci_if_error: true
          flags: python-${{ matrix.python-version }}

  build:
    name: Build & Verify Package
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@<PIN_SHA>
        with:
          persist-credentials: false

      - uses: actions/setup-python@<PIN_SHA>
        with:
          python-version: "3.11"

      - name: Install build tools
        run: pip install build twine

      - name: Build wheel and sdist
        run: python -m build

      - name: Verify package with twine
        run: twine check dist/*

      - name: Test install from wheel
        run: |
          pip install dist/*.whl
          python -c "import oblisk; from oblisk.vault import Vault; print('Package OK')"

  smoke:
    name: Smoke Test Examples
    runs-on: ubuntu-latest
    needs: [build]
    steps:
      - uses: actions/checkout@<PIN_SHA>
        with:
          persist-credentials: false

      - uses: actions/setup-python@<PIN_SHA>
        with:
          python-version: "3.11"

      - name: Install
        run: pip install -e .

      - name: Run all examples
        run: |
          python examples/simple_agent.py
          python examples/vault_demo.py
          python examples/governance_demo.py
          python examples/multi_agent.py

Tasks

CI Overhaul

Ruff Configuration

  • Add [tool.ruff] and [tool.ruff.lint] to pyproject.toml:
    [tool.ruff]
    target-version = "py311"
    line-length = 100
    
    [tool.ruff.lint]
    select = ["E", "W", "F", "I", "N", "UP", "S", "B", "ANN"]
    ignore = ["ANN101", "ANN102", "S101"]
    
    [tool.ruff.lint.per-file-ignores]
    "tests/**" = ["S", "ANN"]  # relax security and annotation rules in tests
  • Run ruff format oblisk/ to auto-format entire codebase
  • Fix all ruff check violations

MyPy Configuration

  • Add [tool.mypy] to pyproject.toml with strict = true
  • Add type annotations to all public functions and methods in oblisk/
  • Run mypy oblisk/ --strict and fix all errors
  • Use py.typed marker file in oblisk/ package

Pre-commit Hooks

  • Create .pre-commit-config.yaml:
    repos:
      - repo: https://github.com/astral-sh/ruff-pre-commit
        rev: v0.4.7
        hooks:
          - id: ruff
            args: [--fix]
          - id: ruff-format
      
      - repo: https://github.com/pre-commit/pre-commit-hooks
        rev: v4.6.0
        hooks:
          - id: trailing-whitespace
          - id: end-of-file-fixer
          - id: check-yaml
          - id: check-toml
          - id: check-merge-conflict
          - id: debug-statements
          - id: no-commit-to-branch
            args: [--branch, main]
      
      - repo: https://github.com/pre-commit/mirrors-mypy
        rev: v1.10.0
        hooks:
          - id: mypy
            args: [--strict]
            additional_dependencies: ["cryptography", "pydantic"]
  • Add pre-commit install to CONTRIBUTING.md setup instructions
  • Add pre-commit CI check to ci.yml

Codecov Configuration

  • Create .codecov.yml:
    coverage:
      precision: 2
      round: down
      range: "90...100"
      status:
        project:
          default:
            target: 100%
            threshold: 0%
        patch:
          default:
            target: 100%
    comment:
      layout: "reach,diff,flags,tree"
      behavior: default
      require_changes: false

README Badges

  • Add CI status badge
  • Add Codecov coverage badge (targeting 100%)
  • Add OpenSSF Scorecard badge
  • Add PyPI version badge (once published)
  • Add Python versions badge

Acceptance Criteria

  • ci.yml has 4 jobs: lint, test, build, smoke
  • pytest --cov-fail-under=100 in CI — fails if coverage drops
  • ruff format --check fails CI if unformatted code is pushed
  • ruff check fails CI on any lint violation
  • mypy --strict fails CI on any type error
  • ✅ Codecov reports 100% coverage on every PR
  • ✅ No || echo fallback patterns anywhere in workflows
  • ✅ Python 3.11 and 3.12 both pass
  • ✅ Pre-commit hooks prevent violations locally before push
  • ✅ All 4 README badges render correctly

Dependencies

Requires: #6 (package layout), #9 (tests exist)
Related: #11 (SHA pinning), #12 (Scorecard workflow)
Estimated effort: 4-6 hours

Priority: P0 — CI quality gate is the foundation of everything
Labels: ci/cd, quality, mypy, ruff, coverage, P0

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions