Table of Contents
1. What is CI/CD
Basically, CI/CD is an automated workflow where your development process could automatically run a series of command-line tools to achieve something.
1.1. CI
Series of command-line tools to check project quality & stability, usually by analyzing source code and running unit test
1.2. CD
Optional process run after CI on certain condition, to publish the project. By publishing, it means: build the project (if needed) > upload runnable project > notify update detail to stakeholders
2. Tools
Basic tools:
- Runner machine (server/local machine)
- Required command-line tools for your project tech-stacks
- example:
npm
,gradle
,flutter
,xcode-project
,cargo
,gcc
,javac
,unity-editor
,firebase
- example:
- Source control tools.
- example:
git
- example:
Helper tools:
- CI/CD service, either self-hosted or cloud service.
- example: Jenkins, Gitlab CI, Github Actions
- Docker
- Third-party helper tools.
- example:
Fastlane
- example:
3. Restrictions
- In most case, CI/CD is available for any type of project, just need different approach.
- In rare case, CI/CD won’t work if your project is not able to be built/published using non-interactive command-line interface (CLI).
- by non-interactive CLI, it means:
- your app have must not rely on user interface to do the process (have command-line tools)
- command-line tools must be able to be run without human interference, such as password input prompt, etc
- by non-interactive CLI, it means:
- In docker runner and cloud services such as Github Runner / Gitlab CI, you will need to include tool installation steps before CI/CD steps since they’re barebone automation kit.
Notes:
- If your background is a programmer who uses IDE to compile and run your app, such as android/iOS developer, you will find it hard at first. But trust me, even iOS which relies on its own proprietary software on specific OS (Mac OS), they can even use command line to build IPA and upload it to testflight.
- If you heavily rely on community-made script using docker image/github action, and think: “Hey, it’s impossible for me to migrate this to my own self-hosted CI/CD from scratch”. Actually, it’s possible, every community-made script is made of script/codes, which can be reverse engineered, and you will reveal its process.
4. How it Works
- A user (developer) make changes, then push / create merge request
- Push / merge request exist on source control, this will trigger source control to send event to your CI/CD service via webhooks
- CI/CD service will then filter these events
- if events are whitelisted, spawn CI/CD runner (docker, remote server, or even self-hosted machine connected via tunnel)
- Series of commands will be executed based on source control event
- Usually CI is mandatory process, except CI is filtered only when merge request/specific commit message
- usually CI will notify developers about its result, one of its method is via merge request comment
- CD is run on specific event, such as commit with specific message on specific branch
- Usually CI is mandatory process, except CI is filtered only when merge request/specific commit message
- finished
5. Example
Since it is complex and tool-reliance to give example with certain CI/CD service, we will do semi-automatic things, by creating custom script and run it when needed. I’ll give example for flutter android apps, from doing unit test, build, and upload to firebase app distribution.
Requirements:
- Linux OS (VPS/local machine)
- Preinstalled tools (on docker CI/CD runner/cloud provider, must create non interactive install scripts for these tools):
- Firebase project, enable Firebase App Distribution
- Firebase Service Account
Steps:
- Create CI/CD script and place it on your project, let’s say it’s
buildscript/ci.sh
andbuildscript/cd.sh
. don’t forget tochmod +x buildscript/*.sh
after file created
flutter test --coverage
genhtml -o coverage/html coverage/lcov.info --ignore-errors empty
flutter build apk --release --obfuscate --split-debug-info=build/flutter_mapping
firebase appdistribution:distribute build/app/outputs/flutter-apk/app-release.apk \
--app $FIREBASE_APP_ID \
--release-notes-file build/changelog.txt \
--groups-file FirebaseDistributionConfig/groups.txt
- commit & push the scripts
When you need to run CI tools:
- go to your linux
- clone the project
- pull latest changes
- switch to desired branch/commit
- run
buildscript/ci.sh
Preparation before running CD tools:
- prepare
build/changelog.txt
. fill it with current version changelog - prepare
FirebaseDistributionConfig/groups.txt
, with group name that should be able to receive this updates. - commit & push
When you need to run CD tools:
- run previous CI steps, flutter test must passed, if not: go back to your IDE, fix, push again, repeat CI steps until it passed
- register service account variable using command
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
- set firebase app id using
export FIREBASE_APP_ID=yourappid
. This can be found in your firebase “General” Project Settings, for example:export FIREBASE_APP_ID=1:87732788080:android:57b4da20b7760391644db6
- run
buildscript/cd.sh
Note:
- These CI/CD steps where you clone, pull, export variable, is further automated when you use CI/CD services.
- In more advanced but self-made CI/CD service, you can create a simple web service which accept git webhook, and automatically run things when the webservice is run.