Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 63 additions & 8 deletions .github/workflows/android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ on:
- main
- "feature/**"
- "fix/**"
- "parity/**"
tags:
- "v*"
pull_request:
Expand All @@ -16,6 +17,10 @@ on:
permissions:
contents: read

concurrency:
group: android-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

jobs:
build:
name: Build APK
Expand All @@ -29,24 +34,24 @@ jobs:

steps:
- name: Check out source
uses: actions/checkout@v4
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6

- name: Set up JDK
uses: actions/setup-java@v4
uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5
with:
distribution: temurin
java-version: "21"

- name: Set up Android SDK
uses: android-actions/setup-android@v3
uses: android-actions/setup-android@40fd30fb8d7440372e1316f5d1809ec01dcd3699 # v4
with:
packages: platform-tools

- name: Install Android platform and build tools
run: sdkmanager "platforms;android-35" "build-tools;35.0.0"

- name: Set up Gradle
uses: gradle/actions/setup-gradle@v4
uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5

- name: Make Gradle wrapper executable
run: chmod +x ./gradlew
Expand All @@ -58,11 +63,14 @@ jobs:
- name: Run unit tests
run: ./gradlew --no-daemon :app:testDebugUnitTest

- name: Run Android lint
run: ./gradlew --no-daemon :app:lintDebug

- name: Build debug APK
run: ./gradlew --no-daemon :app:assembleDebug

- name: Upload debug APK
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: Arcane-debug-apk
path: app/build/outputs/apk/debug/*.apk
Expand Down Expand Up @@ -101,7 +109,7 @@ jobs:

- name: Upload signed release APK
if: startsWith(github.ref, 'refs/tags/v') && env.HAS_RELEASE_SIGNING == 'true'
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: Arcane-release-signed-apk
path: Arcane-${{ github.ref_name }}.apk
Expand All @@ -111,6 +119,53 @@ jobs:
if: startsWith(github.ref, 'refs/tags/v') && env.HAS_RELEASE_SIGNING != 'true'
run: echo "Release signing secrets are not configured; debug APK artifact was uploaded."

instrumented:
name: API 30 instrumented tests
if: github.event_name != 'push' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
permissions:
contents: read

steps:
- name: Check out source
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6

- name: Set up JDK
uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5
with:
distribution: temurin
java-version: "21"

- name: Set up Android SDK
uses: android-actions/setup-android@40fd30fb8d7440372e1316f5d1809ec01dcd3699 # v4
with:
packages: platform-tools

- name: Install Android SDK packages
run: sdkmanager "platforms;android-35" "build-tools;35.0.0"

- name: Set up Gradle
uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5

- name: Make Gradle wrapper executable
run: chmod +x ./gradlew

- name: Enable KVM access
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm

- name: Run deterministic Compose and route tests
uses: ReactiveCircus/android-emulator-runner@a421e43855164a8197daf9d8d40fe71c6996bb0d # v2
with:
api-level: 30
arch: x86_64
profile: pixel_2
disable-animations: true
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -no-metrics -camera-back none
script: ./gradlew --no-daemon :app:connectedDebugAndroidTest

publish-release:
name: Publish signed release
runs-on: ubuntu-latest
Expand All @@ -121,13 +176,13 @@ jobs:

steps:
- name: Download signed release APK
uses: actions/download-artifact@v4
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: Arcane-release-signed-apk
path: .

- name: Attach signed APK to GitHub Release
uses: softprops/action-gh-release@v2
uses: softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64 # v3
with:
files: Arcane-${{ github.ref_name }}.apk
fail_on_unmatched_files: true
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ captures/
*.hprof
lint-results*
lint-baseline.xml
!app/lint-baseline.xml

# ----------------------------
# Test & coverage artefacts
Expand Down
18 changes: 15 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
> [!IMPORTANT]
> This project is still under development and is not intended to be used on devices yet.
> Arcane Mobile is a public alpha. Use it with disposable or well-backed-up environments while the
> beta release matrix is being completed; it can perform destructive Docker operations.

<div align="center">

Expand All @@ -22,11 +23,15 @@ Arcane Mobile is the official Android companion for [Arcane](https://github.com/
For setup instructions, configuration details, and development guides, visit the **[official documentation site](https://getarcane.app/docs)**.

For continuation context from the currently running Android app, see [`docs/current-app-state.md`](docs/current-app-state.md).
Release support, promotion gates, and known limitations are documented in
[`docs/release-readiness.md`](docs/release-readiness.md). Testing/security gates and the accessibility/
localization foundation are documented in [`docs/testing-and-quality-gates.md`](docs/testing-and-quality-gates.md)
and [`docs/accessibility-and-localization.md`](docs/accessibility-and-localization.md).

## Requirements

- Android 7.0 (API 24) or later
- An Arcane server reachable over HTTPS
- Arcane 2.10.2 or later, reachable over HTTPS (newer features remain capability-gated)

## Building

Expand All @@ -49,8 +54,13 @@ Run the same checks used by CI with:

```sh
./gradlew :app:testDebugUnitTest :app:assembleDebug
./gradlew :app:lintDebug
```

The API 30 instrumentation lane runs with `./gradlew :app:connectedDebugAndroidTest`. Destructive or
streaming live-server checks are a separately reported disposable-server lane; see the testing guide
before supplying test credentials.

Release APK signing is optional for local builds. To sign a release APK, provide:

```sh
Expand All @@ -72,7 +82,9 @@ before cutting a signed release tag:
- `ARCANE_RELEASE_KEY_ALIAS`
- `ARCANE_RELEASE_KEY_PASSWORD`

Fastlane/F-Droid metadata lives under `fastlane/metadata/android/en-US/`.
Fastlane metadata lives under `fastlane/metadata/android/en-US/`. F-Droid preparation and its current
dependency-eligibility blockers are documented in [`docs/fdroid-release-preparation.md`](docs/fdroid-release-preparation.md);
the project has not been submitted to F-Droid.

### Android Studio run configuration

Expand Down
12 changes: 11 additions & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ android {
}

buildTypes {
debug {
isPseudoLocalesEnabled = true
}
release {
if (hasReleaseSigning) {
signingConfig = signingConfigs.getByName("release")
Expand All @@ -65,6 +68,13 @@ android {
buildConfig = true
compose = true
}

lint {
baseline = file("lint-baseline.xml")
abortOnError = true
warningsAsErrors = true
checkReleaseBuilds = true
}
}

kotlin {
Expand Down Expand Up @@ -100,7 +110,7 @@ dependencies {

// OkHttp HTTP engine for Ktor: robust TLS/HTTP-2 on Android (the pure-Kotlin CIO engine
// fails the TLS handshake against some Cloudflare-fronted hosts, e.g. demo.getarcane.app).
implementation("io.ktor:ktor-client-okhttp:3.0.3")
implementation(libs.ktor.client.okhttp)

implementation(libs.androidx.core.ktx)
implementation(libs.androidx.activity.compose)
Expand Down
Loading