Forem

Cover image for I Keep Forgetting About My Long-Running Mobile App Builds
Jared Hall
Jared Hall

Posted on

I Keep Forgetting About My Long-Running Mobile App Builds

I'm a mobile developer. My Android builds take me easily 15-20 minutes. iOS with Fastlane, tests, code signing, and TestFlight upload? Easily 30 minutes.

Every time I make a PR, I'd start a build, switch to something else, and forget about it. An hour later, I'd come back and check the Actions tab to see that the build failed 45 minutes ago. Or that the build actually worked and QA has been waiting on this for a long time.

This has been happening too many times for me to count, so I built something to solve this problem.

The problem

There's no way to automatically sense that the build is complete. You just need to keep an eye on the Actions tab or wait for your PR to become mergeable.

What I actually wanted:

  • A push notification on my phone the moment the build finishes
  • A direct link that I could tap the notification and go straight to Firebase App Distribution or TestFlight
  • Different messages for success and failure
  • A link to the GitHub Actions run for failed builds so that I can see what went wrong
  • No waiting around, no checking every 10 minutes and no post-it notes under the monitor

What I did

I created a simple service that sends push notifications to your phone. You send it an event via the API or GitHub Actions, and it buzzes your phone. The key feature for CI/CD pipelines is that it can include a link in the notification. You can tap the notification to get to where you need to go. You can find the service at API Alerts.

Here's what my Android staging workflow looks like:

- name: Upload to Firebase
  uses: wzieba/Firebase-Distribution-Github-Action@v1
  with:
    appId: ${{ secrets.ANDROID_FIREBASE_APP_ID }}
    serviceCredentialsFileContent: ${{ secrets.GCP_CREDENTIALS }}
    groups: staging
    file: app/build/outputs/apk/release/app-release.apk

- name: Notify
  if: success() || failure()
  uses: apialerts/notify-action@v2
  with:
    api_key: ${{ secrets.API_ALERTS_KEY }}
    channel: 'developer'
    message: ${{ job.status == 'success' && 'πŸš€ Android staging deployed' || '❌ Android staging failed' }}
    tags: 'deploy,staging,android'
    link: ${{ job.status == 'success' && 'https://appdistribution.firebase.google.com/testerapps/MY_APP_ID' || format('{0}/{1}/actions/runs/{2}', github.server_url, github.repository, github.run_id) }}
Enter fullscreen mode Exit fullscreen mode

The if: success() || failure() is important. It sends a notification no matter the outcome but uses different messages

The workflow now

  1. Push code to a PR
  2. Context switch. Make a coffee, quick power nap, play with my cat Earl, review another PR, whatever
  3. Phone buzzes: "πŸš€ Android staging deployed"
  4. Tap β†’ Firebase App Distribution opens β†’ install β†’ test

Or:

  1. Phone buzzes: "❌ Android staging failed"
  2. Tap β†’ The GitHub Actions run opens β†’ see exactly what broke

The entire process from "push code" to "testing the build on my phone" now requires zero attention

iOS too

I use the same approach for iOS builds. My Fastlane workflow uploads to Firebase App Distribution (or TestFlight) and then sends the notification:

- name: Test App
  run: fastlane ios tests

- name: Build
  run: fastlane ios build_beta

- name: Deploy
  run: fastlane ios deploy_beta group:staging

- name: Notify
  if: success() || failure()
  uses: apialerts/notify-action@v2
  with:
    api_key: ${{ secrets.API_ALERTS_KEY }}
    channel: 'developer'
    message: ${{ job.status == 'success' && 'πŸš€ iOS staging deployed' || '❌ iOS staging failed' }}
    tags: 'deploy,staging,ios'
    link: ${{ job.status == 'success' && 'https://appdistribution.firebase.google.com/testerapps/MY_APP_ID' || format('{0}/{1}/actions/runs/{2}', github.server_url, github.repository, github.run_id) }}
Enter fullscreen mode Exit fullscreen mode

Staging vs production

I use separate channels to keep things organised:

  • developer for staging and feature branch builds. Just me.
  • releases for production builds. The messages are different too:
# Production
channel: 'releases'
message: ${{ job.status == 'success' && '🚒 Android production ready to submit' || '❌ Android production failed' }}
link: ${{ job.status == 'success' && 'https://play.google.com/store/apps/details?id=com.myapp' || '...' }}
Enter fullscreen mode Exit fullscreen mode

It's not just mobile

I’ve taken this approach and applied it to my backend deployments, web builds, and even SDK releases. Any build or deployment that takes more than a minute and may fail now sends a notification.

The GitHub action is a simple step to add to any workflow. If you’re a mobile dev spending your day waiting on CI, try adding this action.

I wrote a more detailed step-by-step blog post on the API Alerts blog if you want the full walkthrough.


I'm the developer behind API Alerts, I built it because I needed it. If you have questions about the setup or want to see other use cases, drop a comment.

Top comments (2)

Collapse
 
devjp profile image
Justin

Cool project, however, you know that the GitHub app can send push notifications on result of an action, right? I use for the exact reason you described.

Collapse
 
jaredhall profile image
Jared Hall

Thanks Justin! I did try that, but the direct link to my builds were a game changer for me. That and I have a separate github account for some work projects. One click on the notification and I'm installing from Firebase App Distribution or TestFlight, not navigating through GitHub.
Spoiler, I got a big 2.0 release coming in the next few weeks. Push wont be the only way of getting notified πŸ˜‰