Skip to content

Commit 1b2988f

Browse files
committed
ci: build apk and app on each commit
1 parent 27fb72a commit 1b2988f

7 files changed

Lines changed: 313 additions & 15 deletions

File tree

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
name: Build Android
2+
3+
on:
4+
push:
5+
branches: [master]
6+
paths:
7+
- '.github/workflows/build-android.yml'
8+
- 'mobile-app/android/**'
9+
- 'mobile-app/package.json'
10+
- 'mobile-app/yarn.lock'
11+
- 'mobile-app/package-lock.json'
12+
- 'mobile-app/src/**'
13+
- 'mobile-app/*.js'
14+
- 'mobile-app/*.ts'
15+
- 'mobile-app/*.tsx'
16+
- 'mobile-app/*.json'
17+
pull_request:
18+
branches: [master]
19+
paths:
20+
- '.github/workflows/build-android.yml'
21+
- 'mobile-app/android/**'
22+
- 'mobile-app/package.json'
23+
- 'mobile-app/yarn.lock'
24+
- 'mobile-app/package-lock.json'
25+
- 'mobile-app/src/**'
26+
- 'mobile-app/*.js'
27+
- 'mobile-app/*.ts'
28+
- 'mobile-app/*.tsx'
29+
- 'mobile-app/*.json'
30+
workflow_dispatch:
31+
32+
jobs:
33+
build-android:
34+
name: Build Android APK
35+
runs-on: ubuntu-latest
36+
37+
steps:
38+
- name: Checkout repository
39+
uses: actions/checkout@v4
40+
with:
41+
submodules: recursive
42+
43+
- name: Setup Node.js
44+
uses: actions/setup-node@v4
45+
with:
46+
node-version: '20'
47+
cache: 'npm'
48+
cache-dependency-path: mobile-app/package-lock.json
49+
50+
- name: Install dependencies
51+
working-directory: mobile-app
52+
run: npm ci
53+
54+
- name: Setup Nim
55+
run: |
56+
# Install build essentials and C compiler
57+
sudo apt-get update
58+
sudo apt-get install -y build-essential curl
59+
60+
# Download and install prebuilt Nim binaries
61+
cd /tmp
62+
curl -L -o nim.tar.xz "https://nim-lang.org/download/nim-2.0.8-linux_x64.tar.xz"
63+
tar -xf nim.tar.xz
64+
sudo mv nim-2.0.8 /opt/nim
65+
66+
# Add to PATH
67+
echo "/opt/nim/bin" >> $GITHUB_PATH
68+
echo "$HOME/.nimble/bin" >> $GITHUB_PATH
69+
export PATH="/opt/nim/bin:$HOME/.nimble/bin:$PATH"
70+
71+
# Verify installation
72+
nim --version
73+
nimble --version
74+
75+
- name: Install Nim dependencies
76+
working-directory: mobile-app/nim
77+
run: |
78+
if [ -f "nimbridge.nimble" ]; then
79+
nimble install -d
80+
fi
81+
82+
- name: Build Nim code for Android
83+
working-directory: mobile-app
84+
run: |
85+
# Run the build script to compile Nim for Android
86+
chmod +x tools/build-mobile.sh
87+
./tools/build-mobile.sh
88+
89+
- name: Setup JDK 17
90+
uses: actions/setup-java@v4
91+
with:
92+
java-version: '17'
93+
distribution: 'zulu'
94+
cache: 'gradle'
95+
96+
- name: Cache Gradle packages
97+
uses: actions/cache@v4
98+
with:
99+
path: |
100+
~/.gradle/caches
101+
~/.gradle/wrapper
102+
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
103+
restore-keys: |
104+
${{ runner.os }}-gradle-
105+
106+
- name: Clear Metro cache
107+
working-directory: mobile-app
108+
run: |
109+
npx @react-native-community/cli clean
110+
rm -rf node_modules/.cache
111+
rm -rf /tmp/metro-* || true
112+
113+
- name: Grant execute permission for gradlew
114+
run: chmod +x mobile-app/android/gradlew
115+
116+
- name: Build Release APK
117+
working-directory: mobile-app/android
118+
env:
119+
NODE_ENV: production
120+
EXPO_USE_FAST_RESOLVER: 1
121+
run: ./gradlew assembleRelease --no-daemon --build-cache
122+
123+
- name: Upload Release APK
124+
uses: actions/upload-artifact@v4
125+
with:
126+
name: app-release
127+
path: mobile-app/android/app/build/outputs/apk/release/app-release.apk
128+
retention-days: 7
129+
130+
- name: Stop Gradle daemon
131+
if: always()
132+
working-directory: mobile-app/android
133+
run: ./gradlew --stop

