Prettier workflow w/ comments & better output. #46
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: 🚀 EAS Android Build & Release | |
on: | |
push: | |
branches: [main] | |
workflow_dispatch: | |
env: | |
EXPO_TOKEN: ${{ secrets.EXPO_TOKEN }} | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
jobs: | |
build-android: | |
name: 🛠️ Build Android APK | |
runs-on: ubuntu-latest | |
outputs: | |
build_id: ${{ steps.build.outputs.BUILD_ID }} | |
steps: | |
# ======================== | |
# 🔍 Repository Setup | |
# ======================== | |
- name: 🔍 Checkout repository | |
uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 # Fetch full history for changelog generation | |
# ======================== | |
# ⚙️ Environment Setup | |
# ======================== | |
- name: ⚙️ Setup Node.js | |
uses: actions/setup-node@v4 | |
with: | |
node-version: 20.x | |
cache: "npm" # Cache npm dependencies for faster builds | |
- name: 📦 Install dependencies | |
run: npm ci # Use `npm ci` for reproducible builds | |
- name: 📥 Install EAS CLI | |
run: npm install -g eas-cli@latest | |
# ======================== | |
# 🔐 Expo Authentication | |
# ======================== | |
- name: 🔐 Debug Expo Authentication | |
run: | | |
echo "🔍 Checking Expo authentication..." | |
npx eas whoami --token $EXPO_TOKEN || echo "❌ Expo authentication check failed!" | |
# ======================== | |
# 🚀 Start EAS Build | |
# ======================== | |
- name: 🚀 Start EAS Build | |
id: build | |
run: | | |
echo "🚀 Starting EAS build..." | |
sudo apt-get install -y jq # Install jq for JSON parsing | |
# Start the build and capture JSON output | |
BUILD_JSON=$(npx eas build -p android --profile production --non-interactive --json) | |
echo "📄 Raw build output: $BUILD_JSON" | |
# Extract BUILD_ID from JSON output | |
BUILD_ID=$(echo "$BUILD_JSON" | jq -r '.[0].id') | |
if [[ -z "$BUILD_ID" || "$BUILD_ID" == "null" ]]; then | |
echo "❌ Error: Failed to retrieve BUILD_ID!" | |
exit 1 | |
fi | |
echo "✅ EAS Build started with ID: $BUILD_ID" | |
echo "BUILD_ID=$BUILD_ID" >> $GITHUB_ENV | |
echo "BUILD_ID=$BUILD_ID" >> $GITHUB_OUTPUT | |
env: | |
EXPO_TOKEN: ${{ secrets.EXPO_TOKEN }} | |
download-apk: | |
name: 📥 Download APK | |
runs-on: ubuntu-latest | |
needs: build-android | |
outputs: | |
apk_path: ${{ steps.download.outputs.APK_PATH }} | |
steps: | |
# ======================== | |
# 🔍 Repository Setup | |
# ======================== | |
- name: 🔍 Checkout repository | |
uses: actions/checkout@v4 | |
# ======================== | |
# ⚙️ Environment Setup | |
# ======================== | |
- name: ⚙️ Setup Node.js | |
uses: actions/setup-node@v4 | |
with: | |
node-version: 20.x | |
- name: 🛠️ Install Required Tools | |
run: | | |
npm install -g eas-cli@latest | |
sudo apt-get update | |
sudo apt-get install -y jq curl # Install tools for JSON parsing and file downloads | |
- name: 📦 Install Project Dependencies (Including dotenv) | |
run: npm ci | |
# ======================== | |
# 🔍 Verify Project Files | |
# ======================== | |
- name: 🔍 Verify Project Files | |
run: | | |
echo "📂 Current directory contents:" | |
ls -la | |
echo "🔍 Checking for eas.json:" | |
cat eas.json || echo "❌ No eas.json found!" | |
# ======================== | |
# ⏳ Wait for EAS Build to Complete | |
# ======================== | |
- name: ⏳ Wait for EAS Build to Complete | |
run: | | |
cd $GITHUB_WORKSPACE | |
BUILD_ID=${{ needs.build-android.outputs.build_id }} | |
echo "🔍 Starting build monitoring for BUILD_ID: $BUILD_ID" | |
# Initial check without JSON for better error visibility | |
npx eas build:view $BUILD_ID || true | |
RETRY_COUNT=0 | |
MAX_RETRIES=120 | |
SLEEP_TIME=30 | |
while [[ $RETRY_COUNT -lt $MAX_RETRIES ]]; do | |
echo -e "\n=== Attempt $((RETRY_COUNT+1))/$MAX_RETRIES ===" | |
# Fetch build status in JSON format | |
BUILD_STATUS_JSON=$(npx eas build:view --json $BUILD_ID) | |
echo "📄 Raw API response: $BUILD_STATUS_JSON" | |
# Validate JSON and check for empty response | |
if ! echo "$BUILD_STATUS_JSON" | jq empty >/dev/null 2>&1 || [[ -z "$BUILD_STATUS_JSON" ]]; then | |
echo "❌ Error: Invalid or empty response from EAS API! Retrying..." | |
RETRY_COUNT=$((RETRY_COUNT+1)) | |
sleep $SLEEP_TIME | |
continue | |
fi | |
BUILD_STATUS=$(echo "$BUILD_STATUS_JSON" | jq -r '.status') | |
ERROR_MESSAGE=$(echo "$BUILD_STATUS_JSON" | jq -r '.error.message // empty') | |
echo "🔍 Parsed status: $BUILD_STATUS" | |
[[ -n "$ERROR_MESSAGE" ]] && echo "❌ Error message: $ERROR_MESSAGE" | |
case $BUILD_STATUS in | |
"FINISHED") | |
APK_URL=$(echo "$BUILD_STATUS_JSON" | jq -r '.artifacts.buildUrl') | |
if [[ -z "$APK_URL" || "$APK_URL" == "null" ]]; then | |
echo "❌ Error: Successful build but no APK URL found!" | |
exit 1 | |
fi | |
echo "✅ APK_URL=$APK_URL" >> $GITHUB_ENV | |
exit 0 | |
;; | |
"ERRORED"|"CANCELLED") | |
echo "❌ Build failed! Error details:" | |
echo "$BUILD_STATUS_JSON" | jq . | |
exit 1 | |
;; | |
"NEW"|"IN_QUE"|"IN_PROGRESS"|"PENDING") | |
echo "⏳ Build is still in progress..." | |
;; | |
*) | |
echo "❌ Unknown build status: $BUILD_STATUS" | |
exit 1 | |
;; | |
esac | |
RETRY_COUNT=$((RETRY_COUNT+1)) | |
sleep $SLEEP_TIME | |
done | |
echo "❌ Error: Build did not complete within the expected time!" | |
exit 1 | |
env: | |
EXPO_TOKEN: ${{ secrets.EXPO_TOKEN }} | |
# ======================== | |
# 📥 Download APK | |
# ======================== | |
- name: 📥 Download APK | |
id: download | |
run: | | |
echo "📥 Downloading APK from: $APK_URL" | |
curl -L "$APK_URL" -o app-release.apk | |
ls -lh app-release.apk | |
echo "✅ APK_PATH=app-release.apk" >> $GITHUB_OUTPUT | |
echo "📦 Downloaded APK size: $(du -h app-release.apk | cut -f1)" | |
# ======================== | |
# 📤 Upload APK as Artifact | |
# ======================== | |
- name: 📤 Upload APK as artifact | |
uses: actions/upload-artifact@v4 | |
with: | |
name: android-apk | |
path: app-release.apk | |
generate-changelog: | |
name: 📝 Generate Changelog | |
runs-on: ubuntu-latest | |
needs: build-android | |
outputs: | |
changelog: ${{ steps.changelog.outputs.CHANGELOG }} | |
steps: | |
# ======================== | |
# 🔍 Repository Setup | |
# ======================== | |
- name: 🔍 Checkout repository | |
uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 # Fetch full history for changelog generation | |
# ======================== | |
# 📝 Generate Changelog | |
# ======================== | |
- name: 📝 Generate Changelog | |
id: changelog | |
run: | | |
echo "📝 Generating changelog..." | |
# Generate formatted changelog (last 10 commits) | |
CHANGELOG=$(git log --pretty=format:"- %s (%h) by %an" -n 10) | |
echo "📄 Changelog content:" | |
echo "$CHANGELOG" | |
# Set as an output using the proper multiline format | |
echo "CHANGELOG<<EOF" >> $GITHUB_ENV | |
echo "$CHANGELOG" >> $GITHUB_ENV | |
echo "EOF" >> $GITHUB_ENV | |
# Save to a file as well | |
echo "$CHANGELOG" > changelog.txt | |
shell: bash | |
# ======================== | |
# 📤 Upload Changelog as Artifact | |
# ======================== | |
- name: 📤 Upload Changelog as artifact | |
uses: actions/upload-artifact@v4 | |
with: | |
name: changelog | |
path: changelog.txt | |
create-release: | |
name: 🚀 Create GitHub Release | |
runs-on: ubuntu-latest | |
needs: [download-apk, generate-changelog] | |
steps: | |
# ======================== | |
# 📥 Download Artifacts | |
# ======================== | |
- name: 📥 Download APK artifact | |
uses: actions/download-artifact@v4 | |
with: | |
name: android-apk | |
- name: 📥 Download Changelog artifact | |
uses: actions/download-artifact@v4 | |
with: | |
name: changelog | |
# ======================== | |
# 🚀 Create GitHub Release | |
# ======================== | |
- name: 🚀 Create GitHub Release | |
uses: softprops/action-gh-release@v2 | |
with: | |
tag_name: v1.0.${{ github.run_number }} | |
name: Release v1.0.${{ github.run_number }} | |
body_path: changelog.txt | |
draft: false | |
prerelease: false | |
files: app-release.apk |