| name | android-fastlane-setup |
| description | Setup Fastlane for Play Store deployment with supply and screengrab |
| category | android |
| version | 1.0.0 |
| inputs | [object Object], [object Object] |
| outputs | Gemfile, fastlane/Appfile, fastlane/Fastfile, fastlane/Screengrabfile, fastlane/metadata/android/ structure |
| verify | bundle exec fastlane --version && bundle exec fastlane lanes |
Android Fastlane Setup
Configures Fastlane with supply for Play Store deployment and screengrab for screenshot automation.
Prerequisites
- Ruby 2.7+ installed
- Android project
- Play Store service account JSON
Inputs
| Input | Required | Default | Description |
|---|---|---|---|
| package_name | Yes | - | Android app package name (e.g., com.example.app) |
| service_account_path | Yes | - | Path to service account JSON file |
Process
Step 1: Check Ruby Installation
# Check Ruby version
ruby --version || echo "❌ Ruby not found. Please install Ruby 2.7+ first."
# Install Bundler if needed
gem install bundler --no-document
Step 2: Create Gemfile
Create ./Gemfile:
source "https://rubygems.org"
gem "fastlane"
gem "screengrab"
Step 3: Install Dependencies
bundle install
This will create Gemfile.lock and install all dependencies.
Step 4: Create Fastlane Directory Structure
mkdir -p fastlane
mkdir -p fastlane/metadata/android/en-US/images/phoneScreenshots
mkdir -p fastlane/metadata/android/en-US/images/sevenInchScreenshots
mkdir -p fastlane/metadata/android/en-US/images/tenInchScreenshots
mkdir -p fastlane/metadata/android/en-US/changelogs
Step 5: Create Appfile
Create ./fastlane/Appfile:
# Path to service account JSON for Play Store API
json_key_file(ENV['PLAY_STORE_SERVICE_ACCOUNT'] || "service-account.json")
# Your app's package name
package_name("{PACKAGE_NAME}")
Important: Replace {PACKAGE_NAME} with the actual package name.
Step 6: Create Fastfile
Create ./fastlane/Fastfile with comprehensive deployment lanes:
default_platform(:android)
platform :android do
# ============================================
# Build Lanes
# ============================================
desc "Build debug APK and test APK for screenshots"
lane :build_for_screenshots do
gradle(task: "clean")
gradle(task: "assembleDebug")
gradle(task: "assembleAndroidTest")
end
desc "Build release bundle"
lane :build_release do
gradle(task: "clean")
gradle(task: "bundleRelease")
end
# ============================================
# Screenshot Lane
# ============================================
desc "Capture screenshots for Play Store"
lane :screenshots do
build_for_screenshots
capture_android_screenshots
end
# ============================================
# Deployment Lanes
# ============================================
desc "Deploy to internal testing track"
lane :deploy_internal do
build_release
upload_to_play_store(
track: "internal",
release_status: "completed",
aab: "app/build/outputs/bundle/release/app-release.aab"
)
end
desc "Deploy to beta/closed testing track"
lane :deploy_beta do |options|
build_release
# Support staged rollout
rollout = options[:rollout] || 1.0
upload_to_play_store(
track: "beta",
release_status: rollout < 1.0 ? "inProgress" : "completed",
rollout: rollout < 1.0 ? rollout.to_s : nil,
aab: "app/build/outputs/bundle/release/app-release.aab"
)
end
desc "Deploy to production track"
lane :deploy_production do |options|
build_release
# Default to 10% staged rollout for safety
rollout = options[:rollout] || 0.1
upload_to_play_store(
track: "production",
release_status: rollout < 1.0 ? "inProgress" : "completed",
rollout: rollout < 1.0 ? rollout.to_s : nil,
aab: "app/build/outputs/bundle/release/app-release.aab"
)
end
desc "Increase production rollout percentage"
lane :increase_rollout do |options|
rollout = options[:rollout] || 0.5
upload_to_play_store(
track: "production",
release_status: rollout < 1.0 ? "inProgress" : "completed",
rollout: rollout < 1.0 ? rollout.to_s : nil,
skip_upload_aab: true,
skip_upload_metadata: true,
skip_upload_images: true,
skip_upload_screenshots: true
)
end
desc "Halt production rollout"
lane :halt_rollout do
upload_to_play_store(
track: "production",
release_status: "halted",
skip_upload_aab: true,
skip_upload_metadata: true,
skip_upload_images: true,
skip_upload_screenshots: true
)
end
# ============================================
# Metadata Lanes
# ============================================
desc "Upload metadata only (no APK/AAB)"
lane :upload_metadata do
upload_to_play_store(
skip_upload_aab: true,
skip_upload_apk: true
)
end
desc "Upload screenshots only"
lane :upload_screenshots do
upload_to_play_store(
skip_upload_aab: true,
skip_upload_apk: true,
skip_upload_metadata: true
)
end
# ============================================
# Version Management
# ============================================
desc "Get current version from version.properties"
lane :get_version do
version_file = "../version.properties"
if File.exist?(version_file)
props = {}
File.readlines(version_file).each do |line|
key, value = line.strip.split("=")
props[key] = value if key && value
end
UI.message("Version: #{props['VERSION_NAME']} (#{props['VERSION_CODE']})")
props
else
UI.user_error!("version.properties not found. Run /devtools:version-management first.")
end
end
# ============================================
# Full Release Workflows
# ============================================
desc "Full internal release: screenshots + build + deploy"
lane :release_internal do
screenshots
deploy_internal
end
desc "Full beta release: build + deploy"
lane :release_beta do |options|
deploy_beta(rollout: options[:rollout])
end
desc "Full production release: build + deploy with staged rollout"
lane :release_production do |options|
deploy_production(rollout: options[:rollout])
end
end
Step 7: Create Screengrabfile
Create ./fastlane/Screengrabfile:
# App package name
app_package_name("{PACKAGE_NAME}")
# Test instrumentation runner (AndroidX)
test_instrumentation_runner("androidx.test.runner.AndroidJUnitRunner")
# APK paths
app_apk_path("app/build/outputs/apk/debug/app-debug.apk")
tests_apk_path("app/build/outputs/apk/androidTest/debug/app-debug-androidTest.apk")
# Locales to capture (add more as needed)
locales(["en-US"])
# Output directory (matches supply's expected structure)
output_directory("fastlane/metadata/android")
# Clear old screenshots
clear_previous_screenshots(true)
# Use specific test class for screenshots
use_tests_in_classes(["{PACKAGE_NAME}.screenshots.ScreenshotTest"])
# Ending locale (restore device to this locale after)
ending_locale("en-US")
Important: Replace {PACKAGE_NAME} with the actual package name.
Step 8: Create Metadata Templates
Create initial metadata files:
fastlane/metadata/android/en-US/title.txt:
Your App Name
fastlane/metadata/android/en-US/short_description.txt:
Short description (max 80 characters)
fastlane/metadata/android/en-US/full_description.txt:
Full description of your app.
Features:
• Feature 1
• Feature 2
• Feature 3
For more information, visit our website.
fastlane/metadata/android/en-US/changelogs/default.txt:
• Bug fixes and performance improvements
fastlane/metadata/android/en-US/video.txt:
(Empty file - add YouTube URL if you have a promo video)
Step 9: Update .gitignore
Add to .gitignore:
# Fastlane
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots
fastlane/test_output
fastlane/readme.md
vendor/bundle
# Don't ignore metadata (we want to track store listing)
!fastlane/metadata/
Verification
MANDATORY: Run these commands:
# Verify Fastlane installed
bundle exec fastlane --version
# Verify lanes are available
bundle exec fastlane lanes
# Test service account connection (optional, requires service account JSON)
# bundle exec fastlane run validate_play_store_json_key
Expected output:
- Fastlane version number
- List of all lanes (deploy_internal, deploy_beta, etc.)
Completion Criteria
-
Gemfileexists with fastlane and screengrab -
bundle installsucceeds -
fastlane/Appfileconfigured with package name -
fastlane/Fastfilehas all deployment lanes -
fastlane/Screengrabfileconfigured - Metadata directory structure created
- Metadata template files created
-
.gitignoreupdated -
bundle exec fastlane lanesshows all lanes
Outputs
| Output | Location | Description |
|---|---|---|
| Gemfile | ./Gemfile | Ruby dependencies |
| Gemfile.lock | ./Gemfile.lock | Locked dependency versions |
| Appfile | ./fastlane/Appfile | Fastlane app configuration |
| Fastfile | ./fastlane/Fastfile | Fastlane lanes |
| Screengrabfile | ./fastlane/Screengrabfile | Screenshot configuration |
| Metadata | ./fastlane/metadata/android/en-US/ | Store listing metadata |
Troubleshooting
"Ruby not found"
Cause: Ruby not installed Fix: Install Ruby 2.7+ (use rbenv, rvm, or system package manager)
"bundle: command not found"
Cause: Bundler not installed
Fix: Run gem install bundler --no-document
"Fastlane lanes don't show"
Cause: Fastfile has syntax errors
Fix: Run bundle exec fastlane lanes and check for Ruby syntax errors
"Service account validation fails"
Cause: Invalid or missing service account JSON Fix: Ensure JSON file exists and has correct permissions in Play Console
Next Steps
After completing this skill:
- Run
/devtools:android-app-iconto generate app icon - Run
/devtools:android-screenshot-automationto setup screenshot capture - Run
/devtools:android-store-listingto create feature graphic and metadata - Run
/devtools:android-workflow-internalto setup GitHub Actions