One commit: 6e524ec, the fix for the guard failure that PR #4 triggered.
Why this merge exists
#4's Android lane failed (run 4857) and ci.yml's gate correctly withheld the image behind it. So main's current tip has published only two of its three artifacts:
guard-forward.sh has a branch for "this channel has published nothing yet — pass, there is nothing to go backwards from." It was unreachable. published="$(published_for ...)" under set -e dies on the substitution before it, and silently, because everything the pipeline would have printed goes into the capture rather than the log.
Which lookups carried it was decided by the last command in the pipeline — sed on empty input exits 0, grep exits 1. Three of the four end in sed. Android's version_code ends in grep -oE '[0-9]+$', so it was the only one, and only on a channel with no APK on it. dev has had one since day one; stable never did. The bug could not fire until #4 created its one precondition, which is why a week of green dev pushes ran past it.
Each lookup is now wrapped so it returns empty rather than failing, with a comment naming the pipeline-tail asymmetry at the point where the next lookup will be copied from one of these four.
Tests
The guard's feed-facing half had no coverage at all — only its pure compare mode did, which is the half that worked. A curl_stub fixture shadows curl on PATH so the other half is testable and still hermetic: an empty channel passes the guard and reports true from should-build.sh, a lower published version passes, a higher one fails the lane, and an equal Android versionCode is refused because Android will not install it.
All four lanes green on 6e524ec — Android 4864, CI & Build 4865, Desktop 4866, and the dispatched image build 4869.
One commit: `6e524ec`, the fix for the guard failure that PR #4 triggered.
## Why this merge exists
#4's Android lane failed (run 4857) and `ci.yml`'s gate correctly withheld the image behind it. So `main`'s current tip has published only two of its three artifacts:
| | after #4 | after this |
|---|---|---|
| desktop `stable` | `1.0.3502363` ✓ | `1.0.3503145` |
| android `stable` | **nothing** | first APK + sidecar |
| server image | **`:latest` still pre-merge** | `:latest` + `:<sha>` for this commit |
## The bug
`guard-forward.sh` has a branch for "this channel has published nothing yet — pass, there is nothing to go backwards from." It was unreachable. `published="$(published_for ...)"` under `set -e` dies on the substitution before it, and silently, because everything the pipeline would have printed goes into the capture rather than the log.
Which lookups carried it was decided by the last command in the pipeline — `sed` on empty input exits 0, `grep` exits 1. Three of the four end in `sed`. Android's `version_code` ends in `grep -oE '[0-9]+$'`, so it was the only one, and only on a channel with no APK on it. `dev` has had one since day one; `stable` never did. The bug could not fire until #4 created its one precondition, which is why a week of green `dev` pushes ran past it.
Each lookup is now wrapped so it returns empty rather than failing, with a comment naming the pipeline-tail asymmetry at the point where the next lookup will be copied from one of these four.
## Tests
The guard's feed-facing half had no coverage at all — only its pure `compare` mode did, which is the half that worked. A `curl_stub` fixture shadows `curl` on `PATH` so the other half is testable and still hermetic: an empty channel passes the guard and reports `true` from `should-build.sh`, a lower published version passes, a higher one fails the lane, and an equal Android `versionCode` is refused because Android will not install it.
All four lanes green on `6e524ec` — Android 4864, CI & Build 4865, Desktop 4866, and the dispatched image build 4869.
Recorded as issue #3233.
The first merge to `main` took the Android lane down (run 4857): the decide
job exited 1 in 0.16 seconds with no output at all, and the image build
skipped behind it because a failing lane must not publish.
`stable` had never published an APK, which the guard treats as a pass — there
is nothing to go backwards from, and `[ -z "$published" ]` says so in a branch
of its own. That branch was unreachable. `published="$(published_for ...)"`
under `set -e` dies on the substitution before it, and everything the pipeline
would have printed goes into the capture rather than the log.
What decided which lookups had the bug is the last command in the pipeline.
`sed` on empty input exits 0; `grep` exits 1. Three of the four end in `sed`.
Android's version_code ends in `grep -oE '[0-9]+$'`, so it was the only one —
and only on a channel with nothing on it, which is why a week of dev pushes
never saw it.
The tests now reach the half of the guard that talks to a feed, with `curl`
shadowed on PATH so they stay hermetic: an empty channel passes and builds, a
lower published version passes, a higher one fails the lane, and an equal
Android code is refused because Android will not install it.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
One commit:
6e524ec, the fix for the guard failure that PR #4 triggered.Why this merge exists
#4's Android lane failed (run 4857) and
ci.yml's gate correctly withheld the image behind it. Somain's current tip has published only two of its three artifacts:stable1.0.3502363✓1.0.3503145stable:lateststill pre-merge:latest+:<sha>for this commitThe bug
guard-forward.shhas a branch for "this channel has published nothing yet — pass, there is nothing to go backwards from." It was unreachable.published="$(published_for ...)"underset -edies on the substitution before it, and silently, because everything the pipeline would have printed goes into the capture rather than the log.Which lookups carried it was decided by the last command in the pipeline —
sedon empty input exits 0,grepexits 1. Three of the four end insed. Android'sversion_codeends ingrep -oE '[0-9]+$', so it was the only one, and only on a channel with no APK on it.devhas had one since day one;stablenever did. The bug could not fire until #4 created its one precondition, which is why a week of greendevpushes ran past it.Each lookup is now wrapped so it returns empty rather than failing, with a comment naming the pipeline-tail asymmetry at the point where the next lookup will be copied from one of these four.
Tests
The guard's feed-facing half had no coverage at all — only its pure
comparemode did, which is the half that worked. Acurl_stubfixture shadowscurlonPATHso the other half is testable and still hermetic: an empty channel passes the guard and reportstruefromshould-build.sh, a lower published version passes, a higher one fails the lane, and an equal AndroidversionCodeis refused because Android will not install it.All four lanes green on
6e524ec— Android 4864, CI & Build 4865, Desktop 4866, and the dispatched image build 4869.Recorded as issue #3233.