Using swift-format from a docker container

Docker and Swift logos

There is a tiny command line tool as part of the Swift toolchains called swift-format. It’s still a work in progress, but a few days ago I wanted to try it on an existing project, for fun. It’s very simple to use, as the documentation suggests:

swift-format sample.swift -o sample-formatted.swift

As Swift evolves, this tool is bound to evolve with it. That’s why I looked for a way to be able to continuously use it, without necessarily installing all the Swift toolchains on my Mac. Instead, I’m going to use Docker.

Creating a docker image

There are a lot of Docker images to run Swift in a container, a good example are the ones from IBM or the official ones on the Docker Hub.

If you want to write your own, the official Swift documentation covers all the required step to use a Swift toolchain:

  1. Install clang and libicu-dev, which are required
  2. Follow carefully the code signing thingie. It’s a bit intimidating but it’s important as you want to make sure that the version of Swift you’re going to use is legit
  3. Download Swift, check the signature, extract the archive

Using swift-format through docker

You can use swift-format to tweak your files and make the changes in place. This is definitely the easier way and there are very little risk if you’re using a version control system like Git. In fact, given a folder, why not run it against all the Swift file we can find?

find /MyProject/Sources -name "*.swift" -exec swift-format -in-place {} \;

This works, but doesn’t use the Docker image that we’ve created, so we’ll need to tweak it a little.

First, we’ll declare a /source volume in our Docker file. This is where we’ll expect to find Swift files when we run the image:

VOLUME /source

Then, we’ll create a bash script that we’ll add to our Docker image and declare it as an entry point to our docker container. That means that instead of starting a bash shell like most of the docker image, it will run our script right away.

#!/bin/bash

set -e

find /source -name "*.swift" -exec swift-format -in-place {} \;
COPY format-all.sh /
RUN chmod +x /format-all.sh

# ...

ENTRYPOINT [ "/format-all.sh" ]

Once all of this is done, build and tag your Docker image, and run it wherever you want:

docker build -t pcs-swift .

git clone git@github.com:apple/swift-nio-extras.git
cd swift-nio-extras
docker run -it -v $PWD:/source swift-format-all

That’s it! Now you can run swift-format on any project without actually installing the toolchain. In fact, you can even make it an alias for your shell. I use ZSH, but the approach for bash should be fairly similar:

alias swift-format-all='docker run -v $PWD:/source -it pcs-swift:latest'

cd /path/to/project
swift-format-all

As long as your docker daemon is running, no one will ever know swift-format is running from a Docker container. I swear I won’t tell if you don’t!

Conclusion

There are several tools out there that helps you juggle with multiple version of Swift. The most common one being swiftenv. I like my approach for this specific tool because I don’t necessarily want to install the toolchain just because I want to try swift-format.

I mentioned earlier that swift-format is a work in progress, but this is a very easy way to keep track of the progress made on this tool with very little hassle.