Skip to content

Commit 9c37f3c

Browse files
ci: add android build workflow
1 parent ae6c896 commit 9c37f3c

2 files changed

Lines changed: 123 additions & 0 deletions

File tree

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
name: Build Android App
2+
3+
on:
4+
# Called by release-please when a new version is released
5+
workflow_call:
6+
# Manual trigger for testing
7+
workflow_dispatch:
8+
# PR testing - only when Android-relevant files change
9+
pull_request:
10+
branches: [main]
11+
paths:
12+
- 'src-tauri/**'
13+
- '!src-tauri/gen/apple/**'
14+
- '!src-tauri/icons/ios/**'
15+
- 'fastlane/**'
16+
- '!fastlane/metadata/ios/**'
17+
- 'Taskfile.yml'
18+
- 'taskfiles/**'
19+
- '!taskfiles/ios.yml'
20+
- 'Gemfile*'
21+
- 'package*.json'
22+
- '.github/workflows/build-android-app.yml'
23+
24+
# Cancel in-progress builds when a newer one is triggered
25+
concurrency:
26+
group: ${{ github.workflow }}-${{ github.ref }}
27+
cancel-in-progress: true
28+
29+
jobs:
30+
build:
31+
runs-on: self-hosted
32+
env:
33+
BUNDLE_FROZEN: "true"
34+
RUBYOPT: "-W0"
35+
ANDROID_HOME: /opt/homebrew/share/android-commandlinetools
36+
ANDROID_NDK_HOME: /opt/homebrew/share/android-commandlinetools/ndk/28.2.13676358
37+
steps:
38+
- name: Checkout repository
39+
uses: actions/checkout@v6
40+
with:
41+
fetch-depth: 1
42+
43+
- name: Setup Ruby
44+
uses: ruby/setup-ruby@v1
45+
with:
46+
ruby-version: '4.0.1'
47+
bundler-cache: true
48+
49+
- name: Setup Node.js
50+
uses: actions/setup-node@v6
51+
with:
52+
node-version: '24'
53+
cache: 'npm'
54+
55+
- name: Install npm dependencies
56+
run: npm ci
57+
58+
- name: Setup Rust
59+
uses: dtolnay/rust-toolchain@stable
60+
with:
61+
targets: aarch64-linux-android,armv7-linux-androideabi,i686-linux-android,x86_64-linux-android
62+
63+
- name: Cache Rust
64+
uses: Swatinem/rust-cache@v2
65+
with:
66+
workspaces: src-tauri -> target
67+
cache-targets: true
68+
cache-on-failure: true
69+
70+
- name: Cache Task checksums
71+
uses: actions/cache@v5
72+
with:
73+
path: .task
74+
key: ${{ runner.os }}-task-v1
75+
restore-keys: |
76+
${{ runner.os }}-task-
77+
78+
- name: Cache Android build artifacts
79+
uses: actions/cache@v5
80+
with:
81+
path: src-tauri/gen/android/app/build
82+
key: ${{ runner.os }}-android-build-${{ hashFiles('src-tauri/src/**/*.rs', 'src-tauri/Cargo.toml', 'src-tauri/Cargo.lock', 'src-tauri/tauri.conf.json', 'src-tauri/dist/**/*', 'src-tauri/icons/icon.png', 'fastlane/Fastfile', 'fastlane/Appfile') }}
83+
restore-keys: |
84+
${{ runner.os }}-android-build-
85+
86+
- name: Install Task
87+
uses: go-task/setup-task@v1
88+
89+
- name: Setup Android signing
90+
env:
91+
ANDROID_KEY_ALIAS: lunch
92+
run: |
93+
cd src-tauri/gen/android
94+
echo "keyAlias=$ANDROID_KEY_ALIAS" > keystore.properties
95+
echo "password=${{ secrets.ANDROID_KEY_PASSWORD }}" >> keystore.properties
96+
base64 -d <<< "${{ secrets.ANDROID_KEY_BASE64 }}" > $RUNNER_TEMP/keystore.jks
97+
echo "storeFile=$RUNNER_TEMP/keystore.jks" >> keystore.properties
98+
99+
- name: Build and upload to Google Play
100+
run: task android:testflight
101+
env:
102+
FASTLANE_OPT_OUT_USAGE: 1
103+
SUPPLY_JSON_KEY_DATA: ${{ secrets.GOOGLE_PLAY_JSON_KEY }}
104+
105+
- name: Cleanup signing artifacts
106+
if: always()
107+
run: |
108+
rm -f src-tauri/gen/android/keystore.properties
109+
rm -f "$RUNNER_TEMP/keystore.jks"

docs/android.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,20 @@ task android:testflight
172172
task android:release
173173
```
174174

175+
### CI/CD (GitHub Actions)
176+
177+
The workflow `.github/workflows/build-android-app.yml` automates builds on PR and release.
178+
179+
**Required GitHub Secrets:**
180+
181+
| Secret | Description | How to Generate |
182+
|--------|-------------|-----------------|
183+
| `ANDROID_KEY_PASSWORD` | Keystore password | Same as `ANDROID_KEYSTORE_PASSWORD` in `.env` |
184+
| `ANDROID_KEY_BASE64` | Base64-encoded keystore | `base64 -i ~/lunchjs-release.jks \| tr -d '\n'` |
185+
| `GOOGLE_PLAY_JSON_KEY` | Service account JSON contents | Copy contents of service account JSON file |
186+
187+
The key alias `lunch` is hardcoded in the workflow.
188+
175189
---
176190

177191
## Fastlane Lanes

0 commit comments

Comments
 (0)