Automated iOS Code Reviews with SwiftLint and Danger at YNAP

At YOOX NET-A-PORTER GROUP (YNAP), we use Swift for building iOS apps.

Swift is a modern, fast and type-safe programming language. And in iOS app development, getting instant feedback on Swift code is essential.

Being a type-safe language, most of the safety checks on Swift are done by the Swift compiler at compilation phase. However, there are many clean coding practices like syntax check, styling and more that need to be enforced.

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, and even more so with Swift being a new programming language.

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, rather than waiting until a CI build reaches the Xcode build phase script — we wanted feedback on our code as soon as the build starts.

To do this, we needed a mechanism that provided early feedback on a CI build as it runs. We also wanted the feedback provided SwiftLint to be visible via pull request so that we could take immediate 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. It also allows us to go beyond the basics 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 configuration file — known as the Dangerfile. Rules can be written in Ruby, JavaScript or Swift. However, the Swift implementation is relatively new and we wanted to run Danger within the pre-configured environment on CI with a scripting language.

Fortunately, Travis CI macOS images come up with Ruby and RVM preinstalled, making it easier to install Danger and most of the Danger plugins such as a Rubygems. Therefore, we decided to write Dangerfile rules with Ruby so that we could run them explicitly on Travis CI ahead of actually starting the build. 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.lockupdated? if so ignore that big Pull Request

These are the pretty basic checks that Danger makes easy — but its real power comes via the SwiftLint plugin for Danger. This plugin applies all the SwiftLint rules to the code review process in the Pull Request, allowing Danger to automatically comment on the Pull Request wherever SwiftLint warnings or errors are 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 comment on Pull Requests. In order to do that, we also needed to create a Github Personal Access Token with write access that gave 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.ymlto install the Danger and SwiftLint Danger plugin in the before_scriptphase 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 the 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 just using the command danger to execute all the rules. This runs all the checks configured in the Dangerfilefor our project.

However, things can get tricky if you are using the build matrix feature of Travis CI to run multiple builds in parallel. With build matrix, Danger will execute on every parallel build resulting in multiple comments on the Pull Requests.

To overcome this and ensure that Danger only commented once on Pull Requests per matrix we created a conditional build execution with a variable environment called

To overcome this and ensure that Danger only commented once on Pull Requests oper matrix. We have achieved this by conditional build execution with Environment Variable DANGER="ALLOW" in Travis CI. The configuration looks like this

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, we have set up the variable DANGER=”ALLOW” only once in the build matrix. Also, in the before_scriptphase, we have set the conditional execution of Danger when that environmental variable is set. By doing so we can avoid multiple Danger comments.

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_scriptphase. As soon as Danger finished running, it puts comments on the Pull Requests or reports any issues on the Pull Requests. For example, if we forget to add unit tests then we get notified on Pull Requests

Danger will also notify us of code styling issues like whitespaces, extra lines etc.

Now we have a fully automated code review process for Swift. Our Github bot reviews all our Pull Requests, and if there are any comments reported by the bot which needs to be fixed as part of the Pull Request. Once Danger is happy and other developers finished logical review, then the Pull Request get approved.

Pull Request Approved!

Benefits

We have achieved many benefits from automated code reviews, including:

  • Developers no longer have to spend time making low-level comments on the Pull Requests and can focus more important, detailed logical code review. This automated approach has 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 is improving each day, which has boosted the confidence of our developers that we are not building any technical debt in the code and we have well-tested code

Conclusion

At YNAP, by combining the SwiftLint Danger plugin and Travis CI, we have achieved faster code reviews and improved code quality in our apps.

We have come a long way, but of course, we are not done — next step: add stricter rules to make our code more robust and reliable!

What are your experiences of automating iOS code reviews? Share in the comments below.