7a1e6b06c1
- docker/android.Dockerfile: install nodejs (image ships Bun; ci-android-sign.sh patches build.gradle with a Node script). - buffer polyfill: whisper.rn -> safe-buffer requires Node's `buffer`, absent in Metro/RN. Add `buffer` dep, alias it in metro.config.js, set the global in _layout. Web export unaffected (verified). Validated locally end-to-end: assembleRelease BUILD SUCCESSFUL, 117MB APK across all 4 ABIs with librnwhisper.so, signed (CN=Wisp, O=briggen.dev). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
104 lines
4.6 KiB
Docker
104 lines
4.6 KiB
Docker
# syntax=docker/dockerfile:1
|
|
#
|
|
# docker/android.Dockerfile — full Android build for Wisp -> signed release APK.
|
|
# ---------------------------------------------------------------------------
|
|
# Two stages:
|
|
# toolchain : JDK17 + Android SDK (platform/build-tools) + NDK + CMake + Bun.
|
|
# Reusable on its own (docker build --target toolchain).
|
|
# build : COPYs the repo, installs JS deps, `expo prebuild`, signs, and
|
|
# runs `gradlew assembleRelease`. The signed APK lands at
|
|
# /workspace/android/app/build/outputs/apk/release/app-release.apk
|
|
#
|
|
# This is socket-safe for CI: the whole build happens inside `docker build`
|
|
# (context streamed to the daemon — NO host bind mounts, which don't resolve
|
|
# over a mounted Docker socket). CI then extracts the APK via docker create/cp.
|
|
#
|
|
# Signing secrets are passed as BuildKit secrets (NOT build args / layers):
|
|
# --secret id=ks_b64 -> ANDROID_KEYSTORE_BASE64 (base64 of the .keystore)
|
|
# --secret id=ks_pass -> ANDROID_KEYSTORE_PASSWORD
|
|
# --secret id=ks_alias -> ANDROID_KEY_ALIAS
|
|
# --secret id=ks_keypass -> ANDROID_KEY_PASSWORD
|
|
#
|
|
# JDK pinned to 17 (AGP 8.x); versions track RN 0.85 / Expo SDK 56
|
|
# (compileSdk/targetSdk 36, buildTools 36.0.0, NDK 27.1.12297006).
|
|
# ---------------------------------------------------------------------------
|
|
|
|
FROM eclipse-temurin:17-jdk AS toolchain
|
|
|
|
ARG ANDROID_PLATFORM_VERSION=36
|
|
ARG ANDROID_BUILD_TOOLS_VERSION=36.0.0
|
|
ARG ANDROID_NDK_VERSION=27.1.12297006
|
|
ARG ANDROID_CMAKE_VERSION=3.22.1
|
|
ARG ANDROID_CMDLINE_TOOLS_VERSION=11076708
|
|
|
|
ENV ANDROID_HOME=/opt/android-sdk \
|
|
ANDROID_SDK_ROOT=/opt/android-sdk \
|
|
DEBIAN_FRONTEND=noninteractive \
|
|
GRADLE_USER_HOME=/opt/gradle \
|
|
BUN_INSTALL=/root/.bun
|
|
ENV PATH=/root/.bun/bin:${ANDROID_HOME}/cmdline-tools/latest/bin:${ANDROID_HOME}/platform-tools:${PATH}
|
|
|
|
# OS deps for SDK download + RN/CMake native builds.
|
|
RUN apt-get update \
|
|
&& apt-get install -y --no-install-recommends \
|
|
unzip curl git bash ca-certificates \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
# Bun (Wisp's package manager / task runner).
|
|
RUN curl -fsSL https://bun.sh/install | bash && bun --version
|
|
|
|
# Android commandline-tools into $ANDROID_HOME/cmdline-tools/latest.
|
|
RUN mkdir -p ${ANDROID_HOME}/cmdline-tools \
|
|
&& curl -fsSL -o /tmp/ct.zip \
|
|
"https://dl.google.com/android/repository/commandlinetools-linux-${ANDROID_CMDLINE_TOOLS_VERSION}_latest.zip" \
|
|
&& unzip -q /tmp/ct.zip -d /tmp/ct \
|
|
&& mv /tmp/ct/cmdline-tools ${ANDROID_HOME}/cmdline-tools/latest \
|
|
&& rm -rf /tmp/ct.zip /tmp/ct
|
|
|
|
# Licenses + SDK packages. NDK + CMake are required because whisper.rn compiles
|
|
# native C++ (whisper.cpp) via externalNativeBuild.
|
|
RUN yes | sdkmanager --licenses > /dev/null \
|
|
&& sdkmanager --install \
|
|
"platform-tools" \
|
|
"platforms;android-${ANDROID_PLATFORM_VERSION}" \
|
|
"build-tools;${ANDROID_BUILD_TOOLS_VERSION}" \
|
|
"ndk;${ANDROID_NDK_VERSION}" \
|
|
"cmake;${ANDROID_CMAKE_VERSION}" > /dev/null \
|
|
&& yes | sdkmanager --licenses > /dev/null
|
|
|
|
WORKDIR /workspace
|
|
|
|
# ---------------------------------------------------------------------------
|
|
FROM toolchain AS build
|
|
|
|
# Install JS deps first (cached unless package.json/bun.lock change).
|
|
COPY package.json bun.lock ./
|
|
RUN bun install --frozen-lockfile
|
|
|
|
# Bring in the rest of the source (.dockerignore excludes node_modules, android/, ios/, dist...).
|
|
COPY . .
|
|
|
|
# Generate the native android/ project (autolinks whisper.rn, reanimated, etc.).
|
|
RUN bunx expo prebuild --platform android --no-install
|
|
|
|
# Node is required by scripts/ci-android-sign.sh (this image ships Bun, not Node).
|
|
# Installed AFTER prebuild so the cached toolchain + prebuild layers are reused.
|
|
RUN apt-get update && apt-get install -y --no-install-recommends nodejs && rm -rf /var/lib/apt/lists/*
|
|
|
|
# Decode the keystore + wire release signing, then assemble the signed APK.
|
|
# Secrets are mounted as files under /run/secrets and exported only for this RUN.
|
|
RUN --mount=type=secret,id=ks_b64 \
|
|
--mount=type=secret,id=ks_pass \
|
|
--mount=type=secret,id=ks_alias \
|
|
--mount=type=secret,id=ks_keypass \
|
|
ANDROID_KEYSTORE_BASE64="$(cat /run/secrets/ks_b64)" \
|
|
ANDROID_KEYSTORE_PASSWORD="$(cat /run/secrets/ks_pass)" \
|
|
ANDROID_KEY_ALIAS="$(cat /run/secrets/ks_alias)" \
|
|
ANDROID_KEY_PASSWORD="$(cat /run/secrets/ks_keypass)" \
|
|
bash scripts/ci-android-sign.sh \
|
|
&& cd android \
|
|
&& ./gradlew assembleRelease --no-daemon -x lint --stacktrace
|
|
|
|
# The signed APK (handy for `docker create` + `docker cp` extraction in CI).
|
|
# /workspace/android/app/build/outputs/apk/release/app-release.apk
|