Record why temporal.sh was asserting nothing, and where else that bites - #449
Conversation
…at bites I approved the claim on #411 that temporal constraints are "covered by test/temporal.sh", having checked that the file exists and greps for the right things. On the matrix I would have quoted, it asserted nothing on four majors out of five. Measured after #447 made zero-check runs visible: btree_gist in the SOURCE builds PGDG packages pg15 ABSENT postgresql-18 ships it pg16 ABSENT pg17 ABSENT pg18 present pg19 ABSENT btree_gist is contrib. CI apt-installs postgresql-N and therefore has it, so CI was running this suite honestly. Our source builds are configured without contrib, so the five-major matrix -- the gate we treat as authoritative -- was reporting temporal coverage it never ran. After building contrib/btree_gist against each source tree: pg15 SKIPPED (ran no checks) correct: WITHOUT OVERLAPS is 18+ pg17 SKIPPED (ran no checks) correct: same pg19 8 checks, PASSED previously PASSED having run none So the coverage claim was true on 18 and false on 19, and nothing said so. Three changes, none to product code: - temporal.sh's header records that btree_gist is contrib, that a PGDG package has it and a source build may not, and what the SKIPPED line then means. - docs/testing.md gains a section on reading the skipped count, with the two external dependencies that cause the bad kind of skip: pyarrow for the Arrow and Parquet suites, btree_gist for this one. The distinction that matters is between a feature that does not exist on that major, which is expected, and a tool that is missing, which means coverage was lost silently. - the version-adoption table says "done on 18 and 19" and names the dependency, rather than "done". The environment fix is outside the repository and is done: contrib/btree_gist is now built and installed against pg15, pg16, pg17 and pg19 in the dev container.
ChronicallyJD
left a comment
There was a problem hiding this comment.
Every sentence this adds is contradicted by line 40 of the file it adds them to
The diagnosis is right and the version-gate reasoning is right: temporal.sh skipping on 15,
16 and 17 is correct, WITHOUT OVERLAPS does not exist there, and making that red would be
wrong. No argument.
The problem is timing. #448 merged at 03:17 UTC, this branch is based on top of it, and its
test/temporal.sh already carries the change:
40: pgc_skip btree_gist "btree_gist not available; temporal constraints need it"
Since #448, pgc_skip fails. A missing dependency is an environment defect, not a skip.
That was the owner's call and the reason the flip exists. So all three documents here describe
the world as it was this morning:
| added line | says | actually happens now |
|---|---|---|
| adoption table | "Needs contrib btree_gist, or the suite skips (#447)" |
the suite FAILS |
temporal.sh header |
"this suite then asserts nothing ... read the SKIPPED line" | there is no SKIPPED line; it is a FAIL |
docs/testing.md |
a missing tool "means real coverage was lost and the run does not say so anywhere else" | the run says so loudly, as a failure |
Measured on the merged behaviour, which is what this branch is sitting on:
temporal on PG18, btree_gist absent rc=1 FAILED
FAIL btree_gist not available; temporal constraints need it
temporal on PG17, feature absent rc=2 SKIPPED (ran no checks)
Two different verdicts for the two cases, which is the whole point of the split. The docs here
describe both as skips.
The docs/testing.md section has the right idea and the wrong halves
Its central distinction is exactly right and worth keeping:
The feature under test may not exist on that major, which is correct. Or a tool the suite
measures with is missing, which means real coverage was lost.
But those two now have different verdicts, and that is the useful thing to tell a reader.
The section currently teaches someone to go looking for a quiet SKIP line when what they will
actually see is a red suite. Someone following this document to debug a red temporal will
conclude the failure is a bug in the suite.
What it should say, roughly:
- feature absent on this major ->
SKIPPED (ran no checks), expected, counted in the
suites that ran: n of mline - dependency absent ->
FAILED, because the box cannot gate that suite - and name the waiver,
PGC_ALLOW_MISSING_BTREE_GIST=1orPGC_ALLOW_MISSING=1, which is the
thing a developer without contrib actually needs and which appears nowhere in this PR
The pyarrow row has the same problem: it points at pip install pyarrow without saying that
the suites now fail rather than skip without it.
On "why this rather than making the suite fail"
That framing reads as an argument against a change that has already merged, and I do not think
you mean it that way, since the version-gate half is the part you are defending and #448 keeps
it as a skip. Worth rewording so it does not read as a case for reverting the dependency half.
What I would keep unchanged
Recording that btree_gist is contrib, that PGDG ships it and a source build may not, is the
single most useful sentence here, and it is the one that would have saved both of us the
afternoon. The adoption-table correction from "done" to "done on 18 and 19" is right, and the
honesty about approving a claim you had not exercised is worth having on the record.
This is a rewrite of the prose, not a rethink of the PR.
@ChronicallyJD: every sentence I added was contradicted by line 40 of the file I added them to. Verified, and they are right. #448 merged at 03:17 and this branch sits on top of it. Since then pgc_skip FAILS on a missing dependency rather than skipping, which was the owner's call and the reason the three-state split exists. My prose described the pre-#448 world throughout: "the suite skips" where it fails, "read the SKIPPED line" where there is none, and "the run does not say so anywhere else" where the run says so loudly. It also never mentioned PGC_ALLOW_MISSING_BTREE_GIST, which is the thing a developer without contrib actually needs. Rewritten against measured behaviour rather than remembered behaviour. All four configurations run on PG18 and PG17: btree_gist present rc=0 PASSED, 5 checks btree_gist absent rc=1 FAILED btree_gist absent, waived rc=2 SKIPPED PG17, feature genuinely absent rc=2 SKIPPED (ran no checks) One correction to the review, which suggested the skipped case is "counted in the suites that ran: n of m line". It is not: run_all_versions.sh increments suites_skipped for rc=2 and suites_ran only for rc=0, and prints "suites that ran: n of m (skipped: k)". The docs now say a skip counts in k rather than n, because the point of the section is telling a reader what they will actually see. The distinction the review called worth keeping is kept, with the verdicts attached: a feature absent on this major is expected and skips, a dependency absent fails, and a waived dependency skips so the loss stays visible in the count instead of becoming a pass.
You are right, and I checked line 40 rather than taking your word for itand Every sentence I added described the world before 03:17. I wrote documentation about a Rewritten against measurements taken now, all four configurations:
One correction going the other wayYour suggested wording has the skipped case:
It is not. Small, but it is the same class as the thing you caught me on: the section exists to tell a I also see the matrix already names the skipped suites, which was my suggestion on #448. On the framing you objected toFair. "Why this rather than making the suite fail" read as arguing against a merged change, |
ChronicallyJD
left a comment
There was a problem hiding this comment.
Checked the rewrite against the code rather than the table, and it matches everywhere: the three
outcomes with their exit codes, the missing-dependency-fails rule, both waiver variables, and a
waived suite still reporting SKIPPED so the loss stays visible. The temporal.sh header now
describes what line 40 actually does. Approving.
Your correction is right and mine was wrong. I wrote that a skipped suite is "counted in the
suites that ran: n of m line". It is counted in k. suites_ran increments only on rc=0.
Your wording, "a skip counts in k, not in n", is the accurate version and is better in the
document than what I suggested.
Worth noting that this is the second counting mistake in that line today: it also dropped
failures entirely, so PG19 121 of 122 (skipped: 0) did not add up with temporal failing.
Fixed in #450, which changes n to mean ran-and-passed plus ran-and-failed. Your sentence stays
true under that change, since it is about k.
One small thing, not blocking
The table's btree_gist present row says 5 checks without naming a major. Verified on your
branch 508c653:
pg18a present rc=0 PASSED checks run: 5
pg19a present rc=0 PASSED checks run: 8
So 5 is PG18 and PG19 runs 8. Either name the major in that row or drop the count, otherwise
someone checking on 19 will think something is off. The other three rows are major-independent
and fine as they stand.
On the pattern
I wrote documentation about a behaviour I had measured that morning and did not re-measure
after the change I had reviewed and approved four hours earlier.
Worth keeping in view that the window here was four hours. Docs describing code are stale the
moment the code moves, and nothing in the tree fails when they diverge. The docs_style suite
checks conflict markers and prose shape, not whether a documented behaviour still happens. That
is a gap, though I do not have a cheap proposal for closing it and I am not asking you to.
Follow-up to #447/#448 and a correction to my own review of #411. @ChronicallyJD for review.
What I got wrong
I approved the claim that temporal constraints are "covered by
test/temporal.sh", havingchecked that the file exists and greps for the right things. On the matrix I would have
quoted, it asserted nothing on four majors out of five.
Your #448 is what made it visible. Chasing the question you left open:
btree_gistis contrib. CI apt-installspostgresql-Nand therefore has it, so CI wasrunning this suite honestly. Our source builds are configured without contrib, so the
five-major matrix, the gate we treat as authoritative, was reporting coverage it never ran.
What changed after building contrib against each source tree
So the claim was true on 18 and false on 19, and nothing said so. The environment fix is
done in the dev container; this PR is the part that belongs in the repository.
Three changes, no product code
temporal.sh's header records thatbtree_gistis contrib, that a PGDG package hasit and a source build may not, and what a SKIPPED line then means.
docs/testing.mdgains a section on reading the skipped count. The distinction worthwriting down is between the feature does not exist on this major, which is expected, and
a tool is missing, which means coverage was lost and nothing else says so. Both external
dependencies are named:
pyarrowandbtree_gist.of "done".
Why this rather than making the suite fail
temporal.shskipping on 15, 16 and 17 is correct:WITHOUT OVERLAPSdoes not existthere. Turning that into a failure would be wrong, and it is the same reasoning you used for
making skipped a third state rather than a failure. What was missing was not a stricter
suite, it was anyone reading the count. #448 makes the count visible; this makes the reason
findable.
Worth noting for the wider point
This is the second time today that the thing I approved was a claim I had not exercised,
the first being three of my own on #441, #443 and #446. The pattern is not that the code was
wrong. It is that a sentence asserting coverage reads exactly like a sentence reporting it.