CI/CD With Jenkins, Docker and Fastlane — Part 1 — Primer
CI/CD
We in Multinet inventiv believe in the latest technologies and try to embrace them as much as we can. One big improvement we had in our mind was the CI/CD process.
What are the benefits of CI/CD process for us?
- We are sending daily betas before the daily scrum. This makes our daily scrums more accurate, because when you send a card to test, you know it is on the testers phone.
- Jenkins and our Fastlane scripts takes lots of work from our hands. We don’t care about the build or certificates etc. We know it will do appropriate jobs for each branch. We just commit.
- We don’t prepare for app store. The tests we wrote does that job for us and what’s left for us is just open the beta application after the delivery to double check.
For this tutorial we used MultiPay app. You can check it for App Store (link) and Google Play Store (link).
Article can be divided into 4 main parts.
PART I : In the first part we give short primer into CI/CD method.
PART II: Then in the second part we talk about Jenkins and we install Jenkins with Docker. We will talk about Docker before we start the install process.
PART III: In the 3rd part, we will talk about Jenkinsfile. Jenkinsfile will contain general solution for a mobile CI/CD workflow and we will provide iOS scripts for Jenkinsfile.
1) Primer for CI/CD
1.1) Continuous Integration
Continuous integration is a practice that encourages developers to integrate their code into a main branch of a shared repository early and often. Instead of building out features in isolation and integrating them at the end of a development cycle, code is integrated with the shared repository by each developer multiple times throughout the day.
The idea of the continuous integration is making early considerations about the code. Conflicts can be solved with less effort and coders can continue doing their job without too much hassle. Especially, in iOS development process, Xcode project files can be tricky to solve their conflicts and if there are multiple weeks of difference, it can introduce two file changes with different branch paths and voila. You have a conflict that is nearly impossible to solve.
Integrating code continuously can be a problem for some organizations. If you don’t have good and robust test suite, every change will require test iterations and that may not be cost effective. Because, integrating continuously will not mean the quality improvement.
The end goal of CI is integrating code changes frequently and filtering deficiencies. With a good test suite, nearly all of the problems can be detected right after committing. CI will lead teams to write clean code and relieve testers.
Test types
Smoke tests
When projects have big amounts of tests, they will try to predict fails early. Smoke tests enter the scene here. They may be used to check business use cases before extensive testing, or check readiness to deployment etc.
Unit and UI tests
A software is a group of units and one or more units may come together to provide a UI. In OOP world, a unit can be thought as a method. Making every unit work as expected will provide robustness to software and unit tests will do that.
Unit tests make sure that every unit in a software runs perfectly as expected. Having good and robust unit test suite will guard software from any type of technical bugs. Because unit tests will cover any case out there.
Having perfect units may not provide the best outcomes. For example, a wrong UI flow can be created from perfectly valid unit tests. UI tests can solve this.
Integration tests
Integration tests will test groups of units. It can be thought as UI tests. Units can be valid but having wrong units come together may not pass the requirement.
Acceptance tests
Acceptance tests will test the software from the client’s perspective. This phase will make sure that the software is compatible with the client requirements and every use case is provided with valid groups of units.
1.2) Continuous Delivery
Continuous Delivery takes CI principles and takes them one step further. In Continuous Delivery, committed changes will be deployed to at least one environment. That may be staging or testing.
Always having the latest code in pre-prod environment will ensure teams that their code is working properly and can be deployed anytime. Because, the code having a broken test will never pass the Continuous Integration step. It will also give a sneak peek to product owners.
Continuous Deployment relies on Pipelines. Automated pipelines will include configs, credentials and certificates and it will be aware of the environment it is going to deliver the code.
Having good Continuous Integration / Continuous Delivery flow will make project members sure that the code is always up to date in pre-prod environment and can be deployed anytime.
1.3) Continuous Deployment
Continuous Deployment is an extension of Continuous Delivery. Every build that is passed the full test phase, will be deployed. To have a successful Continuous Deployment, teams should have successful test suite and written tests should cover every case that manual testing does.
Teams should note that with Continuous Deployment, they have to take responsibility for main repository commits. Because committers will decide when to deploy. Test suite must be up to date with changes and cover all the use cases.
Deployment strategies
- Rolling Deployment: Rolling Deployment can be thought of as partial deployment. Let’s say you have 5 load balanced web servers. Rolling Deployment will deploy changes to one server at 5-minute intervals.
- Canary Deployment: Canary Deployment is releasing the new version to a small subset of users, that thought as canary group. After the release, canary group is monitored for bugs and crashes, and if none release is sent to all users.
- Dark Deployment: Dark Deployment is deploying changes to users when traffic is the lowest. An example for that may be 00:00–06:00 A.M.
Before we switch to Jenkins, we need to refresh our memory for Fastlane and iOS prerequisites for CI/CD.
1.4) Strategies We Used At Inventiv
We are currently planning to re-write Unit and UI Tests for both Android and iOS. In iOS UI Tests can be thought as Integration Tests.
We may introduce the smoke testing idea to table and given the complexity of some features we probably will need that. With smoke testing, we can skip testing payment flows or small screens if we didn’t touch them.
For CD flow, master branch is checked every 5 minutes. If there is new commits, we are sending new version to app store right away.
We have two branches(dev and test) for beta testing. Dev branch is checked daily at 00:00 AM to provide new version to testers is there are new commits. Test branch is the place we use to send features to testers instantly. We rebase the branch containing new feature into test and Build Server picks up change to send beta.
That’s It
We are done with the part 1. In the next part, we will talk about Jenkins. We will learn what is a pipeline, define scripted and declarative pipeline. Then, we will talk about Docker and install Jenkins in docker container.