ci: fix dpkg-query format-string escaping in check-versions.yml - #1170
Merged
Conversation
The "Check PGDG minor versions" step always reported every supported PG
version as stale, failing the job on every scheduled run regardless of
whether PGDG had actually released anything new.
Root cause: dpkg-query -f="\\${Version}" postgresql-${pg} -- this line
sits inside docker run --rm "$IMAGE" bash -c '...', where the entire
inner script is single-quoted by the outer (runner) shell, so no
expansion happens there and \\${Version} is passed through literally.
Inside the container's own bash -c, though, that text is inside a
double-quoted -f="..." argument: \\ collapses to one literal backslash,
and the now-unescaped ${Version} gets parameter-expanded as a shell
variable -- which was never set, so it expands to nothing. dpkg-query
ends up invoked with a bare backslash as its format string instead of
the literal ${Version} template it needs, and returns nothing.
With `installed` always empty and `available` resolving correctly via
the separately (correctly) quoted apt-cache/awk one line below, every
PG version compared unequal and got flagged STALE, forcing
pgdg_changed=true unconditionally.
Fix: \\${Version} -> \${Version} (one fewer backslash). The outer
single quotes still pass it through unchanged; the container's bash
now sees \$ inside the double-quoted string, which escapes to a
literal $, yielding the literal string ${Version} dpkg-query expects.
Verified locally: built a throwaway debian:bookworm-slim container,
installed postgresql-17 from the real PGDG repo the same way
Dockerfile.base does, and ran both the old and fixed format strings
against it.
old (\\${Version}): installed=[] (garbage, always empty)
new (\${Version}): installed=[17.10-1.pgdg12+1]
available=[17.10-1.pgdg12+1] (correctly matches -> not stale)
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.
Problem
The weekly "Check PGDG + Citus versions" workflow (
check-versions.yml) has been failing on every scheduled run, for every supported PG version (14–17), regardless of whether PGDG actually released anything new:This is a false negative in the check script itself, not a real version drift —
installedis always empty, for every version, every run.Root cause
installed=$(dpkg-query -W -f="\\${Version}" postgresql-${pg} 2>/dev/null || echo "")This line sits inside
docker run --rm "$IMAGE" bash -c '...', where the entire inner script is single-quoted by the outer (runner) shell — so the outer shell passes\\${Version}through completely unchanged. Inside the container's ownbash -c, though, this text is part of a double-quoted-f="..."argument:\\collapses to one literal backslash, and the now-unescaped${Version}gets parameter-expanded as a shell variable.Versionwas never set anywhere, so it silently expands to nothing.dpkg-queryends up invoked with a bare backslash as its format string, instead of the literal${Version}template it needs (that'sdpkg-query's own field-substitution syntax, not a shell variable) — and returns nothing.With
installedalways empty andavailableresolving correctly one line below (via a separately, correctly, double-quotedapt-cache/awkpipeline), every PG version compares unequal and gets flaggedSTALE, forcingpgdg_changed=trueunconditionally on every run.Fix
Drop one backslash:
\\${Version}→\${Version}. The outer single-quoting still passes it through unchanged; the container's bash now sees\$inside its double-quoted string, which escapes to a literal$, yielding the literal string${Version}thatdpkg-queryexpects.Verification
Reproduced the exact quoting locally, then built a throwaway
debian:bookworm-slimcontainer and installedpostgresql-17from the real PGDG repo the same wayDockerfile.basedoes, to test both the old and fixed format strings against a real installed package:No functional change to what the workflow does when a version genuinely is stale — only fixes the comparison so it stops reporting every run as stale unconditionally.