GitHubのDependabotでSwift Packageのアップデートを監視する
2023/8/1にようやくDependabotがSwiftをサポートしました🎉
ということで、Dependabotを使ってSwift Packageのアップデートを監視する方法をまとめます。
前提
- Dependabotには
Dependabot alerts
とDependabot security updates
とDependabot version updates
の3種類があるが、今回は3つ目の話 - あくまでSwift Packageの依存ライブラリのアップデート検出が対象
- アップデートを監視できるのは
Package.swift
で依存の定義をしている外部Package - Xcode Project(
.xcodeproj
)で依存の定義をした外部Packageは対象外
- アップデートを監視できるのは
方法
Dependabot version updatesを有効にするには、リポジトリのルートディレクトリに.github
というディレクトリを配置し、その中にdependabot.yml
ファイルを置くだけでよいです。
例えば、以下のような構成の自作のSwift PackageでDependabot version updatesを有効にする場合
.
├── LICENSE
├── README.md
├── Package.swift
├── Package.resolved
├── Sources
└── Tests
以下のようにYAMLを書けば、毎日深夜2時にライブラリのアップデートを確認してPRを立ててくれます。(細かい構文に関してはこちら)
version: 2
updates:
- package-ecosystem: "swift"
directory: "/"
schedule:
interval: "daily"
timezone: "Asia/Tokyo"
time: "02:00"
なお、重要なポイントとして、Dependabotが動作するにはPackage.resolved
が必須です。
これがないと
updater | 2023/09/15 04:35:45 ERROR <job_722281318> Error processing github.com/firebase/firebase-ios-sdk (NoMethodError)
updater | 2023/09/15 04:35:45 ERROR <job_722281318> undefined method `content' for nil:NilClass
updater |
updater | return if updated_lockfile_content == lockfile.content
updater | ^^^^^^^^
のようなログを吐くエラーとなって、Dependabotの処理が失敗します。
次に、Xcode Project(要はアプリ)でローカルのSwift Packageによるマルチモジュール構成などを構築している場合
.
├── SampleApp
├── SampleApp.xcodeproj
└── LocalPackage
├── Package.swift
├── Package.resolved (普通はない状態だと思われる)
├── Sources
└── Tests
まず、LocalPackageだけをXcodeで開いてResolve Package Dependenciesを走らせれば、Package.resolved
ファイルが生成されます。これが必須です。
この状態で以下のようにYAMLを書けばDependabot version updatesが有効になります。
version: 2
updates:
- package-ecosystem: "swift"
directory: "/LocalPackage"
schedule:
interval: "daily"
timezone: "Asia/Tokyo"
time: "02:00"
ちなみに、ここでLocalPackage/Package.resolved
ではなく、SampleApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
のシンボリックリンクをおけばうまく動かないかなと思って実験してみましたがダメでした。
動作確認
リポジトリのInsights > Dependency graph > dependabot > Check for updates を押せば、手動でdependabot.yml
を動かすことができますが、この場合にはPRが作られません。あくまで。また、pushしただけでもCheck for updatesが走るのですが、その間はschedule
で指定した時間に自動で動いたときにだけPRが作られることに注意してくださいschedule
で指定した方の処理も行われないので、動作確認をしたいときは10分後くらいに発火するようにするといいです。
依存パッケージがプライベートリポジトリの場合
社内ライブラリや個人の公開していないライブラリを使って運用している場合、プライベートリポジトリのSwift Packageに依存することになると思います。その場合は、それ用に別途設定が必要です。
DependabotのSwift対応状況は、プライベートリポジトリに関してgit onlyと書かれているので、type: git
のregistry設定が必要です。
version: 2
registries:
private-libraries: #ここの名前は任意
type: git
url: https://github.com
username: user-name #プライベートリポジトリへのRead権限を持つアカウント名
password: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
updates:
- package-ecosystem: "swift"
registries: "*"
・・・
- YAMLファイルに
registries
の記述をする - 各プライベートリポジトリへのRead権限を持つアカウントを用意する
- 上記のアカウントのPersonal Access Tokenを発行する
- Personal Access TokenをDependabotを動かしたいリポジトリのSettings > Secrets and Variables > Dependabotに登録する
Swift PackageライブラリのURL指定に気をつける
現状のDependabotはPackage.swift
で指定されているSwift Packageのurl
とPackage.resolved
で指定されているSwift Packageのlocation
が完全一致していないと、更新の監視対象から除外してしまうようです。
dependencies: [
+ .package(url: "https://github.com/org/repo-name.git", exact: "1.0.0"),
]
{
"pins": [
{
"identity" : "library-name",
"kind" : "remoteSourceControl",
+ "location" : "https://github.com/org/repo-name",
"state" : {
"revision" : "b35827a61c1420e40ff8e7c584b5042144d20195",
"version" : "1.0.0"
}
},
],
"version" : 3
}
上記のようにPackage.swift
の方には末尾に.git
が含まれ、Package.resolved
の方には末尾に.git
が含まれていないような場合、Pull Requestを立ててくれなくなってしまいます。
これはDependabotの考慮不足なところであると推測します。
Discussion