Renovate の Package 更新に合わせて Package.resolved も GitHub Actions で更新する
パッケージの更新を自動で行ってくれる Renovate ですが、記事執筆時点では残念ながら SwiftPM に完全に対応されているわけではなく、Package.swift
と一緒に更新されて欲しい Package.resolved
の更新は行ってくれません (issue は作られていて作業も少し進んでいるようではあります)。
ただ、現状の Renovate でも Package.swift
の更新だけは行ってくれるので、それに合わせて Package.resolved
を更新してくれる GitHub Actions の workflow を作成しようと思い、実際に作成しました。
あくまで例とはなりますが、以下のような workflow でそのような機能が実現できました。
name: Update Package.resolved for Renovate
on:
pull_request:
types: [opened, synchronize]
paths:
- "**/Package.swift"
jobs:
get-changed-files:
runs-on: ubuntu-latest
# branch 名に `renovate` が含まれていなければ処理を skip する
if: contains(github.head_ref, 'renovate')
outputs:
all_changed_files: ${{ steps.changed-files.outputs.all_changed_files }}
steps:
- uses: actions/checkout@v3
with:
token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v36
update-package-resolved:
runs-on: macos-latest
needs: get-changed-files
# `Package.resolved` が含まれている場合には処理を実行しないようにして、workflow の無限ループを防いでいる
if: ${{ !contains(join(needs.get-changed-files.outputs.all_changed_files, ' '), 'Package.resolved') }}
steps:
- uses: actions/checkout@v3
with:
token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
- name: Setup Xcode
uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: latest-stable
- name: Setup ssh
run: |
SSH_PATH="$HOME/.ssh"
mkdir -p "$SSH_PATH"
touch "$SSH_PATH/known_hosts"
echo "$SSH_PRIVATE_KEY" > "$SSH_PATH/id_rsa"
chmod 700 "$SSH_PATH"
ssh-keyscan github.com >> ~/.ssh/known_hosts
chmod 600 "$SSH_PATH/known_hosts"
chmod 600 "$SSH_PATH/id_rsa"
eval $(ssh-agent)
ssh-add "$SSH_PATH/id_rsa"
env:
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
# xcodebuild -resolvePackageDependencies で任意の workspace などを指定して `Package.resolved` をアップデートする
- name: Update Package.resolved
run: |
...
xcodebuild -resolvePackageDependencies -workspace "$workspace" -scheme "$scheme"
# 既存の Action を利用しているが、単純な操作なので普通に git command でも良さそう
- uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: Update Package.resolved
commit_user_name: ...
commit_user_email: ...
commit_author: ...
env:
GITHUB_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
特に複雑な workflow ではないですが、以下の 2 点だけ簡単に補足しておこうと思います。
get-changed-files
- private な Swift Package を取得するための ssh の設定
get-changed-files
自分が今回関わっていたプロジェクトではいくつかの Package.swift
が存在していました。
そのため、「変更された Package.swift
の file path に基づいて、特定の Package.resolved
を更新する」という挙動を実現するために、ファイルの差分を取得しています。
また、PR の差分に Package.resolved
が含まれているかどうかの判定のためにも利用しています。
ssh の設定
private な Swift Package を CI 上で取得したい場合、例えば ssh を利用して Package を取得するようにしておく必要があります (詳しい話については以下を参考にさせていただきました)。
その場合、以下の記事に記載されているような手順で ssh の設定も行っておく必要があります (Node の話ですが、ssh のための設定手順は同じです)。
後は、ssh のセットアップを workflow 上で行った後で xcodebuild を実行すれば、xcodebuild は自動でマシンの ssh 設定を使ってくれるため、問題なく private な Swift Package も取得できるようになります。
xcodebuild の挙動などについては以下の記事を参考にしました。
おわりに
ちなみに、この workflow を作ってしまった後で、「実は既にそういうもの作られているのでは...?」と思って軽く検索してみただけでもいくつかヒットしてしまい、最初に検索しておかなかったことを少し後悔しました。
自分が今回紹介した workflow は、プロジェクトによってはもっとシンプルにできたり、そもそも冗長な処理があるものになってしまっているかもしれない (今パッと見ただけでもいくつかありそうだった) ですが、Renovate の利用中に困ったときなど、何かの参考になったら嬉しいです。
Discussion