All articles
Article 4 min read

Journey from Manual Releases to Automating Android App Deployments

In this post, we share our experience transforming a dual Android app release process into an automated one and the challenges we faced along the way, including debugging code and system limitations.

Introduction

Deploying mobile applications efficiently is crucial for development teams looking to streamline their processes. While many developers rely on manual methods for releasing apps, the journey to automating these releases can be fraught with unexpected challenges. In this article, we’ll explore our experience of automating the release of two Android applications—targeting staff and students—from a single Expo React Native codebase. Along the way, we’ll highlight common pitfalls and how to navigate them effectively.

The Setup: One Codebase for Two Apps

To begin our automation journey, we leveraged a single codebase for two separate Android applications. This approach not only simplified our development process but also allowed for shared components, reducing redundancy. However, it also meant we needed to establish clear differentiation between the two apps in their build configurations, which posed some initial challenges.

Transitioning to Automation

Manual APK Releases: A Tireless Task

Initially, we packaged and released our applications manually. This process involved generating APKs, uploading them to the Google Play Console, and handling user feedback as each version was released. While effective, this manual approach was time-consuming, prone to error, and often frustrating.

Enter Automation: The Vision

The goal was to transition to an automated process using GitHub Actions to manage builds and deployments, minimizing human intervention and streamlining release cycles. We envisioned a seamless pipeline that would automatically build each app and push them to the Google Play Store.

Challenges Faced

1. EAS Free-Tier Limitations

Expo Application Services (EAS) provides robust tools for building and deploying React Native applications. However, we ran into limitations on the free tier that impacted our ability to test and deploy efficiently. Each build consumed credits, and with two applications, we quickly found ourselves hitting the cap. This limitation necessitated careful planning and build scheduling, ultimately slowing the automation process.

2. Version Code Management

As we dived deeper into automation, we ran into an issue with the versionCode. In Android, the versionCode must be incremented with each new release. However, our automation scripts failed to update it correctly, leading to builds that had the same versionCode for multiple uploads. This mistake caused Google Play to reject our release attempts, forcing us to manually adjust the code and causing delays.

To mitigate this, we modified our GitHub Actions workflow to include a step that detects the previous versionCode and automatically increments it:

yaml
- name: Increment versionCode
  run: |
    VERSION_CODE=$(grep "versionCode" app/build.gradle | awk '{print $2}')
    NEW_VERSION_CODE=$((VERSION_CODE + 1))
    sed -i "s/versionCode $VERSION_CODE/versionCode $NEW_VERSION_CODE/" app/build.gradle

3. Misleading Play Store Errors

At one point, we encountered an error from the Play Store that indicated a problem with our app description. After thorough investigation, we discovered that the issue stemmed from an invalid package name in the build configuration. The error message we received was neither descriptive nor related to the actual issue, wasting several hours of debugging. Ensuring accurate configuration files became critical to prevent these misleading errors.

4. A One-Liner Bug in GitHub Actions

Throughout our automation process, we heavily relied on GitHub Actions to trigger builds. A tiny issue—a misplaced line in our workflow file—invalidated the entire configuration. It was a simple syntax error, but the resulting failure cascade made it near impossible to trace the source immediately. It was a harsh reminder of the need to maintain meticulous attention to detail in automation scripts.

Lessons Learned

Emphasize Testing

Testing should not be an afterthought. Implementing thorough testing routines as part of the CI/CD pipeline would have flagged issues much earlier—especially those related to versioning and configuration mismatches.

Keep Documentation Updated

Document every aspect of your build and release process meticulously. This helps identify issues faster and serves as a reference to mitigate future pitfall encounters.

Use Version Control Effectively

Incorporate best practices with version control, such as tagging releases and maintaining a changelog. This minimizes confusion around versioning and can help track issues back to specific commits.

Conclusion

Automating the release of Android applications from a shared codebase is a worthy goal that can substantially enhance a development team's efficiency. Our journey taught us that attention to detail, rigorous testing, and a keen understanding of the tools at our disposal are crucial for success. By sharing our experiences and challenges, we hope to empower other developers facing similar hurdles on their automation journeys. With patience and diligence, the transition from manual releases to a well-oiled automated machine is achievable—and immensely rewarding.