GitHub Actions has been around for a few years, and while there are several alternatives like Circle CI, Travis CI, etc., it certainly has some advantages.
If you spend some time on GitHub, you've certainly noticed the Actions tab sitting right there. GitHub Actions is deeply integrated into the GitHub ecosystem, which is, if nothing else, convenient. No more do we need to create an account in some other service and integrate the two tools. On the other hand, not everyone will enjoy having a single point of failure for their source control and CI tool, specially when considering that GitHub has been having some downtimes.
You can run your workflows in Linux, Mac and Windows. The runners have loads of tools included by default (you can find the complete list here). That being said, the Android tools and licenses we need to build our app are already included and ready to be used.
Overview of (some) pros & cons
Pros
- Deeply integrated tools
- Prepared for Android
- Considerably faster
Cons
- Young ecosystem
- Single point of failure
Getting started
There are three major concepts in GitHub Actions that are important to be aware of.
1. Workflow
Each workflow has its own YAML file under the .github/workflows
folder. A single workflow defines one or more jobs that can run sequentially or in parallel.
2. Trigger
A trigger is what defines when a workflow runs. You can run a workflow in reaction to a pull request, a push, a tag or even a manual trigger. The complete guide on how to trigger a workflow can be found here.
3. Job
You can have several jobs in a single workflow and each will define a series of steps necessary to achieve a given task.
Let's get started with creating a workflow to test, build and distribute our app via Firebase App Distribution. The first thing we need is to create the workflow file and define a trigger.
name: Distribute app
on:
push:
branches:
- main # Only trigger when pushing to the 'main' branch.
Running the tests
Before building the app we should run the tests to make sure everything is OK and eligible for distribution. In the following sample we're also making sure we have the correct Java version.
The cache: gradle
property indicates the action to persist the Gradle binaries, so it's not downloaded every time it runs.
jobs:
test:
name: Run tests
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup JDK
uses: actions/setup-java@v2
with:
distribution: adopt
java-version: 11
cache: gradle
- name: Run unit tests
run: ./gradlew test --stacktrace --no-daemon
Building the app
By default, all jobs in a workflow will run in parallel unless we configure otherwise.
The build
job should only run after the test
job and to do so, we can use the needs
property which lets you provide a list of jobs that need to run successfully, before the given job can run.
It's also a good practice to keep the build binaries for future reference, and in this case, we'll need them for the distribute_to_firebase
job.
jobs:
build:
name: Build
runs-on: ubuntu-latest
needs:
- test
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup JDK
uses: actions/setup-java@v2
with:
distribution: adopt
java-version: 11
cache: gradle
- name: Build the app
run: ./gradlew assembleRelease --stacktrace --no-daemon
- name: Upload binaries
uses: actions/upload-artifact@v2
with:
name: app-release
path: app/build/outputs/apk/release/app-release.apk
Distributing to Firebase
Before we can upload anything to Firebase, we need to authenticate the runner. The easiest way to do so is to create a refresh token and store that in a GitHub Actions secret.
Run the following command in your terminal, copy the generated token and create a firebase_token
secret.
firebase login:ci
Lastly, create an additional firebase_app_id
secret to indicate which Firebase app to use when uploading. This id can be found in your project settings by selecting the intended app.
jobs:
distribute_to_firebase:
name: Distribute to Firebase
runs-on: ubuntu-latest
needs:
- build
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Download binaries
uses: actions/download-artifact@v2
with:
name: app-release
- name: Upload to Firebase
uses: wzieba/Firebase-Distribution-Github-Action@v1
with:
appId: ${{ secrets.firebase_app_id }}
token: ${{ secrets.firebase_token }}
groups: your-app-distribution-groups-here
file: app-release.apk
Conclusion
As you can see, with just a few lines of YAML we can set up a CI/CD system with the help of GitHub Actions. If you're a GitHub citizen, you're probably keeping tab on your GH notifications already, and you should start receiving a few more regarding the workflow executions.
As always, we hope you liked this article and if you have anything to add, we are available via our Support Channel.