ci(create-release): scope the cascade-guard comment to the publishing predecessors (#960) - #961
Conversation
d180f6b to
93dbdc9
Compare
|
NEEDS CHANGES at It built eight mutants and three stayed green while breaking the intent. The serious one: Logically just One correction to its report, which I verified before relying on either version. Its table says all eight mutants fail once the neighbouring test's third assertion ( So I took its stronger alternative rather than the matching-idiom one — the set of comparisons against It also showed my comment-only check was weak. Two prose points it settled that I had asked about: a skipped Round 2 running against |
93dbdc9 to
4ce1ee4
Compare
|
NEEDS CHANGES at The set assertion anchored Semantically identical to the mutation the test was written to catch, and it reported The argument behind the fix is why I took it whole rather than patching those two spellings. The set form's failure mode is asymmetric: rewrite the real clause in an unrecognised spelling and the set goes empty, which fails loudly and safely; add an unrecognised weakening alongside the retained clause and it passes silently. So the test now strips whitespace and asserts both the comparison set and Reproduced myself at the new head, each mutant It also confirmed my correction and withdrew its own table row, which is worth recording: its round-1 column labelled "with the missing assertion" had in fact measured the third Two judgements it offered that I agree with. The set form is not over-strict: a loosening must fail by design, and a redundant tightening like I took its note on the failure message: the maintainer-facing explanation moved into the docstring, which now records why substrings cannot pin this clause and names the two forms the count exists for. Unverified, and it says so: whether Actions accepts whitespace-padded property dots, and whether it rejects double-quoted literals. Both would need a real run, which is forbidden here. The whitespace-padded mutant's reachability therefore rests on unconfirmed syntax — but the other two holes do not, and either alone justifies the fix. Round 3 running against |
4ce1ee4 to
b6a1c6d
Compare
|
NEEDS CHANGES at Seven mutants kept exactly one
The fix is one more assertion: the clause must appear as a top-level I took its scope judgement rather than its tightest option. It offered a prefix anchor that closes everything including a It also found that whitespace-stripping can invent a false reading — an identifier or literal split across the folded scalar's line break compacts to the pristine form and passes. Low severity and I am keeping the compaction: those expressions are ones Actions rejects, so the real gate fails closed and nothing publishes, whereas the hole compaction closes fails open. The docstring now records that trade. Two of my questions it settled with measurement rather than argument. The principled endpoint it identified, which I am not doing here: this module already contains Round 4 running against |
b6a1c6d to
414c525
Compare
… predecessors (#960) The comment above `jobs:` said `tag`, `pypi` and `conda` spell the guard as the success-or-skipped equality pair "for each of their own direct dependencies". That is false for `version_check`, a direct dependency of all three (:443, :521, :620) which each require to have strictly succeeded, with no `|| 'skipped'` (:445, :523, :622). The equality pair applies only to `github`, and for `conda` also `tag`. The comment is where the documentation got the claim from -- #958 was the same error in releasing.rst, corrected in #959 -- so leaving it would have had the docs describe this file more accurately than the file describes itself. Comment text only; no executable YAML changed. Verified by parsing both revisions with `yaml.safe_load` and comparing the loaded structures, which is stronger than a `grep -vE '^[+-]#'` -- that pattern only matches `#` at column zero and says nothing about indented YAML. Also adds test_version_check_must_strictly_succeed, which nothing in the module covered. An `assertNotIn` over known-bad spellings cannot pin this clause, since `(!= 'failure' || == 'success')` keeps the literal while meaning the opposite. Two assertions over a whitespace-stripped condition instead: - the clause appears as a top-level `&&` conjunct, because vocabulary is not structure -- a one-character `&&`-to-`||` slip keeps every token while nullifying the gate; - `version_check.result` is referenced exactly once, which closes the rest: anything added alongside the real clause raises the count however spelled. A comparison-set assertion was carried for two rounds and is dropped as provably redundant: the conjunct substring guarantees one occurrence followed by `== 'success'`, the count guarantees it is the only one, so the set is necessarily `{('==', 'success')}`. Brute-forced over 173,088 synthetic conditions -- zero cases where it fires alone. Knowingly not closed, and now recorded in the docstring: a top-level `||` outside the conjunction chain. Conjunction is monotone, so adding `&&` conjuncts can only strengthen the gate; disjunction is the only remaining weakening and catching it needs the expression evaluated rather than matched. Tracked as #962. Falsifiability confirmed against mutated copies, each valid YAML first. Head passes, a legitimate extra `&&` conjunct still passes, and `|| == 'skipped'`, `(!= 'failure' || == 'success')`, reversed operands, `contains(fromJSON(...))`, `|| event_name`, a negation, `&&`-to-`||` and the clause deleted all fail. tests/project/test_release_gates.py: 35 passed, 26 subtests, re-derived as 35 under plain unittest.
414c525 to
a93e726
Compare
|
NEEDS CHANGES at The comparison-set assertion was provably redundant, and I reproduced the proof before removing it. Given the conjunct substring and And it caught me recording the residual in the wrong place, and describing it too narrowly. I grepped my own output: the That is the thesis of #960 applied to this PR: an undocumented hole became a documented one. Its docstring cut was specific and I took it as given — the catalogue of defeated spellings went, since that is recoverable from this PR's history and #962; the #960 provenance and the whitespace fail-open/fail-closed trade stayed, since neither is recoverable elsewhere. ~20 lines down to ~12. Branch rebased onto Round 5 running to confirm. Staying at |
|
GOOD TO GO at The parent is the merge-base, so the branch is genuinely on top of current A detail from its matrix worth recording: m14, m16 and m17 are caught by the conjunct assertion alone — the count assertion reads clean on all three. That assertion is the one round 4 added, and it is load-bearing for exactly the two defect shapes rated as plausible, including the one-character It found one fifth-generation candidate and then disqualified it honestly. A duplicate Its closing observation is the one I would keep. Five rounds found four real defects — Still open by design: a top-level Labelled |
Please follow the guide below
make pylint,make mypy,make isort)make testpasses, and a test case covers the changedocs/source/changelog/and regeneratedCHANGELOG.md, if the change is user-visible — N/A — a workflow comment and a test; no library behaviour changeWhat is the purpose of your pull request?
fix— corrects a defectfeat— adds a featureperf— changes performance, not behaviourrefactor— changes neither behaviour nor performancetest— tests onlydocs— documentation onlyci— workflows or build toolingchore— anything elseDescription of your pull request and other information
Closes #960. The third and last instance of one error: the comment above
jobs:increate-release.ymlsaidtag,pypiandcondaspell the cascade guard as the success-or-skipped equality pair "for each of their own direct dependencies".That is false for
version_check, a direct dependency of all three —needs: [ github, version_check ]at:443and:521,[ tag, github, version_check ]at:620— which each require to have strictly succeeded, with no|| 'skipped', at:445,:523,:622. The equality pair applies only togithub, and forcondaalsotag.Why a comment is worth a pull request. This comment is where the documentation got the claim from. #958 was the identical error in
releasing.rst, corrected in #959;pep.rstcarried a related one, corrected in #957. Leaving this would have had the docs describe this file more accurately than the file describes itself, and the next person reconciling the two would reasonably have trusted the code.No executable YAML changed.
git diff -- .github/workflows/create-release.yml | grep -E '^[+-]' | grep -vE '^(\+\+\+|---)' | grep -vE '^[+-]#'returns nothing — every changed line is a#comment.yaml.safe_loadstill parses the file.A test that nothing covered.
test_release_gates.pypinned the publishing predecessors' equality pair but had noversion_check.resultassertion at all, so neither the comment nor the prose had cover for that clause.test_version_check_must_strictly_succeednow asserts, per job, thatneeds.version_check.result == 'success'is present andneeds.version_check.result == 'skipped'is not. The fully-qualified string avoids a substring false-pass.Falsifiability, shown both ways. The "fix" here is the workflow's existing behaviour, so a passing test proves nothing on its own. Against a copy of the workflow with
|| needs.version_check.result == 'skipped'added totag:Against the real file:
OK. I ran both myself rather than relying on the report.Counts:
tests/project/test_release_gates.py35 passed, 26 subtests, re-derived as 35 tests, OK under plainunittest(pytest-subtestsundercounts, hence the second run).Not verified: the workflow was not dispatched, and must not be — it publishes releases. The comment change cannot affect its behaviour, which is what the
grepabove establishes.