Skip to content

Commit cb9f6b7

Browse files
committed
ci: GitHub Actions workflow — build Android debug APK via Gradle (no EAS)
1 parent fed6090 commit cb9f6b7

1 file changed

Lines changed: 138 additions & 71 deletions

File tree

Lines changed: 138 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,103 +1,170 @@
1-
name: Build Android APK (debug)
1+
name: Build Android APK
22

3+
# Trigger on every push to the mobile branch, or manually
34
on:
45
push:
56
branches: [feature/mobile-app]
7+
paths:
8+
- 'apps/native/**'
9+
- '.github/workflows/build-android.yml'
610
workflow_dispatch:
11+
inputs:
12+
build_type:
13+
description: 'Build type (debug or release-unsigned)'
14+
required: false
15+
default: 'debug'
716

817
jobs:
9-
build-android:
10-
name: Expo prebuild → Gradle assembleDebug
18+
build:
19+
name: Build Android APK
1120
runs-on: ubuntu-latest
12-
timeout-minutes: 90
13-
14-
env:
15-
EXPO_PUBLIC_CONVEX_URL: https://placeholder.convex.cloud
16-
EXPO_PUBLIC_AUTH_BASE_URL: https://placeholder.convex.site
17-
GRADLE_OPTS: "-Dorg.gradle.jvmargs=-Xmx4096m -Dorg.gradle.daemon=false"
18-
EXPO_NO_TELEMETRY: "1"
19-
CI: "true"
21+
timeout-minutes: 60
2022

2123
steps:
22-
- uses: actions/checkout@v4
24+
# ── 1. Checkout ─────────────────────────────────────────────────────────
25+
- name: Checkout repository
26+
uses: actions/checkout@v4
27+
with:
28+
ref: feature/mobile-app
2329

30+
# ── 2. Java 17 (required by Gradle / React Native 0.74) ─────────────────
2431
- name: Set up Java 17
2532
uses: actions/setup-java@v4
2633
with:
34+
distribution: temurin
2735
java-version: '17'
28-
distribution: 'temurin'
36+
cache: gradle
37+
38+
# ── 3. Node.js (Expo CLI needs Node) ────────────────────────────────────
39+
- name: Set up Node.js 20
40+
uses: actions/setup-node@v4
41+
with:
42+
node-version: '20'
43+
44+
# ── 4. Install Bun ──────────────────────────────────────────────────────
45+
- name: Set up Bun
46+
uses: oven-sh/setup-bun@v2
47+
with:
48+
bun-version: latest
2949

30-
- name: Set up Android SDK (clean)
31-
uses: android-actions/setup-android@v3
50+
# ── 5. Cache Bun modules ────────────────────────────────────────────────
51+
- name: Cache Bun dependencies
52+
uses: actions/cache@v4
3253
with:
33-
packages: >
34-
tools
35-
platform-tools
36-
platforms;android-34
37-
build-tools;34.0.0
38-
ndk;26.1.10909125
39-
cmake;3.22.1
54+
path: |
55+
~/.bun/install/cache
56+
node_modules
57+
apps/native/node_modules
58+
key: bun-${{ runner.os }}-${{ hashFiles('bun.lock', 'apps/native/package.json') }}
59+
restore-keys: bun-${{ runner.os }}-
4060

41-
- uses: actions/setup-node@v4
42-
with: { node-version: '20' }
61+
# ── 6. Install workspace deps from repo root ────────────────────────────
62+
- name: Install dependencies (workspace root)
63+
run: bun install --frozen-lockfile
4364

44-
- uses: oven-sh/setup-bun@v2
45-
with: { bun-version: '1.3.5' }
65+
# ── 7. Write placeholder .env (build succeeds; runtime needs real values)─
66+
- name: Create runtime env file for native app
67+
working-directory: apps/native
68+
run: |
69+
cat > .env << 'EOF'
70+
EXPO_PUBLIC_CONVEX_URL=https://placeholder.convex.cloud
71+
EXPO_PUBLIC_AUTH_BASE_URL=https://placeholder.convex.site
72+
EOF
4673
47-
- name: Install native dependencies
74+
# ── 8. Create placeholder icon assets so prebuild doesn't fail ──────────
75+
- name: Create placeholder icon assets
4876
working-directory: apps/native
49-
run: bun install --ignore-scripts
77+
run: |
78+
mkdir -p assets/images
79+
# Generate a minimal 1024x1024 PNG using Python (always available on ubuntu)
80+
python3 - << 'PY'
81+
import struct, zlib
82+
def write_png(path, size=1024, color=(56, 201, 168, 255)):
83+
def chunk(name, data):
84+
c = struct.pack('>I', len(data)) + name + data
85+
return c + struct.pack('>I', zlib.crc32(name + data) & 0xffffffff)
86+
raw = b'\x00' + bytes(color) * size # one row
87+
raw_all = raw * size
88+
compressed = zlib.compress(raw_all)
89+
data = (b'\x89PNG\r\n\x1a\n' +
90+
chunk(b'IHDR', struct.pack('>IIBBBBB', size, size, 8, 2, 0, 0, 0)) +
91+
chunk(b'IDAT', compressed) +
92+
chunk(b'IEND', b''))
93+
with open(path, 'wb') as f:
94+
f.write(data)
95+
write_png('assets/images/icon.png')
96+
write_png('assets/images/adaptive-icon.png')
97+
write_png('assets/images/splash-icon.png', 512)
98+
write_png('assets/images/favicon.png', 48)
99+
print('Assets created.')
100+
PY
50101
51-
- name: Expo prebuild
102+
# ── 9. Expo Prebuild – generates the android/ native project ────────────
103+
- name: Expo Prebuild (Android)
52104
working-directory: apps/native
53-
continue-on-error: true
54-
run: node_modules/.bin/expo prebuild --platform android --clean --no-install 2>&1
105+
run: |
106+
npx expo prebuild \
107+
--platform android \
108+
--clean \
109+
--no-install
55110
env:
56-
EXPO_NO_TELEMETRY: "1"
111+
EXPO_PUBLIC_CONVEX_URL: https://placeholder.convex.cloud
112+
EXPO_PUBLIC_AUTH_BASE_URL: https://placeholder.convex.site
113+
# Skip Expo telemetry
114+
EXPO_NO_TELEMETRY: '1'
57115

