窓を作っては壊していた人のブログ

この謎のブログタイトルの由来を知るものはもういないだろう

SwiftLintをCIで使う時はCI上のSwift Toolkitのバージョンを気にかけよう

タイトル通りです。

最近iOSアプリを作るプロジェクトに参加しまして、SwiftLintの導入が行われました。 CI上でformatterをかけてdiffが出ていたらCIをfailedにするというTaskを追加した所、無事にfailedして手元でformatterかけたはずでは……?となって原因調査をしたところCI上のSwiftのバージョンと手元のバージョンが異なっていることが原因でした。

要点

  • Swift Toolkitのバージョンが違うと異なる結果になることがある
  • CIではdefaultのバージョンを使わずに指定する

環境

GitHub Actions macOS Host 10.15 - Swift 5.2.4, 5.3.0 - Xcode 11.7, 12.0

Local - Swift 5.3.0 - Xcode 12.0

どうなったか

Xcode 12.0 両方の結果が見たいのでfail-fastじゃなくていいです · yamachu/swift-5.2x-5.3-swiftlint-different@d164e32 · GitHub

Xcode 11.7 両方の結果が見たいのでfail-fastじゃなくていいです · yamachu/swift-5.2x-5.3-swiftlint-different@d164e32 · GitHub

手元がXcode 12.0の時CIが12.0であればdiffは出ていませんが、CIが11.7を使用している時はdiffが出ています。

対策

  1. CI上のXcodeのバージョンを指定する

今回はGitHub Actionsを使用しました。

virtual-environments/macos-10.15-Readme.md at ce5572effe3843a3397fa1ea2e015d48d0c1994d · actions/virtual-environments · GitHub

検証時はXcodeのdefaultが11.7だったため

swift-5.2x-5.3-swiftlint-different/swift.yml at d164e32d11bd803bf90724e223055197820b0d67 · yamachu/swift-5.2x-5.3-swiftlint-different · GitHub

    - name: Switch Xcode version
      run: sudo xcode-select -s /Applications/Xcode_12.app

のようにして使用するXcodeをローカルと同じバージョンになるように指定しました。

www.jessesquires.com

の記事中にあるように DEVELOPER_DIR という環境変数に設定することでXcodeのバージョンを指定するのも良さそうです。

  1. swiftenvで対象バージョンのSwiftをインストールし、それを使うようにする

ビルド時に同じバージョンを使ってくれるかと言われると怪しいので、Xcodeのバージョンを変えることを推奨しますが、仮にローカルでmacOSのバージョン問題があり、CI上と異なってしまうみたいなことがある場合は、swiftenvでCIで使用されているSwiftのバージョンをインストールし、

$ TOOLCHAIN_DIR=/Library/Developer/Toolchains/swift-5.3.0-RELEASE.xctoolchain ./Pods/SwiftLint/swiftlint

のような形でswiftlintを実行すると、ローカル、CI上共に同じ結果を得ることができます。

この複数のSwiftバージョンを使うことに関しては

github.com

SwiftLintのREADMEに書いてあります。