Better iOS projects: How to manage your tooling with mint

In the series "Better iOS projects", we have a look at the various tools and environments that are useful to have a more convenient and efficient handling of iOS projects.

July 3, 2018, by Wolfgang Lutz(Twitter, GitHub)

Mint: How to manage your tooling with min

How to manage your tooling with mint

Since the (still recent, in comparison to other languages) release of the Swift programming language, a lot of tooling has been added to support developing in it.

We got SwiftLint to lint our code, SwiftFormat to apply format and coding guidelines, SwiftGen to get rid of all the string-dependent API calls and Sourcery to generate huge amounts of code we would have to tediously write by hand otherwise.

But all this tooling is third-party and because of this, we need to manage it by ourselves.

Some of the approaches on how to install these tools are:

  • download a binary
  • install it via CocoaPods
  • install it via Homebrew

There are some downsides to these approaches:

  • The method of installation might not be supported: Not all dependencies are available as a binary AND via CocoaPods AND via Homebrew, so you end up with a mix of systems.
  • You depend on the update being published to the manager you use, which can take some time.
  • You cannot specify the exact version to use.
  • You might need to clutter your repository with large binary blobs.

What do we need from a Tool-Version Manager?

You want to have the exact same version of the tool for you, your team members and your CI Server. This way, all the tools behave the same way across your development team and everybody gets the same warnings and generates the same code, thus avoiding differences in behavior.

You do not want to have to be forced to update your tooling on the day you want to give your App into review, so you need to be able to install a specific version instead of having to use the most up to date version of the tool. This helps to avoid problems in the case there is a bug in the newest version of the tool you are using (happened to us with Sourcery).

You want to be able to install a specific version per project. Different projects have different needs for synchronization. Having a tool as a global dependency just does not work in some cases.

What is the Problem with brew?

Homebrew is a really great tool for providing terminal tools. Installing additional tools is a charm. But: for most tools, Homebrew no longer has the option to install a specific version of the tool. As you can not go back to a previous version, the only way to keep versions synchronized across team members is to install the latest version available. This becomes absolutely infeasible for agencies with lots of projects and additional external developers. Somebody will always forget to upgrade brew. Installing your own internal tools is possible by creating your own Homebrew tap, but it adds some additional overhead and maintenance.

What does Mint do?

Mint is a dependency manager that internally uses Apple's Swift Package Manager (SPM) to build swift tools. If the tool is written using SPM (which is the way to go to be able to use external dependencies for CLI, see this great post by @JohnSundell) it usually can be built using mint without a problem. So far, SwiftLint, SwiftFormat, Marathon, XcodeGen and Sourcery are some of the most relevant tools that can be installed using mint. SwiftGen will be installable when the next version (v6.0) is released.

Install mint

You can find several ways to install mint on GitHub.

One easy way is to run

brew install mint
    

mint run

To just run a package, type

mint run <repo-name>
    

e.g.

mint run yonaskolb/xcodegen
    

This installs and runs the latest version.

To run a specific version, you can add a release tag or a branch or a git commit hash:

mint run yonaskolb/xcodegen@1.8.0
    

You can also pass git URLs like git@github.com:yonaskolb/Mint.git to the install command. This allows you to also install and run internal, non-public tools from their repositories.

mint install

To install a specific version for later use, you can use mint install:

mint install yonaskolb/xcodegen@1.8.0
    

This installs the given version (and links it to usr/local/bin).

How do I use the Mintfile?

To define the versions to use in your project, you can add a file called Mintfile to your project's root folder. In it, you can define the tools to use along with their versions:


      krzysztofzablocki/Sourcery@0.13.1
      realm/SwiftLint@0.25.1
      yonaskolb/XcodeGen@1.8.0
      nicklockwood/SwiftFormat@0.33.7
    

For commands run in this folder, that do not contain a version specification, mint will look up the version in the Mintfile.

So, running

mint run xcodegen
    

with the Mintfile present will install and run version "1.8.0" instead of a newer version. Note that you can leave out the user part (e.g. "yonaskolb/") as it is defined in the Mintfile already.

mint bootstrap

Running

mint bootstrap
    

installs the versions defined in the Mintfile (without linking them), so that you are prepared to use the versions from inside your buildscripts in Xcode.

Automating the installation via mint

At Number42, we always include a script called bootstrap.sh in our projects, which does the most basic setup calls needed to run the project afterwards. Whenever something does not work out of the box after cloning (or pulling) a project, calling sh bootstrap.sh is able to sort out the larger part of problems in most cases. We use this the same way for iOS and web projects. We will have a closer look at the bootstrap script in an upcoming episode of this series.

This is an excerpt of the script, which shows how we install mint and run mint bootstrap:

#!/bin/sh

    brew update

    function install_current {
      echo "trying to update $1"
      # https://docs.travis-ci.com/user/reference/osx/
      # avoids errors
      brew upgrade $1 || brew install $1 || true
      brew link $1
    }

    if [ -e "Mintfile" ]; then
      install_current mint
      mint bootstrap
    fi
    

What to do if something is broken

Mint installs tools to /usr/local/lib/mint, so you can delete files here if something goes wrong.

Acknowledgments

Thanks to Yonas Kolb for reviewing this article before release. Also thanks, as always, to Melanie Kloss for the great banner image.

Everything from the series 'Better iOS Projects':