Welcome to the NativeBridge CI/CD documentation! This directory contains all the guides you need to understand and use the automated build and deployment pipeline.
QUICKSTART_CICD.md - Start here!
- Quick overview of the release process
- How to create releases with one command
- Testing and troubleshooting tips
- Perfect for: First-time users
NATIVEBRIDGE_CICD.md - Project-specific guide
- How NativeBridge is integrated into THIS project
- Setup instructions for GitHub Secrets
- Configuration options
- Troubleshooting specific to this pipeline
- Perfect for: Team members working on this project
NATIVEBRIDGE_API_INTEGRATION.md - General guide
- Integrate NativeBridge into ANY CI/CD platform
- Examples for 8+ platforms (GitHub Actions, Jenkins, GitLab, etc.)
- Reusable code snippets
- Best practices
- Perfect for: Using NativeBridge in other projects
application_upload_api.md - Complete API reference
- Full API documentation
- All parameters explained
- Response formats
- Example scenarios
- Perfect for: Deep dive into the API
SECRETS_SETUP.md - GitHub Secrets guide
- How to configure secrets
- Security best practices
- Production vs development setup
- Perfect for: Setting up GitHub Secrets
RELEASE_AUTOMATION.md - Release script guide
- How the
release.shscript works - Usage examples
- Troubleshooting
- Perfect for: Understanding the release process
NativeBridge is a revolutionary cloud platform that lets you run Android apps instantly in your browser without any installation:
- ☁️ Cloud Emulators - Test on virtual Android devices instantly in your browser
- 📱 Real Physical Devices - Run on actual Android hardware in the cloud
- 🚀 One-Click Launch - No setup, no downloads, just click and test
- 🌐 Universal Access - Works on Windows, Mac, Linux, even mobile browsers
- 🔗 Shareable Magic Links - Send links to anyone for instant testing
- 🎮 Auto-Start Sessions - Automatically start test sessions after upload
- 📧 Email Notifications - Automatic notifications when new versions are uploaded
- 💬 Slack Integration - Get notified in Slack when sessions are ready
- 🔒 Access Control - Public or private apps with user allowlists
- Upload APK via API (automated in CI/CD)
- Get Magic Link instantly
- Share Link with your team
- Run App in cloud emulator or real device
- Test Anywhere - no installation required!
- Log in to NativeBridge
- Go to API Keys: https://nativebridge.io/dashboard/api-keys
- Click Generate New API Key or Create API Key
- Copy the API key
- Go to your repository → Settings → Secrets and variables → Actions
- Click New repository secret
- Add:
- Name:
NATIVEBRIDGE_API_KEY - Value: Your API key from Step 1
- Name:
- Click Add secret
For session notifications:
- Create a Slack incoming webhook at https://api.slack.com/messaging/webhooks
- Go to Settings → Secrets and variables → Actions
- Add:
- Name:
SLACK_WEBHOOK_URL - Value: Your Slack webhook URL
- Name:
# Basic release
./scripts/release.sh 1.0.0
# With auto-start session
./scripts/release.sh 1.0.0 --start-session
# Custom session settings
./scripts/release.sh 1.0.0 --start-session \
--device-id your-device-id \
--session-validity 180That's it! The pipeline will:
- ✅ Build your APK
- ✅ Upload to NativeBridge
- ✅ Generate magic link for cloud testing
- ✅ [NEW] Auto-start test session (if
--start-sessionused) - ✅ [NEW] Send Slack notification (if configured)
- ✅ Create GitHub Release with session URL
- ✅ Send email notifications
.github/
├── workflows/
│ ├── release-build.yml # Main CI/CD workflow
│ └── application_upload_api.md # Complete API documentation
│
├── NATIVEBRIDGE_CICD.md # Project integration guide
├── NATIVEBRIDGE_API_INTEGRATION.md # General CI/CD guide
├── SECRETS_SETUP.md # GitHub Secrets setup
└── README.md # This file
scripts/
├── release.sh # Automated release script
└── README.md # Release script documentation
QUICKSTART_CICD.md # Quick start guide
RELEASE_AUTOMATION.md # Release automation guide
BUILD_GUIDE.md # Build instructions
graph LR
A[Run release.sh] --> B[Bump Version]
B --> C[Git Commit & Tag]
C --> D[Push to GitHub]
D --> E[Trigger CI/CD]
E --> F[Build APK]
F --> G[Upload to NativeBridge]
G --> H[Create GitHub Release]
H --> I[Send Notifications]
-
Version Bumping
- Updates
package.json - Updates
android/app/build.gradle - Creates git commit
- Updates
-
Git Operations
- Creates annotated tag
- Pushes to GitHub
- Triggers workflow
-
Build Process
- Sets up environment
- Generates/decodes keystore
- Builds signed APK
- Fixes Kotlin compilation issues
-
NativeBridge Upload
- Uploads APK via API
- Parses response
- Extracts magic links and app ID
- Saves for later steps
-
Session Start (Optional)
- Starts test session on NativeBridge device
- Uses device ID and validity from tag
- Generates session URL
- Sends Slack notification (if configured)
-
GitHub Release
- Downloads APK artifact
- Creates release
- Includes NativeBridge cloud link
- Includes active session URL (if started)
- Attaches APK file
-
Notifications
- Email via NativeBridge (if enabled)
- Slack via webhook (if session started)
- GitHub notifications
- Build summaries with session info
| Secret | Required | Description |
|---|---|---|
NATIVEBRIDGE_API_KEY |
Yes | API key for NativeBridge uploads |
| Secret | Required | Description |
|---|---|---|
NATIVEBRIDGE_API_KEY |
Yes | API key for NativeBridge uploads |
ANDROID_KEYSTORE_BASE64 |
No | Base64-encoded release keystore |
ANDROID_KEYSTORE_PASSWORD |
No | Keystore password |
ANDROID_KEY_ALIAS |
No | Key alias in keystore |
ANDROID_KEY_PASSWORD |
No | Key password |
| Secret | Required | Description |
|---|---|---|
SLACK_WEBHOOK_URL |
No | Slack webhook for session notifications |
Note: If keystore secrets are not provided, the workflow generates a temporary keystore for CI builds.
# Bump to version 1.0.0 and create release
./scripts/release.sh 1.0.0# Release with automatic session start (2 min default)
./scripts/release.sh 1.0.0 --start-session
# Custom session duration (3 minutes)
./scripts/release.sh 1.0.0 --start-session --session-validity 180
# Specific device with custom duration
./scripts/release.sh 1.0.0 --start-session \
--device-id 67a642531a4aa535498192f8 \
--session-validity 240
# Quick 30-second smoke test
./scripts/release.sh 1.0.0 --start-session --session-validity 30| Parameter | Description | Default | Valid Range |
|---|---|---|---|
--start-session |
Enable auto-start session | disabled | - |
--device-id <id> |
NativeBridge device ID | 67a642531a4aa535498192f8 |
Any valid ID |
--session-validity <s> |
Session duration (seconds) | 120 |
30-300 |
# See what would happen without actually releasing
./scripts/release.sh 1.0.0 --dry-run
# Test with session options
./scripts/release.sh 1.0.0 --start-session --dry-run# Standard release
npm run release 1.0.0
# Dry run
npm run release:dry 1.0.0# Build debug APK locally
cd android && ./gradlew assembleDebug
# Build release APK locally
cd android && ./gradlew assembleRelease# Make app private for internal testing
-F "accessType=private" \
-F "allowedUsers=dev@company.com" \
-F "allowedUsers=qa@company.com"# Send notifications to QA team
-F "sendNotification=true" \
-F "notificationEmails=qa@company.com" \
-F "notificationEmails=product@company.com"# Create separate app entry for staging
-F "versionAction=create_new_app"Problem: "NATIVEBRIDGE_API_KEY secret not configured"
Solution:
- Verify secret is added to GitHub Secrets
- Check secret name is exactly
NATIVEBRIDGE_API_KEY - Re-run the workflow
Problem: Kotlin compilation errors
Solution:
- Workflow includes automatic patches
- If still fails, check Android Gradle plugin compatibility
- Review workflow logs for specific errors
Problem: API returns 401 Unauthorized
Solution:
- Verify API key is correct
- Check for extra spaces/newlines in secret
- Regenerate API key if needed
Problem: API returns 429 Rate Limit
Solution:
- Wait 60 seconds before retrying
- NativeBridge allows 10 requests/minute
- Website: https://nativebridge.io
- Dashboard: https://nativebridge.io/dashboard
- API Keys: https://nativebridge.io/dashboard/api-keys
- Documentation: https://docs.nativebridge.io
- GitHub Actions Docs: https://docs.github.com/actions
- This Project's Workflow: workflows/release-build.yml
- Quick Start: QUICKSTART_CICD.md
- Check NATIVEBRIDGE_CICD.md troubleshooting section
- Review GitHub Actions logs
- Check this README
- Read workflows/application_upload_api.md
- Contact: api-support@nativebridge.io
- Dashboard: https://nativebridge.io/dashboard
- See NATIVEBRIDGE_API_INTEGRATION.md
- Examples for your CI/CD platform
- Best practices guide
- ✅ One Command Release -
./scripts/release.sh 1.0.0 - ✅ Automatic Versioning - No manual file editing
- ✅ Signed APKs - Production-ready builds
- ✅ Cloud Testing - Test without installing
- ✅ Instant Access - Click magic link to test
- ✅ No Installation - Run in browser
- ✅ Real Devices - Test on actual hardware
- ✅ Email Notifications - Know when new versions are ready
- ✅ Easy Sharing - Send links to stakeholders
- ✅ Version History - All versions accessible
- ✅ Quick Demos - No setup for demonstrations
- ✅ Cross-Platform - Share with anyone, any device
The pipeline can automatically start test sessions on one or more NativeBridge devices after uploading your Android app. This is controlled via command-line parameters when creating a release.
New in v1.3.0: Support for multiple sessions on different devices using comma-separated device IDs.
💡 Need Device IDs? See How to Get Device IDs section below to find available devices using the NativeBridge API.
- Run release script with
--start-sessionflag - Session config is embedded in git tag message
- CI/CD workflow parses the config from tag
- After APK upload, session API is called
- Session URL is generated and included in release
# Enable session with defaults
./scripts/release.sh 1.0.0 --start-session
# Customize device and duration
./scripts/release.sh 1.0.0 --start-session \
--device-id your-device-id \
--session-validity 180--start-session- Enable automatic session start--device-id <ids>- Device ID(s) - single or comma-separated for multiple (default:67a642531a4aa535498192f8)--session-validity <seconds>- Duration in seconds (default: 120, range: 30-300)
Examples:
# Single device
--device-id 682dba7233c7787633294734
# Multiple devices (starts 3 sessions)
--device-id 682dba7233c7787633294734,685bf304ec144f98463c221d,69581275499de2e1a23c44f9When a session is started, you'll find the URL in:
- ✅ GitHub Actions summary (under "🚀 Active Session")
- ✅ GitHub Release notes (under "🎮 Active Session")
- ✅ Slack notification (if webhook configured)
To receive Slack notifications when sessions start:
- Create webhook at https://api.slack.com/messaging/webhooks
- Add
SLACK_WEBHOOK_URLto GitHub Secrets - Use
--start-sessionwhen creating release
You'll receive a formatted message with:
- App version and session ID
- Device ID and validity
- Clickable session URL
- Link to GitHub Actions workflow
Quick smoke test (30 seconds):
./scripts/release.sh 1.0.1 --start-session --session-validity 30Standard testing (2 minutes):
./scripts/release.sh 1.0.1 --start-sessionExtended manual testing (5 minutes):
./scripts/release.sh 1.0.1 --start-session --session-validity 300Specific test device:
./scripts/release.sh 1.0.1 --start-session --device-id abc123The session is created using the NativeBridge Session API:
- Endpoint:
POST /v1/device/session - Parameters: deviceType, deviceId, appId, region, executionValidity
- Response: sessionId, sessionUrl
For complete API documentation, see NATIVEBRIDGE_API_INTEGRATION.md.
The pipeline supports building two variants simultaneously - production and beta builds. This allows you to:
- Upload both production and beta apps to NativeBridge in a single trigger
- Start sessions on TWO different devices (one for prod, one for beta)
- Test both variants in parallel
- Get separate magic links and session URLs for each variant
- Run release script with
--betaflag - Beta configuration is embedded in git tag message
- CI/CD workflow builds/copies BOTH variants:
- Production:
NativeBridge-v1.0.0.apk - Beta:
NativeBridge-v1.0.0-beta.apk
- Production:
- Both APKs are uploaded to NativeBridge
- Sessions are started on separate devices (if
--start-sessionis used) - Both variants are included in GitHub Release
# Basic beta + production build
./scripts/release.sh 1.0.0 --beta
# Beta build with single session on each variant
./scripts/release.sh 1.0.0 --beta --start-session \
--device-id prod-device-id \
--beta-device-id beta-device-id
# MULTIPLE SESSIONS: 1 prod session + 2 beta sessions
./scripts/release.sh 1.0.0 --beta --start-session \
--device-id 682dba7233c7787633294734 \
--beta-device-id 67a6424f1a4aa535498192f7,67a642531a4aa535498192f8
# MULTIPLE SESSIONS: 2 prod sessions + 2 beta sessions
./scripts/release.sh 1.0.0 --beta --start-session \
--device-id dev1-id,dev2-id \
--beta-device-id beta-dev1-id,beta-dev2-id \
--session-validity 240
# Production only with 3 sessions on different devices
./scripts/release.sh 1.0.0 --start-session \
--device-id device1,device2,device3New in v1.3.0: You can now start sessions on multiple devices by providing comma-separated device IDs.
Examples:
--device-id dev1,dev2- Starts 2 production sessions--beta-device-id beta1,beta2,beta3- Starts 3 beta sessions- Mix and match: 1 prod + 2 beta, or 3 prod + 1 beta, etc.
Use Cases:
- Test on multiple Android versions simultaneously
- QA team: parallel testing on different devices
- Region testing: different device configurations
- Performance comparison across devices
To find available devices for testing, use the NativeBridge Devices API:
API Endpoint:
curl -X 'GET' \
'https://api.nativebridge.io/v1/devices?device_type=android&emulated=false' \
-H 'accept: application/json' \
-H 'X-Api-Key: YOUR_API_KEY'Response Example:
{
"data": [
{
"id": "682dba7233c7787633294734",
"type": "android",
"osVersion": "14",
"modelName": "Samsung Galaxy S22 Ultra",
"isEmulator": false,
"deviceOwner": "shared",
"userPlan": "all"
},
{
"id": "685bf304ec144f98463c221d",
"type": "android",
"osVersion": "13",
"modelName": "Pixel 5",
"isEmulator": false,
"deviceOwner": "shared",
"userPlan": "free"
},
{
"id": "68d153469457da61a16488b9",
"type": "android",
"osVersion": "15",
"modelName": "Motorola G05",
"isEmulator": false,
"deviceOwner": "aspora.com",
"userPlan": "free"
},
{
"id": "69581275499de2e1a23c44f9",
"type": "android",
"osVersion": "14",
"modelName": "Xiaomi Poco C75",
"isEmulator": false,
"deviceOwner": "shared",
"userPlan": "free"
},
{
"id": "695a9249f6a40ebd23e29565",
"type": "android",
"osVersion": "13",
"modelName": "Realme 3 Pro",
"isEmulator": false,
"deviceOwner": "shared",
"userPlan": "free"
}
]
}Understanding the Response Fields:
id- Device ID (use this in--device-idparameter)type- Device platform (androidorios)osVersion- Operating system version (e.g., "13", "14", "15")modelName- Device model (e.g., "Samsung Galaxy S22 Ultra", "Pixel 5")isEmulator-truefor virtual devices,falsefor real physical devicesdeviceOwner- Important:"shared"- Public device available to all users"aspora.com","example.com", etc. - Dedicated device reserved for specific organization (uses domain part of company email)
userPlan- Access level ("free","all", etc.)
Query Parameters:
device_type- Filter by device type (androidorios)emulated- Filter by emulator status (truefor emulators,falsefor real devices)
How to Use Device IDs:
-
List available devices:
curl -X GET 'https://api.nativebridge.io/v1/devices?device_type=android&emulated=false' \ -H 'X-Api-Key: YOUR_API_KEY'
-
Copy device IDs from the response (the
idfield) -
Use them in your release:
# Single device ./scripts/release.sh 1.0.0 --start-session \ --device-id 682dba7233c7787633294734 # Multiple devices (comma-separated) ./scripts/release.sh 1.0.0 --start-session \ --device-id 682dba7233c7787633294734,685bf304ec144f98463c221d,69581275499de2e1a23c44f9
Selecting Devices by Criteria:
-
Test on different Android versions:
- Android 15:
68d153469457da61a16488b9(Motorola G05) - Dedicated to aspora.com - Android 14:
682dba7233c7787633294734(Samsung S22 Ultra) - Shared - Android 13:
685bf304ec144f98463c221d(Pixel 5) - Shared
- Android 15:
-
Test on different manufacturers:
- Samsung:
682dba7233c7787633294734(Shared) - Google Pixel:
685bf304ec144f98463c221d(Shared) - Motorola:
68d153469457da61a16488b9(Dedicated to aspora.com) - Xiaomi:
69581275499de2e1a23c44f9(Shared) - Realme:
695a9249f6a40ebd23e29565(Shared)
- Samsung:
-
Device Ownership:
- Shared Devices (
deviceOwner: "shared"): Available to all users, may have queue times - Dedicated Devices (
deviceOwner: "aspora.com","yourcompany.com", etc.): Reserved for specific organization (matches email domain), typically faster access
- Shared Devices (
Example - Cross-Version Testing:
# Test on Android 13, 14, and 15 simultaneously
# Using shared devices for broader compatibility testing
./scripts/release.sh 1.0.0 --start-session \
--device-id 695a9249f6a40ebd23e29565,682dba7233c7787633294734,685bf304ec144f98463c221dExample - Using Dedicated Devices:
# If you have dedicated devices (deviceOwner matches your organization)
# These typically provide faster, exclusive access
./scripts/release.sh 1.0.0 --start-session \
--device-id 68d153469457da61a16488b9💡 Pro Tips:
-
Shared vs Dedicated Devices:
- Use shared devices for general testing and CI/CD pipelines
- Use dedicated devices (when available) for critical releases or performance testing
- Check the
deviceOwnerfield - if it matches your email domain (e.g., user@aspora.com →deviceOwner: "aspora.com"), you have priority access to that device
-
Choosing Multiple Devices:
- Mix shared and dedicated devices for cost-effective testing
- Example:
--device-id dedicated-device,shared-device1,shared-device2
-
Filter Dedicated Devices:
# Get all your organization's dedicated devices (replace with your email domain) # Example: if your email is john@aspora.com, search for "aspora.com" curl -X GET 'https://api.nativebridge.io/v1/devices?device_type=android&emulated=false' \ -H 'X-Api-Key: YOUR_API_KEY' | grep -A 6 '"deviceOwner": "aspora.com"'
--beta- Enable beta build (builds both production and beta)--device-id <ids>- Device IDs for production sessions (comma-separated for multiple)--beta-device-id <ids>- Device IDs for beta sessions (comma-separated for multiple, defaults to production device IDs)
Important: This workflow uses pre-built APKs instead of building from source. This approach:
- ✅ Completes in ~30 seconds (vs 8-10 minutes for actual builds)
- ✅ Enables fast testing of NativeBridge integration
- ✅ Avoids CI resource exhaustion
- ✅ Still provides full cloud testing capabilities
Pre-built APK Locations:
- Production:
builds/NativeBridge-Production.apk - Beta:
builds/NativeBridge-Beta.apk
To create a beta variant APK with a different package name:
# 1. Update package name in android/app/build.gradle
android {
defaultConfig {
applicationId "com.yourapp.beta" // Different from production
}
}
# 2. Build the APK
cd android && ./gradlew assembleRelease
# 3. Copy to builds folder
cp app/build/outputs/apk/release/app-release.apk \
../../builds/NativeBridge-Beta.apk
# 4. Commit the pre-built APK
git add ../../builds/NativeBridge-Beta.apk
git commit -m "Update pre-built beta APK"For actual multi-variant builds, use Product Flavors:
android {
flavorDimensions "version"
productFlavors {
production {
dimension "version"
applicationId "com.yourapp"
versionNameSuffix ""
}
beta {
dimension "version"
applicationId "com.yourapp.beta"
versionNameSuffix "-beta"
}
}
}Build both:
# Build production
./gradlew assembleProductionRelease
# Build beta
./gradlew assembleBetaRelease
# Copy to builds folder
cp app/build/outputs/apk/production/release/app-production-release.apk \
../../builds/NativeBridge-Production.apk
cp app/build/outputs/apk/beta/release/app-beta-release.apk \
../../builds/NativeBridge-Beta.apkWhen you use --beta, the pipeline creates:
Artifacts:
NativeBridge-v1.0.0.apk- Production APKNativeBridge-v1.0.0-beta.apk- Beta APKNativeBridge-iOS-v1.0.0.app.zip- iOS app (unchanged)
NativeBridge Uploads:
- Production app with magic link and versioned link
- Beta app with separate magic link and versioned link
Sessions (if --start-session used):
- Multiple production sessions (one per device ID in
--device-id) - Multiple beta sessions (one per device ID in
--beta-device-id) - Example:
--device-id d1,d2 --beta-device-id b1,b2,b3creates 2 prod + 3 beta sessions
Slack Notifications (if configured):
- Production session notification
- Beta session notification (separate message)
Testing new features before production:
# Beta includes experimental features, production is stable
./scripts/release.sh 1.5.0 --beta --start-session \
--device-id stable-device \
--beta-device-id test-deviceDifferent backend environments:
# Production points to prod API, beta points to staging API
./scripts/release.sh 2.0.0 --beta --start-sessionQA testing on multiple devices:
# QA team testing on 3 devices per variant (6 sessions total!)
./scripts/release.sh 1.2.3 --beta --start-session \
--device-id qa-android10,qa-android11,qa-android12 \
--beta-device-id qa-tablet1,qa-tablet2,qa-phone1 \
--session-validity 300Load testing / Performance comparison:
# Test production on 5 different device configurations
./scripts/release.sh 1.3.0 --start-session \
--device-id low-end,mid-range,high-end,tablet,foldableAfter release, you'll find beta variant info in:
GitHub Release Notes:
- "🧪 Android (Beta): Launch Beta in NativeBridge Cloud" link
- "🧪 Active Session - Beta" section with session URL
- Download link for
NativeBridge-v1.0.0-beta.apk
GitHub Actions Summary:
- "🧪 NativeBridge Upload - Beta" section
- "🧪 Active Session - Beta" section
Slack Notification:
- Separate "🧪 NativeBridge Beta Session Started" message
The beta feature is fully backward compatible:
- Without
--betaflag, only production build is created (works exactly as before) - Existing releases continue to work without changes
- Beta is opt-in via command-line flag
- Read QUICKSTART_CICD.md
- Get NativeBridge API key from https://nativebridge.io/dashboard/api-keys
- Add
NATIVEBRIDGE_API_KEYto GitHub Secrets - Run
./scripts/release.sh 1.0.0 --dry-runto test - Create first release:
./scripts/release.sh 1.0.0 - Check GitHub Actions for build status
- Test magic link in GitHub Release
- Share with team!
- (Optional) Create Slack incoming webhook
- (Optional) Add
SLACK_WEBHOOK_URLto GitHub Secrets - Test session with:
./scripts/release.sh 1.0.1 --start-session --dry-run - Create release with session:
./scripts/release.sh 1.0.1 --start-session - Check session URL in GitHub Release
- Verify Slack notification (if configured)
- Build your beta variant APK with different package name
- Save beta APK to
builds/NativeBridge-Beta.apk - Commit the pre-built beta APK to repository
- Test beta build:
./scripts/release.sh 1.0.2 --beta --dry-run - Create release with beta:
./scripts/release.sh 1.0.2 --beta - Verify both APKs in GitHub Release
- Test both magic links (production and beta)
- (Optional) Test with sessions:
./scripts/release.sh 1.0.3 --beta --start-session --beta-device-id <id>
Last Updated: 2026-01-13
Version: 1.0
Workflow File: workflows/release-build.yml