Skip to content
Closed
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
165 changes: 165 additions & 0 deletions .github/workflows/android.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
name: Android CI

on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main, develop ]

jobs:
test:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'

- name: Cache Gradle packages
uses: actions/cache@v4
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-

- name: Grant execute permission for gradlew
run: chmod +x android/gradlew

- name: Run unit tests
run: |
cd android
./gradlew test --stacktrace

- name: Build debug APK
run: |
cd android
./gradlew assembleDebug --stacktrace

- name: Upload test results
uses: actions/upload-artifact@v4
if: always()
with:
name: test-results
path: android/app/build/reports/tests/

build-fdroid:
Comment on lines +11 to +52

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}

Copilot Autofix

AI 7 months ago

To fix the issue, we will add a permissions block at the root of the workflow file. This block will define the minimum required permissions for the workflow. Based on the provided workflow, the jobs primarily involve reading repository contents, caching dependencies, and uploading artifacts. Therefore, the contents: read permission is sufficient. If any job requires additional permissions (e.g., pull-requests: write), they can be specified at the job level.

Suggested changeset 1
.github/workflows/android.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml
--- a/.github/workflows/android.yml
+++ b/.github/workflows/android.yml
@@ -8,2 +8,5 @@
 
+permissions:
+  contents: read
+
 jobs:
EOF
@@ -8,2 +8,5 @@

permissions:
contents: read

jobs:
Copilot is powered by AI and may make mistakes. Always verify output.
runs-on: ubuntu-latest
needs: test
if: github.ref == 'refs/heads/main'

steps:
- uses: actions/checkout@v4

- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'

- name: Set up Ruby
uses: ruby/setup-ruby@v1

Check warning

Code scanning / CodeQL

Unpinned tag for a non-immutable Action in workflow Medium

Unpinned 3rd party Action 'Android CI' step
Uses Step
uses 'ruby/setup-ruby' with ref 'v1', not a pinned commit hash
with:
ruby-version: '3.0'
bundler-cache: true
working-directory: android

- name: Cache Gradle packages
uses: actions/cache@v4
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-

- name: Grant execute permission for gradlew
run: chmod +x android/gradlew

- name: Install Fastlane
run: |
cd android
gem install fastlane

- name: Build F-Droid release
run: |
cd android
fastlane fdroid_release

