# Android Playbook <!-- omit in toc -->

This playbook is meant to provide developers with all the information needed to get a CI/CD pipeline up and running for the Android side of a React Native application.

## Table of Contents

<!-- TOC -->

- [Table of Contents](#table-of-contents)
- [Google Play Account](#google-play-account)
  - [API Access setup](#api-access-setup)
- [App Signing](#app-signing)
- [CircleCI](#circleci)
- [Messaging](#messaging)
- [Gotchas](#gotchas)
<!-- /TOC -->

## Google Play Account

For a fully fledged deployment process you need a [Google Developer Account](https://play.google.com/console) setup and working. In addition, there are a couple of best practices to get everything working as well as possible:

1. Access to the [Google Play Developer API](https://developers.google.com/android-publisher). Please see section below for more details on this.
2. A user that is the account owner (that does not need to be you). The above credentials will be enough to upload and release the app completely. A developer does not need to be a user on the account although it does help for oversight/help.

### API Access setup

To create the required credentials please follow the [guide](http://docs.fastlane.tools/getting-started/android/setup/#collect-your-google-credentials) in the fastlane docs. Or alternatively look at the [official](https://developers.google.com/android-publisher/getting_started#using_a_service_account) Android docs.

Once the account owner has the JSON file saved on a local disk they can share it (as a string) to the relevant developers using a LastPass note. Please note that these credentials are very sensitive and should be shared only when necessary.

The developer can then use a stringified version of this JSON (example of the file below) and save it in an environment variable(`GOOGLE_PLAY_KEY`) on CircleCI or in their local terminal to run deploys.

```json
{
  "type": "service_account",
  "project_id": "some_id"
}
```

gets stringified into

```js
{"type":"service_account","project_id":"some_id"}
```

using `JSON.stringify` in Node.js.

**[⬆ back to top](#table-of-contents)**

## App Signing

Android takes care of the most complicated part of [app signing](https://support.google.com/googleplay/android-developer/answer/9842756?hl=en) for the developer. The apk still needs to be signed with your own key before it is uploaded to Google Play. There is a useful [guide](https://reactnative.dev/docs/signed-apk-android) for doing this in the React Native docs.

There are options for saving the keystore:

1. Save the keystore in a s3 bucket and download at build time.
2. Save the keystore in a base64 encoded string and create the keystore file at build time.
3. Encrypt the keystore file and decrypt the keystore file at build time.

As the s3 solution requires an extra external dependency it is recommended to use a base64 encoded string. Please follow the steps below to use this method:

1. Use `openssl base64 -A -in <PATH_TO_KEYSTORE>` to create the base64 string.
2. Save the value that was output to terminal to LastPass/CircleCI/terminal under the name `KEYSTORE_BASE64`.
3. When doing a build create the keystore file with `echo $KEYSTORE_BASE64 | base64 -d > <PATH_TO_KEYSTORE>`. A npm script (`npm run create:keystore`) showcasing this is included in the example project.

**[⬆ back to top](#table-of-contents)**

## CircleCI

While this playbook is written with CircleCI in mind, most of the information can be transferred to other CI/CD tools. There are a couple of important environment variables that you would need for CircleCI to deploy your application.

1. The variables below are expected by the generated CircleCI config.yml. These variables can be updated as desired after generation.
   - `KEY_FILE` the name of the key file (e.g. release.keystore). This needs to be a path if keystore is not in `<ROOT_PROJECT_FOLDER>/android/app` folder.
   - `KEYSTORE_BASE64`
   - `KEYSTORE_ALIAS`
   - `KEYSTORE_PASSWORD`
   - `GOOGLE_PLAY_KEY` the stringified JSON value created from [API Access setup](#api-access-setup).
   - `SLACK_URL`
2. It is best practice to use CircleCI [contexts](https://circleci.com/docs/2.0/contexts/) where relevant. Be sure to check what [contexts](https://app.circleci.com/settings/organization/github/Nona-Creative/contexts) Nona has set up when working within the Nona GitHub account.
3. The generated config.yml assumes that an organisation context called `dockerhub_credentials` is in place with the variables `DOCKERHUB_USERNAME` and `DOCKERHUB_PASSWORD`. While this is not a hard requirement by CircleCI it is still [recommended](https://circleci.com/docs/2.0/private-images/) to use your own Docker Hub authentication.

**[⬆ back to top](#table-of-contents)**

## Messaging

The fastlane template that gets generated will assume that there is a slack webhook setup. This process of setting up messaging is a two-step process.

1. Set up a [slack webhook](https://api.slack.com/messaging/webhooks). It is good practice to use one webhook per project (iOS and android).
2. Set the `SLACK_URL` environment variable in CircleCI for your project.

**[⬆ back to top](#table-of-contents)**

## Gotchas

It is important to note that sometimes there are unforeseen issues when it comes to building the mobile applications on CI. Rerunning a build might be all that is needed most times before looking for other issues. That being said, there are some general things to look out for.

1. Slow build times are common (can be improved somewhat by choosing a bigger [resource class](https://circleci.com/docs/2.0/configuration-reference/#resource_class) on CircleCi).
2. Android has some [historical issues](https://support.circleci.com/hc/en-us/articles/360021812453-Common-Android-memory-issues) with memory while building (to be fixed with either bigger resource class or configuration).

**[⬆ back to top](#table-of-contents)**
