ci: run the test matrix and docs build on every push and pull request - #7
Merged
Conversation
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Intent
Make GitHub run pyGD's tests automatically on every push and every pull request so nothing lands untested. Add a GitHub Actions workflow at .github/workflows/tests.yml that installs the library exactly the way the repository's own README instructions describe - using the 'test' extra (pip install -e ".[test]") rather than installing pytest by hand - runs pytest, and does so across the FULL range of Python versions the repo claims to support. That claim was read from pyproject.toml (requires-python >=3.8 plus classifiers for 3.8 through 3.14) and the README ('Requires Python 3.8+'), so the matrix is deliberately 3.8-3.14 rather than a convenient subset; deliberately NOT dropping any claimed version was an explicit requirement. A second job builds the manual with the 'docs' extra (pip install -e ".[docs]" then sphinx-build) so a broken documentation build is caught too. The workflow was required to stay readable and boring: only actions/checkout and actions/setup-python, a plain version matrix, no dependency caching, no third-party actions. fail-fast is false so one failing version does not hide the others. The docs job intentionally pins a single Python (3.12) since documentation only needs to build once. The published install recipe was verified to work as written on a clean environment, so no README fix was needed. Scope was constrained to adding only the workflow file - no other repository changes. The branch was pushed and the resulting run observed on GitHub: all seven matrix entries (3.8-3.14) and the docs job passed.
What Changed
.github/workflows/tests.yml, a GitHub Actions workflow triggered on every push and pull request.testjob installs the library the way the README documents (pip install -e ".[test]") and runspytestacross afail-fast: falsematrix covering Python 3.8 through 3.14, the full range declared bypyproject.toml(requires-python >=3.8plus classifiers) and the README.docsjob pins Python 3.12, installs thedocsextra, and runssphinx-build -b html docs docs/_build/htmlso a broken manual build fails CI too. The workflow uses onlyactions/checkoutandactions/setup-python, with no dependency caching or third-party actions.No source, packaging, or documentation files were touched. The pipeline's Test phase located the real GitHub run for this commit (
32224258403) and confirmed all 8 jobs green - the seven matrix entries plus docs - and reproduced both README install recipes in a clean environment. Review left three informational notes for later consideration: no explicitpermissions:block, noconcurrencygroup to cancel superseded runs, and the floatingubuntu-latestlabel being the eventual failure point for the end-of-life 3.8 leg.Risk Assessment
✅ Low: The change adds a single 32-line CI workflow file with no library or product code touched, it satisfies every source-verifiable criterion in the intent, and the only observations are non-blocking hardening and future-fragility notes.
Testing
I validated this CI change against the surface an end user actually sees: the GitHub Actions run itself. A run for the exact target commit already existed and I confirmed it succeeded across all seven matrix entries (3.8-3.14) and the docs job, then pulled the real CI logs to prove each entry ran on its claimed interpreter with 5 tests passing and that every job installed via the declared extras rather than hand-installing pytest or sphinx. I separately reproduced both published README recipes verbatim in a fresh venv on a clean copy of the repo, and both succeeded, corroborating the intent's claim that the install instructions work as written. A parsing check confirmed every explicit constraint (full matrix matching the pyproject classifiers with nothing dropped, fail-fast false, docs pinned to 3.12, no caching, no third-party actions) and that the diff adds only the workflow file. Visual evidence is a screenshot of the run summary page showing the green checks; the log-based artifacts back it with the actual pytest and sphinx output. One gap worth stating plainly: the observed run was triggered by push, so the declared pull_request trigger is verified by inspection and by GitHub successfully parsing the workflow, but not yet by a live PR - that evidence appears once a PR is opened. No test failures, flakiness, or setup problems surfaced, and I removed the temporary venv and log caches created during testing.
Evidence: Per-job evidence extracted from the real CI logs
GitHub Actions run 32224258403 - workflow 'Tests' - EternalTime/pyGD branch fm/ci-pygd commit 69f2cec event: push conclusion: SUCCESS duration: 55s --- test (3.8) --- Python 3.8.18, pytest-8.3.5 5 passed in 8.79s --- test (3.9) --- Python 3.9.25, pytest-8.4.2 5 passed in 7.32s --- test (3.10) --- Python 3.10.20, pytest-9.1.1 5 passed in 4.11s --- test (3.11) --- Python 3.11.15, pytest-9.1.1 5 passed in 4.84s --- test (3.12) --- Python 3.12.13, pytest-9.1.1 5 passed in 7.41s --- test (3.13) --- Python 3.13.15, pytest-9.1.1 5 passed in 7.41s --- test (3.14) --- Python 3.14.7, pytest-9.1.1 5 passed in 7.00s --- docs --- Running Sphinx v9.1.0 build succeeded. Install recipe actually executed on every CI job: test (3.8) .. test (3.14) pip install -e ".[test]" (no hand-installed pytest) docs pip install -e ".[docs]" (no hand-installed sphinx)Evidence: Clean-environment run of the README 'Tests' recipe (pip install -e ".[test]" + pytest)
$ pip install -e ".[test]" Successfully installed ... pyGD-0.1.0 pytest-9.1.1 ... $ pytest = test session starts == platform darwin -- Python 3.14.5, pytest-9.1.1, pluggy-1.6.0 configfile: pyproject.toml collected 5 items tests/test_slice.py ..... [100%] == 5 passed in 4.03s ===Evidence: Clean-environment run of the README 'Documentation' recipe (same commands as the CI docs job)
$ pip install -e ".[docs]" Successfully installed ... sphinx-9.1.0 sphinx-copybutton-0.5.2 sphinx-rtd-theme-3.1.0 sphinxcontrib-bibtex-2.7.0 ... $ sphinx-build -b html docs docs/_build/html writing output... [100%] theory generating indices... genindex py-modindex done build succeeded. The HTML pages are in docs/_build/html.Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
.github/workflows/tests.yml:1- The workflow declares nopermissions:block, so both jobs inherit the repository's default GITHUB_TOKEN scopes (read/write on all scopes for repos created before the default changed). No step needs more than read access to the repo contents. Add a top-levelpermissions: contents: readaftername: Tests; it is a single key and keeps the workflow's deliberately boring shape..github/workflows/tests.yml:3-on: push:with no branch filter pluspull_request:means a branch in this repo with an open PR triggers the full 7-entry matrix plus the docs job twice for every push, and with noconcurrencygroup superseded runs keep running to completion. This is the direct consequence of the intent's explicit "every push and every pull request" requirement, so noting the cost only - narrowing the push trigger or adding cancel-in-progress concurrency would change the author's stated behavior and is the user's call..github/workflows/tests.yml:9-runs-on: ubuntu-latestis a floating label while the matrix pins Python 3.8, which is past end-of-life. actions/setup-python resolves 3.8 on the current image (verified: run 32224258403 hastest (3.8)green), but prebuilt 3.8 artifacts stop being published for newer runner images, so the 3.8 leg is the first thing that breaks when the label rolls forward. No change needed now; the fix at that point is pinning an olderruns-onfor the oldest matrix entries rather than dropping the claimed version.✅ **Test** - passed
✅ No issues found.
gh-axi run list --commit 69f2cecf6b59085a7613bb514daebb5f47ea3156- located the real CI run for the target commitgh-axi run view 32224258403- confirmed 8/8 jobs succeeded (test 3.8-3.14 + docs)gh-axi run view 32224258403 --job <id> --logfor all 8 jobs - extracted per-job interpreter version, pytest result, and sphinx build result from the real CI logsGrepped all 8 CI logs forpip install -e ".[test]"/".[docs]"and for any barepip install pytest|sphinx- extras used everywhere, no hand-installed test depsClean-environment reproduction of the README 'Tests' recipe on a fresh copy of the repo outside the worktree:python3 -m venv .venv && pip install -e ".[test]" && pytest-> 5 passedClean-environment reproduction of the README 'Documentation' recipe (identical to the CI docs job):pip install -e ".[docs]" && sphinx-build -b html docs docs/_build/html-> build succeededConstraint check script parsing.github/workflows/tests.ymlagainstpyproject.toml: matrix vs classifiers equality, requires-python floor, push + pull_request triggers, fail-fast false, [test]/[docs] extras, docs pinned to 3.12, no cache key, only actions/checkout + actions/setup-pythonCaptured the GitHub Actions run summary page at 1440x1000 viachrome-devtools-axi screenshotgit diff --stat 1b72a4e..69f2cec- change scope is exactly one file,.github/workflows/tests.ymlgit status --porcelain --ignored- worktree clean after testing, no transient artifacts left behindREADME.md:92- Judgment call, deliberately left unactioned: README.md now understates its own guarantees - CI verifies the Tests and Documentation install recipes on every push and PR across Python 3.8-3.14, but the README carries no status badge or note saying so. This is an addition rather than a staleness fix, and the change's stated scope was 'only the workflow file - no other repository changes', so I made no edit. Surfacing it so a future maintainer can decide to add a badge; README.md owns the user-facing introduction and would be the single correct home for it.✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.