Skip to content

Commit 26cc559

Browse files
committed
Make CI check things it was not checking
Four defects, one duplication: - `format` reformats `jupyddl/` and commits straight to main, but `web/dist` embeds those sources verbatim and `pages` refuses to deploy a bundle that has drifted from them. A reformat of any bundled module would have left main undeployable. The rebuild now happens in the same commit. - Mergify's auto-merge rule required `check-success=tests`. That is the workflow name; the checks are the matrix jobs, `test (ubuntu-latest, 3.12, dev)` and friends. The rule matched nothing and never fired. Match the jobs by pattern so growing the matrix cannot break it again. - The `viz` extra was never installed, so six test modules `importorskip`ed matplotlib and the entire charting surface went untested. One matrix entry now installs it; the rest stay without matplotlib, which is both what most people install and a standing check that the core never imports it. - `flake8` skipped `tools/`, which is where the bundle builder and the thousand-line promo renderer live. `build` was a strict subset of `tests` — same matrix, same editable install, same two flake8 invocations — so it cost a second full matrix for no signal. It now builds the sdist and wheel, `twine check`s them, installs the wheel into a clean environment and plans with it from outside the repository. That catches packaging breakage, which is precisely what an editable install cannot show. Verified end to end locally: build, check, clean install, generate, solve, `Valid: True`. Also runs the suite on 3.13 and 3.14 (both pass locally; the core is stdlib-only), adds concurrency groups so superseded pushes stop burning runners, and renames the pages job to `bundle` so it cannot be mistaken for the `build` check Mergify keys on. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Meb35zHKsyBkH2sbWoyKMT
1 parent 63b7a11 commit 26cc559

7 files changed

Lines changed: 156 additions & 35 deletions

File tree

‎.github/workflows/build.yml‎

Lines changed: 45 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,52 @@
11
name: build
22

3+
# What gets published, rather than what is in the working tree. `tests.yml`
4+
# already lints and tests the sources across the whole matrix; running the same
5+
# flake8 twice bought no extra signal, so this workflow builds the
6+
# distributions instead and proves the wheel stands on its own — no source
7+
# tree, no demos folder, no editable install.
8+
39
on: [push]
410

