はじめに
「コードフォーマットが適用されておりません。」
こんな指摘をした人、された人。いるのではないでしょうか?
今回はコードフォーマットをCIツールで実行し、開発者はフォーマッターの実行をしないような仕組みを紹介します。
この記事を書こうと思った動機
お客様指定のコードスタイルのある規約があるプロダクトにおいて以下の問題に直面し、結果的に工数が増大したため。
ケース1. ローカルで「コードフォーマッター」が適用されずにPull Requestを出すケース
ケース2. すり抜けコードをベースに修正し、コードフォーマッターを適用したら、改修箇所以外の差分が抽出された
【コードフォーマッターが適用されないわけ】
- 開発環境構築手順書・開発フローにコードフォーマッターの記載されていない。(曖昧なドキュメント)
- 開発メンバー間でのフローの引き継ぎもない(開発メンバーが流動的)
折角コードフォーマッターの設定ファイルを用意しても、運用されていなければ意味がありません。
ドキュメントをしっかり書いたとしても、プロジェクトメンバー全員の開発環境設定が同じであることを確認するにも限度があります。そのため、同じような悩みを持っているコードオーナの方向けにCIツール側でコードフォーマッターを適用する方法について紹介しようと思いました。
CIツールでコードフォーマッターを実行する
解決アイディア : 開発環境に依存するのでは無く、フォーマッタはレビュー実施前に自動的に適用される方式とする。
前提
CIツールとコードフォーマッターを連携するために以下の要件を満たす必要があります。
- バージョン管理ツールへのPushやPull Request(Merge Request)を検出する仕組み
- 以下に対応したコードフォーマッターが存在すること
- コマンドラインから実行可能で且つ、スタンドアロンで動作可能なツールであること
- CIツールに対応したツールであること
後述の方式は上記の要件を満たしたツールを選定しておりますが、もし存在しない( 特に [1.] ) は自作することもご検討ください。
コードフォーマット自動適用例
今回のサンプルは以下の仕様のもとで作成するものとする。
項目 | 内容 |
---|---|
プログラミング言語 | Java |
コードスタイル | Google Java Style Guide に準拠 |
ツール | google-java-format |
CIツールで自動的にコードフォーマッターを実行する
CI用コード(GitHub Action)
コードの前提
以下のScriptはGitHub MarketplaceでVerifiedとなっているプラグインのみ利用して実現しております。
(※手早く実装したい場合はMarketplaceにあるプラグインをどんどん活用しましょう)
name: Reformat Java source code
on:
pull_request:
jobs:
format:
runs-on: ubuntu-latest
steps:
# Pull Requestされたブランチをチェックアウト
- uses: actions/checkout@v2
with:
ref: ${{ github.head_ref }}
# Java のセットアップ
- name: Set up JDK 11
uses: actions/setup-java@v1
with:
java-version: 11
# Gitの設定
- name: Git settings
run: |
# Git リポジトリの設定
git config --local user.name "ユーザ名"
git config --local user.email "E-Mailアドレス"
# コードフォーマットの実行(※1)
- name: Code format
run: |
wget -q -O google-java-format.jar \
https://github.com/google/google-java-format/releases/download/google-java-format-1.9/google-java-format-1.9-all-deps.jar
# 以下の例ではすべての変更に対してフォーマッタを加えております。
# プルリクエスト時の変更を取る場合はgit logで変更差分のみ取得してフォーマッタをかけましょう。(※2)
java -jar google-java-format.jar -replace $(git ls-files src/**/*.java)
# 変更確認
- name: Check for modified files
id: git-check
run: echo ::set-output name=modified::$(if git diff-index --quiet HEAD --; then echo "false"; else echo "true"; fi)
# 変更されていた場合、コミット・プッシュを行う(※3)
- name: Push
if: steps.git-check.outputs.modified == 'true'
run: |
git commit -am "Automated :Reformat Java source code."
git push
※1 … google-java-format
※2 … get-all-changed-files
※3 … Git Auto Commit
実行結果
PullRequst実施、変更時にコードフォーマッターが適用された新しいコミットが追加される
サンプルリポジトリ
上記は以下のリポジトリで実現されております。(ブランチ: feature/format-action)
https://github.com/yukiusa/github-action-auto-java-format-sample/tree/feature/format-action
さいごに
いかがだったでしょうか?
今回はCIツールを利用し「開発環境に依存せずルールを遵守させる仕組み」について紹介しました。
本取り組みを実施することで
- 開発環境の作成の手間を減らす
- チェックの工数を削減する
- レビューア・レビューイの負荷を減らす
などの効果が期待できるかと思います。
今後の業務の改善案の一つとしてお役立ていただければ幸いでございます。
最後まで読んでいただきましてありがとうございました。
改訂履歴
@naminodarie 様からの指摘一部修正。ご指摘ありがとうございました。