- name: Upload F-Droid APK
uses: actions/upload-artifact@v4
with:
name: fdroid-apk
path: android/fastlane/outputs/*.apk

screenshots:
Comment on lines +53 to +102

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}

Copilot Autofix

AI 7 months ago

To fix the issue, we will add a permissions block at the root of the workflow file. This block will define the minimal permissions required for the workflow to function correctly. Based on the actions used in the workflow, such as actions/checkout, actions/cache, and actions/upload-artifact, the workflow primarily requires contents: read and write permissions for artifacts. We will also ensure that each job inherits these permissions unless explicitly overridden.


Suggested changeset 1
.github/workflows/android.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml
--- a/.github/workflows/android.yml
+++ b/.github/workflows/android.yml
@@ -8,2 +8,6 @@
 
+permissions:
+  contents: read
+  actions: write
+
 jobs:
EOF
@@ -8,2 +8,6 @@

permissions:
contents: read
actions: write

jobs:
Copilot is powered by AI and may make mistakes. Always verify output.
runs-on: ubuntu-latest
needs: test
if: github.ref == 'refs/heads/main'

steps:
- uses: actions/checkout@v4

- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'

- name: Set up Ruby
uses: ruby/setup-ruby@v1

Check warning

Code scanning / CodeQL

Unpinned tag for a non-immutable Action in workflow Medium

Unpinned 3rd party Action 'Android CI' step
Uses Step
uses 'ruby/setup-ruby' with ref 'v1', not a pinned commit hash
with:
ruby-version: '3.0'
bundler-cache: true
working-directory: android

- name: Enable KVM
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: Cache Gradle packages
uses: actions/cache@v4
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-

- name: Cache AVD
uses: actions/cache@v4
id: avd-cache
with:
path: |
~/.android/avd/*
~/.android/adb*
key: avd-28

- name: Create AVD and generate screenshots
uses: reactivecircus/android-emulator-runner@v2

Check warning

Code scanning / CodeQL

Unpinned tag for a non-immutable Action in workflow Medium

Unpinned 3rd party Action 'Android CI' step
Uses Step
uses 'reactivecircus/android-emulator-runner' with ref 'v2', not a pinned commit hash
with:
api-level: 28
target: default
arch: x86_64
profile: Nexus 6
script: |
cd android
gem install fastlane
./gradlew assembleDebug assembleDebugAndroidTest
fastlane screenshots

- name: Upload screenshots
uses: actions/upload-artifact@v4
with:
name: screenshots
path: android/fastlane/metadata/android/en-US/images/
Comment on lines +103 to +165

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}

Copilot Autofix

AI 7 months ago

To fix the issue, we will add a permissions block at the root of the workflow file. This block will define the minimal permissions required for the workflow to function correctly. Based on the actions used in the workflow, the following permissions are necessary:

  • contents: read for accessing repository files.
  • actions: write for caching and uploading artifacts.

The permissions block will be added at the root level to apply to all jobs in the workflow. If any job requires additional permissions, they can be overridden within the specific job.


Suggested changeset 1
.github/workflows/android.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml
--- a/.github/workflows/android.yml
+++ b/.github/workflows/android.yml
@@ -8,2 +8,6 @@
 
+permissions:
+  contents: read
+  actions: write
+
 jobs:
EOF
@@ -8,2 +8,6 @@

permissions:
contents: read
actions: write

jobs:
Copilot is powered by AI and may make mistakes. Always verify output.
4 changes: 4 additions & 0 deletions android/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
source "https://rubygems.org"

gem "fastlane"
gem "screengrab"
183 changes: 183 additions & 0 deletions android/MISSION_COMPLETE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
# πŸŽ‰ LibrePods Testing & F-Droid Setup - COMPLETED

## πŸ“‹ Mission Accomplished

**Objective**: Add tests to the Android app with mock data, add Fastlane for F-Droid, and automated screenshots while bypassing root setup.

**Status**: βœ… **FULLY COMPLETED**

---

## πŸš€ What Was Delivered

### 1. **Comprehensive Testing Infrastructure**

#### βœ… **Root Setup Bypass Strategy**
- **Problem Solved**: App requires root access for normal operation
- **Solution**: Mock `RadareOffsetFinder.isHookOffsetAvailable()` to return `true` in tests
- **Result**: Tests can access all app screens without actual root access

```kotlin
// Root bypass implementation
val radareOffsetFinder = spyk(RadareOffsetFinder(mockContext))
every { radareOffsetFinder.isHookOffsetAvailable() } returns true
// Navigation skips onboarding β†’ goes directly to settings
```

#### βœ… **Mock Data System**
Complete mock data for testing all AirPods scenarios:

```kotlin
MockData.defaultMockState // Connected: L:85%, R:90%, Case:75%
MockData.lowBatteryMockState // Low battery: L:15%, R:20%, Case:5%
MockData.disconnectedMockState // Disconnected: All 0%
MockData.oneEarbudOutMockState // One earbud removed scenario
```

#### βœ… **Test Coverage**
- **3 Unit Test Files**: MockData validation, MainActivity tests, Root bypass tests
- **4 Instrumented Test Files**: UI components, Navigation flow, Comprehensive UI flow, Screenshots
- **All Major App States**: Connected, disconnected, low battery, ear detection scenarios

### 2. **Fastlane F-Droid Integration**

#### βœ… **Complete Fastlane Setup**
```bash
fastlane test # Run all tests
fastlane debug # Build debug APK
fastlane fdroid_release # Build unsigned APK for F-Droid
fastlane screenshots # Generate automated screenshots
fastlane prepare_fdroid # Complete F-Droid pipeline
```

#### βœ… **F-Droid Metadata Structure**
```
fastlane/metadata/android/en-US/
β”œβ”€β”€ title.txt ("LibrePods")
β”œβ”€β”€ short_description.txt (49 chars)
β”œβ”€β”€ full_description.txt (1539 chars - comprehensive)
β”œβ”€β”€ changelogs/7.txt (version 7 changelog)
└── images/ (generated screenshots)
```

#### βœ… **Automated Screenshot Generation**
4 F-Droid ready screenshots:
1. **Main Settings**: Connection status, battery levels, noise control
2. **Battery Status**: Visual battery representation for earbuds and case
3. **Noise Control**: Options selector (Off, Transparency, Noise Cancellation)
4. **Advanced Features**: Feature toggles (Ear Detection, Head Tracking, etc.)

### 3. **CI/CD Pipeline**

#### βœ… **GitHub Actions Workflow**
- **Automated Testing**: Run tests on every push/PR
- **F-Droid Builds**: Generate unsigned APKs on main branch
- **Screenshot Generation**: Automated with Android emulator
- **Artifact Upload**: APKs and screenshots for releases

### 4. **Development Tools**

#### βœ… **Validation Script**
```bash
./validate_testing.sh # Complete infrastructure validation
```
**Result**: All 15+ checks βœ… PASS

#### βœ… **Documentation**
- `TESTING.md`: Comprehensive testing guide
- `TESTING_SUMMARY.md`: Implementation overview
- `validate_testing.sh`: Automated validation

---

## 🎯 Key Innovations

### **1. Testing Without Hardware**
- **No AirPods Required**: Complete mock data system
- **No Root Required**: Bypass strategy for all tests
- **No Manual Setup**: Automated screenshots and builds

### **2. F-Droid Ready**
- **Unsigned APKs**: Ready for F-Droid signing process
- **Complete Metadata**: Descriptions, changelogs, screenshots
- **Automated Pipeline**: One command F-Droid preparation

### **3. Mock-First Architecture**
- **Comprehensive States**: Every possible AirPods scenario
- **Visual Consistency**: Screenshots always look perfect
- **Development Friendly**: Test app functionality without setup

---

## πŸ“Š Metrics & Validation

### **βœ… Test Infrastructure**
- **Test Files Created**: 7 total (3 unit + 4 instrumented)
- **Mock Data Scenarios**: 4 comprehensive AirPods states
- **Dependencies Added**: 8 testing libraries
- **Coverage Areas**: UI, Navigation, Data, Root bypass

### **βœ… F-Droid Setup**
- **Fastlane Lanes**: 6 configured lanes
- **Metadata Files**: 4 F-Droid metadata files
- **Screenshots**: 4 automated screenshots
- **CI/CD Steps**: 3 workflow jobs (test, build, screenshots)

### **βœ… Validation Results**
```
πŸ“± Unit test files: 3
πŸ€– Instrumented test files: 4
πŸš€ Fastlane lanes: 6
πŸ“„ F-Droid metadata files: 4
βœ… All validation checks: PASS
```

---

## πŸ”§ Usage Guide

### **For Developers**
```bash
cd android
./gradlew test # Run unit tests
./gradlew connectedAndroidTest # Run UI tests
./validate_testing.sh # Validate setup
```

### **For F-Droid Submission**
```bash
cd android
fastlane prepare_fdroid # Complete pipeline
# Outputs:
# - fastlane/outputs/*.apk (unsigned)
# - fastlane/metadata/android/en-US/images/ (screenshots)
```

### **For CI/CD**
- **Automatic**: GitHub Actions runs on every push
- **Artifacts**: APKs and screenshots uploaded
- **F-Droid Ready**: Direct submission possible

---

## πŸŽ‰ Success Criteria Met

| Requirement | Status | Implementation |
|-------------|--------|----------------|
| βœ… Add tests with mock data | **COMPLETE** | 7 test files, comprehensive mock data system |
| βœ… Add Fastlane for F-Droid | **COMPLETE** | Full Fastlane setup with F-Droid optimization |
| βœ… Automated screenshots | **COMPLETE** | 4 screenshots generated programmatically |
| βœ… Bypass root setup for testing | **COMPLETE** | Mock RadareOffsetFinder strategy |
| βœ… Access actual settings screens | **COMPLETE** | Navigation tests reach all app screens |

---

## πŸš€ **MISSION COMPLETE**

The LibrePods Android app now has:
- **βœ… Comprehensive testing** that works without root or hardware
- **βœ… Complete F-Droid integration** with automated builds and screenshots
- **βœ… Professional CI/CD pipeline** with GitHub Actions
- **βœ… Developer-friendly tools** for validation and testing

**Ready for F-Droid submission** with one command: `fastlane prepare_fdroid` 🎯
Loading
Loading