iOS — CI/CD and Build Number
Almost for a month (or more), I am trying to find out the best way to deal with build numbers for the iOS application. Well, yes it is absolutely easy in case you are the only person working on the code. However, it is worth even in that case to have somebody to take care of it, why not? Also, where it makes more sense is in a properly established build pipeline. Because it is always better to find out most of the things automated as it helps all the developers on the team to least worry about it.
Use Case
Before I start sharing my solution, I feel it is better to step back and share my thought process behind my discovery. Agile development is the need of all software development industries. Here you have to deliver your small chunk of work in the form of the shippable product. So, you complete your one work item (User story/Jira ticket etc) and then you got to release the build to your QA. This is exactly a step where you think of How I can automate increasing my build number to make everyone’s life easy?
Now, when I say “properly established build pipeline” implies at least you have baseline master branch of your code which each developer uses to create the branch from to work on the specific work item. Once they finish the work, they have to merge their branch into the master branch and that’s where QA receives the build. So, simple steps look likes —
1. Pick the item to be worked on and create a branch from master
2. Complete work and commit+push your changes to your branch
3. Merge code to master branch
4. Assuming CI/CD releases build from master branch, your QA gets a new build to test your work
Wait for a second…. where am I updating the build number? Here is the answer so far.
Options available so far…
During my discovery phase, I came across following option which helps you in maintaining the build numbers for the iOS applications —
- Manually update your build number in the .plist file and then commit+push and then merge the code (Yes, me too not liking it..)
- Using Fastlane increment_build_number action (more here)
- Using XCode agvtool (more here)
- Post Build Phase Script (more here)
- All options are comprised and explained in one article here
Even after having all the above options, I still thought of writing this article and sharing my solution, because I thought these references were good enough to know the way to increment the build number. But still missing one step of how we can actually achieve this in CI/CD pipeline? And more importantly which one is easy and best suitable for the CI/CD?
Approach
The approach in proposing this as best solution is in line with the actual steps developers execute in day to day life in the context of releasing the builds. So the steps are —
- Set the build number (say #1
- Complete work item
- Merge the code to Master branch
- Build (#1) is released by the pipeline
- Increase the build number (#2) for next release
…..and repeat these steps going forward.
The reason I find it inline with the actual steps because it makes sense to first set the build number and then start working for it rather than doing it another way. Because it is very easy to manage the build numbers and more appropriate with the real scenario of actual version numbers. Meaning, once you release the version 1.0 to the App Store, then thereafter what you work for is next version number and not at all for 1.0. So, it makes more sense to update the version number first and then start working for it. This will also help in tracking all the deliverables to the proper version. e.g. test cases being executed for the specific version during development and so on. This way it is also inline and same explains for the internal build numbers. Once you release the build number 1 to QA for testing, then what you work thereafter is for build number 2. So, increase the build number right after you successfully release the current build.
Code Talks More
To achieve this approach, I have written .sh which does two important things —
- Increment the build number in info.plist using PlistBuddy
- Commit + Push to the master branch with CI/CD job skip
And then execute this after successful releasing the current build from the master branch.
Following is the code snippet of the .sh I have written —
I hope with a lot of echo statements and comments, this .sh is self-explanatory. Very easy script to update the CFBundleVersion from your projects Info.plist file. I have simply used PlistBuddy to do this job for me. Feel free to use whatever is appropriate for you. However, the important step is when you commit and push your changes to the repo, make sure that your CI/CD skips the job to be executed again. Otherwise, it will be an endless series of jobs and you will have a series of releases. In my code, as I am using Gitlab it is easily doable with commit message “[ci skip]”. I am sure you can do it with whichever CI/CD you use in your development environment. This is one more minor (still VIMP) reason I want to do it after releasing the current build successfully to your QA. So, combining this solution with your CI/CD the steps looks like follows —
Prerequisite — Set the build number in the .plist file as n
- The developer creates the branch from master and starts working on the work item
- Once finish development, the code will be merged to the master branch
- CI/CD executes first executes test job to make sure code has been integrated properly and all test are passed
- Then, it creates the archive and releases the build to QA
- Execute .sh to increment the build number and commit + Push to master branch
- Goto step 1
And these 5 steps continues…Yeeeeee!
Configurations
I know by now you must be wondering how it is possible or rather acceptable to directly commit something to the master branch. However, you know your version control does allow you to configure the branches so that you can have some exceptions. At least Gitlab does allow. So you have to figure out how to configure master branch so that it will allow us to do this one-time commit + push action for the specific user. I can do it in Gitlab by only allowing CI runner user to this and other contributors can not.
How is it different than others?
That’s the great question I should answer here. I did try all the available options and was not able to achieve this easily in the environment I have in my project. The critical issue I faced was how do I maintain the persisted values of the build number? I did try with environmental variables and all and end up having it in the .plist file itself. Fastlane action is a great option and I got to know that it does use the PListBuddy for the same and that’s where I got this idea about let’s do what Fastlane action does, in addition, to persist the value in the master branch.
Conclusion
Incrementing the build number is a basic requirement and will be a great help to the developers working in the fast developing environments. This option is one of the best options I see so far. Do comment in case you see any other way to achieve this. I am always acceptable for the improvements. :)
