概要
自分用にRustのプロジェクトで使用するGitHub ActionsのCIワークフローを作成したので、まとめてみました。
ワークフロー
まずはどのようなワークフローにしたかをご紹介します。
.github/workflows/rust_test.yml
に以下の内容を書くことで、GitHub Actionsの設定を行うことができます。
GitHub Actionsの詳細は以下などをご参照ください。
name: Rust_CI
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
env:
CARGO_TERM_COLOR: always
RUSTFLAGS: "-Dwarnings"
jobs:
test:
runs-on: ubuntu-latest
defaults:
run:
working-directory: test_rust
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Cache cargo registry
uses: actions/cache@v4
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Build test
run: cargo build --release --verbose
- name: Run tests
run: cargo test --verbose
- name: Lint with clippy
run: cargo clippy --all-targets --all-features
- name: Check formatting
run: cargo fmt --all --check
例
以下のリポジトリで実験を行っています。
各項目の説明
ここからはそれぞれで何をしているかをできるだけ書いていきたいと思います。
(間違っていたり補足などあればご指摘お願いします)
name
name: Rust_CI
はワークフローの名前です。
こんな感じで表示されます。
on
on
にはどのタイミングでこのワークフローが実施されるかを設定します。
私の場合は以下のようにしています。
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
つまり、mainブランチへのpush時と、mainブランチへのpull_request時のみ、ワークフローが走るようになっています。
以下で詳しく書いていきますが、結構厳しめの設定で作っているので、mainブランチに関する変更の場合のみ動かすようにしています。
また、各ブランチでは、もしかしたら一時的に動かないコードをあげたい……となるかもしれないですが、そのときにCIでエラーがでてしまうと煩わしいかなと思ったので、mainブランチのみ対象にしています。
env
env:
ではワークフロー全体の環境変数を設定しています。
CARGO_TERM_COLOR
ターミナルへの出力時に色をつけるかどうかを指定します。
色がないと見づらいので、always
にして色をつける設定にしています。
RUSTFLAGS
RUSTFLAGS
にはCargoが実行するコマンドに共通して渡すフラグを設定することができます。
今回はRUSTFLAGS: -Dwarnings
としていて、warningが出たときにエラーになるようにしています。
これでwarningをCIで見つけられるようにしています。
jobs
ワークフローは1つ以上のjobで構成されます。
今回は一つのjob(testという名前)だけで構成されています。
jobs:
test:
# 以下でtest jobの設定
runs-on
runs-on: ubuntu-latest
ではjobを実行するOS(今回はubuntu-latest
)を指定しています。
ちなみにこの中にはRustの最低限のあれこれが入っているようなので、Cargoをinstallするなどといったことはする必要はないようです。
defaults
defaults:
ではそのjob内で共通の設定を行うことができます。
working-directory
defaults:
run:
working-directory: test_rust
working-directory
にディレクトリを設定することで、そのディレクトリでコマンドを実行してくれるようになります。
私は基本的にリポジトリ直下にRustのプロジェクトを置かないので、この設定を入れています。
steps
steps:
で実行するタスクを設定します。
基本的には設定した順番で実行されますが、場合によってはステップの実行後に後処理を自動で加えてくれる場合もあります。
例えば、今回使用しているワークフローの中だとactions/checkout
とactions/cache
については、jobのclean upをするステップを最後に追加します。
Checkout
- name: Checkout
uses: actions/checkout@v4
このステップでは、GitHubリポジトリのコードをこの後のステップでアクセスできるようにしてくれています。
ちなみにnameはステップの名前なので、好きな名前を設定することができます。
Cache
- name: Cache cargo registry
uses: actions/cache@v4
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
このステップでは依存関係のダウンロード時間を節約するために、Cargoの依存関係のキャッシュを設定しています。
詳細については省略しますが、以下などを参考にしました。
参考にしたサイトに書いてあったことですが、私の設定だとリポジトリ内のコードのビルドはフルビルドになっていて、Cacheをうまく使えていないようです。
その原因や解決方法などは、上記の1つめのサイトをご参照ください。
※ もしかしたらこの問題は解決されていて、最近ではリポジトリ内のコードのビルドについてもキャッシュされるようになっているかもしれませんが、詳細は調べていません
Build
- name: Build test
run: cargo build --release --verbose
buildがうまくいくかどうかをテストしています。
Test
- name: Run tests
run: cargo test --verbose
テストを実行しています。
Lint
- name: Lint with clippy
run: cargo clippy --all-targets --all-features
このステップでは、Lintツールであるclippyを使用して確認をしています。
clippyについての詳細は以下がわかりやすかったです。
こちらでは以下を参考に、--all-targets
ですべてのビルドターゲット(binやlibだけでなく、テスト、exsamplesなども)に対して、--all-features
ですべての機能(features)に対してLintの対象になるようにしています。
Format
- name: Check formatting
run: cargo fmt --all --check
このステップでは、コードフォーマットツールであるrustfmtを使用しています。
こちらもrustfmtについての詳細は以下がわかりやすかったです。
それぞれのフラグについてですが、--all
ですべてのコードを対象にフォーマットを行っています。
また、cargo fmtのデフォルトでは実行するとコードを書き換えるようになっているのですが、今回のCIではコードの書き換えを許していないので、--check
で書き換える代わりにエラーで知らせてくれるようにしています。
ちなみに書き換えることを許可する場合はGitHubでの設定がたしか必要になった気がします。
おわりに
以前こちらでRustとWebAssemblyでWebサービスを行う際の設定の記事を書きました。
こちらの記事の中ではテスト関連についてはあまり書いていませんでしたが、いずれ今回の内容もふまえてアップデート版を書きたいと思います。