+++ title = "React Native with Gitlab CI/CD" date = "2020-04-06" author = "Ceda EI" authorTwitter = "" #do not include @ cover = "" tags = ["react-native", "javascript", "gitlab"] keywords = ["react-native", "javascript", "gitlab", "ci", "cd"] description = "Recently, I decided to set up automated builds for [Sonzai](https://gitlab.com/ceda_ei/sonzai.git)." showFullContent = false +++ ## Introduction The aim of setting up CI/CD is to automatically build the app on every commit and send the APK. I looked into Gitlab CI/CD for this purpose since my [project repository](https://gitlab.com/ceda_ei/sonzai/) is already hosted on Gitlab. ## Build Stage To get started, I needed to choose a docker image in which the repo would be built. After looking around a bit, I found that the [react-native-community](https://github.com/react-native-community/) has an official [Docker image](https://hub.docker.com/r/reactnativecommunity/react-native-android), the source of which can be found on [GitHub](https://github.com/react-native-community/docker-android). Gitlab CI/CD is controlled by a versioned file in the repo: `.gitlab-ci.yml`. To start off, I added the `build` job in the file and set image to the docker image above. ```yml stages: - build build: image: reactnativecommunity/react-native-android stage: build ``` I needed to add the commands to be executed in order to build the app. Those commands are added under the `script` key as an array. In my case, I need to run `yarn install` to install all dependencies followed by `./gradlew assembleRelease` in the `android` directory. The file now looks like. ```yml stages: - build build: image: reactnativecommunity/react-native-android stage: build script: - yarn install - cd android && chmod +x gradlew - ./gradlew assembleRelease ``` Next, once the build is done, I need to export the `outputs` generated in the build to be consumed by the deploy stage. This is done by adding an `artifacts` object which contains a `path` array for all the paths that need to be included in the artifacts. In this case, the outputs are in `android/app/build/outputs/`. The file now looks like: ```yml stages: - build - deploy build: image: reactnativecommunity/react-native-android stage: build script: - yarn install - cd android && chmod +x gradlew - ./gradlew assembleRelease artifacts: paths: - android/app/build/outputs/ ``` The build stage is now done. ## Deploy Stage Although I could use the same image, the image is fairly large and takes time to initialize. So, I used [curlimages/curl](https://hub.docker.com/r/curlimages/curl) which is an alpine image with curl added and thus is really light. I will be using `curl` to upload the file to Telegram. Check out the [documentation](core.telegram.org/bots/api) for bots API. Adding the deploy stage, the file looks as: ```yml stages: - build - deploy build: image: reactnativecommunity/react-native-android stage: build script: - yarn install - cd android && chmod +x gradlew - ./gradlew assembleRelease artifacts: paths: - android/app/build/outputs/ deploy_tg: image: curlimages/curl stage: deploy ``` I created a bot via [@BotFather](https://t.me/BotFather) and added it to a [channel](https://t.me/sonzai_builds). Next, I got the channel's chat ID. I stored the Bot Token and the channel's chat ID as variables in Gitlab's UI under Repository > Settings > CI / CD > Variables as `TG_BOT_TOKEN` and `TG_CHAT_ID` respectively. ![Gitlab's UI screenshot](/gitlab-ci.jpg) Next, I added a curl request in the script array to make the actual request to Telegram Bot API which utilizes these variables. It also utilizes some predefined variables in [Gitlab's default environment](https://gitlab.com/help/ci/variables/predefined_variables.md). Here is the final `.gitlab-ci.yml` ```yml stages: - build - deploy build: image: reactnativecommunity/react-native-android stage: build script: - yarn install - cd android && chmod +x gradlew - ./gradlew assembleRelease artifacts: paths: - android/app/build/outputs/ deploy_tg: image: curlimages/curl stage: deploy script: - >- curl -F chat_id=$TG_CHAT_ID -F document=@android/app/build/outputs/apk/release/app-release.apk -F caption=" Branch: $CI_COMMIT_BRANCH Commit: $CI_COMMIT_SHORT_SHA Tag(if any): $CI_COMMIT_TAG $CI_COMMIT_MESSAGE" -F parse_mode=html https://api.telegram.org/bot${TG_BOT_TOKEN}/sendDocument ``` Here is the first build using this. {{< rawhtml >}} {{< /rawhtml >}}