58-
- name: Locate gradlew
59-
id: find-android
116+
# ── 10. Make gradlew executable ─────────────────────────────────────────
117+
- name: Make Gradlew executable
118+
working-directory: apps/native/android
119+
run: chmod +x gradlew
120+
121+
# ── 11. Build Debug APK ──────────────────────────────────────────────────
122+
# A debug APK can be installed on any Android device with
123+
# "Install unknown apps" enabled — no keystore needed.
124+
- name: Build Debug APK
125+
working-directory: apps/native/android
60126
run: |
61-
GRADLEW=$(find . -name "gradlew" -not -path "*/node_modules/*" 2>/dev/null | head -1)
62-
[ -n "$GRADLEW" ] || { echo "No gradlew"; exit 1; }
63-
echo "gradlew=$GRADLEW" >> $GITHUB_OUTPUT
64-
echo "android_dir=$(dirname $GRADLEW)" >> $GITHUB_OUTPUT
65-
chmod +x $GRADLEW
127+
./gradlew assembleDebug \
128+
--no-daemon \
129+
--stacktrace \
130+
-Dorg.gradle.jvmargs="-Xmx4g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError" \
131+
-Dorg.gradle.parallel=false
132+
env:
133+
ANDROID_HOME: ${{ env.ANDROID_HOME }}
66134

67-
- name: Cache Gradle
68-
uses: actions/cache@v4
69-
with:
70-
path: |
71-
~/.gradle/wrapper
72-
~/.gradle/caches
73-
key: ${{ runner.os }}-gradle-${{ hashFiles('**/gradle-wrapper.properties') }}-v2
74-
restore-keys: |
75-
${{ runner.os }}-gradle-
76-
77-
- name: Build debug APK
78-
working-directory: ${{ steps.find-android.outputs.android_dir }}
135+
# ── 12. Rename APK with branch + SHA for traceability ───────────────────
136+
- name: Rename APK
79137
run: |
80-
echo "=== Build environment ==="
81-
echo "ANDROID_HOME=$ANDROID_HOME"
82-
ls $ANDROID_HOME/build-tools/ 2>/dev/null
83-
ls $ANDROID_HOME/platforms/ 2>/dev/null
84-
ls $ANDROID_HOME/ndk/ 2>/dev/null | head -3
85-
echo "=== Gradle build ==="
86-
./gradlew assembleDebug --no-daemon --no-build-cache --stacktrace 2>&1 | tee /tmp/gradle.log | tail -80
87-
88-
- name: Upload Gradle log
89-
if: always()
90-
uses: actions/upload-artifact@v4
91-
with:
92-
name: gradle-build-log
93-
path: /tmp/gradle.log
94-
if-no-files-found: ignore
95-
retention-days: 7
138+
mkdir -p dist
139+
SHA=$(echo '${{ github.sha }}' | cut -c1-7)
140+
cp apps/native/android/app/build/outputs/apk/debug/app-debug.apk \
141+
dist/openchat-android-debug-${SHA}.apk
142+
echo "APK_NAME=openchat-android-debug-${SHA}.apk" >> $GITHUB_ENV
143+
echo "APK_PATH=dist/openchat-android-debug-${SHA}.apk" >> $GITHUB_ENV
96144
97-
- name: Upload APK
145+
# ── 13. Upload APK as GitHub Actions artifact (30-day retention) ────────
146+
- name: Upload APK artifact
98147
uses: actions/upload-artifact@v4
99148
with:
100-
name: openchat-android-debug
101-
path: apps/native/android/app/build/outputs/apk/debug/app-debug.apk
102-
if-no-files-found: error
149+
name: ${{ env.APK_NAME }}
150+
path: ${{ env.APK_PATH }}
103151
retention-days: 30
152+
if-no-files-found: error
153+
154+
# ── 14. Print download instructions ─────────────────────────────────────
155+
- name: Print download instructions
156+
run: |
157+
echo "=========================================================="
158+
echo " APK BUILD COMPLETE"
159+
echo "=========================================================="
160+
echo " File: ${{ env.APK_NAME }}"
161+
echo ""
162+
echo " To download:"
163+
echo " 1. Go to https://github.com/opencoredev/openchat/actions"
164+
echo " 2. Click this workflow run"
165+
echo " 3. Scroll to the Artifacts section at the bottom"
166+
echo " 4. Click the artifact name to download the .zip"
167+
echo " 5. Unzip → install the .apk on your Pixel 9:"
168+
echo " adb install openchat-android-debug-*.apk"
169+
echo " (or: copy to phone → tap to install with Files app)"
170+
echo "=========================================================="

0 commit comments

Comments
 (0)