Using Github Actions to publish your Flutter APP to Firebase App Distribution

feliperfdev

Felipe Ribeiro

Posted on January 5, 2023

Using Github Actions to publish your Flutter APP to Firebase App Distribution

Hey, everyone! 👋🏻

I want to start talking about my decision for this year, which is to start to write more tech articles to help people, increase my knowledges (cuz I need to study either ^^) and also improve my english writting skills. So, this will be the beggining of this journey and I hope you all could enjoy it :)

Summary

1. Why am I writting this article?
2. Firebase App Distribution
3. The manually way
4. The GitHub workflows way (main topic)
5. Final workflow yaml file result
6. Testing it!

1. Why am I writting this article?

Few months ago I started to develop a Flutter app side-project, which is not available yet, but I intend to publish it on app stores when I feel that it is ready for MVP release.
On this project, I'm using Firebase database to store the app data, authentication, files storaging and some other features. BUT we have one that is the main topic of this article: Firebase App Distribution.

2. Firebase App Distribution

Firebase has it own functionality whose job is literally distribute your app to an user (or a group of users).
When we're talking about Flutter apps, we're also talking about downloading this apps at our mobile devices (in case mobile apps, I'm not going to talk about Flutter Web at this article). Maybe you or your team wanna test it or show it for the team manager or team leader, whatever.
This is the "nice" but rough way to do it. Uploading your app file to Firebase App Distribution.

3. The manually way

First of all, of course, you'll need to generate a build of your Flutter app.



flutter build apk


Enter fullscreen mode Exit fullscreen mode

or



flutter build aab


Enter fullscreen mode Exit fullscreen mode

When you get into your Firebase project console, you have in the left side a shortcuts list, and you will probably see an option named 'App Distribution'. Click on it.

Shortcuts

You'll see a big dashed blue box asking you to upload your app APK or AAB file.

Dashed blue box

After that, it will appear a card with a text field to put the tester e-mail or the name of a tester group (which you can create by clicking at third top navigation bar).

Send to testers

Then, you'll just need to press 'Next' and 'Send to testers'.

Well done! Now, your app is on the devices of all the testers you sent it.
But... Doing this EVERY time sounds like a waste of time. Isn't? Maybe. Maybe not.

But we can do it better. Follow me to the next topic!

4. The GitHub Actions way

Now, in the main topic of this article, I'll show you how automate this process of uploading your app to Firebase App Distribution and send it to testers.
In the end of this topic, you'll know how to do this process just by pushing or opening a pull request on a specific Git branch of your project.

In your project, create a path named .github/workflows, just like that:

Folders path

Inside of it, create a .yaml file with the name of your workflow. I named mine as 'firebase_workflow.yaml'.

Let's beggin by giving a name to the workflow.



name: Firebase APP Workflow


Enter fullscreen mode Exit fullscreen mode

Then, we will need to determine when this workflow will be triggered. Pushing to a branch? Creating a pull request to a branch?

Exemple of how it should looks like the yaml file until here:



name: Firebase APP workflow

on:
  push:
    branches:
      - main

  pull_request:
    branches:
      - main


Enter fullscreen mode Exit fullscreen mode

We need to put jobs on our workflow file. Above we have an exemple of setting that is very important for the whole workflow operation.

I created a key named firebase_distribution and gave it the name "Firebase App Distribution". Then, I setted the virtual machine which would it runs on. You can read more about this here.



jobs:
  firebase_distribution:
    name: Firebase App Distribution
    runs-on: ubuntu-latest ## virtual machine
    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-java@v1
        with:
          java-version: "12.x"


Enter fullscreen mode Exit fullscreen mode

Then, we have two important initial steps to define. The first one is an official GitHub Action used to check-out a repository so a workflow can access it. The second one it's pretty more complex but, briefly, downloads and set up a requested version of Java.

Continuing the steps:

Give a name to this step, now we gonna make our workflow decode the most important file which makes Firebase work on our project: the google-services.json.



      - name: Decode google-services.json
        env: 
            GOOGLE_SERVICES_JSON: ${{ secrets.GOOGLE_SERVICES_JSON }}
        run: echo "$GOOGLE_SERVICES_JSON" > android/app/google-services.json


Enter fullscreen mode Exit fullscreen mode

Inside env key we put another key called GOOGLE_SERVICES_JSON. But, for now, I'll need to explain what is this "secrets.GOOGLE_SERVICES_JSON" here.

For this, open your Github project repository and get into settings page.

On the left side options, look for the security session and click on "Secrets" > "Actions".

options

We need to create 3 secret keys. Each one for:

  • Firebase App ID
  • Firebase Token
  • Google Services Json

Name them by your preference.

The Firebase App ID can be found by following this short click steps on your Firebase project console:

Firebase App ID

We just need to copy and paste it on our secret key.

Firebase token can be obtained by running a few commands on your machine.

At first, we'll need to install npm and run the following command:



npm install -g firebase-tools


Enter fullscreen mode Exit fullscreen mode

Then, run this second command:



firebase login:ci


Enter fullscreen mode Exit fullscreen mode

After that, the token will be shown by your CLI.

For the last key, we just need to open the google-services.json on our project in path "android/app/google-services.json", copy the whole content inside and paste it on the respective secret key in your Github project repository.

Now, we can get back into our workflow and understand what will happen from now:



      - name: Decode google-services.json
        env: 
            GOOGLE_SERVICES_JSON: ${{ secrets.GOOGLE_SERVICES_JSON }}
        run: echo "$GOOGLE_SERVICES_JSON" > android/app/google-services.json


Enter fullscreen mode Exit fullscreen mode

Basically, using secrets.KEY_NAME allows us to access our project secret keys.

We're accessing the secret key named GOOGLE_SERVICES_JSON and running a command on it.

Now, we can continue writting our workflow:



      - uses: subosito/flutter-action@v1
        with:
          channel: "stable"


Enter fullscreen mode Exit fullscreen mode

subosito/flutter-actions@v1 is just a Flutter enviroment running on our workflow. So, now we have 'access' to Flutter enviroment, we can choose a Flutter channel to use. Read about this action here.

From now, we will run Flutter commands inside our workflow:



      - run: flutter pub get
      - run: flutter build apk
      - uses: actions/upload-artifact@v1
        with:
          name: release-apk
          path: build/app/outputs/apk/release/app-release.apk


Enter fullscreen mode Exit fullscreen mode

Notice that already known commands like flutter pub get and flutter build apk now it shows up on our workflow. But, to upload the generated app file (artifact), we'll need to use the action upload-artifact@v1 and parse the build path which it will be storing the app file.

To finally finish this (I swear), we complete our workflow with a Firebase action that will have the responsability to upload the app to Firebase App Distribution. Read about wzieba/Firebase-Distribution-Github-Action. This action uploads your artifacts with .apk, .aab and .ipa (this last one for iOS) extensions to Firebase App Distribution.



      - name: upload artifact to Firebase App Distribution
        uses: wzieba/Firebase-Distribution-Github-Action@v1
        with:
            appId: ${{secrets.FIREBASE_APP_ID}}
            token: ${{secrets.FIREBASE_TOKEN}}
            groups: testers
            file: build/app/outputs/flutter-apk/app.apk


Enter fullscreen mode Exit fullscreen mode

We'll need to parse the remeaning secret keys, the tester group name (which you created at your Firebase project console) and the file path. In Flutter, by default, it is stored at build/app/outputs/apk/release/app-release.apk.

That's it! Our workflow process file is done!

5. Final workflow yaml file result

This is how your workflow file should looks like:



name: Firebase APP workflow

on:
push:
branches:
- main

pull_request:
branches:
- main

jobs:
firebase_app:
name: Run Firebase Workflow
runs-on: ubuntu-latest ## virtual machine
steps:
- uses: actions/checkout@v2
- uses: actions/setup-java@v1
with:
java-version: "12.x"

  <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Decode google-services.json</span>
    <span class="na">env</span><span class="pi">:</span> 
        <span class="na">GOOGLE_SERVICES_JSON</span><span class="pi">:</span> <span class="s">${{ secrets.GOOGLE_SERVICES_JSON }}</span>
    <span class="na">run</span><span class="pi">:</span> <span class="s">echo "$GOOGLE_SERVICES_JSON" &gt; android/app/google-services.json</span>

  <span class="pi">-</span> <span class="na">uses</span><span class="pi">:</span> <span class="s">subosito/flutter-action@v1</span>
    <span class="na">with</span><span class="pi">:</span>
      <span class="na">channel</span><span class="pi">:</span> <span class="s2">"</span><span class="s">stable"</span>
  <span class="pi">-</span> <span class="na">run</span><span class="pi">:</span> <span class="s">flutter pub get</span>
  <span class="pi">-</span> <span class="na">run</span><span class="pi">:</span> <span class="s">flutter build apk</span>
  <span class="pi">-</span> <span class="na">uses</span><span class="pi">:</span> <span class="s">actions/upload-artifact@v1</span>
    <span class="na">with</span><span class="pi">:</span>
      <span class="na">name</span><span class="pi">:</span> <span class="s">release-apk</span>
      <span class="na">path</span><span class="pi">:</span> <span class="s">build/app/outputs/apk/release/app-release.apk</span>
  <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Upload to Firebase App Distribution</span>
    <span class="na">uses</span><span class="pi">:</span> <span class="s">wzieba/Firebase-Distribution-Github-Action@v1</span>
    <span class="na">with</span><span class="pi">:</span>
        <span class="na">appId</span><span class="pi">:</span> <span class="s">${{secrets.FIREBASE_APP_ID}}</span>
        <span class="na">token</span><span class="pi">:</span> <span class="s">${{secrets.FIREBASE_TOKEN}}</span>
        <span class="na">groups</span><span class="pi">:</span> <span class="s">testers</span>
        <span class="na">file</span><span class="pi">:</span> <span class="s">build/app/outputs/flutter-apk/app.apk</span>
Enter fullscreen mode Exit fullscreen mode
Enter fullscreen mode Exit fullscreen mode



  1. Testing it!

Now, we just need to push our project to github's project branch which we had chosen or merge pull request (it depends on what did you choose to do) to trigger the workflow.

After that, you can see the process working by clicking at "Actions" tab in your project repository.

Actions tab

This is how it should your workflow alert looks like:

Workflow


That's it!

Thanks A LOT for reading until here! I hope this article may help you create github actions workflows to upload your app to Firebase APP Distribution.

💖 💪 🙅 🚩
feliperfdev
Felipe Ribeiro

Posted on January 5, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related