.github/workflows/build-ios.yml

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
name: Build iOS
2+
3+
on:
4+
push:
5+
branches: [master]
6+
paths:
7+
- '.github/workflows/build-ios.yml'
8+
- 'mobile-app/ios/**'
9+
- 'mobile-app/package.json'
10+
- 'mobile-app/yarn.lock'
11+
- 'mobile-app/package-lock.json'
12+
- 'mobile-app/src/**'
13+
- 'mobile-app/*.js'
14+
- 'mobile-app/*.ts'
15+
- 'mobile-app/*.tsx'
16+
- 'mobile-app/*.json'
17+
pull_request:
18+
branches: [master]
19+
paths:
20+
- '.github/workflows/build-ios.yml'
21+
- 'mobile-app/ios/**'
22+
- 'mobile-app/package.json'
23+
- 'mobile-app/yarn.lock'
24+
- 'mobile-app/package-lock.json'
25+
- 'mobile-app/src/**'
26+
- 'mobile-app/*.js'
27+
- 'mobile-app/*.ts'
28+
- 'mobile-app/*.tsx'
29+
- 'mobile-app/*.json'
30+
workflow_dispatch:
31+
32+
jobs:
33+
build-ios:
34+
name: Build iOS IPA
35+
runs-on: macos-latest
36+
37+
steps:
38+
- name: Checkout repository
39+
uses: actions/checkout@v4
40+
with:
41+
submodules: recursive
42+
43+
- name: Setup Node.js
44+
uses: actions/setup-node@v4
45+
with:
46+
node-version: '20'
47+
cache: 'npm'
48+
cache-dependency-path: mobile-app/package-lock.json
49+
50+
- name: Install dependencies
51+
working-directory: mobile-app
52+
run: npm ci
53+
54+
- name: Setup Nim
55+
run: |
56+
# Install Nim
57+
brew install nim
58+
echo "$HOME/.nimble/bin" >> $GITHUB_PATH
59+
60+
# Verify installation
61+
nim --version
62+
nimble --version
63+
64+
- name: Install Nim dependencies
65+
working-directory: mobile-app/nim
66+
run: |
67+
if [ -f "nimbridge.nimble" ]; then
68+
nimble install -d
69+
fi
70+
71+
- name: Build Nim code for iOS
72+
working-directory: mobile-app
73+
run: |
74+
# Run the build script to compile Nim for iOS
75+
chmod +x tools/build-mobile.sh
76+
./tools/build-mobile.sh
77+
78+
- name: Setup Ruby
79+
uses: ruby/setup-ruby@v1
80+
with:
81+
ruby-version: '3.0'
82+
bundler-cache: true
83+
working-directory: mobile-app/ios
84+
85+
- name: Cache CocoaPods
86+
uses: actions/cache@v4
87+
with:
88+
path: mobile-app/ios/Pods
89+
key: ${{ runner.os }}-pods-${{ hashFiles('**/Podfile.lock') }}
90+
restore-keys: |
91+
${{ runner.os }}-pods-
92+
93+
- name: Install CocoaPods dependencies
94+
working-directory: mobile-app/ios
95+
run: |
96+
pod install --repo-update || pod install
97+
98+
- name: Select Xcode
99+
run: sudo xcode-select -s /Applications/Xcode.app
100+
101+
- name: Install xcbeautify
102+
run: brew install xcbeautify
103+
104+
- name: Clear Metro and Xcode caches
105+
working-directory: mobile-app
106+
run: |
107+
npx @react-native-community/cli clean
108+
rm -rf node_modules/.cache
109+
rm -rf /tmp/metro-* || true
110+
rm -rf ios/build || true
111+
112+
- name: Build iOS Simulator App
113+
working-directory: mobile-app/ios
114+
run: |
115+
set -o pipefail
116+
xcodebuild -workspace nimrnmobileapp.xcworkspace \
117+
-scheme nimrnmobileapp \
118+
-sdk iphonesimulator \
119+
-configuration Release \
120+
-destination 'platform=iOS Simulator,name=iPhone 15' \
121+
-derivedDataPath build \
122+
CODE_SIGNING_ALLOWED=NO \
123+
ARCHS=arm64 \
124+
ONLY_ACTIVE_ARCH=YES \
125+
| xcbeautify
126+
127+
- name: Prepare iOS app for upload
128+
working-directory: mobile-app/ios/build/Build/Products/Release-iphonesimulator
129+
run: |
130+
cp -r nimrnmobileapp.app nim-rn-ios.app
131+
132+
- name: Upload Simulator Build
133+
uses: actions/upload-artifact@v4
134+
with:
135+
name: nim-rn-ios.app
136+
path: mobile-app/ios/build/Build/Products/Release-iphonesimulator/nim-rn-ios.app
137+
retention-days: 60
Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1 @@
1-
//
2-
// @generated
3-
// A blank Swift file must be created for native modules with Swift files to work correctly.
4-
//
1+
import Foundation

