fix: unbreak the APK build (malformed manifest XML) and CI (missing ALSA headers) #46

Merged
jeroen merged 2 commits from fix/manifest-xml-comment into main 2026-08-11 04:59:18 +00:00
Owner

Two faults that only surfaced once #45 landed, both of the same shape: a cheap gate placed first was hiding an expensive one behind it.

The manifest was not well-formed XML. deploy-android.yml compiled the whole Bevy stack for aarch64-linux-android — thirteen minutes — and then aapt2 refused AndroidManifest.xml. Two separate faults, both added while wiring the splash theme and the version fallbacks:

  • --version-code written inside an XML comment. A double hyphen is illegal there.
  • a comment placed among an element's attributes. A comment is a node; a node cannot live in an attribute list.

Neither is exotic, and both are invisible to a human reader — the file looks entirely reasonable. What made them expensive is where they were caught. So build-apk.sh now checks the manifest and everything under res/ for well-formedness before cargo ndk runs: one second instead of sixteen minutes. Verified by reintroducing the original comment and watching the guard reject it.

CI has been failing on alsa-sys since #43. bevy_audio pulls it, its build script is a pkg-config call, and viberfox-ci:latest has no alsa.pc — so both jobs died before compiling a line of this project. Nobody saw it because cargo fmt --check was the first step and was failing. #45 moved fmt last, which is what surfaced this.

Installed as a step rather than baked into the image only because the image lives in another repo; deploy-android.yml installs its JRE the same way. Building CI --no-default-features would have been the cheap fix and the wrong one — it would leave every line behind cfg(feature = "audio") uncompiled, which is exactly the rot the wasm and Android lanes exist to prevent.

Combined into one PR so the APK deploy runs once rather than twice.

Two faults that only surfaced once #45 landed, both of the same shape: a cheap gate placed first was hiding an expensive one behind it. **The manifest was not well-formed XML.** `deploy-android.yml` compiled the whole Bevy stack for `aarch64-linux-android` — thirteen minutes — and then aapt2 refused `AndroidManifest.xml`. Two separate faults, both added while wiring the splash theme and the version fallbacks: - `--version-code` written inside an XML comment. A double hyphen is illegal there. - a comment placed *among an element's attributes*. A comment is a node; a node cannot live in an attribute list. Neither is exotic, and both are invisible to a human reader — the file looks entirely reasonable. What made them expensive is *where* they were caught. So `build-apk.sh` now checks the manifest and everything under `res/` for well-formedness before `cargo ndk` runs: one second instead of sixteen minutes. Verified by reintroducing the original comment and watching the guard reject it. **CI has been failing on `alsa-sys` since #43.** `bevy_audio` pulls it, its build script is a `pkg-config` call, and `viberfox-ci:latest` has no `alsa.pc` — so both jobs died before compiling a line of this project. Nobody saw it because `cargo fmt --check` was the first step and was failing. #45 moved fmt last, which is what surfaced this. Installed as a step rather than baked into the image only because the image lives in another repo; `deploy-android.yml` installs its JRE the same way. Building CI `--no-default-features` would have been the cheap fix and the wrong one — it would leave every line behind `cfg(feature = "audio")` uncompiled, which is exactly the rot the wasm and Android lanes exist to prevent. Combined into one PR so the APK deploy runs once rather than twice.
fix(android): the manifest was not well-formed XML, and nothing said so early
Some checks failed
CI / cargo check (push) Has been cancelled
CI / build & test viberfox (push) Has been cancelled
01df43950a
`deploy-android.yml` compiled the entire Bevy stack for `aarch64-linux-android`
— thirteen minutes — and then aapt2 refused the manifest. Two separate XML
faults, both introduced while adding the splash theme and the version
fallbacks:

- `--version-code` written inside an XML comment. A double hyphen is illegal
  there, full stop; it terminates nothing and the parser gives up.
- a comment placed *among an element's attributes*. A comment is a node, and a
  node cannot sit inside an attribute list.

Neither is exotic and both are invisible to a human reader, because the file
looks entirely reasonable. What made them expensive is where they were caught:
aapt2's diagnostic is perfectly good and arrives at the very end, after the
build it invalidates.

So `build-apk.sh` now checks the manifest and everything under `res/` for
well-formedness *before* `cargo ndk` runs. It costs a second and it is the
difference between a one-second failure and a sixteen-minute one. Python
rather than xmllint because the CI image is known to have the former and
should not have to grow `libxml2-utils` for this; if python3 is somehow
absent the script says so and carries on, since aapt2 remains the real gate.

Verified by reintroducing the original `--version-code` comment and watching
the guard reject it, then restoring.
fix(ci): install the ALSA headers the audio feature needs
Some checks failed
CI / cargo check (push) Successful in 2m46s
CI / cargo check (pull_request) Successful in 2m42s
CI / build & test viberfox (push) Successful in 6m27s
CI / build & test viberfox (pull_request) Failing after 4m49s
b20441cfa8
Both CI jobs have been failing on `alsa-sys` since the `audio` feature landed
(#43). `bevy_audio` pulls it, its build script is a `pkg-config` call, and
`viberfox-ci:latest` has no `alsa.pc` — so every `cargo check --workspace` and
every `cargo test -p viberfox` died before compiling a line of this project.

Nobody saw it, and the reason is the same one that hid the Android build
break: `cargo fmt --check` was the *first* step of the `check` job and was
failing, so the job ended before reaching any cargo command. That ordering was
fixed in the previous commit, which is what surfaced this. Two faults, one
shape — a cheap gate placed first hides an expensive one behind it.

Installed as a step rather than baked into the image only because the image
lives in another repo; `deploy-android.yml` installs its JRE the same way for
the same reason. Building CI `--no-default-features` instead would have been
the cheap fix and the wrong one: it would leave every line behind
`cfg(feature = "audio")` uncompiled, which is precisely the rot the wasm and
Android lanes exist to prevent.
jeroen merged commit 5a544c8158 into main 2026-08-11 04:59:18 +00:00
Sign in to join this conversation.
No description provided.