feat(ci): android gets a baked builder image; apple gets sccache and a pinned DerivedData
Android was the last job still downloading its world every run: ~3 GB of SDK/NDK/CMake from Google, a from-source cargo-ndk build, and one monolithic cache key where a gradle edit invalidated the cargo registry and the Rust target/ with it. punktfunk-android-ci (content-keyed, LAN registry) bakes JDK 21 + SDK + NDK + cargo-ndk + sccache; the workflow shrinks to checkout → two caches → gradle. The cargo-home cache joins the fleet-wide namespace (same lockfile, same layout — it was the same bytes under a private key), gradle gets its own key shared with android-screenshots (which stored the identical content under a second name), and target/ leaves the cache — sccache covers the three ABI builds now. Apple: sccache (self-healing ~/.local/bin install + already provisioned on the mini) covers every cargo invocation build-xcframework.sh makes across the swift job, the screenshots job and release.yml — three jobs that each recompiled the same core. screenshots.sh learns PF_SHOT_DERIVED_DATA so CI pins one stable DerivedData root instead of cold-building into two throwaway mktemp trees per run (release.yml's disease, same cure), and the Simulators get shut down after capture (the 846-leaked-sims lesson). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -22,25 +22,15 @@ jobs:
|
||||
screenshots:
|
||||
if: startsWith(github.ref, 'refs/tags/v') || github.event_name == 'workflow_dispatch'
|
||||
runs-on: ubuntu-24.04
|
||||
# JDK 21 + SDK baked (AGP 9.3 + Robolectric's SDK-36 android-all jar both want 17–21).
|
||||
# The tests are pure JVM (no NDK), but sharing android.yml's image means one image to
|
||||
# keep warm instead of a per-run setup-java + sdkmanager download pair.
|
||||
container:
|
||||
image: 192.168.1.58:5010/punktfunk-android-ci:latest
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: JDK 21 (AGP 9.3 + Robolectric's SDK-36 android-all jar both want 17–21)
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: "21"
|
||||
|
||||
- name: Android SDK
|
||||
# SHA-pinned for parity with android.yml (third-party action). v3 = 9fc6c4e.
|
||||
uses: android-actions/setup-android@9fc6c4e9069bf8d3d10b2204b1fb8f6ef7065407 # v3
|
||||
|
||||
# No NDK/CMake — the screenshot unit tests are pure JVM. compileSdk 37 auto-downloads via AGP
|
||||
# if the platform channel lacks it (same note as android.yml).
|
||||
- name: platform-tools + platform 36 + build-tools
|
||||
run: sdkmanager "platform-tools" "platforms;android-36" "build-tools;37.0.0"
|
||||
|
||||
- name: Cache (gradle)
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
@@ -49,9 +39,10 @@ jobs:
|
||||
~/.gradle/wrapper
|
||||
# gradle-wrapper.properties is in the key on purpose: `~/.gradle/wrapper` caches the
|
||||
# Gradle DISTRIBUTION, so a wrapper bump with no .gradle.kts change would otherwise
|
||||
# restore a key that can never hold the new one.
|
||||
key: android-screenshots-${{ hashFiles('clients/android/**/*.gradle.kts', 'clients/android/gradle/wrapper/gradle-wrapper.properties') }}
|
||||
restore-keys: android-screenshots-
|
||||
# restore a key that can never hold the new one. Namespace shared with android.yml —
|
||||
# it is the same content; two keys just stored it twice in the central cache.
|
||||
key: gradle-${{ hashFiles('clients/android/**/*.gradle.kts', 'clients/android/gradle/wrapper/gradle-wrapper.properties') }}
|
||||
restore-keys: gradle-
|
||||
|
||||
# Roborazzi renders Compose on the JVM (Robolectric Native Graphics). `-PskipRustBuild` keeps
|
||||
# the cargo-ndk native build out of the graph — the tests never load libpunktfunk_android.so.
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
# cargo-ndk for all three shipping ABIs and assembles the debug APK (clients/android). Mirrors apple.yml
|
||||
# but on a Linux runner — the NDK is cross-platform, so no self-hosted host is needed.
|
||||
#
|
||||
# Prereq: the runner needs ~6 GB free + internet (it pulls the Android SDK/NDK and the Gradle
|
||||
# distribution in-job). If android-actions/setup-android is not mirrored on this Gitea instance,
|
||||
# replace that step with a manual cmdline-tools download, or bake an `android-ci` image like
|
||||
# ci/rust-ci.Dockerfile. Emulator instrumentation tests are deferred until a KVM-capable runner
|
||||
# exists (they self-skip otherwise, like apple.yml's RemoteFirstLightTests).
|
||||
# Runs in the punktfunk-android-ci builder image (ci/android-ci.Dockerfile, content-keyed on
|
||||
# the LAN registry): JDK 21, the Android SDK/NDK/CMake pins, cargo-ndk and sccache are all
|
||||
# baked, so the multi-GB per-run Google downloads this job used to make are gone. Emulator
|
||||
# instrumentation tests are deferred until a KVM-capable runner exists (they self-skip
|
||||
# otherwise, like apple.yml's RemoteFirstLightTests).
|
||||
name: android
|
||||
# One pending run per workflow+ref: a newer push supersedes the queued/running one and cancels
|
||||
# it (a canary only needs the latest commit; each release tag is its own ref so tag runs never
|
||||
@@ -46,66 +46,62 @@ on:
|
||||
- '.gitea/workflows/android.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
# Shared compile cache: sccache -> RustFS S3 (storage.unom.io, LAN-pinned via ci-core's
|
||||
# unbound). The NDK clang targets get their own key universes automatically (keys embed
|
||||
# compiler hash + target), so the three ABI builds share the bucket with everything else.
|
||||
env:
|
||||
RUSTC_WRAPPER: sccache
|
||||
SCCACHE_BUCKET: unom-ci-sccache
|
||||
SCCACHE_ENDPOINT: https://storage.unom.io
|
||||
SCCACHE_REGION: home-central
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.SCCACHE_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.SCCACHE_SECRET_ACCESS_KEY }}
|
||||
# sccache and incremental compilation are mutually exclusive; CI wants the shared
|
||||
# cache, dev boxes keep incremental.
|
||||
CARGO_INCREMENTAL: "0"
|
||||
|
||||
jobs:
|
||||
android:
|
||||
runs-on: ubuntu-24.04
|
||||
container:
|
||||
image: 192.168.1.58:5010/punktfunk-android-ci:latest
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: JDK 21 (AGP 9.3 runs on JDK 17–21, not the host default)
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: "21"
|
||||
# Everything below the checkout used to be four download steps (JDK, SDK,
|
||||
# NDK+CMake, cargo-ndk — the flakiest, heaviest part of the job); it is all baked
|
||||
# into the image now. This guard only re-asserts the Android targets so a
|
||||
# rust-toolchain.toml pin bump keeps working against an older image (:latest lags
|
||||
# one image rebuild, same bootstrap note as ci.yml's dep steps).
|
||||
- name: Rust Android targets (no-op unless the toolchain pin outran the image)
|
||||
run: rustup target add aarch64-linux-android armv7-linux-androideabi x86_64-linux-android
|
||||
|
||||
- name: Rust toolchain + Android targets (self-healing on a fresh runner)
|
||||
run: |
|
||||
if ! command -v rustup >/dev/null && [ ! -x "$HOME/.cargo/bin/rustup" ]; then
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \
|
||||
| sh -s -- -y --no-modify-path --profile minimal
|
||||
fi
|
||||
RUSTUP="$(command -v rustup || echo "$HOME/.cargo/bin/rustup")"
|
||||
dirname "$RUSTUP" >> "$GITHUB_PATH"
|
||||
"$RUSTUP" target add aarch64-linux-android armv7-linux-androideabi x86_64-linux-android
|
||||
|
||||
- name: Android SDK
|
||||
# SHA-pinned: this workflow's release job carries the signing keystore + Play service-account
|
||||
# secrets, so a moved tag on a third-party action could exfiltrate them. v3 = 9fc6c4e.
|
||||
uses: android-actions/setup-android@9fc6c4e9069bf8d3d10b2204b1fb8f6ef7065407 # v3
|
||||
# Same key namespace as ci.yml/deb.yml ON PURPOSE: identical Cargo.lock, identical
|
||||
# CARGO_HOME layout (/usr/local/cargo), so the registry/git downloads dedupe with
|
||||
# the rest of the fleet in the central cache. target/ is deliberately NOT cached
|
||||
# anymore — sccache covers recompilation without shipping multi-GB tars per run.
|
||||
- name: Cache (cargo registry)
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
# Only platform-tools — NOT the action's default legacy `tools`, whose dependency chain
|
||||
# drags in the ~250 MB emulator nobody here runs (instrumentation tests are deferred).
|
||||
# That download was the single flakiest piece of this job: the shared runner fleet drops
|
||||
# packets under parallel-job load and sdkmanager's streamed unzip turns a truncated
|
||||
# stream into "Error on ZipFile unknown archive" (observed 2026-07-22, twice).
|
||||
packages: platform-tools
|
||||
|
||||
- name: NDK r30 + platform 36 + build-tools + CMake (libopus cross-build)
|
||||
# cmake;3.22.1 installs cmake + ninja under $ANDROID_SDK/cmake/3.22.1/bin — the exact path
|
||||
# kit/build.gradle.kts prepends to PATH for cargo-ndk's audiopus_sys (libopus) CMake build.
|
||||
# Note: platforms;android-37 is sometimes missing from standard channels; AGP will
|
||||
# auto-download it if needed during the build.
|
||||
# retry.sh: sdkmanager is a single-shot multi-hundred-MB fetch, exactly the class the
|
||||
# helper exists for (fleet-load packet drops truncate the stream mid-unzip); a failed
|
||||
# attempt leaves no partial package behind, so a plain re-invoke is safe.
|
||||
run: bash scripts/ci/retry.sh 4 sdkmanager "platform-tools" "platforms;android-36" "build-tools;37.0.0" "ndk;30.0.14904198" "cmake;3.22.1"
|
||||
path: |
|
||||
/usr/local/cargo/registry
|
||||
/usr/local/cargo/git
|
||||
key: cargo-home-${{ hashFiles('Cargo.lock') }}
|
||||
restore-keys: cargo-home-
|
||||
|
||||
- name: Caches (cargo + gradle)
|
||||
- name: Cache (gradle)
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/registry
|
||||
~/.cargo/git
|
||||
~/.gradle/caches
|
||||
~/.gradle/wrapper
|
||||
target
|
||||
# gradle-wrapper.properties is in the key on purpose — see android-screenshots.yml.
|
||||
key: android-${{ hashFiles('Cargo.lock', 'clients/android/**/*.gradle.kts', 'clients/android/gradle/wrapper/gradle-wrapper.properties') }}
|
||||
restore-keys: android-
|
||||
|
||||
- name: cargo-ndk
|
||||
run: command -v cargo-ndk >/dev/null || cargo install cargo-ndk
|
||||
# gradle-wrapper.properties is in the key on purpose: `~/.gradle/wrapper` caches the
|
||||
# Gradle DISTRIBUTION, so a wrapper bump with no .gradle.kts change would otherwise
|
||||
# restore a key that can never hold the new one. Namespace shared with
|
||||
# android-screenshots.yml — same content, one copy in the central store.
|
||||
key: gradle-${{ hashFiles('clients/android/**/*.gradle.kts', 'clients/android/gradle/wrapper/gradle-wrapper.properties') }}
|
||||
restore-keys: gradle-
|
||||
|
||||
- name: assembleDebug (cargo-ndk → jniLibs → APK)
|
||||
working-directory: clients/android
|
||||
|
||||
@@ -44,6 +44,21 @@ on:
|
||||
- '.gitea/workflows/apple.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
# Shared compile cache: sccache -> RustFS S3 (storage.unom.io — the mini resolves it via
|
||||
# the router, i.e. the hairpin path whose TLS always validated). Covers every cargo/rustc
|
||||
# invocation build-xcframework.sh makes, incl. the tvOS -Zbuild-std std builds; the Swift
|
||||
# side stays on DerivedData (sccache doesn't cache swiftc).
|
||||
env:
|
||||
RUSTC_WRAPPER: sccache
|
||||
SCCACHE_BUCKET: unom-ci-sccache
|
||||
SCCACHE_ENDPOINT: https://storage.unom.io
|
||||
SCCACHE_REGION: home-central
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.SCCACHE_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.SCCACHE_SECRET_ACCESS_KEY }}
|
||||
# sccache and incremental compilation are mutually exclusive; the shared cache makes the
|
||||
# runner's persistent target/ disposable instead of precious.
|
||||
CARGO_INCREMENTAL: "0"
|
||||
|
||||
jobs:
|
||||
# SECURITY: builds/tests PULL-REQUEST code on the host-mode, persistent `macos-arm64` runner shared
|
||||
# with the release-signing job (release.yml, which loads the App Store Connect key). Untrusted PR
|
||||
@@ -70,6 +85,18 @@ jobs:
|
||||
dirname "$RUSTUP" >> "$GITHUB_PATH"
|
||||
"$RUSTUP" target add aarch64-apple-darwin x86_64-apple-darwin
|
||||
|
||||
# Shared compile cache. ~/.local/bin is on the runner daemon's PATH; GITHUB_PATH is
|
||||
# belt-and-braces. bsdtar (macOS) globs by default — no --wildcards.
|
||||
- name: sccache (self-healing install)
|
||||
run: |
|
||||
if ! command -v sccache >/dev/null; then
|
||||
mkdir -p "$HOME/.local/bin"
|
||||
curl -fsSL https://github.com/mozilla/sccache/releases/download/v0.10.0/sccache-v0.10.0-aarch64-apple-darwin.tar.gz \
|
||||
| tar -xz --strip-components=1 -C "$HOME/.local/bin" '*/sccache'
|
||||
fi
|
||||
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
|
||||
sccache --version
|
||||
|
||||
# `punktfunk-core` now decodes Opus in-core for the Apple client (surround), pulling
|
||||
# `audiopus_sys`, which builds a vendored static libopus via CMake when pkg-config can't find a
|
||||
# system Opus — so the xcframework is self-contained (no runtime libopus.dylib on end-user Macs).
|
||||
@@ -128,6 +155,18 @@ jobs:
|
||||
"$RUSTUP" target add aarch64-apple-darwin x86_64-apple-darwin \
|
||||
aarch64-apple-ios aarch64-apple-ios-sim x86_64-apple-ios
|
||||
|
||||
# Shared compile cache. ~/.local/bin is on the runner daemon's PATH; GITHUB_PATH is
|
||||
# belt-and-braces. bsdtar (macOS) globs by default — no --wildcards.
|
||||
- name: sccache (self-healing install)
|
||||
run: |
|
||||
if ! command -v sccache >/dev/null; then
|
||||
mkdir -p "$HOME/.local/bin"
|
||||
curl -fsSL https://github.com/mozilla/sccache/releases/download/v0.10.0/sccache-v0.10.0-aarch64-apple-darwin.tar.gz \
|
||||
| tar -xz --strip-components=1 -C "$HOME/.local/bin" '*/sccache'
|
||||
fi
|
||||
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
|
||||
sccache --version
|
||||
|
||||
# See the swift job: audiopus_sys (via the in-core Opus decode) builds vendored libopus with CMake.
|
||||
- name: CMake (for the vendored libopus audiopus_sys builds)
|
||||
run: |
|
||||
@@ -144,6 +183,20 @@ jobs:
|
||||
# inherits this from the env during the xcframework build).
|
||||
echo "CMAKE_POLICY_VERSION_MINIMUM=3.5" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Pin + prune DerivedData (same disease release.yml already cures)
|
||||
# screenshots.sh builds into a throwaway mktemp DerivedData per invocation — two
|
||||
# fresh ~1 GB trees per run, zero reuse. Pin one stable root (PF_SHOT_DERIVED_DATA,
|
||||
# honored by the script) so repeat runs are incremental, and GC anything a week old
|
||||
# in the default DerivedData root that no pin owns.
|
||||
run: |
|
||||
DD="$HOME/ci/derived-data/screenshots"
|
||||
mkdir -p "$DD"
|
||||
echo "PF_SHOT_DERIVED_DATA=$DD" >> "$GITHUB_ENV"
|
||||
if [ -d "$HOME/Library/Developer/Xcode/DerivedData" ]; then
|
||||
find "$HOME/Library/Developer/Xcode/DerivedData" -mindepth 1 -maxdepth 1 \
|
||||
-mtime +7 -exec rm -rf {} + 2>/dev/null || true
|
||||
fi
|
||||
|
||||
- name: Build PunktfunkCore.xcframework (mac + iOS slices)
|
||||
run: BUILD_IOS=1 bash scripts/build-xcframework.sh
|
||||
|
||||
@@ -157,6 +210,10 @@ jobs:
|
||||
bash tools/screenshots.sh ipad || echo "::warning::iPad 13\" screenshots skipped"
|
||||
echo "Produced:"; ls -la screenshots || true
|
||||
|
||||
- name: Shut the Simulators down (leaked booted sims once piled up 846 deep)
|
||||
if: always()
|
||||
run: xcrun simctl shutdown all || true
|
||||
|
||||
- name: Upload screenshots (zip artifact)
|
||||
if: always()
|
||||
# v3, not v4: Gitea's artifact backend identifies as GHES, which @actions/artifact v2+
|
||||
|
||||
@@ -65,6 +65,11 @@ jobs:
|
||||
dockerfile: ci/fedora-rpm.Dockerfile
|
||||
buildargs: --build-arg FEDORA_VERSION=44
|
||||
keysuffix: -f44
|
||||
# Android builder (JDK + SDK/NDK + cargo-ndk + sccache) — android.yml and
|
||||
# android-screenshots.yml run in it; ~3 GB of per-run Google downloads became
|
||||
# image layers.
|
||||
- image: punktfunk-android-ci
|
||||
dockerfile: ci/android-ci.Dockerfile
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
|
||||
@@ -88,6 +88,21 @@ on:
|
||||
required: false
|
||||
default: "true"
|
||||
|
||||
# Shared compile cache: sccache -> RustFS S3 (storage.unom.io — the mini resolves it via
|
||||
# the router, i.e. the hairpin path whose TLS always validated). Covers every cargo/rustc
|
||||
# invocation build-xcframework.sh makes, incl. the tvOS -Zbuild-std std builds; the Swift
|
||||
# side stays on DerivedData (sccache doesn't cache swiftc).
|
||||
env:
|
||||
RUSTC_WRAPPER: sccache
|
||||
SCCACHE_BUCKET: unom-ci-sccache
|
||||
SCCACHE_ENDPOINT: https://storage.unom.io
|
||||
SCCACHE_REGION: home-central
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.SCCACHE_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.SCCACHE_SECRET_ACCESS_KEY }}
|
||||
# sccache and incremental compilation are mutually exclusive; the shared cache makes the
|
||||
# runner's persistent target/ disposable instead of precious.
|
||||
CARGO_INCREMENTAL: "0"
|
||||
|
||||
jobs:
|
||||
apple:
|
||||
runs-on: macos-arm64
|
||||
@@ -157,6 +172,18 @@ jobs:
|
||||
# inherits this from the env during the xcframework build).
|
||||
echo "CMAKE_POLICY_VERSION_MINIMUM=3.5" >> "$GITHUB_ENV"
|
||||
|
||||
# Shared compile cache. ~/.local/bin is on the runner daemon's PATH; GITHUB_PATH is
|
||||
# belt-and-braces. bsdtar (macOS) globs by default — no --wildcards.
|
||||
- name: sccache (self-healing install)
|
||||
run: |
|
||||
if ! command -v sccache >/dev/null; then
|
||||
mkdir -p "$HOME/.local/bin"
|
||||
curl -fsSL https://github.com/mozilla/sccache/releases/download/v0.10.0/sccache-v0.10.0-aarch64-apple-darwin.tar.gz \
|
||||
| tar -xz --strip-components=1 -C "$HOME/.local/bin" '*/sccache'
|
||||
fi
|
||||
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
|
||||
sccache --version
|
||||
|
||||
- name: Pin + prune Xcode DerivedData
|
||||
# Without -derivedDataPath, xcodebuild derives its DerivedData directory name from the
|
||||
# PROJECT'S ABSOLUTE PATH — and act_runner rotates its workspace
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
# Android CI builder: JDK 21 + Android SDK/NDK/CMake + pinned Rust with the three shipping
|
||||
# Android targets + cargo-ndk + sccache. Everything android.yml used to download per run
|
||||
# (~3 GB of NDK + SDK packages from Google, plus a from-source cargo-ndk build) is baked
|
||||
# here instead; the image is content-keyed and rebuilt only when the ci/ tree changes
|
||||
# (docker.yml `builders`).
|
||||
#
|
||||
# docker build -f ci/android-ci.Dockerfile -t punktfunk-android-ci ci
|
||||
#
|
||||
# Version pins mirror what android.yml installed via sdkmanager: AGP 9.3 wants JDK 17–21;
|
||||
# cmake;3.22.1 because kit/build.gradle.kts prepends $ANDROID_SDK/cmake/3.22.1/bin to PATH
|
||||
# for cargo-ndk's audiopus_sys (libopus) CMake build; platforms;android-37 is deliberately
|
||||
# absent (AGP auto-downloads it if a build ever needs it — same note as the old workflow).
|
||||
FROM ubuntu:26.04
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
ca-certificates curl git unzip zip python3 openjdk-21-jdk-headless \
|
||||
build-essential pkg-config \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64
|
||||
|
||||
# Android SDK: cmdline-tools must land under cmdline-tools/latest for sdkmanager to
|
||||
# find its own root.
|
||||
ENV ANDROID_HOME=/opt/android-sdk \
|
||||
ANDROID_SDK_ROOT=/opt/android-sdk
|
||||
ARG CMDLINE_TOOLS=13114758
|
||||
RUN mkdir -p "$ANDROID_HOME/cmdline-tools" \
|
||||
&& curl -fsSL -o /tmp/clt.zip "https://dl.google.com/android/repository/commandlinetools-linux-${CMDLINE_TOOLS}_latest.zip" \
|
||||
&& unzip -q /tmp/clt.zip -d "$ANDROID_HOME/cmdline-tools" \
|
||||
&& mv "$ANDROID_HOME/cmdline-tools/cmdline-tools" "$ANDROID_HOME/cmdline-tools/latest" \
|
||||
&& rm /tmp/clt.zip
|
||||
ENV PATH=$ANDROID_HOME/cmdline-tools/latest/bin:$ANDROID_HOME/platform-tools:$PATH
|
||||
RUN yes | sdkmanager --licenses >/dev/null \
|
||||
&& sdkmanager "platform-tools" "platforms;android-36" "build-tools;37.0.0" \
|
||||
"ndk;30.0.14904198" "cmake;3.22.1" \
|
||||
&& chmod -R a+rX "$ANDROID_HOME"
|
||||
|
||||
# Toolchain shared across CI users (jobs may run as different uids) — same shape as
|
||||
# rust-ci.Dockerfile, plus the Android cross targets and cargo-ndk. The registry/git
|
||||
# download caches are stripped after the cargo-ndk install: jobs restore those from the
|
||||
# shared actions cache, and baking them would only bloat every pull.
|
||||
ENV RUSTUP_HOME=/usr/local/rustup \
|
||||
CARGO_HOME=/usr/local/cargo \
|
||||
PATH=/usr/local/cargo/bin:$PATH
|
||||
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \
|
||||
| sh -s -- -y --no-modify-path --profile minimal \
|
||||
&& rustup target add aarch64-linux-android armv7-linux-androideabi x86_64-linux-android \
|
||||
&& cargo install cargo-ndk --locked \
|
||||
&& rm -rf "$CARGO_HOME/registry" "$CARGO_HOME/git" \
|
||||
&& chmod -R a+w "$RUSTUP_HOME" "$CARGO_HOME" \
|
||||
&& rustc --version && cargo-ndk --version
|
||||
|
||||
# Shared compile cache: jobs set RUSTC_WRAPPER=sccache (backend = RustFS S3 on the LAN,
|
||||
# see .gitea/workflows — the env lives there so dev use of this image stays uncached).
|
||||
ARG SCCACHE_VERSION=0.10.0
|
||||
RUN curl -fsSL "https://github.com/mozilla/sccache/releases/download/v${SCCACHE_VERSION}/sccache-v${SCCACHE_VERSION}-x86_64-unknown-linux-musl.tar.gz" \
|
||||
| tar -xz --wildcards --strip-components=1 -C /usr/local/bin '*/sccache' \
|
||||
&& sccache --version
|
||||
@@ -116,7 +116,10 @@ shoot_sim() {
|
||||
xcrun simctl bootstatus "$udid" -b >/dev/null 2>&1 || true
|
||||
|
||||
log "$prefix — building ($scheme)…"
|
||||
local dd; dd="$(mktemp -d)"
|
||||
# PF_SHOT_DERIVED_DATA (optional): a STABLE DerivedData root, so repeat runs reuse the
|
||||
# incremental build instead of cold-building into a throwaway tmpdir — CI pins this
|
||||
# (apple.yml); local runs keep the self-cleaning mktemp default.
|
||||
local dd; dd="${PF_SHOT_DERIVED_DATA:-$(mktemp -d)}"; mkdir -p "$dd"
|
||||
xcodebuild -project Punktfunk.xcodeproj -scheme "$scheme" -configuration Debug \
|
||||
-sdk "$sdk" -destination "id=$udid" -derivedDataPath "$dd" \
|
||||
CODE_SIGNING_ALLOWED=NO build >/dev/null \
|
||||
|
||||
Reference in New Issue
Block a user