Repository navigation
151 lines (134 loc) · 6.96 KB
/
Copy pathci-python-zensical.yml
File metadata and controls
151 lines (134 loc) · 6.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# ============================================================
# .github/workflows/ci-python-zensical.yml (ALL-PY-SRC-REPOS)
# ============================================================
# Updated: 2026-10-11
#
# WHAT: A GitHub Actions workflow that automatically checks project quality.
# GitHub Actions is GitHub's built-in project automation service.
# This YAML file tells GitHub what commands to run and when to run them.
#
# WHEN: Use for Python projects that also use Zensical to build a
# professional documentation website describing the project,
# its data, methods, processes, and results.
#
# TRIGGER: Runs automatically when changes are pushed to the main branch
# or a pull request targets main. It can also be started manually.
# GitHub runs the checks on a fresh, temporary computer.
#
# WHY: Automated checks catch errors early and help ensure that the project
# works consistently beyond the developer's own computer.
# This workflow checks project configuration, Python code, tests,
# and whether the Zensical documentation builds successfully.
#
# CI/CD: Continuous Integration (CI) automatically checks changes.
# Continuous Delivery/Deployment (CD) prepares or publishes work.
# This workflow performs CI only; it does not publish the website.
# A separate workflow handles deployment.
#
# SKILLS: Git, GitHub, GitHub Actions, CI/CD, automated testing,
# project automation, and documentation builds.
#
# REQ: Repository MUST contain .python-version.
# REQ: CI MUST NOT introduce rules that are not reproducible locally.
# REQ: CI MUST validate only; it never persists file changes or deploys docs.
# ============================================================
# Name shown in the repository Actions tab.
name: CI (Python + Zensical)
on:
push:
branches: [main] # WHY: Validate on every push to GitHub branch `main`.
pull_request:
branches: [main] # WHY: Validate pull requests before merge.
workflow_dispatch: # WHY: Allow manual trigger from Actions tab.
permissions: # WHY: Least privilege; this job only needs repository read access.
contents: read # WHY: CI validates repository contents and never pushes changes.
concurrency:
group: ci-python-zensical-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
# WHY: Cancel a running CI check when new code is pushed to the same branch.
env:
PYTHONUNBUFFERED: "1" # WHY: Display Python output immediately in CI logs.
UV_FROZEN: "1" # WHY: Use the committed lockfile without updating it.
jobs:
ci:
name: Repo 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@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false
# WHY: Required so all subsequent steps can access repo files.
- name: A2) Install uv (with caching and uv.lock awareness)
uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
with:
enable-cache: true
# WHY: Cache uv-managed artifacts for faster subsequent runs.
cache-dependency-glob: "uv.lock"
# WHY: Invalidate dependency cache when the committed lockfile changes.
- name: A3) Install project Python
run: uv python install
# WHY: Ensures the Python version declared in .python-version is available.
# OBS: uv manages the interpreter locally in the CI environment.
- name: A4) Install dependencies from committed lockfile
run: uv sync --frozen
# WHY: Create the project environment exactly from the committed uv.lock.
# REQ: CI MUST fail rather than update a stale or incompatible lockfile.
- name: A5) Show tool versions
run: |
uv --version
uv run python --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 repository hooks on all files (prek)
run: uvx prek run --all-files
# WHY: Run the same repository hygiene checks used locally.
# OBS: uvx runs prek independently of the project environment.
# OBS: prek reads the repository's prek.toml configuration.
# OBS: A clean commit should already pass without file changes.
# OBS: Autofixing hooks may modify the ephemeral CI checkout.
# If they do, the hook runner fails because the committed files
# were not already in their required final state.
# FIX: Run uvx prek run --all-files locally, review any autofixes,
# fix remaining issues by hand, then git add, commit, and push.
# ============================================================
# B) BASELINE CHECKS: Tools not covered by hooks
# ============================================================
- name: B1) Validate pyproject.toml schema
run: uvx "validate-pyproject[all]" pyproject.toml
# WHY: Catch malformed project metadata before downstream CI or release work.
- name: B2) Run ty type checker
run: uv run ty check
continue-on-error: true
# WHY: Catch type errors that Ruff does not check.
# OBS: ty uses the installed project environment for analysis.
# OBS: Not included in hooks because it requires the full environment.
# OBS: continue-on-error keeps type checking non-blocking in this workflow.
# ============================================================
# C) COVERAGE & TESTING: Python tests
# ============================================================
- name: C1) Run pytest
run: uv run python -m pytest
# WHY: Confirm all Python tests pass in a clean CI environment.
# OBS: pytest config lives in pyproject.toml [tool.pytest.ini_options].
# OBS: Not included in hooks because tests can be slow.
# ============================================================
# D) DOCS: Build documentation without 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: Confirm documentation builds without errors.
# OBS: This workflow builds only; deployment is handled separately.
# OBS: Conditional on zensical.toml so this workflow remains reusable
# across Python-managed repositories that may not use Zensical.