name: Android ARM verification on: push: branches: - main - 'codex/**' pull_request: workflow_dispatch: permissions: code: read actions: write env: CARGO_TERM_COLOR: always CARGO_BUILD_JOBS: '1' CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUSTFLAGS: -C link-arg=-fuse-ld=lld jobs: rust: runs-on: linux-arm64 timeout-minutes: 90 env: CI: 'true' CARGO_INCREMENTAL: '0' CARGO_PROFILE_TEST_DEBUG: line-tables-only steps: - uses: https://github.com/actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Install workspace system libraries run: | df -h . df -i . python3 - <<'PYDOCKER' import http.client, json, os, socket, stat target = "c4e1879061ce13246c14f8134c727543d548264bd58a41dff00a0bcde2fcafa2" class UnixHTTP(http.client.HTTPConnection): def connect(self): self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) self.sock.settimeout(self.timeout) self.sock.connect(self.host) candidates = ["/var/run/docker.sock", "/var/run/user/1000/docker.sock"] host = os.environ.get("DOCKER_HOST", "") if host.startswith("unix://"): candidates.insert(0, host[7:]) for path in dict.fromkeys(candidates): if not os.path.exists(path) or not stat.S_ISSOCK(os.stat(path).st_mode): continue try: connection = UnixHTTP(path, timeout=20) connection.request("GET", "/containers/" + target + "/json?size=1", headers={"Host": "localhost"}) response = connection.getresponse() print("Issue94 Docker diagnostic", path, response.status) data = json.loads(response.read()) if response.status == 200: assert data["Id"] == target print(json.dumps({"id": data["Id"], "names": data.get("Name"), "state": data.get("State", {}).get("Status"), "writable_bytes": data.get("SizeRw"), "mounts": [{k: x.get(k) for k in ("Type", "Name", "Destination")} for x in data.get("Mounts", [])]}, sort_keys=True)) else: print("Target inspection unavailable; no Docker mutation attempted") connection.close() connection = UnixHTTP(path, timeout=30) connection.request("GET", "/system/df", headers={"Host": "localhost"}) response = connection.getresponse() print("Issue94 Docker disk accounting", response.status) data = json.loads(response.read()) if response.status == 200: volumes = data.get("Volumes") or [] containers = data.get("Containers") or [] print(json.dumps({"volume_count": len(volumes), "volume_bytes": sum(max(0, x.get("UsageData", {}).get("Size", 0)) for x in volumes), "container_count": len(containers), "container_writable_bytes": sum(x.get("SizeRw", 0) for x in containers), "build_cache_bytes": data.get("BuildCacheSize"), "issue94_volumes": [{"name": x["Name"], "usage": x.get("UsageData")} for x in volumes if x.get("Name", "").startswith("GITEA-ACTIONS-TASK-618")], "issue94_containers": [{"id": x["Id"], "names": x.get("Names"), "state": x.get("State"), "writable_bytes": x.get("SizeRw")} for x in containers if x.get("Id") == target or any(n.lstrip("/").startswith("GITEA-ACTIONS-TASK-618") for n in x.get("Names", []))]}, sort_keys=True)) connection.close() except (OSError, ValueError, KeyError, AssertionError) as error: print("Issue94 Docker diagnostic unavailable:", type(error).__name__) PYDOCKER available=$(df --output=avail -B1 . | tail -n 1) if [ "$available" -lt 17179869184 ]; then echo 'Rust CI needs at least 16 GiB free in its checkout filesystem.' >&2 exit 1 fi apt-get update apt-get install -y --no-install-recommends python3 lld pkg-config libfontconfig1-dev libasound2-dev libudev-dev libxkbcommon-dev libwayland-dev - name: Install pinned Rust uses: https://github.com/taiki-e/install-action@9534c84618278caac52cb373bb164ed464dbd8af with: tool: rust@1.97.1 fallback: none - name: Install formatting and Clippy components run: rustup component add --toolchain 1.97.1 rustfmt clippy - name: Formatting run: cargo +1.97.1 fmt --all -- --check - name: Warnings as errors run: RUSTFLAGS="-D warnings" cargo +1.97.1 check --locked --workspace --all-targets - name: Clippy run: cargo +1.97.1 clippy --locked --workspace --all-targets -- -D warnings - name: Workspace tests including deterministic clocks and secret backends run: | cargo +1.97.1 test --locked --workspace du -sh target - name: Reclaim this checkout's generated build directories if: always() run: python3 .gitea/scripts/android_ci.py clean-ci android: runs-on: linux-arm64 timeout-minutes: 150 env: ANDROID_HOME: /opt/ironstorage-android-sdk JAVA_HOME: /usr/lib/jvm/java-25-openjdk-arm64 CI: 'true' CARGO_INCREMENTAL: '0' CARGO_PROFILE_DEV_DEBUG: line-tables-only GRADLE_OPTS: -Dorg.gradle.workers.max=1 -Dorg.gradle.jvmargs=-Xmx1g -Dkotlin.daemon.jvm.options=-Xmx512m steps: - uses: https://github.com/actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Install native ARM64 Java and build prerequisites run: | df -h . df -i . available=$(df --output=avail -B1 . | tail -n 1) if [ "$available" -lt 25769803776 ]; then echo 'Android CI needs at least 24 GiB free in its checkout filesystem.' >&2 exit 1 fi apt-get update apt-get install -y --no-install-recommends openjdk-25-jdk python3 ca-certificates curl unzip xz-utils gcc lld pkg-config libfontconfig1-dev - name: Install pinned Rust uses: https://github.com/taiki-e/install-action@9534c84618278caac52cb373bb164ed464dbd8af with: tool: rust@1.97.1 fallback: none - name: Install selected Android targets and cargo-ndk run: | rustup target add --toolchain 1.97.1 aarch64-linux-android armv7-linux-androideabi cargo +1.97.1 install cargo-ndk --version 4.1.2 --locked - name: Check build orchestration run: python3 .gitea/scripts/android_ci.py test - name: Install checksummed native Linux ARM64 SDK and NDK tools run: python3 .gitea/scripts/android_ci.py prepare-linux - name: Compile, test, lint and audit unsigned ARM packages run: python3 .gitea/scripts/android_ci.py build - name: Upload reviewed packages, matching symbols, safe test summaries and SBOM uses: https://github.com/actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: android-arm-verification path: android/build/ci-artifacts/ if-no-files-found: error retention-days: 14 - name: Reclaim this checkout's generated build directories after upload if: always() run: python3 .gitea/scripts/android_ci.py clean-ci