あなたの現場のGoのフォーマット環境整備屋さん 2.CIでフォーマットチェックの巻
どもーこんちくわ
ルノアールで執筆作業中ですー
ルノアールすごい椅子がフカフカで好きなんですよね😊
落ち着いた雰囲気も好きです!
さて今回は、フォーマット環境整備第二弾!CIの実装です!
今回実装するのはCIはどんな内容か
GitHubにPR作成またはコミットしたときに、CIを動作させます。
そこで、フォーマットチェックをします。
フォーマットが整備されていなかった場合は、CIエラーと判断します。
そんな内容になっています!
CIの内容を定義するファイルを作ろう
まずは下記コマンドでCIに指示を出すymlファイルを作成しましょう!
# フォルダ作成
mkdir -p .github/workflows
# ファイル作成
touch .github/workflows/format.yml
作成したファイルにこのように書いてください!
name: gofmt
on:
pull_request:
push:
branches: [ main ]
jobs:
gofmt:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version-file: go.mod
cache: true
- name: gofmt -s check
shell: bash
run: |
set -euo pipefail
# -w はしない(CIでは“差分が出たら落とす”)
files="$(gofmt -l -s .)"
if [ -n "$files" ]; then
echo "These files are not gofmt -s formatted:"
echo "$files"
echo
echo "Run: gofmt -w -s ."
exit 1
fi
CIファイルの内容説明
runs-on: ubuntu-latest
GitHubが用意しているUbuntuの仮想環境で実行されます。
- uses: actions/checkout@v4
リポジトリのコードをCI環境にチェックアウトします。
これがないと、CI環境にはソースコードが存在しません。
- uses: actions/setup-go@v5
with:
go-version-file: go.mod
cache: true
go.mod に記載されているGoバージョンを利用
キャッシュを有効にして高速化
これで gofmt コマンドが使用可能になります。
set -euo pipefail
Bashの中断設定
-e : エラーが出たら即終了
-u : 未定義変数をエラー扱い
pipefail : パイプ処理内の失敗も検知
CIではほぼ必須の設定です。
files="$(gofmt -l -s .)"
差分ファイルの取得
- -l : 整形が必要なファイル名を出力
- -s : simplify(簡略化オプション)
- . : リポジトリ全体を対象
つまり、
フォーマットされていないファイル一覧を取得
しています。
if [ -n "$files" ]; then
$files が空でなければ、
= フォーマットが崩れているファイルが存在する
という意味です。
echo "These files are not gofmt -s formatted:"
echo "$files"
echo
echo "Run: gofmt -w -s ."
exit 1
CIを失敗させる
整形が必要なファイルを表示
修正コマンドを表示
exit 1 でジョブを失敗させる
これにより、フォーマットが崩れているコードはマージできない仕組みになります。
動作確認してみよう!
CIフォルダ、ファイル作成
$ mkdir -p .github/workflows
$ touch .github/workflows/format.yml
# でお好みのエディタで適当にCI設定を記載
そういえばPR作成用ブランチを作っていなかったので作成
$ git checkout -b test/gofmt
Switched to a new branch 'test/gofmt'
$ git push -u origin test/gofmt
Total 0 (delta 0), reused 0 (delta 0), pack-reused 0
remote:
remote: Create a pull request for 'test/gofmt' on GitHub by visiting:
remote: https://github.com/KM-rira/gofmt-ci/pull/new/test/gofmt
remote:
To github.com:KM-rira/gofmt-ci.git
* [new branch] test/gofmt -> test/gofmt
branch 'test/gofmt' set up to track 'origin/test/gofmt'.
go.modも作成する(今の状態だとエラーになるため)
$ go mod init gofmt-ci
go: creating new go.mod: module gofmt-ci
go: to add module requirements and sums:
go mod tidy
$ go mod tidy
フォーマットができていないファイルを作成する
$ touch main.go
(私の愛しのNeovimエディタは保存時に勝手にフォーマットする設定となっているので、viで編集)
package main
import "fmt"
func main() {
arr := []int{1, 2, 3}
// -s(simplify) で簡略化される(0:len(arr) → :)
s := arr[0:len(arr)]
fmt.Println(s)
// -s で簡略化される(int(1) → 1 など)
x := []int{int(1), int(2), int(3)}
fmt.Println(x)
// これは通常の gofmt でも整形される(スペースなど)
y := 1
fmt.Println(y)
}
このようになればOK
# フォーマットされていないファイルを出力する
$ gofmt -l -s .
main.go
ステージング、コミット、プッシュ!(雑)
$ git add main.go
$ git commit -m "test commit"
[test/gofmt 920de89] test commit
1 file changed, 19 insertions(+)
create mode 100644 main.go
$ git push
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 16 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 536 bytes | 536.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
To github.com:KM-rira/gofmt-ci.git
6154612..920de89 test/gofmt -> test/gofmt
お!動いてる!

フォーマットされていないため、期待通りNG!!

ではフォーマットしましょう!
$ gofmt -w -s .
再度コミットプッシュ
$ git add main.go
$ git commit -m "gofmt -w -s"
$ git push
結果は?

OK!!これで安全なGoの明るいフォーマット未来は保証された!!
みんなも導入してみてね✨
ではでは
Discussion