Conversation
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
--platformfromcommon-args/run-argswas only ever applied todocker run, neverdocker build, so the image built for the host's native arch and then refused to start under the forced platform. Now applied to both.ppa:rabbitmq/rabbitmq-erlang-28doesn't publish arm64 builds of the individualerlang-base/erlang-dev/... packageserlang--setup.shinstalls 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.shnow verifies the installed OTP major matches what was requested and fails immediately with a clear explanation;elixir-exampleis re-pinned to OTP 25 + Elixir 1.18.4, which installs identically on amd64 and arm64.chownapp files tocoder:coderat build time, butcoder'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+rwXfor AFFiNE (a plainmkdir), and a runtimechownfor AnythingLLM (Prisma'scopy_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--setup.shsilentlyexit 0s on arm64 (Google only publishes the Linux SDK for x86_64) — install skipped entirely, so every in-booth test failed looking for aflutter/dartthat was never there. Same fix pattern as android-example: force--platform linux/amd64..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 viaPATH— 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 passandroid-example: SDK install + APK build pass (genuine amd64 build, not skipped)affine-example: server reaches "Nest application successfully started", HTTP 200anythingllm-example: server reaches "listening on port 3001", HTTP 200flutter-example: SDK install, web build, and widget test all passNote: the
variants/base/setups/*.shfixes (affine, anythingllm, erlang) live in scripts baked into the publishednawaman/codingbooth:baseimage, 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