initial #1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # ============================================================ | |
| # .github/workflows/ci-python-zensical.yml (Continuous Integration) | |
| # ============================================================ | |
| # Updated: 2026-04-22 | |
| # | |
| # WHY-FILE: Validate repository hygiene, Python correctness, and documentation builds. | |
| # REQ: CI MUST NOT introduce arbitrary rules that are not reproducible locally. | |
| # OBS: CI validates only; it does not edit files or deploy docs. | |
| # OBS: yamllint config lives at .github/yamllint.yml (not repo root). | |
| # | |
| # === COVERAGE === | |
| # | |
| # COVERED BY PRE-COMMIT - not repeated as explicit steps: | |
| # - ruff-check (lint with autofix) | |
| # - ruff-format (formatting) | |
| # - trailing whitespace, line endings, JSON/TOML/YAML syntax, large files | |
| # | |
| # WHY SEPARATE: These tools are slower, require the full environment, | |
| # or produce output worth seeing in CI logs independently. | |
| name: CI (Python + Zensical) | |
| on: | |
| push: | |
| branches: [main] # WHY: Validate every push to main. | |
| pull_request: | |
| branches: [main] # WHY: Validate PRs before merge. | |
| workflow_dispatch: # WHY: Allow manual trigger from Actions tab. | |
| permissions: | |
| contents: read # WHY: Least privilege; CI only reads, never writes. | |
| env: | |
| PYTHONUNBUFFERED: "1" # WHY: Real-time log output in CI. | |
| PYTHONIOENCODING: "utf-8" # WHY: Consistent encoding across platforms. | |
| PYTHON_VERSION: "3.15" | |
| UV_PYTHON: "3.15" | |
| jobs: | |
| ci: | |
| name: Repository / Python checks and Zensical build | |
| runs-on: ubuntu-latest # WHY: Linux matches most production deployments. | |
| timeout-minutes: 30 # WHY: Fail fast if a step hangs unexpectedly. | |
| steps: | |
| # ============================================================ | |
| # A) ASSEMBLE: Checkout code and set up environment | |
| # ============================================================ | |
| - name: A1) Checkout repository code | |
| uses: actions/checkout@v6 | |
| # WHY: Required so all subsequent steps can access repo files. | |
| - name: A2) Install uv (with caching) | |
| uses: astral-sh/setup-uv@v7 | |
| with: | |
| enable-cache: true | |
| # WHY: Cache the uv tool itself for faster subsequent runs. | |
| cache-dependency-glob: "uv.lock" | |
| # WHY: Invalidate cache only when locked dependencies change. | |
| - name: A3) Install Python ${{ env.PYTHON_VERSION }} | |
| run: uv python install ${{ env.PYTHON_VERSION }} | |
| # WHY: Ensures the pinned Python version is available in CI. | |
| # OBS: Does not modify the repo; uv manages the interpreter locally. | |
| - name: A4) Install all dependencies | |
| run: uv sync --extra dev --extra docs --upgrade | |
| # WHY: Install dev and docs extras so all check and build tools are available. | |
| # OBS: --upgrade ensures CI catches dependency drift early. | |
| - name: A5) Show tool versions | |
| run: | | |
| uv --version | |
| uv run python --version | |
| uv run python -m ruff --version | |
| uv run python -m pyright --version | |
| if [ -f "zensical.toml" ]; then | |
| uv run python -m zensical --version | |
| fi | |
| # WHY: Version output makes CI logs easier to debug when tools change. | |
| - name: A6) Run pre-commit on all files | |
| run: uv tool run pre-commit run --all-files | |
| # WHY: Enforces formatting, linting, and file hygiene in one step. | |
| # OBS: Covers ruff-check, ruff-format, whitespace, line endings, | |
| # and JSON/TOML/YAML syntax checks defined in .pre-commit-config.yaml. | |
| # OBS: Pre-commit hook order (lint then format) differs from manual | |
| # command order (format then lint). See .pre-commit-config.yaml. | |
| # ============================================================ | |
| # B) BASELINE CHECKS: Tools not covered by pre-commit | |
| # ============================================================ | |
| - name: B1) Run Pyright type checker | |
| run: uv run python -m pyright | |
| # WHY: Catches type errors that ruff does not check. | |
| # OBS: Pyright reads settings from pyproject.toml [tool.pyright]. | |
| # OBS: Not included in pre-commit because it requires the full venv. | |
| # ============================================================ | |
| # C) COVERAGE & TESTING: Python tests (pytest) | |
| # ============================================================ | |
| - name: C1) Run pytest | |
| run: uv run python -m pytest | |
| # WHY: Confirms all Python tests pass in a clean CI environment. | |
| # OBS: pytest config lives in pyproject.toml [tool.pytest.ini_options]. | |
| # OBS: Not included in pre-commit because tests can be slow. | |
| # ============================================================ | |
| # D) Docs build (no deployment) | |
| # ============================================================ | |
| - name: D1) Build documentation with Zensical | |
| run: | | |
| if [ -f "zensical.toml" ]; then | |
| uv run python -m zensical build | |
| else | |
| echo "No zensical.toml found; skipping docs build." | |
| fi | |
| # WHY: Confirms docs build cleanly without errors or broken references. | |
| # OBS: Build only; deployment is handled by a separate workflow if needed. | |
| # OBS: Conditional on zensical.toml so this workflow is reusable across | |
| # repos that may not yet have docs configured. |