fix(issueflow): issue_payload_valid refuses an empty payload on jq 1.6 too (#198)
All checks were successful
CI / test (pull_request) Successful in 3m3s
CI / release-exercise (pull_request) Successful in 11s
CI / self-guards (pull_request) Successful in 6s
CI / action-exercise (pull_request) Successful in 6s
CI / docs-sync-exercise (pull_request) Successful in 6s
Refs guard / refs-not-closing (pull_request) Successful in 5s
labels / labels (pull_request) Successful in 45s
All checks were successful
CI / test (pull_request) Successful in 3m3s
CI / release-exercise (pull_request) Successful in 11s
CI / self-guards (pull_request) Successful in 6s
CI / action-exercise (pull_request) Successful in 6s
CI / docs-sync-exercise (pull_request) Successful in 6s
Refs guard / refs-not-closing (pull_request) Successful in 5s
labels / labels (pull_request) Successful in 45s
`CI / test` was red at 97e63ac on a case that passes on this box: upstream's
own "an empty payload is refused". The cause is not the test.
`jq -e` disagrees with itself across versions on EMPTY input. jq 1.7 exits 4 —
no valid result was ever produced. jq 1.6 exits 0. Measured both ways today
against the same filter. This instance's runner image
(ghcr.io/catthehacker/ubuntu:act-22.04) carries jq 1.6.
So on this forge the guard #247 D3 added specifically to refuse an unreadable
read was ACCEPTING one: an empty body read as a valid issue payload, and the
sweep would have reconciled an issue from a payload it never received. The
test is upstream's, it is correct, and it passes on a GitHub runner — which is
why upstream never saw this.
The fix does not depend on jq's exit code for an input it never receives: the
payload is read, emptiness is decided in the shell, and jq judges only a
non-empty body.
Verified under BOTH jq versions, not just the one on this box: empty refused
and healthy accepted on 1.6 and 1.7, and the whole suite green under jq 1.6 —
28 test files, 0 failed — as well as under 1.7.
Refs #198
This commit is contained in:
parent
06f05aebec
commit
728102a3ba
2 changed files with 19 additions and 1 deletions
|
|
@ -609,9 +609,22 @@ issue_payload_valid() { # $1 = the requested issue; payload on stdin
|
||||||
# one catches an HTTP 200 whose body is `null`, which exits 0 and empties it
|
# one catches an HTTP 200 whose body is `null`, which exits 0 and empties it
|
||||||
# just the same. `.number` is checked against the issue asked for, so a
|
# just the same. `.number` is checked against the issue asked for, so a
|
||||||
# payload about some other issue can never be reconciled as this one.
|
# payload about some other issue can never be reconciled as this one.
|
||||||
|
# THE EMPTINESS CHECK IS NOT REDUNDANT, and it is not stylistic. `jq -e`
|
||||||
|
# disagrees with itself across versions on empty input: jq 1.7 exits 4 (no
|
||||||
|
# valid result was ever produced), jq 1.6 exits **0**. This instance's
|
||||||
|
# runner image (ghcr.io/catthehacker/ubuntu:act-22.04) carries jq 1.6, so
|
||||||
|
# without this line an EMPTY payload reads as a valid issue payload here —
|
||||||
|
# the precise thing D3 added this guard to refuse — and the sweep would
|
||||||
|
# reconcile an issue from a body it never received. Measured both ways,
|
||||||
|
# 2026-08-05: `jq -e '<this filter>' </dev/null` → rc 0 on 1.6, rc 4 on 1.7.
|
||||||
|
# The test that caught it is upstream's own and passes on a GitHub runner
|
||||||
|
# (#198).
|
||||||
|
local payload
|
||||||
|
payload="$(cat)"
|
||||||
|
case "$payload" in *[![:space:]]*) ;; *) return 1 ;; esac
|
||||||
jq -e --arg n "$1" '
|
jq -e --arg n "$1" '
|
||||||
type == "object" and (.number | tostring) == $n and (.labels | type) == "array"
|
type == "object" and (.number | tostring) == $n and (.labels | type) == "array"
|
||||||
' >/dev/null 2>&1
|
' <<<"$payload" >/dev/null 2>&1
|
||||||
}
|
}
|
||||||
|
|
||||||
skipped_tail() { # $1 = skip count, $2 = the issue numbers → the D6 line, or nothing
|
skipped_tail() { # $1 = skip count, $2 = the issue numbers → the D6 line, or nothing
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,11 @@
|
||||||
speaks and refuses by name on a runner without it, instead of dying with
|
speaks and refuses by name on a runner without it, instead of dying with
|
||||||
`command not found` on every sweep. #205 ports it to REST (#198).
|
`command not found` on every sweep. #205 ports it to REST (#198).
|
||||||
|
|
||||||
|
- `issue_payload_valid` refuses an empty payload on jq 1.6 as well as 1.7.
|
||||||
|
`jq -e` exits 4 on empty input under 1.7 and **0** under 1.6, and this
|
||||||
|
instance's runner carries 1.6 — so the guard #247 D3 added to refuse an
|
||||||
|
unreadable read was accepting one here (#198).
|
||||||
|
|
||||||
- The post-merge nudge strips a trailing slash from the server URL, so a forge
|
- The post-merge nudge strips a trailing slash from the server URL, so a forge
|
||||||
URL carrying one does not render `//owner/repo` (#198).
|
URL carrying one does not render `//owner/repo` (#198).
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue