Swift/UnwrapDiscover about Swift, iOS and architecture patterns

DangerSwift

April 16, 2024

Have you ever heard about Danger? It’s a tool created by Orta allowing to use your merge request metadata to automate reviewing such as linting, naming convention, …

Today I’ll show you its Swift counterpart: DangerSwift. See this article as a cheat sheet… for myself 🤣: while the tool is not complex we/I tend to always forget how to use it.

Here are the steps we’ll see:

  1. Installing the tool
  2. Making our own Dangerfile.swift
  3. Testing locally
  4. Connecting the tool to our CI

Installation

You have plenty of possibilities to install the tool:

  • 📦 SPM… but according to the doc you’ll have to install DangerJS first 🤔
  • 🏃‍♂️ Marathon… which has been deprecated
  • 🍺 Homebrew

So my advice is simple: go with homebrew.

Dangerfile

Dangerfile.swift contains all your validation rules. Avoid creating it by hand and rather prefer using danger-swift edit command. This will launch Xcode with your configuration file.

Even better, you’ll get autocompletion! In my opinion this is super useful and the biggest advantage of DangerSwift over Danger Ruby or Danger JS.

There is no rule on how to make your danger file. But here how I do it:

  1. Create a function per rule.
  2. Call each rule at the beginning of the file.

Here’s a small snippet:

let danger = Danger()

// 2. Call each rule here
checkMRTitleConvention(danger)
checkPatchIsOnReleaseBranch(danger)
checkViewModelsAreAnnotatedMainActor(danger)

/// 1. One rule == One function

/// Checks the merge request title follow our convention
/// i.e, feat|tech|fix(<title>): [IOS-XX] <description>
func checkMRTitleConvention(_ danger: DangerDSL) {
  let title = Regex {
    Optionally { "Draft: " } // if MR is marked as draft on Gitlab
    ChoiceOf {
      "feat"
      "tech"
      "fix"
    }
    "("
    OneOrMore(.word)
    ")"
    ": [IOS-"
    OneOrMore(.digit)
    "] "
    OneOrMore(.word)
  }

  guard danger.gitLab.mergeRequest.title.wholeMatch(of: title) != nil else {
    fail("Title is not respecting convention: feat|tech|fix(<title>): [IOS-XX] <description>")
    return
  }
}

Test

Having validation rules is one thing, but having validation rules working is far better!

To test your code you test locally and check the result: danger-swift local -b master -d Dangerfile.swift. Unfortunately this command crashes as soon as start using GitLab/Github DSL (so pretty quickly).

Only solution is to test on an existing merge request using danger-swift pr <url> . However this command will require having an Access Token, just like on CI.

Continuous integration

Whether being for local test on merge requests or from CI, you’ll need an Access Token.

Documentation is pretty clear on how to generate a token, so just follow it. You then just have to run danger-swift ci .

Command have multiple options which can be useful:

  • --removePreviousComments removes comments made by previous build allowing to have at most one report at a time.
  • --danger_id=xx gives a unique ID to your comment. This is useful if you decide to run Danger at multiple steps, like at the beginning of the build for validating and at the end for generating test report.
  • -d path to your Dangerfile. Very useful when using DangerSwift from fastlane 😉

CheatSheet

Let’s summarize all this as a cheatsheet:

  1. 🍺 Setup using homebrew
  2. ✏️ Use danger-swift edit to edit your Dangerfile
  3. 🔨 Generate an https://danger.systems/js/guides/getting_started.html DANGER_XX_API_TOKEN
  4. ✅ Test locally
    1. danger-swift local -b <branch>
    2. danger-swift pr <url>
  1. 🤖 Run on CI
    • danger-swift ci -f --removePreviousComments --danger_id=<unique_name> -d Dangerfile.swift