Building APKs from Slack using Circle CI and Firebase cloud functions
For small teams or small projects, it might not be easy to have full self hosted CI/CD pipelines for building apks. Sharing apks within the team for testing purposes might also be difficult. With a simple Slack app and CircleCI integration in the project, we can have automated apk building and anyone can trigger the build from Slack for a branch and build variant.
/build-apk [branch] or [buildVariant]|[branch]
The whole process will look like this:
- Slack app and a slash command that triggers the build
- Receiving POST request from the Slack app with the command details. If your project uses Firebase, this can be a simple Firebase Cloud Function.
- Triggering the build on Circle CI according to branch and build variant
- Uploading the artifcat from Circle CI back to Slack
/build-apk
slash command.
Create a new Slack app and setup a slack command as below -
Slack will send a HTTP POST request to the Request URL mentioned when creating the Slash command. We can enter the url for the firebase cloud function here.
Firebase cloud function that handles the Slack command request and triggers Circle CI job
If your project uses Firebase, you can create the cloud function in your Android project repo itself. Run firebase login
and firebase init functions
in your project directory.
Let’s setup the function to recieve POST request and trigger build on Circle CI using Circle CI API trigger.
Note that there are some issues in firebase cloud function working with unescaped characters due to which we are avoiding using space in the slash command. We can use pipe |
as the separator for build variant and branch name as branch names can often have /
or -
.
One thing to note here is that Slack expects a response within 300ms after executing slash command or else it will show operation_tiemout
error. Initialising the function might take more than 300ms and then waiting for Circle CI api trigger response will certaintly cross 300ms time limit. To work around this, we write the response instantly using response.write()
and then trigger the Circle CI API in response of which we finally end the response. Note that if you instantly end the response with res.end()
the cloud function will terminate soon after so we can’t do response.send()
or response.end()
before the circle ci api trigger is complete.
Also see Circle CI- Using the API to trigger jobs
src/index.ts
Circle CI config for building APKs and uploading to Slack
.circleci/config.yml
Circle CI config will be your existing config with an extra step for uploading generated artifact to Slack. We can run following CURL to upload file to Slack -
curl -F file=@app/build/outputs/apk/debug/app-debug.apk -F channels=qa-android -F token=$SLACK_TOKEN -F filename=app-debug.apk https://slack.com/api/files.upload
The Slack token can be found in the OAuth & Permissions section of your app homepage. Note that you will have to give the bot the files:write
and commands
permissions.
If your gradle configuration updates the output apk name according to current branch and version like app-debug-v7.8.50-master.apk
, then you will need to slightly change the final step to find the newly built apk.
filePath = $(find app/build/outputs/apk/debug -name 'app-debug*')
fileName = $(find app/build/outputs/apk/debug -name 'app-debug*' -exec basename {} \;)
That’s it! Now you can get the APKs by just running the /build-apk
command from Slack.
Notes
- You should be using a debug keystore that is included in your repository so that your APK can be signed
-
For building release APK, you will probably need to put the release keystore inside your repo itself and then set the store passwords in environment variables in Circle CI. Unfortunately, it looks like Circle CI doesn’t have access to environment variables if job is triggered through API and this may not be the ideal way for building release APKs
-
If using firebase cloud function, you will see frequent operation_timeout error on the slash command due to Slack’s 300ms response time limit, but the function would still have been executed (if there are no errors in the function itself) and the build would have been triggered on Circle CI
-
All the 3 steps can be replaced with some other comibination of services. Instead of Circle CI, you might use Travis CI which should also have similar API triggers. Instead of Slack to initiate build, you can have some other form of trigger that can directly call Circle CI API to start the build.
Posted by Naman Dwivedi
on 13 Apr 2020
Tags- Android
,Circle CI
, Slack
, APK