Skip to content

configure.sh check mode needs jq 1.6+, and fails to compile rather than degrade on jq 1.5 #549

Description

@ptr727

repo-config/configure.sh check mode uses jq's walk/1, which is absent from jq 1.5. On a host carrying jq 1.5 the ruleset comparison does not degrade, it aborts with a compile error, so check cannot report on the repository at all.

Audited against hub main 3a7cc64. Found by a Copilot review on ptr727/Blog#11, which re-vendors this canonical into that repo, and re-verified by hand before filing.

The evidence

The $norm filter introduced with the payload-driven check mode (#540) is built on walk:

norm='def n: walk(if type=="array" then (if length==0 then . elif ...) else . end); n'

repo-config/configure.sh:222 defines it, and check_ruleset applies it to both sides of every parameterized rule comparison.

Reproduced on jq 1.5 and on jq 1.7, using the same filter shape rather than the real payloads:

$ jq --version
jq-1.7
$ echo '{"a":[3,1,2]}' | jq -c 'def n: walk(if type=="array" then sort else . end); n'
{"a":[1,2,3]}

$ jq --version
jq-1.5
$ echo '{"a":[3,1,2]}' | jq -c 'def n: walk(if type=="array" then sort else . end); n'
jq: error: walk/1 is not defined at <top-level>, line 1:
def n: walk(if type=="array" then sort else . end); n
jq: 1 compile error

Why it is worth fixing rather than documenting

The failure mode is the one the script's own design notes argue against. A jq that cannot compile the filter makes check_ruleset fail on every parameterized rule, so a run on such a host reports drift it never compared, which is the inverse of the "clean audit over drift it never compares" defect #538 already tracks.

It also lands where the script is least likely to be exercised before it matters. A maintainer runs check on whatever host is in front of them, and the fleet's supported platforms do not pin a jq version anywhere I can find.

Two shapes, and the tradeoff

  • Define walk locally in the jq program. It is eight lines of jq and works across versions, so the script keeps one code path. It grows the filter, which is already the longest inline jq in the file.
  • Assert the jq version up front, next to the existing tool checks, and fail with a message naming the requirement. Smaller, and it turns a compile error into an explanation, but it makes the script refuse to run on a host where everything except this one comparison would have worked.

The first is the better default, since check is the read-only mode and refusing to run is a worse outcome than running. Stated as a preference, not a decision, and it is yours.

Not proposing a downstream fix

configure.sh is carried verbatim, so the finding is declined on ptr727/Blog#11 and raised here instead. Whatever lands re-vendors to the nine repos the ledger currently lists as carrying a stale copy.

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions