Give the nightly's publisher a curl to publish with
ci / build and test (push) Successful in 1m57s
ci / android head (push) Successful in 3m30s
ci / api image (push) Successful in 36s

The android job builds its APK in a glibc container and then does the publishing
on the host, and the host is Alpine — busybox wget, and no curl anywhere on it.
So the step that talks to the forge six times died on the first of those calls
not written to tolerate a failure, with `curl: command not found` and exit 127,
after the whole build had already been paid for.

It took until the fourth call to say so, and that is the part worth reading. The
lookup for an existing release and the tag delete before it both end in `|| true`
with stderr discarded, which is exactly right for "there is no nightly yet" and
indistinguishable from "there is no curl on this machine". Installing it is what
makes those two different again. Dropping the `|| true` instead would fail the
step on the first run of a channel that has never published, which is the one
state that shape is there to handle.

Not busybox wget in curl's place. The asset upload is a multipart -F, which
busybox wget cannot send — so that reading ends in a release created with no APK
on it, which is the failure the verification at the end of the step exists to
catch, arrived at on purpose this time.

Conditioned exactly like the step it serves, main only, because nothing else in
this job wants curl and a pull request should not pay for a package it will not
use. That is a coupling rather than a tidiness, and it is in the comment: the two
conditions have to move together, and loosening the publish on its own puts the
job back at exit 127 several minutes in.

Unproven until the next main build, since the install path only runs there. What
is checked is that the workflow still parses, that the script is valid under sh
as well as bash like the ensure steps beside it, and that the two conditions read
identically once parsed.
This commit is contained in:
2026-08-05 21:39:58 +02:00
parent 5cb361ea13
commit 205f946450
+40
View File
@@ -499,6 +499,46 @@ jobs:
ls -la "$staged" ls -la "$staged"
# This runner is Alpine, whose image carries busybox wget and no curl at all — and the step below
# talks to the forge six times, so it died on the first call that was not written to tolerate a
# failure: `curl: command not found`, exit 127, after the whole APK had been built.
#
# It took that long to say so because the two lookups before it end in `|| true` with stderr
# discarded, which is the right shape for "no nightly release exists yet" and indistinguishable
# from "there is no curl on this machine". Installing it here is what makes those two different
# again; the alternative of dropping the `|| true` would fail the step for a first-ever run.
#
# Not busybox wget instead. The asset upload is a multipart -F, which busybox wget cannot send,
# so the channel would publish a release with no APK on it — the exact failure the verification
# at the end of the step below exists to catch.
#
# Conditioned exactly like the step it serves, since nothing else in this job wants curl. The two
# conditions have to stay the same: loosen that one without loosening this one and the publish is
# back to exit 127, several minutes into the job.
- name: ensure curl
if: github.ref == 'refs/heads/main'
run: |
set -eu
SUDO=""
[ "$(id -u)" -eq 0 ] || SUDO="sudo"
if ! command -v curl >/dev/null 2>&1; then
echo "Installing curl"
if command -v apk >/dev/null 2>&1; then
$SUDO apk add --no-cache curl
elif command -v apt-get >/dev/null 2>&1; then
$SUDO apt-get update -qq
$SUDO apt-get install -y --no-install-recommends curl
elif command -v dnf >/dev/null 2>&1; then
$SUDO dnf install -y curl
else
echo "No apk, apt-get or dnf here, so curl cannot be installed from inside the job." >&2
echo "Add curl to the runner's image; the nightly cannot be published without it." >&2
exit 1
fi
fi
curl --version | head -1
# ◆ PUBLISHING IT, AND WHAT THAT CAPABILITY IS. # ◆ PUBLISHING IT, AND WHAT THAT CAPABILITY IS.
# #
# Whoever can write a release here can put a build on every nightly phone, because the client fetches # Whoever can write a release here can put a build on every nightly phone, because the client fetches