At Yoox Net-A-Porter(YNAP), we use Swift for building iOS apps. Swift is a modern, fast and type-safe programming language. In the iOS app development, getting an instant feedback on Swift code is essential and Swift being type safe language the most of the safety checks has been done by Swift compiler at compilation phase. However, there are many clean coding practices like syntax check, styling etc needs to be enforced explicitly. In this post, we will explore how we have automated most of the Swift code review process using Danger, Swiftlint and Travis CI in our iOS apps at YNAP.
Swift Code Review before Danger
The process of code reviews can be difficult especially with Swift being a new programming language. The SwiftLint is the de facto tool for linting the Swift source code by enforcing rules suitable for a specific team or project. We implemented SwiftLint on TravisCI which is our Continuous Integration(CI) Server, using some best practices as mentioned in our previous blog post. Our SwiftLint configuration has some strict rules and we used to run SwiftLint as part of Xcode build phase so that developers can see the warnings or errors in the Xcode itself while development. However, on CI we don’t want to wait until CI build reaches to running Xcode build phase script. We wanted the feedback on our code as soon as build starts so we needed a mechanism to give early feedback on whenever CI build runs. We also wanted that feedback provided by SwiftLint should be visible on pull request so that we might take instant action. That’s where Danger comes in the picture.
Danger
Danger is a tool which runs on CI to handle all the trivial code review tasks like the typo, whitespaces, line breaks etc. On top of that, we can also go beyond and add more project specific checks or enforce tests or documentation as part of the pull requests. There is great documentation on how to get started with Danger on the official site here. The rules need to be listed in the Dangerfile which is the configuration file and can be written in Ruby, JavaScript or Swift. With Danger, it’s possible to write rules in the Swift but the Swift implementation is/was new and we want to run Danger with the pre-configured environment on CI with a scripting language. Fortunately, Travis CI macOS images come up with Ruby and RVM preinstalled which makes easier for us to install danger and most of the danger plugins as a Rubygems. Therefore, we decided to write Dangerfile rules with Ruby so that we can run them explicitly on Travis CI as part of the before actual build start. With Danger there are various rules we can configure as mentioned here but we picked following Swift and iOS specific rules.
- Check for big Pull Requests especially if more than 500 line of code
- Check if unit tests added as part of Pull Request if application code has been changed
- Check that Pull Request has a label
- Check that Podfile or Podfile.lock updated if so ignore that big PR
These are the pretty basic checks we can easily do with Danger but the real power of danger comes in a picture with SwiftLint plugin for Danger, where all the SwiftLint rules are applied to code review process in the pull request. Danger can put comments on the pull request wherever SwiftLint warnings or errors found.
Our setup at YNAP
Now that we have covered the basics of the Danger and swiftLint plugin, Let’s talk about how we set that up on our Travis CI server. We needed the following things to setup Danger on Travis CI.
- Dedicated Bot account/Personal Access Token on GitHub
We created a dedicated bot account on GitHub which can able to put comments on Pull Requests. In order to do that, we also need to create Github Personal Access Token with write access to give the Bot an ability to comment on the pull requests. This personal access token can be configured as environmental variable DANGER_GITHUB_API_TOKEN in the Travis CI setting for an iOS project.
- Install Danger and SwiftLint Danger Plugin on Travis CI
Once we have Github access token, next thing we have updated our Travis configuration .travis.yml to install the Danger and SwiftLint Danger plugin in the before_script phase as shown below.
As macOS images of Travis CI are preconfigured with Ruby and RVM, we just need to install the Rubygems as part of the script to install Danger and swiftLint plugin for Danger.
Note: Danger can be run on any CI server as mentioned in the documentation here
- Run Danger on Travis CI
Once installed, it’s fairly easy to run Danger on Travis CI with just command danger to execute all the rules. This will run all the checks configured in the Dangerfile for our project. However, there was a tricky situation, as we are using build matrix feature of Travis CI to run multiple builds in parallel. With build matrix, Danger will execute on every parallel build resulting in putting comments multiple times on the pull requests. We need to find the way to allow Danger to comment on pull requests only once per matrix. We have achieved this by conditional build execution with Environment Variable DANGER=ALLOW in Travis CI. The configuration looks like this
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
before_script: - gem install fastlane --no-ri --no-rdoc --no-document - gem install danger --no-ri --no-rdoc --no-document - gem install danger-swiftlint --no-ri --no-rdoc --no-document - if [ $DANGER == "ALLOW" ]; then danger; ./Pods/SwiftLint/swiftlint lint --config .swiftlint-ci.yml; fi matrix: fast_finish: true include: - osx_image: xcode10 env: CI_BUILD_TARGET='nap' CI_DEVICE='iPhone X (12.0)' DANGER="ALLOW" - osx_image: xcode10 env: CI_BUILD_TARGET='nap' CI_DEVICE='iPad Air 2 (12.0)' |
As you can see that, we have set up the variable DANGER=”ALLOW” only once in the build matrix. Also, in the before_script we have conditional execution of Danger when that environmental variable is set. This way we have avoided the issue of Danger commenting multiple times.
That’s it’s! we have configured Danger to run on our Travis CI server.
Automated Code Reviews
Now let’s see how Danger is doing automated code reviews and how it helps the team to fix coding errors quickly. Whenever a developer creates a pull request, the build triggers on Travis CI and Danger runs as part of the before_script phase. As soon as Danger finished running, it puts comments on the pull requests or reports any issues on the pull requests. e.g If we forget to add unit tests then we get notified on pull requests
Danger will also notify code styling issues like whitespaces, extra lines etc.
Now that, we have a fully automated code review process for Swift. Our Github bot is reviewing all our pull requests, if there any comments reported by the bot which needs to be fixed as part of pull request. Once Danger is happy then pull request is approved.
Benefits
With automated code review process, we have achieved several benefits including
- Developers no longer putting trivial comments on the pull requests and focus on much detailed and logical code review. This automated approach saved developer time in the code review process.
- There are no new warnings or issues being introduced in the Swift code which improves code quality.
- As we added a rule to check if tests are added as part of pull request, our code coverage getting much better day by day which boosted developer confidence that we are not adding any tech debt in the code and we have well-tested code.
Conclusion
With the combination of SwiftLint Danger plugin and Travis CI, we have achieved faster code reviews and improved our code quality in our apps. In the future, we are planning to add strict rules to make our code more robust and reliable. What are your experiences of automating iOS code reviews? Share in the comments below.