mobile-app/metro.config.js

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
1-
const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');
1+
// Learn more https://docs.expo.io/guides/customizing-metro
2+
const { getDefaultConfig } = require('expo/metro-config');
23

3-
/**
4-
* Metro configuration
5-
* https://facebook.github.io/metro/docs/configuration
6-
*/
7-
const config = {};
4+
/** @type {import('expo/metro-config').MetroConfig} */
5+
const config = getDefaultConfig(__dirname);
86

9-
module.exports = mergeConfig(getDefaultConfig(__dirname), config);
7+
// Fix for release build serialization issue
8+
config.serializer = {
9+
...config.serializer,
10+
getModulesRunBeforeMainModule: () => [],
11+
getPolyfills: () => [],
12+
};
13+
14+
module.exports = config;

mobile-app/nim/nimbridge.nimble

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Package
2+
version = "0.1.0"
3+
author = "React Native Nim Bridge"
4+
description = "Nim bridge for React Native"
5+
license = "MIT"
6+
srcDir = "."
7+
8+
# Dependencies
9+
requires "nim >= 2.0.0"
10+
requires "json_serialization >= 0.2.8"

mobile-app/tools/build-android-nim.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ echo "Building Nim code for Android..."
77

88
cd ../nim
99

10+
# Install Nim dependencies if nimble file exists
11+
if [ -f "nimbridge.nimble" ]; then
12+
echo "Installing Nim dependencies..."
13+
nimble install -d
14+
fi
15+
1016
# Clean previous builds
1117
rm -rf cache_android_*
1218
mkdir -p cache_android

mobile-app/tools/build-mobile.sh

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@ echo "Building Nim-React Native Bridge..."
1414
echo "Compiling Nim code..."
1515
cd "$NIM_DIR"
1616

17+
# Install Nim dependencies if nimble file exists
18+
if [ -f "nimbridge.nimble" ]; then
19+
echo "Installing Nim dependencies..."
20+
nimble install -d
21+
fi
22+
1723
# Detect platform and build accordingly
1824
if [[ "$OSTYPE" == "darwin"* ]]; then
1925
# macOS: Build iOS static library AND Android C files
@@ -31,9 +37,9 @@ if [[ "$OSTYPE" == "darwin"* ]]; then
3137
else
3238
# Linux: Generate C files for Android compilation
3339
echo "Building C files for Android..."
34-
echo " Building for Android (multiple architectures)..."
35-
# Generate C files compatible with both 32-bit and 64-bit
36-
nim c -c --os:linux --cpu:i386 -d:release --app:staticlib --noMain:on --nimcache:cache_android nimbridge.nim
40+
echo " Building for Android (arm64-v8a)..."
41+
# Generate C files for 64-bit ARM Android
42+
nim c -c --os:android --cpu:arm64 -d:android -d:release --app:staticlib --noMain:on --nimcache:cache_android nimbridge.nim
3743
BUILD_TARGET="android"
3844
CACHE_DIR="cache_android"
3945
LIB_NAME="libnim_core.a"
@@ -64,8 +70,12 @@ fi
6470

6571
# Fallback detection methods
6672
if [ -z "$NIM_LIB_PATH" ] || [ ! -d "$NIM_LIB_PATH" ]; then
73+
# Check for prebuilt Nim installation (GitHub Actions)
74+
if [ -d "/opt/nim/lib" ]; then
75+
NIM_LIB_PATH="/opt/nim/lib"
76+
echo " Found prebuilt Nim lib at: $NIM_LIB_PATH"
6777
# Try Nix store paths (common when using nix develop)
68-
if command -v nim >/dev/null 2>&1; then
78+
elif command -v nim >/dev/null 2>&1; then
6979
NIM_EXECUTABLE=$(which nim)
7080
if [[ "$NIM_EXECUTABLE" == *"/nix/store/"* ]]; then
7181
# Extract the nix store path and look for lib directory

0 commit comments

Comments
 (0)