Skip to content

Merge pull request #32 from Rahul5430/dependabot/npm_and_yarn/minor-a… #91

Merge pull request #32 from Rahul5430/dependabot/npm_and_yarn/minor-a…

Merge pull request #32 from Rahul5430/dependabot/npm_and_yarn/minor-a… #91

Workflow file for this run

name: Android Build
on:
workflow_run:
workflows: ["Checks"]
types: [completed]
push:
branches: [main]
paths:
- "android/**"
- "src/**"
- "package.json"
- "package-lock.json"
- "metro.config.js"
- "babel.config.js"
- "tsconfig.json"
- "jest.config.js"
pull_request:
branches: [main]
paths:
- "android/**"
- "src/**"
- "package.json"
- "package-lock.json"
- "metro.config.js"
- "babel.config.js"
- "tsconfig.json"
- "jest.config.js"
permissions:
contents: write
jobs:
build-android:
if: ${{ github.event.workflow_run.conclusion == 'success' }}
runs-on: macos-15
concurrency:
group: android-${{ github.event.workflow_run.head_branch || github.ref }}
cancel-in-progress: true
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0 # Fetch full history
- uses: actions/setup-node@v6
with:
node-version: 20
cache: "npm"
- name: Setup Java 17
uses: actions/setup-java@v5
with:
distribution: "temurin"
java-version: "17"
- name: Setup Android SDK
uses: android-actions/setup-android@v3
- name: Setup Gradle Build Action
uses: gradle/gradle-build-action@v3
with:
gradle-version: wrapper
cache-read-only: false
- name: Cache Metro bundler
uses: actions/cache@v5
with:
path: |
~/.cache/metro
node_modules/.cache
key: ${{ runner.os }}-metro-${{ hashFiles('package-lock.json', 'metro.config.js', 'babel.config.js') }}
restore-keys: |
${{ runner.os }}-metro-
- name: Cache node_modules
uses: actions/cache@v5
with:
path: node_modules
key: ${{ runner.os }}-node-modules-${{ hashFiles('package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-modules-
- name: Install Node dependencies
run: npm ci
- name: Build Android debug APK
run: |
cd android
echo "Gradle version:"
./gradlew --version
echo "Building APK with CI optimizations..."
./gradlew assembleDebug --info --parallel --build-cache -Dorg.gradle.caching=true -Dorg.gradle.parallel=true -Dorg.gradle.configureondemand=true
- name: Show APK files
run: |
echo "Checking for APK files..."
find android/app/build/outputs -name "*.apk" -type f
ls -la android/app/build/outputs/apk/debug/ || echo "Debug directory not found"
ls -la android/app/build/outputs/ || echo "Outputs directory not found"
- name: Upload Android debug APK
uses: actions/upload-artifact@v6
with:
name: android-debug-apk
path: |
android/app/build/outputs/apk/debug/app-debug.apk
android/app/build/outputs/apk/debug/output-metadata.json
if-no-files-found: error
- name: Upload APK to Release (latest)
if: ${{ github.event.workflow_run.head_branch == 'main' }}
uses: softprops/action-gh-release@v2
with:
tag_name: android-debug-latest
name: Android Debug Latest
draft: false
prerelease: false
files: |
android/app/build/outputs/apk/debug/app-debug.apk
android/app/build/outputs/apk/debug/output-metadata.json
token: ${{ github.token }}
- name: Generate Job Summary
uses: actions/github-script@v8
with:
script: |
// Get artifact URLs
const artifacts = await github.rest.actions.listWorkflowRunArtifacts({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: context.runId
});
const apkArtifact = artifacts.data.artifacts.find(a => a.name === 'android-debug-apk');
const apkUrl = apkArtifact ?
`[Download APK](${apkArtifact.archive_download_url})` :
'Not available';
// Get APK file size
let apkSize = 'Unknown';
try {
const fs = require('fs');
const apkPath = 'android/app/build/outputs/apk/debug/app-debug.apk';
if (fs.existsSync(apkPath)) {
const stats = fs.statSync(apkPath);
apkSize = `${(stats.size / (1024 * 1024)).toFixed(1)} MB`;
}
} catch (e) {
console.log('Could not get APK size:', e.message);
}
// Get release URL if available
let releaseUrl = 'Not available';
if (context.payload.head_branch === 'main') {
releaseUrl = `[Latest Release](https://github.com/${context.repo.owner}/${context.repo.repo}/releases/download/android-debug-latest/app-debug.apk)`;
}
// Create summary
const summary = `# πŸ€– Android Build Summary
## Build Status
| Component | Status | Details |
|-----------|--------|---------|
| **Gradle Build** | βœ… | Debug APK built successfully |
| **APK Size** | βœ… | ${apkSize} |
| **Artifacts** | βœ… | Uploaded to GitHub Actions |
| **Release** | ${context.payload.head_branch === 'main' ? 'βœ…' : '⏭️'} | ${context.payload.head_branch === 'main' ? 'Updated latest release' : 'Skipped (not main branch)'} |
## Download Links
- πŸ“± **APK Artifact**: ${apkUrl}
- πŸš€ **Stable Release**: ${releaseUrl}
## Build Details
- **Build Type**: Debug
- **Target**: Android API 33+
- **Architecture**: armeabi-v7a, arm64-v8a, x86, x86_64
- **Gradle Cache**: Enabled
- **Parallel Build**: Enabled
---
*Generated by GitHub Actions*`;
// Set as job summary
core.summary
.addHeading('Android Build Summary')
.addTable([
[{data: 'Component', header: true}, {data: 'Status', header: true}, {data: 'Details', header: true}],
['Gradle Build', 'βœ…', 'Debug APK built successfully'],
['APK Size', 'βœ…', apkSize],
['Artifacts', 'βœ…', 'Uploaded to GitHub Actions'],
['Release', context.payload.head_branch === 'main' ? 'βœ…' : '⏭️', context.payload.head_branch === 'main' ? 'Updated latest release' : 'Skipped (not main branch)']
])
.addHeading('Download Links', 2)
.addRaw('')
.addRaw(`- πŸ“± **APK Artifact**: ${apkUrl}\n`)
.addRaw(`- πŸš€ **Stable Release**: ${releaseUrl}\n`)
.addHeading('Build Details', 2)
.addRaw('')
.addRaw(`- **Build Type**: Debug\n`)
.addRaw(`- **Target**: Android API 33+\n`)
.addRaw(`- **Architecture**: armeabi-v7a, arm64-v8a, x86, x86_64\n`)
.addRaw(`- **Gradle Cache**: Enabled\n`)
.addRaw(`- **Parallel Build**: Enabled\n`)
.write();
// Optional: Slack/Discord notification (commented out)
/*
// Uncomment and configure to enable Slack notifications
const slackWebhook = process.env.SLACK_WEBHOOK_URL;
if (slackWebhook) {
const slackMessage = {
text: `πŸ€– Android Build ${context.payload.head_branch === 'main' ? 'Success' : 'Success (PR)'}`,
attachments: [{
color: 'good',
fields: [
{ title: 'Repository', value: `${context.repo.owner}/${context.repo.repo}`, short: true },
{ title: 'Branch', value: context.payload.head_branch || 'main', short: true },
{ title: 'APK Size', value: apkSize, short: true },
{ title: 'Download', value: apkUrl, short: false }
]
}]
};
await fetch(slackWebhook, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(slackMessage)
});
}
*/