Swift Packageのバージョンを最新に解決できない


概要

iOSアプリ開発のCI/CDを行うときは、xcode buildやfastlaneでビルドやテストを行うと思います。その際にプロジェクト(ワークスペース)が参照しているSwift Packageがなかなか狙い通りに解決されなかったため、備忘録として残します。

とりあえず結果

結論としてはxcodebuildやfastlaneのパッケージ解決の方法では難しいことがわかりました。Package.resolvedやDerivedDataを削除しても謎のファクターXを参照して、古いリビジョンを解決してしまいます。

最新リビジョンを取得するワークアラウンド

そのプロジェクトがSPMでない場合でも、Package.swiftを用意し、そこにSPMのパッケージを書きます。
で、アップデートして、Package.resolvedを移動させます。

// swift-tools-version:5.3
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
    name: "Hoge",
    platforms: [
        .iOS(.v14),
    ],
    dependencies: [
        .package(name: "Hoge", url: "https://xxxxxxxxx",
        .branch("master"))
    ]
)



swift package update
mv Package.resolved Hoge.xcworkspace/xcshareddata/swiftpm/
bundle exec fastlane tests

この場合、Package.resolvedを参照してほしいので、fastlaneの場合は、disableAutomaticPackageResolutionを有効にします。

Fastfile.
    run_tests(..,
              xcargs: "-disableAutomaticPackageResolution",
              ...
              )

これで最新版をなんとか解決できました!

パッケージ解決に関与してそうなパラメータ

Package.resolved

XXX.xcodeproj/xcshareddata/swiftpm/Package.resolved というパスにあるファイルです。基本的にこのファイルがある場合は、このファイルに記載されているリビジョンのものがチェックアウトされますが、無視する設定もできるようです。

DerivedData

いわゆるビルド時の中間ファイルです。これがあると最新を取得してきてくれないことがあります。 このパスは指定することができるようで、fastlaneだとcloned_source_packages_pathというパラメータで指定することができます。xcodebuildだとclonedSourcePackagesDirPathというパラメータです。

resolvePackageDependencies

xcodebuildコマンドに渡すパラメータです。このパラメータの挙動を正確に把握していないのですが、プロジェクトAがSwiftPackageBとSwiftPackageCをxcodeprojで参照しており、SwiftPackageBがSwiftPackageCを参照していた場合、プロジェクトAが参照するプロジェクトCのバージョンは、プロジェクトBのPackage.Swiftのバージョンになる、という挙動をしました。

というところまでは調べたのですが、ファクターXがなんなのかが結局わかりませんでした。