Skip to content
All posts
May 3, 20263 min read

Automating Android App Releases: From Code to Play Store in Minutes

Learn how to streamline your Android app deployment pipeline using GitHub Actions and Fastlane, eliminating manual steps and reducing release errors.

AndroidCI/CDAutomationKotlin
Share:

Manual Android app releases are slow, error-prone, and eat up valuable development time. By automating the entire process with GitHub Actions and Fastlane, you can deploy updates in minutes instead of hours—freeing you to focus on building features. As a solo developer managing 22+ apps, I’ve cut my release overhead by 80% using this exact workflow.

The pain points are clear: updating version codes, signing builds, uploading to Play Store—each step introduces potential failures. When I missed a version bump during a critical bug fix, it cost me 48 hours of app store review time. Automation solves this by creating a repeatable pipeline that handles versioning, signing, and deployment consistently.

Setting Up GitHub Actions Workflows

GitHub Actions runs your automation directly in your repository. For Android releases, we’ll create a workflow that triggers on push to your release branch. Start by creating

code
.github/workflows/release.yml
:

yaml
name: Android Release Pipeline

on:
  push:
    branches: [ "main" ]
  workflow_dispatch:

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        
      - name: Setup JDK 17
        uses: actions/setup-java@v4
        with:
          java-version: '17'
          distribution: 'temurin'
          
      - name: Cache Gradle dependencies
        uses: actions/cache@v4
        with:
          path: |
            ~/.gradle/caches
            ~/.gradle/wrapper
          key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
          restore-keys: |
            ${{ runner.os }}-gradle-
            
      - name: Grant gradlew execute permission
        run: chmod +x gradlew
        
      - name: Build release APK
        run: ./gradlew assembleRelease
        
      - name: Setup Ruby
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: 3.1
          bundler-cache: true
          
      - name: Run Fastlane release
        run: bundle exec fastlane deploy
        env:
          GOOGLE_PLAY_JSON_KEY: ${{ secrets.GOOGLE_PLAY_JSON_KEY }}
          KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
          KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
          KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}

This workflow handles environment setup, dependency caching, and executes Fastlane commands. The

code
env
section securely injects secrets needed for signing and Play Store uploads.

[!TIP] Add

code
workflow_dispatch
trigger to manually trigger releases from GitHub’s Actions tab—perfect for hotfixes when you can’t push to main.

Configuring Fastlane for Android Deployment

Fastlane transforms complex deployment tasks into simple Ruby commands. Initialize it in your project root with:

bash
fastlane init

Then edit the generated

code
Fastfile
. Here’s a production-ready configuration:

ruby
default_platform(:android)

platform :android do
  desc "Deploy new version to Play Store"
  lane :deploy do
    # Automatically increment version code
    increment_version_code(
      gradle_file_path: "app/build.gradle",
      bump_type: "patch"
    )
    
    # Update version name (e.g., 1.0.0)
    gradle(
      task: "bumpVersionName",
      gradle_command: "bumpVersionName"
    )
    
    # Build signed APK
    gradle(
      task: "assemble",
      build_type: "Release",
      flags: "-x bundleRelease"
    )
    
    # Sign APK with keystore
    sign_apk(
      apk_path: "app/build/outputs/apk/release/app-release-unsigned.apk",
      keystore_path: "keystore.jks",
      keystore_password: ENV["KEYSTORE_PASSWORD"],
      key_alias: ENV["KEY_ALIAS"],
      key_password: ENV["KEY_PASSWORD"]
    )
    
    # Upload to Play Store
    upload_to_play_store(
      track: "production",
      release_status: "draft",
      aab: "app/build/outputs/bundle/release/app-release.aab",
      package_name: "com.your.package.name",
      json_key_data: ENV["GOOGLE_PLAY_JSON_KEY"]
    )
    
    # Commit version bump
    git_commit(
      path: ["app/build.gradle"],
      message: "Bump version to #{gradle_task("printVersionName")}"
    )
    
    push_to_git_remote
  end
end

This lane handles version management, signing, and Play Store uploads. The

code
git_commit
step ensures version bumps are tracked in version control.

[!WARNING] Never commit keystore files to version control. Store them as GitHub secrets instead—exposing keys can compromise your app’s security.

Managing Credentials and Versioning

Secure credential management is non-negotiable. Here’s how to handle sensitive data:

Credential TypeStorage MethodAccess in Fastlane
KeystoreGitHub Secrets
code
ENV["KEYSTORE_PASSWORD"]
Play API KeyGitHub Secrets
code
ENV["GOOGLE_PLAY_JSON_KEY"]
Git TokenGitHub Secrets
code
ENV["GIT_TOKEN"]

For version management, automate incrementation based on semantic versioning:

ruby
lane :bump_version_name do
  current_version = gradle_task("printVersionName")
  new_version = semantic_bump(current_version, bump_type: "patch")
  replace_in_file(
    path: "app/build.gradle",
    replace: "versionName '#{current_version}'",
    with: "versionName '#{new_version}'"
  )
end

[!NOTE] Always test your workflow on the internal or beta track before deploying to production. This catches signing issues or build failures before affecting users.

Key Takeaways

  • Automate repetitive release tasks with GitHub Actions and Fastlane to reduce human error and cut deployment time from hours to minutes.
  • Securely manage credentials using GitHub secrets—never commit keystore files or API keys to version control.
  • Implement automated version bumping and git commits to maintain accurate version history and ensure releases are traceable.

This workflow has transformed my release process. I can now push a commit and have a new live version ready for review in under 20 minutes—no more manual signing, no more forgotten version bumps, no more last-minute stress.

Share:
S

Sudarshan Chaudhari

AI Systems Builder / Product Engineer

Bangkok, Thailand

Solo Android developer with 13+ years in QA, building Android apps, AI automation systems, and developer tools at SudarshanTechLabs.

Stay updated

Get new posts on Android, Kotlin, and solo dev straight to your inbox.

Newsletter preferences

Related Apps

MyFamilyTracker

Real-time family location sharing — Firebase Realtime DB for sub-second propagation, WorkManager + ForegroundService for OS-compliant background collection, geofencing via Google Maps API.

Building something? Available for Android dev and QA consulting.

Work with me

Comments — powered by Giscus

Apps tagged with this