【Rust/Github Actions】自動でクレートのバージョンアップをするワークフロー
はじめに
この記事では、GitHub Actionsを利用して、クレートのバージョン管理を自動化する方法について説明します。
Rust で独自のクレートを構築し公開している場合、適宜 Cargo.toml
を更新しバージョンアップのためのコミットを入れる必要があります。場合によって、cargo publish
で crates.io に更新をプッシュしたり、タグ打ちを行うケースもあります。このバージョンアップについて、Github Actions で自動化してみましょう。
完成状態
今回構築するワークフローの実装はこちらです。
いくつか特徴をピックアップしておくと、以下のようなツールを利用してワークフローを構築しています。
- リリースのための変更操作 ->
cargo-release
crate - Git,GitHub への操作 -> Git & GitHub CLI
name: Release
on:
workflow_dispatch:
inputs:
level_or_version:
description: 'Parameter specifying update version, to use with `cargo release version` ex: `1.0.0`, `patch` etc'
type: string
env:
RUST_VERSION: 1.76.0
DEFAULT_RELEASE_LEVEL: patch
BASE_BRANCH_NAME: topic/version-up
jobs:
release:
runs-on: ubuntu-latest
env:
GH_TOKEN: ${{ secrets.PAT }}
steps:
- name: Checkout the source code
uses: actions/checkout@v3
- name: Install Rust
run: |
rustup update ${{ env.RUST_VERSION }} --no-self-update
rustup default ${{ env.RUST_VERSION }}
- name: Install cargo-release
run: cargo install cargo-release --locked
- name: Run cargo release
run: |
git config --global user.name "${{ github.actor }}"
git config --global user.email "${{ github.actor }}@users.noreply.github.com"
cargo release version --execute --no-confirm ${{ github.event.inputs.level_or_version || env.DEFAULT_RELEASE_LEVEL }}
PKG_VER=$(cargo metadata --format-version=1 --no-deps | jq ".packages[0].version" | tr -d '"')
git checkout -b ${{ env.BASE_BRANCH_NAME }}-$PKG_VER
cargo release commit --execute --no-confirm
git push -u origin HEAD
gh pr create --fill
gh pr merge --auto
Step By Step
前のセクションで完成したワークフローを展開しましたが、ここでは必要とするパーツごとに解説を加えながら完成系を作る流れを紹介していきます。
リポジトリチェックアウトなどテンプレート部分
まずは、自身のプロジェクトを cargo
で操作できる前提部分を構築します。
リポジトリのチェックアウトは actions/checkout@vN
で実行し、その後 Rust のインストールを行います。
name: Release
on: # TODO
env:
RUST_VERSION: 1.76.0
jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Checkout the source code
uses: actions/checkout@v3
- name: Install Rust
run: |
rustup update ${{ env.RUST_VERSION }} --no-self-update
rustup default ${{ env.RUST_VERSION }}
最小限のバージョンアップの操作
バージョンアップのための修正/コミットには cargo-release
を使用します
cargo-release とは、cargo プロジェクトのリリースに関する操作をコマンドでサポートするクレートの一つです。バージョンアップのための更新処理をコマンド一つで実行したり、changelogs の生成やタグ打ち、リリースまで実行することができます。
まずは cargo-release
をインストールします。
- name: Install Rust
run: |
rustup update ${{ env.RUST_VERSION }} --no-self-update
rustup default ${{ env.RUST_VERSION }}
+ - name: Install cargo-release
+ run: cargo install cargo-release --locked
次にこの cargo-release
を活用して、
-
- バージョンアップのための修正
-
- "1" の変更のコミット
-
- "2" を remote branch にプッシュ
という操作を実施します。
- name: Install cargo-release
run: cargo install cargo-release --locked
+ - name: Run cargo release
+ run: |
+ cargo release version --execute --no-confirm patch # 1)
+ cargo release commit --execute --no-confirm # 2)
+ cargo release push --execute --no-confirm # 3)
cargo release
で cargo-release
クレートを利用します。サブコマンド version
で "バージョンアップのための修正" を行い commit
で "変更のコミット"、 push
で "リモートブランチへのプッシュ" を行います。
最低限実施したいことはこちらで満たすことができていますが、実際に運用しているリポジトリではいくつか問題があります。最たる問題の一つは、この方法ではデフォルトブランチに直接プッシュをしているということです。プライベートではないリポジトリの多くがデフォルトブランチを保護している場合が多くこのままでは利用できないことがほとんどでしょう。次のセクションでは "プルリクエストを介した更新" を行うように修正します。
プルリクエストを介した更新
直接デフォルトブランチにプッシュすることをやめて、プルリクエストを作成する方針とします。GitHub に対する操作のために GitHub CLI
を利用します。GitHub Actions の環境では GitHub CLI がプリインストールされていて、特にインストールコマンド等は不要で使用することができます。
GitHub CLI is preinstalled on all GitHub-hosted runners. For each step that uses GitHub CLI, you must set an environment variable called GH_TOKEN to a token with the required scopes.
Source: https://docs.github.com/en/actions/using-workflows/using-github-cli-in-workflows
以下のように修正をしましょう。
release:
runs-on: ubuntu-latest
+ env:
+ GH_TOKEN: ${{ secrets.PAT }}
steps:
...
- name: Install cargo-release
run: cargo install cargo-release --locked
- name: Run cargo release
run: |
+ git config --global user.name "${{ github.actor }}"
+ git config --global user.email "${{ github.actor }}@users.noreply.github.com"
cargo release version --execute --no-confirm patch
+ PKG_VER=$(cargo metadata --format-version=1 --no-deps | jq ".packages[0].version" | tr -d '"')
+ git checkout -b topic/version-up-$PKG_VER
cargo release commit --execute --no-confirm
- cargo release push --execute --no-confirm
+ git push -u origin HEAD
+ gh pr create --fill
+ gh pr merge --auto
まずは GitHub CLI を使用するために Access Token を環境変数 GH_TOKEN
に設定する必要があります。今回はシークレット PAT
に設定した Personal Access Token を使用することにします。このアクセストークンを job 全体で利用可能にしておきます。
+ env:
+ GH_TOKEN: ${{ secrets.PAT }}
アクセストークン自体の設定方法は以下を参考にしてください。
Managing your personal access tokens - GitHub Docs
Using secrets in GitHub Actions - GitHub Docs
次に git
コマンドを直接利用します。更新のための新規ブランチを作成し、変更をプッシュするまで行います。cargo metadata
を利用することで更新後のバージョン情報を取得し、そのバージョン情報をブランチ名称に適用することでブランチの衝突を避けるようにします。
run: |
+ git config --global user.name "${{ github.actor }}"
+ git config --global user.email "${{ github.actor }}@users.noreply.github.com"
cargo release version --execute --no-confirm patch
+ PKG_VER=$(cargo metadata --format-version=1 --no-deps | jq ".packages[0].version" | tr -d '"')
+ git checkout -b topic/version-up-$PKG_VER
cargo release commit --execute --no-confirm
- cargo release push --execute --no-confirm
+ git push -u origin HEAD
最後に GitHub CLI を利用して、プルリクエストの操作を行います。gh pr create
でプルリクエストの作成をします。オプション --fill
で自動でタイトルやボディを設定してくれます。
+ gh pr create --fill
gh pr create | GitHub CLI | Take GitHub to the command line
gh pr merge
でプルリクエストのマージの操作をすることができます。オプション --auto
により、設定された CI の checks が完了したことを確認した上でマージさせることができます。
+ gh pr merge --auto
gh pr merge | GitHub CLI | Take GitHub to the command line
参考: Github Actionsを使ってプルリクエストを自動でマージしたい - そうきたか
改善: パラメータの変数化
ハードコーディングされている固定値の部分に関して、ここで変数を利用するようにします。これによってなんらか更新をしたい場合に修正箇所を容易に把握できるようなり、ワークフローを利用しようとする人に対してもヒントとなり得ます。
env:
RUST_VERSION: 1.76.0
+ DEFAULT_RELEASE_LEVEL: patch
+ BASE_BRANCH_NAME: topic/version-up
jobs:
release:
...
steps:
...
- name: Run cargo release
run: |
...
+ cargo release version --execute --no-confirm ${{ env.DEFAULT_RELEASE_LEVEL }}
...
+ git checkout -b ${{ env.BASE_BRANCH_NAME }}-$PKG_VER
...
改善: workflow_dispatch の利用
今回のワークフローは手動で発火可能に設定することにします。そのために workflow_dispatch
イベントを利用します。
name: Release
+on:
+ workflow_dispatch:
+ inputs:
+ level_or_version:
+ description: 'Parameter specifying update version, to use with `cargo release version` ex: `1.0.0`, `patch` etc'
+ type: string
また inputs
パラメータを使用することで、実行時にパラメータ指定できるようにしています。今回は level_or_version
でバージョンをどのように更新できるか string 型で指定できるようにしています。このパラメータに設定された値は下記のように job 側で使用できるようにしましょう。
- cargo release version --execute --no-confirm ${{ env.DEFAULT_RELEASE_LEVEL }}
+ cargo release version --execute --no-confirm ${{ github.event.inputs.level_or_version || env.DEFAULT_RELEASE_LEVEL }}
終わりに
この記事では、Rust プロジェクトでのバージョン管理を自動化するための GitHub Actions ワークフローを実装する方法について説明しました。ワークフローの構築には cargo-release
crate や GitHub CLI
を活用しました。
このように GitHub Actions を使用してクレートのバージョン管理を自動化することで、これらにかかる時間をクレートの開発に回すことができると思います!
Discussion