11+
concurrency:
12+
group: build-${{ github.ref }}
13+
cancel-in-progress: true
14+
515
jobs:
616
build:
7-
runs-on: ${{ matrix.os }}
8-
strategy:
9-
fail-fast: false
10-
matrix:
11-
os: [ubuntu-latest]
12-
python-version: ['3.9', '3.10', '3.11', '3.12']
13-
17+
runs-on: ubuntu-latest
1418
steps:
15-
- uses: actions/checkout@v7
16-
with:
17-
submodules: recursive
18-
- name: Set up Python ${{ matrix.python-version }}
19-
uses: actions/setup-python@v7
20-
with:
21-
python-version: ${{ matrix.python-version }}
22-
- name: Install package (dev extras)
23-
run: |
24-
python -m pip install --upgrade pip
25-
python -m pip install -e ".[dev]"
26-
- name: Lint with flake8
27-
run: |
28-
flake8 jupyddl tests --count --select=E9,F63,F7,F82 --show-source --statistics
29-
flake8 jupyddl tests --count --statistics
19+
- uses: actions/checkout@v7
20+
with:
21+
submodules: false
22+
23+
- uses: actions/setup-python@v7
24+
with:
25+
python-version: '3.12'
26+
27+
- name: Build the sdist and the wheel
28+
run: |
29+
python -m pip install --upgrade pip build twine
30+
python -m build
31+
twine check dist/*
32+
33+
- name: Install the wheel into a clean environment
34+
run: |
35+
python -m venv /tmp/fresh
36+
/tmp/fresh/bin/pip install dist/*.whl
37+
38+
- name: Plan with the installed package, away from the repository
39+
working-directory: /tmp
40+
run: |
41+
/tmp/fresh/bin/python -c "import jupyddl; print(jupyddl.__version__)"
42+
/tmp/fresh/bin/jupyddl generate gripper -n 3 --seed 1 -o /tmp/smoke
43+
/tmp/fresh/bin/jupyddl solve \
44+
/tmp/smoke/gripper-03-1/domain.pddl \
45+
/tmp/smoke/gripper-03-1/problem.pddl \
46+
-s astar -H lmcut | tee /tmp/plan.txt
47+
grep -q "Valid: True" /tmp/plan.txt
48+
49+
- uses: actions/upload-artifact@v4
50+
with:
51+
name: distributions
52+
path: dist/

‎.github/workflows/format.yml‎

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,45 @@
11
name: format
2+
23
on:
34
push:
45
branches: [main]
6+
7+
concurrency:
8+
group: format-main
9+
cancel-in-progress: false
10+
511
jobs:
612
format:
713
runs-on: ubuntu-latest
814
steps:
15+
# `github.head_ref` is empty on a push event, so the old `ref:` here was
16+
# a no-op that read as if it did something. This workflow only ever runs
17+
# on main; check that out and say so.
918
- uses: actions/checkout@v7
1019
with:
11-
ref: ${{ github.head_ref }}
20+
ref: main
21+
1222
- name: Set up Python
1323
uses: actions/setup-python@v7
1424
with:
1525
python-version: '3.14'
26+
1627
- name: Install formatter dependencies
1728
run: |
1829
python -m pip install --upgrade pip
1930
python -m pip install black
31+
2032
- name: Format with black
2133
run: |
22-
black jupyddl tests
34+
black jupyddl tests tools
35+
36+
# web/dist embeds the jupyddl sources verbatim, and pages.yml refuses to
37+
# deploy a bundle that has drifted from them. Reformatting the sources
38+
# and committing without rebuilding would push main into exactly that
39+
# state, so the rebuild has to ride along in the same commit.
40+
- name: Rebuild the browser bundle so it matches the formatted sources
41+
run: python tools/build_web.py
42+
2343
- name: Commit changes
2444
uses: stefanzweifel/git-auto-commit-action@v5
2545
with:

‎.github/workflows/pages.yml‎

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,16 @@ concurrency:
1919
cancel-in-progress: true
2020

2121
jobs:
22-
build:
22+
# Not called `build`: .mergify.yml keys a merge rule on a check named
23+
# `build`, and that must mean the packaging workflow, not this one.
24+
bundle:
2325
runs-on: ubuntu-latest
2426
steps:
25-
- uses: actions/checkout@v4
27+
- uses: actions/checkout@v7
2628
with:
2729
submodules: false
2830

29-
- uses: actions/setup-python@v5
31+
- uses: actions/setup-python@v7
3032
with:
3133
python-version: "3.12"
3234

@@ -48,7 +50,7 @@ jobs:
4850
path: web
4951

5052
deploy:
51-
needs: build
53+
needs: bundle
5254
runs-on: ubuntu-latest
5355
environment:
5456
name: github-pages

‎.github/workflows/tests.yml‎

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,32 @@ name: tests
22

33
on: [push]
44

5+
concurrency:
6+
group: tests-${{ github.ref }}
7+
cancel-in-progress: true
8+
59
jobs:
610
test:
711
runs-on: ${{ matrix.os }}
812
strategy:
913
fail-fast: false
1014
matrix:
1115
os: [ubuntu-latest]
12-
python-version: ['3.9', '3.10', '3.11', '3.12']
16+
python-version: ['3.9', '3.10', '3.11', '3.12', '3.13', '3.14']
17+
# The charts are an optional extra, so most of the matrix runs without
18+
# matplotlib — that is the configuration nearly every user installs,
19+
# and it proves the core stays importable without it. One entry pulls
20+
# it in so `jupyddl/viz/` is actually executed rather than skipped.
21+
extras: [dev]
22+
include:
23+
- os: ubuntu-latest
24+
python-version: '3.12'
25+
extras: dev,viz
26+
27+
name: test (${{ matrix.os }}, ${{ matrix.python-version }}, ${{ matrix.extras }})
28+
29+
env:
30+
MPLBACKEND: Agg
1331

1432
steps:
1533
- uses: actions/checkout@v7
@@ -19,14 +37,14 @@ jobs:
1937
uses: actions/setup-python@v7
2038
with:
2139
python-version: ${{ matrix.python-version }}
22-
- name: Install package (dev extras)
40+
- name: Install package (${{ matrix.extras }} extras)
2341
run: |
2442
python -m pip install --upgrade pip
25-
python -m pip install -e ".[dev]"
43+
python -m pip install -e ".[${{ matrix.extras }}]"
2644
- name: Lint with flake8
2745
run: |
28-
flake8 jupyddl tests --count --select=E9,F63,F7,F82 --show-source --statistics
29-
flake8 jupyddl tests --count --statistics
46+
flake8 jupyddl tests tools --count --select=E9,F63,F7,F82 --show-source --statistics
47+
flake8 jupyddl tests tools --count --statistics
3048
- name: Test with pytest
3149
run: |
3250
pytest --cov=jupyddl --cov-report=xml

‎.mergify.yml‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
# `tests` is the *workflow* name; the checks it reports are the matrix jobs,
2+
# `test (ubuntu-latest, 3.12, dev)` and friends. A rule keyed on
3+
# `check-success=tests` therefore matched nothing and the auto-merge never
4+
# fired. Match the jobs by pattern instead, so adding a Python version to the
5+
# matrix does not silently break merging again.
16
pull_request_rules:
27
- name: Assign the main reviewers
38
conditions:
@@ -11,7 +16,7 @@ pull_request_rules:
1116
- name: Automatic merge on approval
1217
conditions:
1318
- "#approved-reviews-by>=1"
14-
- check-success=tests
19+
- check-success~=^test \(
1520
- check-success=build
1621
- check-success=CodeFactor
1722
actions:

‎AGENTS.md‎

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,26 @@ native build step, and the core has zero runtime dependencies.
2525
or `... benchmark demos --dashboard out.png`. Installed as `jupyddl` too.
2626
Also `jupyddl animate` (MP4/GIF replay) and `jupyddl demo` (full chart gallery).
2727

28+
### What CI actually checks
29+
- **`tests`** — lint (`flake8 jupyddl tests tools`) and the suite on Python
30+
3.9–3.14. Most of the matrix installs `.[dev]` *without* matplotlib, which is
31+
what nearly everyone installs and keeps the core honest about not importing
32+
it; one entry installs `.[dev,viz]` so `jupyddl/viz/` is executed rather than
33+
skipped. Six test modules `importorskip` matplotlib, so without that entry
34+
the whole charting surface goes untested.
35+
- **`build`** — builds the sdist and wheel, `twine check`s them, installs the
36+
wheel into a clean venv and plans with it from outside the repository. It
37+
deliberately does *not* repeat the lint: it is there to catch packaging
38+
breakage (a module missing from the wheel, an entry point that does not
39+
resolve), which an editable install hides.
40+
- **`format`** — runs `black` on a push to main and commits the result. It
41+
rebuilds `web/dist` in the same commit; reformatting a bundled source and
42+
committing without the rebuild would leave main in a state where `pages`
43+
refuses to deploy.
44+
- **`pages`** — bundles, refuses to deploy a stale `web/dist`, then deploys.
45+
Its job is called `bundle`, not `build`, because `.mergify.yml` keys a merge
46+
rule on a check named `build` and that has to mean the packaging workflow.
47+
2848
### Layout beyond the core
2949
- `jupyddl/requirements.py` — **the source of truth** for what every PDDL
3050
requirement flag does here. Change support for a feature *here first*; the
@@ -87,7 +107,10 @@ planners must go through the task rather than the operator to honour them:
87107
`jupyddl/` (including a `black` reformat) run `python tools/build_web.py` and
88108
commit the result, or `tests/test_web_bundle.py` and the Pages workflow fail.
89109
The bundle deliberately excludes `jupyddl/viz/` (matplotlib is not loaded in
90-
the browser).
110+
the browser). The builder must stay **byte-reproducible**: it sorts both the
111+
directory walk and the JSON keys, because an unsorted `os.walk` bundles the
112+
same sources in a disk-dependent order and the staleness check then fails on
113+
a bundle that is not stale.
91114
- **The playground's Python lives in `web/bootstrap.py`**, fetched at runtime
92115
rather than embedded in `worker.js`. Do not inline it back into a JS template
93116
literal: reStructuredText double-backticks in a docstring terminate the

‎CHANGELOG.md‎

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,36 @@ All notable changes to this project are documented in this file. The format is
44
based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this
55
project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7+
## [Unreleased]
8+
9+
### Fixed
10+
- **The browser bundle is byte-reproducible again.** `tools/build_web.py`
11+
sorted the files inside each directory but let `os.walk` visit the
12+
subdirectories in filesystem order, so `jupyddl-sources.json` came out
13+
byte-different on a CI runner and the staleness check failed on a bundle that
14+
was not stale.
15+
- **`format` no longer strands `pages`.** It reformats `jupyddl/` and commits to
16+
main; `web/dist` embeds those sources verbatim and `pages` refuses to deploy a
17+
bundle that has drifted, so the reformat could leave main undeployable. The
18+
rebuild now rides along in the same commit.
19+
- **Mergify's auto-merge rule matched no check.** It required
20+
`check-success=tests`, which is the *workflow* name — the checks are the
21+
matrix jobs (`test (ubuntu-latest, 3.12, dev)`), so the rule never fired.
22+
23+
### Changed
24+
- CI runs the suite on Python 3.13 and 3.14 as well as 3.9–3.12, and lints
25+
`tools/` alongside `jupyddl` and `tests`.
26+
- One matrix entry installs the `viz` extra. Six test modules `importorskip`
27+
matplotlib, so the entire charting surface was silently skipped in CI.
28+
- `build` no longer re-runs the lint the `tests` matrix already ran. It builds
29+
the sdist and wheel, `twine check`s them, installs the wheel into a clean
30+
environment and plans with it from outside the repository — packaging
31+
breakage an editable install cannot show.
32+
- `actions/checkout` v4 → v7, `actions/setup-python` v5 → v7,
33+
`codecov/codecov-action` v4 → v7 (#146, #150, #145); the `format` job runs on
34+
Python 3.14 (#149); the Mergify config drops the deprecated
35+
`delete_head_branch` block (#143).
36+
737
## [2.2.0] - 2026-07-28
838

939
Closes the PDDL gap: 20 of the 21 requirement flags are now supported, up from

0 commit comments

Comments
 (0)