[Entry] React Native with Gitlab CI/CD
This commit is contained in:
		
							
								
								
									
										168
									
								
								_posts/2020-04-06-React-Native-with-Gitlab-CI.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										168
									
								
								_posts/2020-04-06-React-Native-with-Gitlab-CI.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,168 @@
 | 
			
		||||
---
 | 
			
		||||
title: React Native with Gitlab CI/CD
 | 
			
		||||
tags: react-native javascript gitlab
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
Recently, I decided to set up automated builds for
 | 
			
		||||
[Sonzai](https://gitlab.com/ceda_ei/sonzai.git).
 | 
			
		||||
 | 
			
		||||
<!--more-->
 | 
			
		||||
 | 
			
		||||
## 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.
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
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=" <b>Branch</b>: <code>$CI_COMMIT_BRANCH</code>
 | 
			
		||||
 | 
			
		||||
            <b>Commit</b>: <code>$CI_COMMIT_SHORT_SHA</code>
 | 
			
		||||
 | 
			
		||||
            <b>Tag(if any)</b>: <code>$CI_COMMIT_TAG</code>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            <code>$CI_COMMIT_MESSAGE</code>"
 | 
			
		||||
            -F parse_mode=html
 | 
			
		||||
            https://api.telegram.org/bot${TG_BOT_TOKEN}/sendDocument
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Here is the first build using this.
 | 
			
		||||
 | 
			
		||||
<script async src="https://telegram.org/js/telegram-widget.js?7" data-telegram-post="sonzai_builds/8" data-width="100%"></script>
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								assets/img/gitlab-ci.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/img/gitlab-ci.jpg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 90 KiB  | 
		Reference in New Issue
	
	Block a user