Public Access
Stop the RPM verification failing on packages that are correct
CI run 161 failed the linux packaging step with
The package was built and /opt/DodoSSH/DodoSSH is not in it.
and then listed the package contents, which contain /opt/DodoSSH/DodoSSH. The
package was fine. The check was not.
◆ A READER THAT STOPS EARLY, UNDER pipefail.
if ! printf '%s\n' "$files" | grep -qxF "$expected"; then
grep -q exits on its first match. printf is still writing thousands of paths, so
it dies of SIGPIPE with status 141; pipefail makes 141 the pipeline's status; `!`
inverts it; and a check that found what it was looking for reports the opposite.
The exit code names the second instance of the same mistake. The diagnostic on the
way out is
printf '%s\n' "$files" | head -40 >&2
exit 1
and head stops at forty lines, so printf takes SIGPIPE again and `set -e` ends the
script there. Which is why the job exited 141 rather than the 1 the script asked
for, and why the listing in the log stops mid-alphabet.
◆ WHY IT LOOKED LIKE SOMEBODY ELSE'S COMMIT.
It is a threshold, not a constant. The writer only blocks once it has more than a
pipe buffer left to write — about 64 KB on Linux — so for as long as the published
tree was small the whole list fitted, printf finished, and the pipeline returned
grep's own 0. The check has been wrong since it was written and correct in effect
until the path text crossed 64 KB, which is what the commit before this one did.
Reproduced both sides of the threshold locally:
4,440 bytes -> pipeline status 0
90,940 bytes -> pipeline status 141
Every reader in that block now consumes all of its input: `grep pattern
>/dev/null` in place of `grep -q pattern`, same exit status, reads to the end; and
`awk 'NR<=40'` in place of `head -40`, same forty lines, reads to the end. `|| true`
would have silenced the symptom and taken a real failure of the writer with it.
The other three checks in the same block had the same shape with small inputs —
requires and provides are dozens of lines — so they were latent rather than
failing. Fixed anyway, because the next thing to grow is not predictable from here.
Same for the three publish-verification loops in ci.yml, which grep a release's
JSON for each asset name it should carry. Small today; the loops exist because a
run once created a release, uploaded nothing and reported success, so a false
answer from them is the one thing they must not give.
`ensure skia's native dependency` is left alone deliberately. `ldconfig -p | grep
-q` is the same shape over an input that genuinely exceeds a pipe buffer, but that
step sets `-eu` without `pipefail`, so the pipeline's status is grep's and the
SIGPIPE is invisible. Changing it would be churn; the reason it is safe is worth
knowing.
Verified by lifting the patched loop out of the script and running it against a
synthetic 89 KB listing: complete package passes, a package genuinely missing
/opt/DodoSSH/DodoSSH exits 1 with its forty lines of diagnostic intact. The real
proof is the next run of the job.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
b8c94ecb73
commit
31c836f6ca
2 files changed
+34
-8
No files matched your search
@@ -915,7 +915,10 @@ jobs:
|
||||
# never made.
|
||||
published="$(curl -fsS -H "$auth" "$api/releases/$release")"
|
||||
for name in $names; do
|
||||
if ! printf '%s' "$published" | grep -qF "\"name\":\"$name\""; then
|
||||
# grep without -q, which has the same exit status and reads to the end of its input. A
|
||||
# reader that stops early under pipefail turns the writer's SIGPIPE into this condition's
|
||||
# answer; see the note in scripts/ci-linux-rpm.sh, where that cost a green build.
|
||||
if ! printf '%s' "$published" | grep -F "\"name\":\"$name\"" >/dev/null; then
|
||||
echo "The release was created but $name is not on it:" >&2
|
||||
printf '%s\n' "$published" >&2
|
||||
exit 1
|
||||
@@ -1226,7 +1229,10 @@ jobs:
|
||||
published="$(curl -fsS -H "$auth" "$api/releases/tags/$TAG")"
|
||||
|
||||
for name in releases.win-nightly.json DodoSSH.Desktop.Nightly-win-nightly-Setup.exe; do
|
||||
if ! printf '%s' "$published" | grep -qF "\"name\":\"$name\""; then
|
||||
# grep without -q, which has the same exit status and reads to the end of its input. A
|
||||
# reader that stops early under pipefail turns the writer's SIGPIPE into this condition's
|
||||
# answer; see the note in scripts/ci-linux-rpm.sh, where that cost a green build.
|
||||
if ! printf '%s' "$published" | grep -F "\"name\":\"$name\"" >/dev/null; then
|
||||
echo "The release was created but $name is not on it:" >&2
|
||||
printf '%s\n' "$published" >&2
|
||||
exit 1
|
||||
@@ -1279,7 +1285,8 @@ jobs:
|
||||
# upload it never made.
|
||||
withRpm="$(curl -fsS -H "$auth" "$api/releases/$release")"
|
||||
for name in $linuxNames; do
|
||||
if ! printf '%s' "$withRpm" | grep -qF "\"name\":\"$name\""; then
|
||||
# grep without -q; see the sibling loops above and scripts/ci-linux-rpm.sh.
|
||||
if ! printf '%s' "$withRpm" | grep -F "\"name\":\"$name\"" >/dev/null; then
|
||||
echo "The release was created but $name is not on it:" >&2
|
||||
printf '%s\n' "$withRpm" >&2
|
||||
exit 1
|
||||
|
||||
Reference in new issue
Block a user