Skip to content

Fix android/elixir/affine/anythingllm/flutter example test failures - #23

Closed
NawaMan wants to merge 3 commits into
mainfrom
fix/example-catalog-failures
Closed

NawaMan wants to merge 3 commits into
mainfrom
fix/example-catalog-failures

Conversation

@NawaMan

@NawaMan NawaMan commented Sep 12, 2026

Copy link
Copy Markdown
Owner

Summary

  • android-example: --platform from common-args/run-args was only ever applied to docker run, never docker build, so the image built for the host's native arch and then refused to start under the forced platform. Now applied to both.
  • elixir-example: ppa:rabbitmq/rabbitmq-erlang-28 doesn't publish arm64 builds of the individual erlang-base/erlang-dev/... packages erlang--setup.sh installs by name, so apt silently fell back to Ubuntu's default OTP 25 on arm64 — and Elixir 1.19 dropped OTP 25 support, surfacing as a confusing 404 far from the actual cause. erlang--setup.sh now verifies the installed OTP major matches what was requested and fails immediately with a clear explanation; elixir-example is re-pinned to OTP 25 + Elixir 1.18.4, which installs identically on amd64 and arm64.
  • affine-example / anythingllm-example: both chown app files to coder:coder at build time, but coder's UID is remapped to the host user's UID/GID at container start (booth-entry), and that remap only re-chowns $HOME — anything outside it keeps its build-time owner. On any host whose UID isn't 1000 (macOS regular accounts start at 501), each app crashed writing to its own install directory (EACCES/EPERM). Fixed per-app: chmod -R a+rwX for AFFiNE (a plain mkdir), and a runtime chown for AnythingLLM (Prisma's copy_file_range-based copy needs real ownership on Docker Desktop's overlay2/virtiofs — verified chmod alone isn't sufficient there). Also widened both examples' readiness-poll ceilings for slower first boots under host contention.
  • flutter-example: flutter--setup.sh silently exit 0s on arm64 (Google only publishes the Linux SDK for x86_64) — install skipped entirely, so every in-booth test failed looking for a flutter/dart that was never there. Same fix pattern as android-example: force --platform linux/amd64.
  • Removed 14 stale vendored copies of builtin setup scripts from .booth/setups/ in 9 examples (affine, anythingllm, appwrite, deno, floci, flutter, turtle, wails-android, wails). These were exact-snapshot-at-creation-time copies that silently shadowed the shared builtin scripts via PATH — including, for affine/anythingllm, shadowing the fixes above. Verified across all 9 examples that removal is either a pure no-op (9 files were byte-identical to the builtin) or the divergence was unreachable (the other 5 had only a stale internal fallback value that each project's own Boothfile always overrides explicitly).

Test plan

  • elixir-example: all 3 in-booth tests pass
  • android-example: SDK install + APK build pass (genuine amd64 build, not skipped)
  • affine-example: server reaches "Nest application successfully started", HTTP 200
  • anythingllm-example: server reaches "listening on port 3001", HTTP 200
  • flutter-example: SDK install, web build, and widget test all pass
  • Regression-tested all 9 examples affected by the vendored-copy removal — no regressions (3 examples have separate, confirmed pre-existing failures unrelated to this change: flutter's non-login-shell PATH — since fixed above — and unrelated wails-example/wails-android-example GUI-display and APK-frontend-packaging issues, left out of scope)

Note: the variants/base/setups/*.sh fixes (affine, anythingllm, erlang) live in scripts baked into the published nawaman/codingbooth:base image, so they won't take effect for real users until that base image is rebuilt and republished — verified locally by rebuilding it and retagging to a local-only repo name.

🤖 Generated with Claude Code

https://claude.ai/code/session_0137yjw6oV573p5vEfCoqNpj

NawaMan and others added 3 commits September 11, 2026 18:08
android-example set common-args=[--platform, linux/amd64] to force the
x86_64-only Android SDK to work under emulation, but that flag only ever
reached `docker run` — buildLocalImage() never passed it to `docker build`,
so the image built for the host's native arch and then failed to start
under the forced platform ("does not provide the specified platform").
Extract --platform from common-args/run-args and apply it to the build too.

elixir-example failed because ppa:rabbitmq/rabbitmq-erlang-28 doesn't
publish arm64 builds of the individual erlang-base/erlang-dev/... packages
erlang--setup.sh installs by name — only a few arch-independent
metapackages. apt silently satisfied those names from Ubuntu's default
archive instead (OTP 25 on arm64), and Elixir 1.19 dropped OTP 25 support,
so the mismatch surfaced as a confusing 404 fetching elixir-otp-25.zip far
from the actual cause. erlang--setup.sh now verifies the installed OTP
major matches what was requested and fails immediately with a clear
explanation instead of silently drifting. elixir-example itself is
re-pinned to erlang 25 + elixir 1.18.4, a combination that installs
identically on amd64 and arm64 without needing the incomplete PPA at all.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0137yjw6oV573p5vEfCoqNpj
Both setup scripts chown app files to coder:coder during the Docker build,
but the container's coder user is remapped to HOST_UID/HOST_GID at start
(see booth-entry) — a remap scoped to $HOME only. Anything outside it, like
/opt/affine or /opt/anythingllm, keeps whatever owner it had at build time
regardless of who "coder" resolves to later, so on any host whose UID isn't
1000 (the base image's build-time default — macOS regular accounts start at
501, not 1000) the app crashes writing to its own install directory:

- AFFiNE's GraphQL module writes a generated schema under $AFFINE_DIR/src on
  every boot -> EACCES on mkdir. Fixed by making the directory world-writable
  at build time (chmod -R a+rwX) — the write here is a plain mkdir, so this
  sidesteps the ownership question entirely with no runtime cost.
- AnythingLLM's `prisma generate` copies files into node_modules/.prisma via
  Node's fs.copyFile, which uses copy_file_range() -> EPERM on Docker
  Desktop's overlay2/virtiofs specifically when the caller doesn't own the
  destination, even though the permission bits allow the write (verified: an
  equivalent `cp` succeeds, Node's copyFile does not). chmod alone isn't
  enough here, so this one re-chowns to the real runtime UID/GID at server
  start instead, in its own STARTER_FILE.

Also widened both examples' own readiness-poll ceilings (demo.sh) from 3/5
minutes to 8/8.3 minutes — first-boot work can legitimately take longer than
that under host contention, independent of the crash above.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0137yjw6oV573p5vEfCoqNpj
flutter--setup.sh has an arch gate: Google only publishes the Flutter
Linux SDK for x86_64, so on arm64 it prints a warning and `exit 0`s
before installing anything — no SDK, no PATH wrappers, no profile entry.
On an arm64 host this example built "successfully" while silently
skipping the entire Flutter install, so every in-booth test failed
looking for a `flutter`/`dart` that was never there. Same situation as
android-example (an x86_64-only SDK), fixed the same way: force
--platform linux/amd64 via common-args (CB_FLUTTER_PLATFORM overrides
it for an arm64 CI runner). Verified end-to-end: SDK install, web build,
and the widget test all pass now.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0137yjw6oV573p5vEfCoqNpj
@NawaMan NawaMan closed this Sep 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant