Repository navigation
Split CI's tests over parallel jobs, and move the slow suites to a nightly - #465
Merged
Merged
Conversation
…ghtly A pull request's run leaves out the tests marked nightly (timings, Oracle's plans, texts past 32 KB), and runs the rest in parts with pytest --shard. The full set runs on a push to main, in nightly.yml, in the release gate, and on a pull request labelled full-ci. A release trusts only a full run.
…ans took 8 minutes on Postgres The MERGE check joined the node table twice, and with the statistics the suite leaves on purpose (#430) Postgres planned it as a nested loop over every node for each node (liberation-data/drivine#680).
…t, and tests/unit on 3.12 and 3.13
…under GitHub's size limit, and test the shard hooks
jasperblues
marked this pull request as ready for review
November 8, 2026 07:28
Member
Author
|
Merged after a rerun: the first run's Oracle 4/4 lost its connection (DPY-4011) on the spec query "collect skips nulls"; the rerun passed 517/517. That matches the Oracle session-poisoning family of drivine4j#670, which Python's own compiler still has until it moves to the shared compiler. If the nightly shows it again, the culprit test gets held for the switch. |
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.
CI took 23 to 32 minutes on every pull request:
test (Oracle)ranpytest -k oraclein one job, 23 to 27 minutes, and each oftest (3.11)totest (3.14)ran the whole suite again in 10 to 17. This splits each of them into parallel jobs, each with its own containers, and moves the slow tests, and those that rest on a timing or a plan, to a nightly set. It is the pytest version of liberation-data/drivine#679.How it's split
pytest --shard i/n(tests/shards.py, a plugin of the tests' own conftest) runs part i of n of what-kand-mpicked. A module goes whole into one part, with its module-scoped fixtures, in collection order. The parts are balanced by how long each module took in CI, astests/durations.jsonrecords it (oracleanddefault). Each job uploads--record-durationsoutput as an artifact (3.11 and Oracle), to refresh that file when the parts drift. I picked this over pytest-split because pytest-split splits test by test, which would run each module fixture in every part and break up modules that share state, such as the write-loop timings'TIMES.test (<python>, 1/3)…3/3-m "not nightly" --shard i/3: on a pull request on 3.11 and 3.14 only, on a full run on all four. Part 1 also runs ruff, pyright andunasync.py --check.test (3.12, unit),test (3.13, unit)tests/unit, with no containers (-o drivine_test_containers=false), plus the same lint stepstest (<python>, nightly)-m nightly, on all four, on a full run onlytest (Oracle, 1/4)…4/4ORACLE_TESTS=true -k oracle -m "not nightly" --shard i/4, on 3.14test (Oracle, nightly)-k oracle -m nightly, on a full run onlytest (Oracle)record the tree,cypher-specA pull request runs the database suite on the oldest and newest Python, 3.11 and 3.14. On 3.12 and 3.13 it runs
tests/unitalone (tests/syncandtests/docsneed a database). The nightly, a push to main,full-ciand the release gate run the database suite on all four, as before. A pull request's run is 14 jobs, down from 19.mainhas no branch protection or rulesets, and nothing in the org readstest (3.x)by name (drivine-release's preflight reads the run's conclusion), so onlytest (Oracle)gets an aggregator.What a pull request leaves out (marker
nightly)Each one is in
tests/integration, and its sync copy intests/sync_integration:sql/test_compiled_write_loop_time.py(ten times the rows; on Postgres it also vacuums and analyzes the tables, the big-row and shm case),postgres/test_compiled_write_keyed_read_time.py(keyed reads, its own graph, VACUUM of 20,000 rows),oracle/test_oracle_era_parse.py.oracle/test_oracle_keyed_label_plan.py,oracle/test_oracle_node_equality.py,oracle/test_oracle_adaptive_plans.py.oracle/test_oracle_long_text_memory.py; intest_cypher_compiled.py, the five Oracle tests whose names end "leaves the session open" (TS'sOracleLongParameterandOracleLongProperty);test_object_manager_saving.py::TestLongText(TS'sStatelessGraphObjectManager.longText).Everything else stays on pull requests, the Cypher spec on every store among it. The full set runs on a push to main, in
nightly.yml(17:00 UTC), in release.yml's gate (full: true), and on a pull request labelledfull-ci.Four Oracle tests that never ran
test (Oracle)picks tests with-k oracle, so an Oracle-only test without "oracle" in its name was skipped in the matrix and deselected in the Oracle job. That happened to four tests intest_cypher_compiled.py, in async and sync, eight in all. They are renamed with_on_oracle(one is now..._for_two_rows_leaves_oracles_session_open, to fit the line), and they pass: the first in the PR set, the other three in the nightly set.Release and trust
ci-tree-pr-set-<tree>, andscripts/ci_trust.pydoesn't trust it. It ignores it straight away instead of waiting for it. There's a new test intests/unit/test_ci_trust.py.ci-tree-<tree>. Checked: thefull-cirun recordedci-tree-e0ca6fd…and the PR-set runci-tree-pr-set-e0ca6fd….full-cilabel.Nightly
nightly.ymlcalls ci.yml withfull: true, with top-levelpermissions: contents: read. It takes over ci.yml's latest-images schedule (04:17 before, now 17:00). The FalkorDB image test is nowgithub.workflow == 'Nightly'. When the nightly fails, itsreportjob (issues: write) opens an issue labellednightly, or comments on the one already open, with:FAILEDandERRORlines for each;A green run closes the issue. On a branch other than main it only writes to the step summary.
#680: the write-loop check (one test-side change)
liberation-data/drivine#680 found an untimed check in the write-loop timing that took 655 s on Postgres. drivine-python has the same check. On main it took only seconds, among the other modules. In the nightly part, run alone,
[postgres-CREATE](which times every write) took 505 s and 498 s (async and sync), and the 3.11 nightly part took 18m28s. The MERGE checkMATCH (:CyLoop)-[r:CY_SELF]->(:CyLoop) RETURN count(r)joins the node table twice, and the suite leaves that table's statistics saying it is empty (#430). It now readsMATCH (n:CyLoop)-[r:CY_SELF]->(n) RETURN count(r), which joins the table once and also checks that each relationship is a self-loop. The CREATE case dropped to 4 s, and the nightly part to 1m55s. The compiled read itself is still slow in that state, and #680 tracks it. drivine4j has the same check: liberation-data/drivine4j#673.Measured
After the change to 3.12 and 3.13: PR run 42456968539 took 7m50s wall clock, and its slowest job
test (3.11, 2/3)took 6m23s. The unit jobs took 1m22s and 1m31s. The release dry run's full gate (42456968569) took 13m19s and passed on all four Pythons. The table below is from before that change, when every Python ran the database suite on a pull request.test (Oracle)23m25s / 26m37sThe wall clock went over 12 minutes on the reruns because jobs waited for runners, not because they ran longer. The longest wait for a job in each attempt was 1.7, 11.5, 25.1, 10.2 and 16.6 minutes. Runs in liberation-data/drivine4j were using the org's runners at the same time (three to five of them, at each check). A PR-set run is 19 jobs. With free runners it takes about the slowest job plus a minute: about 8 minutes.
The full set (label
full-ci, run 42450537394) took 15m19s, and its slowest job took 7m24s. Release dry-run gates with the full set: 42446350553 (before the #680 fix, 36m20s, the 3.11 nightly part at 18m28s) and 42448953588 (after, 23m04s). Both passed.Test counts
After the change to 3.12 and 3.13, from pytest's summary lines (passed + skipped + xfailed):
tests/unit)tests/unit)The full set on each Python is main's 8,557 plus the 10 new tests, and Oracle is main's 2,618 plus the 8 renamed tests.
tests/unitis 2,662 on main, plus the same 10.Before that change:
From pytest's summary lines (passed + skipped + xfailed) in the
full-cirun, andpytest --collect-only -qfor each job's arguments, run in CI on 3.11 and 3.14 (a temporary workflow, now deleted), against main's collection:-k oracle)test_shards.pyand 1 intest_ci_trust.py.-k oraclenow reaches.The nightly, shown working
A workflow can be dispatched only once it is on main. So a temporary branch, now deleted, ran
nightly.ymlon push, with a unit test made to fail (run 42447210074). Its report job wrote, for example:The demo file also failed ruff in part 1, and for that job the report said "No failing test in its log: it failed in a step around the tests". It ended with "No nightly has passed on main yet". Off main it writes only to the summary, so no issue was opened. The labels
full-ciandnightlynow exist.Review: 3 passes, the last CLEAN. Pass 1 capped the nightly issue at 60,000 characters (GitHub refuses longer) and added tests for the shard hooks; pass 2 was CLEAN; pass 3 made a scheduled nightly report a cancelled or timed-out job (a hanging test) instead of exiting silently, and stripped the pr-set- prefix from a ci_trust message.