Get Started With CI/CD Using GitHub Actions and Firebase App Distribution.
Improving CI/CD pipeline for Android via Firebase and GitHub Actions.
So first of all, what is CI/CD?
Continuous Integration is the process of regularly checking-in building and validating code.
Let us suppose we have 5 developers working on the same project and all of them are creating a commit in their local machine but we need an environment/process where we can integrate all the commits from all the devs and check their code quality. To automate these works we need CI. Generally in CI, we check the code is compiled and the test cases are passed.
As a developer, we need to focus on programming and new features as well ad distribute them to testers to test and after testing to a user. We need Continuous deployment(DI) to automate the work and make it easy for this sort of thing.
Once the CI process is complete then we can begin the Continuous delivery process where we deploy our application.
Advantages of CI/CD
1. Reduced Changes & Review Time
2. Enhanced Test Reliability
3. Reduced Backlog
4. Enhanced Transparency & Accountability
5. Frequent Updates & Maintenance
6. Boosted Customer Satisfaction
There are lots of other tools for continuous integration and continuous distribution
The most used CI/CD tools are:
1. Jenkins.
2. GoCD
3. GitHub Actions (We will discuss later)
4. Bitrise
GitHub Actions makes it easy to automate all your software workflows, now with world-class CI/CD. Build, test, and deploy your code right from GitHub. Make code reviews, branch management, and issue triaging work the way you want. You can create custom continuous integration (CI) and continuous deployment (CD) workflows directly in your GitHub repository with GitHub Actions.
In this blog, I'll write about the CI with some testing and app deployment to the firebase app distribution using Github Action Events.
Github Action Events like push, pull_request, check_run, issues, ,merge and other.
Let’s start with an example.
First of all, create a project on android studio and add the project to a remote repository (GitHub).
When you set up CI in your repository, GitHub analyzes the code in your repository and recommends CI workflows based on the language and framework in your repository. As you can see in this image that I am using kotlin so I have a suggestion.
Here in the action tab, we can see the pre-defined workflows. And use one of them by clicking ‘Set up this workflow’ and rename the `.yml` file as your work title add click to the ‘set commit ’. Which will add to this folder `.github/workflows` in the project repository.
Here the workflow is a triggerable set of commands. Different workflows can be used for different build types. Which defines what to do on the GitHub server.
You can set the custom events on the workflow. After adding the workflow to the repository it will listen to the event and trigger the workflow.
In a workflow, we define the trigger event, job, or multiple jobs with steps(How to do the job)
Now let’s talk about the workflow example:
name: CI
on:
push:
branches: [ master ] workflow_dispatch:
jobs:
lint:
runs-on: ubuntu-latest
steps:
- name: Checkout the code
uses: actions/checkout@v2 - name: Run lint
run: ./gradlew lintDebug - name: Upload html test report
uses: actions/upload-artifact@v2
with:
name: lint.html
path: app/build/reports/lint-results-debug.html
Let’s try to understand what is written in this code, First of all, the name for the job, we define the event with ‘on’ keyword. In this example, I added a ‘push’ event on a ‘mater branch’ when there is an event push on master then this job will be run.
Now using the ‘jobs’ keyword we can define the work, you can write multiple jobs. First, the lint check is the process of checking if there are any errors, bugs, stylistic errors, and suspicious constructs in the code. For a lint check, we define in which virtual machine it will run we can define other machines too like macOS-latest, windows-latest.
Talking about the steps we can add the name of the step as ‘name:’ keyword and the work of that step is defined as ‘uses:’ with ‘actions’ which is already defined in the GitHub server. Here ‘actions/checkout@v2’ checkouts the latest commit of your code to a virtual machine by which a machine has access to the code. Once the checkout is done it will run the other steps. ‘./gradlew lintDebug’ will check the codebase, 'actions/upload-artifact@v2’ will upload the result as Artifact with the overall project warnings and errors, which can be download from GitHub action.
You can run other jobs like unit test,static-code-analysis, Notification to slack or teams etc.
Now, let’s jump towards Continuous Deployment (DI). For DI we are using the Firebase.
If you don't know how to add firebase to your project then follow this link. After adding firebase to your project you need to enable the app distribution and add a new group.
Now, For the Continuous Deployment, we need the firebase app id and firebase token.
You can locate the App id in firebase project setting.
Fetching the Firebase token is a bit more tricky. You need to install Firebase CLI first. To do so, follow the instructions at https://firebase.google.com/docs/cli to install the tool based on your operating system.
Once installed, run the following command from the command line:
firebase login:ci
This will open your browser and ask you to sign in using a Google account. If you have multiple accounts, choose the one you used to set up Firebase.
Once you’ve signed in, you have to grant Firebase CLI some permissions. Even though these are simple permissions, you should read through them.
Once you’ve read and granted the permissions, you’ll see a message stating that you can close the browser tab. Go back to the command line you’ll see some text on your terminal which is the token we needed.
Now you need to add this id and token to the GitHub repository.
Open repository -> Settings -> Secrets -> new repository secrets
Add these secrets as FIREBASE_APP_ID and FIREBASE_TOKEN. We need to add these credentials as secrets as per the Github rule we can not add directly on a repo or a project.
Now, Let’s back to the workflow, For Continuous App Deployment on Firebase App Distribution we need to add this code in the workflow.
assemble_distribute_job:
name: Assemble and Upload to Firebase
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Restore Cache
uses: actions/cache@v2
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Assemble
env:
VERSION_CODE: ${{ github.run_id }}
run: ./gradlew assembleDebug
- name: Upload to Firebase App Distribution
uses: wzieba/Firebase-Distribution-Github-Action@v1.2.1
with:
appId: ${{ secrets.FIREBASE_APP_ID }}
token: ${{ secrets.FIREBASE_TOKEN }}
groups: qa
file: app/build/outputs/apk/debug/app-debug.apk
here ‘ groups: qa’ is the name of the group that you careated on firebase.
After adding this code push the code in ‘master’ branch (which is defined in the event) then you can see the process running in the action tab.
If all the tests passed, Github will generate the debug build, and all testers or QA (which is defined on ‘groups:’) will get the email from firebase app distribution with the generated build(APK).
Also, you can distribute the signed APK using GitHub action. I’ll write about it in the next one.
I have tried my best. Hope you can understand.
Happy codding…