# BikeControl builder image. # # One image that can do every job CI asks of it: # - `cargo test` / `clippy` on the host target, which means the *Linux BLE* # stack must be present: btleplug talks to BlueZ over D-Bus, so libdbus is a # hard build dependency, not an optional extra. # - the Tauri desktop bundle (deb / AppImage), which needs the webkit2gtk set. # - the Android APK: SDK, NDK, JDK, and the three Android Rust targets. # # Build and push: # docker build -f Dockerfile.builder -t gitea.tourolle.paris/dtourolle/bikecontrol-builder:latest . # docker push gitea.tourolle.paris/dtourolle/bikecontrol-builder:latest # or run scripts/build-builder-image.sh. FROM ubuntu:24.04 ENV DEBIAN_FRONTEND=noninteractive \ ANDROID_HOME=/opt/android-sdk \ ANDROID_SDK_ROOT=/opt/android-sdk \ NDK_VERSION=27.0.11902837 \ SDK_VERSION=36 \ BUILD_TOOLS_VERSION=35.0.0 \ RUST_BACKTRACE=1 \ CARGO_HOME=/root/.cargo \ PATH="/root/.cargo/bin:$PATH" RUN apt-get update && apt-get install -y --no-install-recommends \ build-essential \ curl \ wget \ git \ ca-certificates \ unzip \ jq \ file \ pkg-config \ openjdk-17-jdk-headless \ libssl-dev \ libclang-dev \ llvm-dev \ # BLE on the host target: btleplug's Linux backend is bluez-async over the # `dbus` crate, which links against libdbus-1. Without this the workspace # does not build at all — `crates/ble` is not optional. libdbus-1-dev \ # Tauri v2 desktop (needed for `cargo test`/`clippy` on the host target and # for the deb/AppImage bundle). libglib2.0-dev \ libgtk-3-dev \ libwebkit2gtk-4.1-dev \ libjavascriptcoregtk-4.1-dev \ libsoup-3.0-dev \ librsvg2-dev \ libayatana-appindicator3-dev \ # AppImage bundling reaches for these at bundle time. fuse3 \ desktop-file-utils \ && rm -rf /var/lib/apt/lists/* # Node 20 for the Vite/Svelte frontend. The UI is plain npm (ui/package-lock.json # is the lockfile CI installs from), so no bun here. RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && \ apt-get install -y --no-install-recommends nodejs && \ rm -rf /var/lib/apt/lists/* # Rust, with every target the release job builds for. RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal && \ . "$CARGO_HOME/env" && \ rustup component add rustfmt clippy && \ rustup target add aarch64-linux-android armv7-linux-androideabi x86_64-linux-android # The Tauri CLI as a cargo subcommand. The frontend package.json deliberately # does not carry @tauri-apps/cli — the shell is a cargo workspace member, so the # CLI belongs to the toolchain, not to the UI's dependency tree. RUN . "$CARGO_HOME/env" && cargo install tauri-cli --locked --version "^2" # --------------------------------------------------------------------------- # Android SDK / NDK. RUN mkdir -p "$ANDROID_HOME" /root/.android && \ printf '### User Sources for `android` cmd line tool ###\ncount=0\n' > /root/.android/repositories.cfg && \ wget -q https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip -O /tmp/cmdline-tools.zip && \ # The zip holds a single top-level cmdline-tools/, and sdkmanager insists on # living in cmdline-tools/latest/ — it derives the SDK root from its own # path and refuses to run from anywhere else. So unpack somewhere neutral # and move that directory into place; unzipping straight into $ANDROID_HOME # puts bin/ where latest/ has to go. unzip -q /tmp/cmdline-tools.zip -d /tmp/cmdline-tools && \ rm /tmp/cmdline-tools.zip && \ mkdir -p "$ANDROID_HOME/cmdline-tools" && \ mv /tmp/cmdline-tools/cmdline-tools "$ANDROID_HOME/cmdline-tools/latest" && \ rmdir /tmp/cmdline-tools && \ test -x "$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" # Licences up front so Gradle never blocks on a prompt in CI. RUN yes | "$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" --sdk_root="$ANDROID_HOME" --licenses > /dev/null RUN "$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" --sdk_root="$ANDROID_HOME" \ "platform-tools" \ "platforms;android-$SDK_VERSION" \ "build-tools;$BUILD_TOOLS_VERSION" \ "ndk;$NDK_VERSION" \ --channel=0 2>&1 | grep -v "Warning" || true ENV NDK_HOME=$ANDROID_HOME/ndk/$NDK_VERSION \ ANDROID_NDK_HOME=$ANDROID_HOME/ndk/$NDK_VERSION \ ANDROID_NDK_ROOT=$ANDROID_HOME/ndk/$NDK_VERSION \ PATH="/opt/android-sdk/platform-tools:/opt/android-sdk/cmdline-tools/latest/bin:$PATH" WORKDIR /app ENTRYPOINT ["/bin/bash"]