Skip to content

Commit 8fea3fa

Browse files
Merge pull request #12 from codebuilderinc/feature/local-build-workflow-setup
Feature/local build workflow setup
2 parents e85dc8a + f5cf652 commit 8fea3fa

11 files changed

+3224
-358
lines changed

.github/workflows/eas-android-build.yml

Lines changed: 358 additions & 358 deletions
Large diffs are not rendered by default.
Lines changed: 274 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,274 @@
1+
name: 🏗️ Local Android Build (Self-Hosted)
2+
permissions:
3+
contents: write
4+
5+
on:
6+
workflow_dispatch:
7+
push:
8+
branches: ['main'] #["**"]
9+
paths:
10+
- '.github/workflows/local-android-build.yml' # Allow manual re-runs of this work6flow
11+
12+
env:
13+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
14+
15+
jobs:
16+
build-android-local:
17+
name: 🔨 Build Android APK (Local Gradle)
18+
runs-on: self-hosted # Use your self-hosted runner / local machine
19+
outputs:
20+
app_version: ${{ steps.version-control.outputs.app_version }}
21+
build_number: ${{ steps.version-control.outputs.build_number }}
22+
build_date: ${{ steps.version-control.outputs.build_date }}
23+
is_production: ${{ steps.version-control.outputs.is_production }}
24+
branch_name: ${{ steps.extract-branch.outputs.branch_name }}
25+
steps:
26+
# ========================
27+
# 🛠️ Repository Setup
28+
# ========================
29+
- name: '📦 Checkout (Full History)'
30+
uses: actions/checkout@v4
31+
with:
32+
fetch-depth: 0
33+
34+
- name: '🔍 Extract branch name'
35+
id: extract-branch
36+
shell: bash
37+
run: |
38+
BRANCH_NAME=${GITHUB_REF#refs/heads/}
39+
echo "branch_name=$BRANCH_NAME" >> $GITHUB_OUTPUT
40+
echo "Branch: $BRANCH_NAME"
41+
42+
# ========================
43+
# ⚙️ Environment Configuration
44+
# ========================
45+
- name: '📦 Setup Node.js 22.x'
46+
uses: actions/setup-node@v4
47+
with:
48+
node-version: 22.x
49+
cache: 'npm'
50+
51+
- name: '🧩 Install dependencies'
52+
run: npm ci --legacy-peer-deps
53+
54+
# ========================
55+
# 🔄 Version Management
56+
# ========================
57+
- name: '🔄 Update Production Version'
58+
if: github.ref == 'refs/heads/main'
59+
run: node scripts/bumpVersion.js
60+
61+
- name: '🔧 Configure Git for Automation'
62+
if: github.ref == 'refs/heads/main'
63+
run: |
64+
git config --global user.name "GitHub Actions"
65+
git config --global user.email "actions@github.com"
66+
67+
- name: '💾 Commit Version Update'
68+
if: github.ref == 'refs/heads/main'
69+
run: |
70+
git add version.json
71+
git commit -m "chore: Auto-increment version [skip ci]" || true
72+
git push || true
73+
74+
# ========================
75+
# 📌 Version Setup
76+
# ========================
77+
- name: '🏷️ Set Build Versions'
78+
id: version-control
79+
run: |
80+
# Use version from version.json
81+
if [ "${{ github.ref }}" == "refs/heads/main" ]; then
82+
APP_VERSION=$(jq -r '.version' version.json)
83+
IS_PRODUCTION="true"
84+
else
85+
# For non-main branches, create a prerelease version with branch name
86+
BRANCH_NAME=${{ steps.extract-branch.outputs.branch_name }}
87+
SANITIZED_BRANCH=$(echo "$BRANCH_NAME" | sed 's/[^a-zA-Z0-9]/-/g')
88+
# Get base version from version.json
89+
BASE_VERSION=$(jq -r '.version' version.json)
90+
APP_VERSION="${BASE_VERSION}-pre.${SANITIZED_BRANCH}.${{ github.run_number }}"
91+
IS_PRODUCTION="false"
92+
fi
93+
94+
# Generate build identifiers
95+
BUILD_NUMBER="${{ github.run_id }}"
96+
BUILD_DATE=$(date +'%Y%m%d-%H%M%S')
97+
98+
# Set outputs for downstream jobs
99+
echo "app_version=$APP_VERSION" >> $GITHUB_OUTPUT
100+
echo "build_number=$BUILD_NUMBER" >> $GITHUB_OUTPUT
101+
echo "build_date=$BUILD_DATE" >> $GITHUB_OUTPUT
102+
echo "is_production=$IS_PRODUCTION" >> $GITHUB_OUTPUT
103+
104+
# Export environment variables
105+
echo "APP_VERSION=$APP_VERSION" >> $GITHUB_ENV
106+
echo "BUILD_NUMBER=$BUILD_NUMBER" >> $GITHUB_ENV
107+
echo "BUILD_DATE=$BUILD_DATE" >> $GITHUB_ENV
108+
109+
# ========================
110+
# 🛠️ Android SDK Check
111+
# ========================
112+
- name: '🔍 Verify & Configure Android SDK'
113+
run: |
114+
# Force a fixed SDK location for the runner
115+
ANDROID_HOME="/home/digitalnomad91/Android/sdk"
116+
117+
# Export for subsequent steps
118+
echo "ANDROID_HOME=$ANDROID_HOME" >> $GITHUB_ENV
119+
echo "✅ ANDROID_HOME: $ANDROID_HOME"
120+
121+
# Verify SDK exists
122+
if [ ! -d "$ANDROID_HOME" ]; then
123+
echo "❌ ANDROID_HOME path does not exist: $ANDROID_HOME"
124+
exit 1
125+
fi
126+
127+
echo "✅ Checking for gradle wrapper..."
128+
ls -la android/gradlew || echo "⚠️ No gradle wrapper found, will use globally installed gradle"
129+
130+
# ========================
131+
# 🏗️ Build Execution
132+
# ========================
133+
- name: '🚀 Prepare Expo Bundle'
134+
run: |
135+
echo "📦 Creating Expo bundle for embedded use..."
136+
npm run prepare
137+
138+
- name: '🔧 Make Gradle Wrapper Executable'
139+
run: |
140+
chmod +x android/gradlew
141+
142+
- name: '🏗️ Build Release APK with Gradle'
143+
run: |
144+
export ANDROID_HOME="/home/digitalnomad91/Android/sdk"
145+
cd android
146+
./gradlew clean assembleRelease \
147+
-x bundleRelease \
148+
--no-daemon \
149+
-Dorg.gradle.jvmargs=-Xmx4096m
150+
cd ..
151+
echo "✅ Build completed successfully!"
152+
153+
# ========================
154+
# 📦 APK Verification & Naming
155+
# ========================
156+
- name: '📍 Locate APK Output'
157+
id: apk-path
158+
run: |
159+
APK_FILE=$(find android/app/build/outputs/apk -name "*.apk" -type f | head -1)
160+
if [ -z "$APK_FILE" ]; then
161+
echo "❌ Error: No APK file generated!"
162+
find android/app/build -name "*.apk" -o -name "*.aab" 2>/dev/null
163+
exit 1
164+
fi
165+
echo "✅ Found APK: $APK_FILE"
166+
echo "APK_PATH=$APK_FILE" >> $GITHUB_OUTPUT
167+
ls -lh "$APK_FILE"
168+
169+
- name: '✏️ Rename APK with Version'
170+
id: final-apk
171+
run: |
172+
SOURCE_APK="${{ steps.apk-path.outputs.APK_PATH }}"
173+
DEST_APK="app-release-${{ env.APP_VERSION }}-build-${{ env.BUILD_NUMBER }}.apk"
174+
cp "$SOURCE_APK" "$DEST_APK"
175+
echo "FINAL_APK=$DEST_APK" >> $GITHUB_OUTPUT
176+
echo "✅ Final APK: $DEST_APK"
177+
ls -lh "$DEST_APK"
178+
179+
# ========================
180+
# 📤 Artifact Upload
181+
# ========================
182+
- name: '📤 Upload APK Artifact'
183+
uses: actions/upload-artifact@v4
184+
with:
185+
name: android-apk-local
186+
path: app-release-${{ env.APP_VERSION }}-build-${{ env.BUILD_NUMBER }}.apk
187+
retention-days: 14
188+
189+
create-release:
190+
name: '🚀 Create GitHub Release'
191+
runs-on: ubuntu-latest
192+
needs: build-android-local
193+
steps:
194+
# ========================
195+
# 📥 Artifact Retrieval
196+
# ========================
197+
- name: '📦 Checkout Repository'
198+
uses: actions/checkout@v4
199+
with:
200+
fetch-depth: 0
201+
202+
- name: '📥 Download APK Artifact'
203+
uses: actions/download-artifact@v4
204+
with:
205+
name: android-apk-local
206+
207+
# ========================
208+
# 📜 Changelog Generation
209+
# ========================
210+
- name: '📋 Create Release Notes'
211+
id: changelog
212+
run: |
213+
echo "📝 Generating changelog from git history..."
214+
CHANGELOG=$(git log --oneline --no-decorate -n 20 | sed 's/^/- /')
215+
echo "$CHANGELOG" > changelog.txt
216+
217+
# Format for GitHub release body
218+
{
219+
echo "## Release: ${{ needs.build-android-local.outputs.app_version }}"
220+
echo ""
221+
echo "**Build Info:**"
222+
echo "- Build Number: ${{ needs.build-android-local.outputs.build_number }}"
223+
echo "- Build Date: ${{ needs.build-android-local.outputs.build_date }}"
224+
echo "- Branch: ${{ needs.build-android-local.outputs.branch_name }}"
225+
echo ""
226+
echo "**Recent Changes:**"
227+
cat changelog.txt
228+
} > release-body.txt
229+
230+
# ========================
231+
# 🏷️ Release Creation
232+
# ========================
233+
- name: '🎚️ Determine Release Type'
234+
id: release-type
235+
run: |
236+
echo "🔍 Detecting release type..."
237+
if [ "${{ needs.build-android-local.outputs.is_production }}" = "true" ]; then
238+
echo "🟢 Production release detected"
239+
RELEASE_TAG="v${{ needs.build-android-local.outputs.app_version }}"
240+
RELEASE_TITLE="📱 Production Release v${{ needs.build-android-local.outputs.app_version }} (Local Build)"
241+
else
242+
echo "🟡 Pre-release build detected"
243+
BRANCH_NAME="${{ needs.build-android-local.outputs.branch_name }}"
244+
RELEASE_TAG="prerelease-local-${BRANCH_NAME}-${{ needs.build-android-local.outputs.build_date }}"
245+
RELEASE_TITLE="📱 Pre-release (${BRANCH_NAME}) v${{ needs.build-android-local.outputs.app_version }} (Local Build)"
246+
fi
247+
echo "RELEASE_TAG=${RELEASE_TAG}" >> $GITHUB_OUTPUT
248+
echo "RELEASE_TITLE=${RELEASE_TITLE}" >> $GITHUB_OUTPUT
249+
250+
- name: '🎉 Publish GitHub Release'
251+
uses: softprops/action-gh-release@v2
252+
with:
253+
tag_name: ${{ steps.release-type.outputs.RELEASE_TAG }}
254+
name: ${{ steps.release-type.outputs.RELEASE_TITLE }}
255+
body_path: release-body.txt
256+
files: app-release-${{ needs.build-android-local.outputs.app_version }}-build-${{ needs.build-android-local.outputs.build_number }}.apk
257+
prerelease: ${{ needs.build-android-local.outputs.is_production != 'true' }}
258+
259+
notify-completion:
260+
name: '✅ Build Completion Notification'
261+
runs-on: ubuntu-latest
262+
needs: [build-android-local, create-release]
263+
if: always()
264+
steps:
265+
- name: '📢 Build Status'
266+
run: |
267+
if [ "${{ needs.build-android-local.result }}" = "success" ] && [ "${{ needs.create-release.result }}" = "success" ]; then
268+
echo "✅ BUILD SUCCESSFUL!"
269+
echo "📱 APK Version: ${{ needs.build-android-local.outputs.app_version }}"
270+
echo "📦 Build completed without Expo.dev charges"
271+
else
272+
echo "❌ BUILD FAILED"
273+
exit 1
274+
fi

0 commit comments

Comments
 (0)