android-assets #13
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
| # Build the Android runtime assets (proot + Ubuntu rootfs with node/claude/codex + | |
| # the localhost server bundle) and upload them as a workflow artifact. The shell APK | |
| # extracts these on first run (see surfaces/android/Installer.kt). | |
| # | |
| # Why this shape: the repo is PRIVATE, so native arm64 runners are metered. Instead we | |
| # run on the free x86 runner and build the aarch64 rootfs inside an arm64 Ubuntu | |
| # container via QEMU (binfmt) — the container gives us both the target arch AND root | |
| # (build-assets.sh needs chroot). Slower than a native arm64 runner, but it's a one-off | |
| # per release and stays in the free tier. | |
| # | |
| # It does NOT log into claude/codex — the rootfs ships them INSTALLED but logged-out; | |
| # the user authenticates on-device (their own subscription/API key). So no credentials | |
| # ever touch the artifact. Manual trigger only (it's a heavy, occasional build). | |
| name: android-assets | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| abi: | |
| description: "Target ABI" | |
| type: choice | |
| options: ["arm64", "x86_64"] | |
| default: "arm64" | |
| jobs: | |
| build: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| # Register QEMU so we can run arm64 containers on the x86 runner. | |
| - name: Set up QEMU (binfmt) | |
| uses: docker/setup-qemu-action@v3 | |
| with: | |
| platforms: arm64 | |
| # Build the localhost bundle on the host (node/pnpm, arch-independent JS) so the | |
| # container step only has to do the arch-specific rootfs work. | |
| - uses: pnpm/action-setup@v4 | |
| with: { version: 9 } | |
| - uses: actions/setup-node@v4 | |
| with: { node-version: 22, cache: pnpm } | |
| - run: pnpm install --frozen-lockfile | |
| - run: pnpm --filter agentnet-localhost build | |
| - run: pnpm --filter agentnet-webview build # the React SPA the server serves | |
| # Build PRoot from the exact Termux recipe we ship, with AgentNet's GPLv2 | |
| # copy-on-link patch applied. The official builder supplies the Android NDK, | |
| # bionic sysroot, process_vm feature detection, libtalloc, libandroid-shmem, | |
| # and the matching unbundled loaders. | |
| - uses: actions/checkout@v4 | |
| with: | |
| repository: termux/termux-packages | |
| ref: 105685dac8697e3b6c2ceb57be24d624afbfa2a3 | |
| path: .termux-packages | |
| - name: Build patched PRoot from source | |
| shell: bash | |
| run: | | |
| case "${{ github.event.inputs.abi }}" in | |
| arm64) TERMUX_ARCH=aarch64 ;; | |
| x86_64) TERMUX_ARCH=x86_64 ;; | |
| esac | |
| cp surfaces/android/proot/patches/0001-copy-on-link.patch \ | |
| .termux-packages/packages/proot/0001-copy-on-link.patch | |
| CI=true CONTAINER_NAME=agentnet-proot-builder \ | |
| TERMUX_BUILDER_IMAGE_NAME=ghcr.io/termux/package-builder@sha256:fa23eb4238ef8eda877cd991a06152ce76e9f274d1cae0d42f28fee3e5cd6016 \ | |
| .termux-packages/scripts/run-docker.sh ./build-package.sh \ | |
| -a "$TERMUX_ARCH" -f -I proot | |
| PROOT_PACKAGE=$(ls .termux-packages/output/proot_*_"$TERMUX_ARCH".deb | tail -1) | |
| test -s "$PROOT_PACKAGE" | |
| echo "PROOT_DEB=/work/$PROOT_PACKAGE" >> "$GITHUB_ENV" | |
| # Run the asset build inside an arm64 Ubuntu container (root + target arch). The | |
| # container has the chroot/apt the rootfs step needs; ALLOW_CROSS lets the script | |
| # proceed since uname inside the arm64 container already reports aarch64. | |
| - name: Build rootfs + pack assets (arm64 container) | |
| run: | | |
| docker run --rm --platform linux/arm64 \ | |
| -v "${{ github.workspace }}:/work" -w /work \ | |
| -e ABI=${{ github.event.inputs.abi }} -e ALLOW_CROSS=1 \ | |
| -e PROOT_DEB="${PROOT_DEB}" \ | |
| ubuntu:24.04 \ | |
| bash -c ' | |
| set -e | |
| apt-get update | |
| apt-get install -y curl ca-certificates xz-utils tar coreutils | |
| # build-assets.sh reuses surfaces/localhost/dist (already built on the host | |
| # above), so it never needs pnpm inside this arm64 container. | |
| bash surfaces/android/scripts/build-assets.sh | |
| ' | |
| # Upload BOTH the assets (rootfs + server bundle tars) and jniLibs (proot + loader + | |
| # libs, shipped as lib*.so so Play Protect doesn't reject loose ELF in assets). The | |
| # artifact's common root is .../main/, so the zip contains assets/ and jniLibs/ at top | |
| # level — drop them into surfaces/android/app/src/main/. | |
| - name: Upload assets | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: android-assets-${{ github.event.inputs.abi }} | |
| path: | | |
| surfaces/android/app/src/main/assets/ | |
| surfaces/android/app/src/main/jniLibs/ | |
| # 90 days (GitHub's max default): the rootfs rarely changes, but android-apk reuses | |
| # this artifact on EVERY app/UI push. A short window silently expired it (7-day | |
| # retention -> apk builds broke ~1 week after the last assets run). Keep it long so | |
| # day-to-day app builds never go red just because nobody rebuilt the rootfs recently. | |
| retention-days: 90 | |
| if-no-files-found: error |