Slide 1

Slide 1 text

GitHub ActionsでGoの テストを並列実行し カバレッジレポートを作る 2024/12/11 @DMM.go プラットフォーム開発本部 第一開発部 ポイントクラブグループ webチーム デザインエンジニア @SANdglAss

Slide 2

Slide 2 text

● 2021年に新卒で入社したバックエンドエンジニア ● 3年目からは「デザインエンジニア」としてUI/UXデザインや UXライティングも担当中 くわしくは「デザインエンジニア」で検索 🔍 自己紹介

Slide 3

Slide 3 text

GoプロジェクトのCIをCircleCI → GitHub Actionsに

Slide 4

Slide 4 text

● とある事情で移行することに ● 無事すべて移行できた ● テストジョブの所要時間が1分半 → 5分になった GoプロジェクトのCIをCircleCI → GitHub Actionsに

Slide 5

Slide 5 text

GoプロジェクトのCIをCircleCI → GitHub Actionsに なんでやねん ● とある事情で移行することに ● 無事すべて移行できた ● テストジョブの所要時間が 1分半 → 5分になった

Slide 6

Slide 6 text

遅くなった主な理由: マシンスペック(コア数) Docker 実行環境の使用 - CircleCI GitHub Actions CircleCI About GitHub-hosted runners - GitHub Enterprise Cloud Docs ↑のドキュメントはエンプラですが Cloudも同じです

Slide 7

Slide 7 text

CIに詳しいマリーアントワネット

Slide 8

Slide 8 text

CIに詳しいマリーアントワネット 「スペックが足りないなら 強いのを使えばいいじゃない」

Slide 9

Slide 9 text

CIに詳しいマリーアントワネット 「スペックが足りないなら 強いのを使えばいいじゃない」 → 現状のDMM Organizationでは使えない ...

Slide 10

Slide 10 text

CIに詳しいマリーアントワネット

Slide 11

Slide 11 text

CIに詳しいマリーアントワネット 「コアが少ないならノード並列で 分割実行すればいいじゃない」

Slide 12

Slide 12 text

CIに詳しいマリーアントワネット 「コアが少ないならノード並列で 分割実行すればいいじゃない」 → それでいきましょう

Slide 13

Slide 13 text

1つのジョブを並列実行: CircleCI編

Slide 14

Slide 14 text

1つのジョブを並列実行: CircleCI編 とてもかんたん

Slide 15

Slide 15 text

1つのジョブを並列実行: GitHub Actions編

Slide 16

Slide 16 text

1つのジョブを並列実行: GitHub Actions編 ない

Slide 17

Slide 17 text

1つのジョブを並列実行: GitHub Actions編 なんでやねん ない

Slide 18

Slide 18 text

1つのジョブを並列実行: GitHub Actions編 ジョブを並列実行する仕組み自体は、ないわけではない

Slide 19

Slide 19 text

1つのジョブを並列実行: GitHub Actions編 ジョブを並列実行する仕組み自体は、ないわけではない その名も matrix ワークフローでのジョブのバリエーションの実行 - GitHub Docs

Slide 20

Slide 20 text

1つのジョブを並列実行: GitHub Actions編 ジョブを並列実行する仕組み自体は、ないわけではない その名も matrix 変数のパターンを 列挙しておくと ワークフローでのジョブのバリエーションの実行 - GitHub Docs

Slide 21

Slide 21 text

1つのジョブを並列実行: GitHub Actions編 ジョブを並列実行する仕組み自体は、ないわけではない その名も matrix 各値が設定された ジョブが並列で 立ち上がる ワークフローでのジョブのバリエーションの実行 - GitHub Docs 変数のパターンを 列挙しておくと

Slide 22

Slide 22 text

1つのジョブを並列実行: GitHub Actions編 ジョブを並列実行する仕組み自体は、ないわけではない その名も matrix 各値が設定された ジョブが並列で 立ち上がる 変数のパターンを 列挙しておくと どうにかして 使えないものか ... ワークフローでのジョブのバリエーションの実行 - GitHub Docs

Slide 23

Slide 23 text

Rubyで用いし先駆者がいた

Slide 24

Slide 24 text

Rubyで用いし先駆者がいた GitHub Actions でテストを並列化して CI 時間を短縮する - Gunosy Tech Blog

Slide 25

Slide 25 text

Rubyで用いし先駆者がいた GitHub Actions でテストを並列化して CI 時間を短縮する - Gunosy Tech Blog 並列化したい数だけ IDを宣言しておいて

Slide 26

Slide 26 text

Rubyで用いし先駆者がいた GitHub Actions でテストを並列化して CI 時間を短縮する - Gunosy Tech Blog 並列化したい数だけ IDを宣言しておいて 全テストをいい感じに 各IDに割り振って

Slide 27

Slide 27 text

Rubyで用いし先駆者がいた GitHub Actions でテストを並列化して CI 時間を短縮する - Gunosy Tech Blog 並列化したい数だけ IDを宣言しておいて 各ノードは自分の IDの テストだけ実行 全テストをいい感じに 各IDに割り振って

Slide 28

Slide 28 text

Rubyで用いし先駆者がいた GitHub Actions でテストを並列化して CI 時間を短縮する - Gunosy Tech Blog 並列化したい数だけ IDを宣言しておいて 各ノードは自分の IDの テストだけ実行 全テストをいい感じに 各IDに割り振って これをGoでも やりたい!

Slide 29

Slide 29 text

Goでのテスト分割は(とりあえず)パッケージ毎で

Slide 30

Slide 30 text

Goでのテスト分割は(とりあえず)パッケージ毎で これが

Slide 31

Slide 31 text

Goでのテスト分割は(とりあえず)パッケージ毎で これが こうなりました

Slide 32

Slide 32 text

Goでのテスト分割は(とりあえず)パッケージ毎で これが こうなりました パッケージのパスを列挙して

Slide 33

Slide 33 text

Goでのテスト分割は(とりあえず)パッケージ毎で これが こうなりました パッケージのパスを列挙して テスト対象外の パッケージを 除外して (無くてもいいしいくつあってもいい )

Slide 34

Slide 34 text

Goでのテスト分割は(とりあえず)パッケージ毎で これが こうなりました パッケージのパスを列挙して 行番号を4(並列数)で割ったあまり == 自分のid なら担当 テスト対象外の パッケージを 除外して (無くてもいいしいくつあってもいい )

Slide 35

Slide 35 text

Goでのテスト分割は(とりあえず)パッケージ毎で これが こうなりました パッケージのパスを列挙して テスト対象外の パッケージを 除外して (無くてもいいしいくつあってもいい ) 行番号を4(並列数)で割ったあまり == 自分のid なら担当 よし!いけるぞ! と言いたいところだが ...

Slide 36

Slide 36 text

唯一の懸念点: カバレッジレポートどうしよう

Slide 37

Slide 37 text

Goは素晴らしい言語なので $ go test -cover ./... -coverprofile=<ファイル名>.out でテスト時にカバレッジのプロファイルを吐き出しておき $ go tool cover -html=<ファイル名>.out -o <ファイル名>.html  でカバレッジレポートを作れる 唯一の懸念点: カバレッジレポートどうしよう

Slide 38

Slide 38 text

唯一の懸念点: カバレッジレポートどうしよう Goは素晴らしい言語なので $ go test -cover ./... -coverprofile=<ファイル名>.out でテスト時にカバレッジのプロファイルを吐き出しておき $ go tool cover -html=<ファイル名>.out -o <ファイル名>.html  でカバレッジレポートを作れる でもnノードで分割実行したら細切れのカバレッジレポートが n個できちゃう

Slide 39

Slide 39 text

唯一の懸念点: カバレッジレポートどうしよう Goは素晴らしい言語なので $ go test -cover ./... -coverprofile=<ファイル名>.out でテスト時にカバレッジのプロファイルを吐き出しておき $ go tool cover -html=<ファイル名>.out -o <ファイル名>.html  でカバレッジレポートを作れる でもnノードで分割実行したら細切れのカバレッジレポートが n個できちゃう → 結論: プロファイルの仕様で (無理やり)解決!

Slide 40

Slide 40 text

唯一の懸念点: カバレッジレポートどうしよう 結論: プロファイルの仕様で (無理やり)解決!

Slide 41

Slide 41 text

唯一の懸念点: カバレッジレポートどうしよう 結論: プロファイルの仕様 で(無理やり)解決!

Slide 42

Slide 42 text

唯一の懸念点: カバレッジレポートどうしよう 結論: プロファイルの仕様 で(無理やり)解決! カバレッジの計算モード set・count・atomicがある(割愛) ※ golang/go/src/cmd/cover/profile.goに該当の実装があります

Slide 43

Slide 43 text

各ファイルのカバレッジ情報 :.,. というフォーマットでカバレッジが大量にメモられている カバレッジの計算モード set・count・atomicがある(割愛) ※ golang/go/src/cmd/cover/profile.goに該当の実装があります 唯一の懸念点: カバレッジレポートどうしよう 結論: プロファイルの仕様 で(無理やり)解決!

Slide 44

Slide 44 text

そしてできあがった.yamlがこちら

Slide 45

Slide 45 text

そしてできあがった.yamlがこちら ※ 環境変数や serviceなど、この発表の範囲外と判断したために一部省略している箇所があります

Slide 46

Slide 46 text

そしてできあがった.yamlがこちら ※ 環境変数や serviceなど、この発表の範囲外と判断したために一部省略している箇所があります 例のID

Slide 47

Slide 47 text

例のID そしてできあがった.yamlがこちら ※ 環境変数や serviceなど、この発表の範囲外と判断したために一部省略している箇所があります テストを実行しプロファイルを出力

Slide 48

Slide 48 text

例のID そしてできあがった.yamlがこちら ※ 環境変数や serviceなど、この発表の範囲外と判断したために一部省略している箇所があります テストを実行しプロファイルを出力 名前にIDを含んだartifactを後続のジョブに遺す

Slide 49

Slide 49 text

例のID そしてできあがった.yamlがこちら ※ 環境変数や serviceなど、この発表の範囲外と判断したために一部省略している箇所があります テストを実行しプロファイルを出力 名前にIDを含んだartifactを後続のジョブに遺す ダウンロード

Slide 50

Slide 50 text

例のID そしてできあがった.yamlがこちら ※ 環境変数や serviceなど、この発表の範囲外と判断したために一部省略している箇所があります テストを実行しプロファイルを出力 名前にIDを含んだartifactを後続のジョブに遺す ダウンロード 1行目を直接書いて最終ファイルを作成 →各プロファイルの2行目以降をくっつける

Slide 51

Slide 51 text

例のID そしてできあがった.yamlがこちら ※ 環境変数や serviceなど、この発表の範囲外と判断したために一部省略している箇所があります テストを実行しプロファイルを出力 名前にIDを含んだartifactを後続のジョブに遺す ダウンロード レポート 作成

Slide 52

Slide 52 text

例のID そしてできあがった.yamlがこちら ※ 環境変数や serviceなど、この発表の範囲外と判断したために一部省略している箇所があります テストを実行しプロファイルを出力 名前にIDを含んだartifactを後続のジョブに遺す ダウンロード レポート 作成 最終レポート(HTML)を保存

Slide 53

Slide 53 text

例のID そしてできあがった.yamlがこちら ※ 環境変数や serviceなど、この発表の範囲外と判断したために一部省略している箇所があります テストを実行しプロファイルを出力 名前にIDを含んだartifactを後続のジョブに遺す ダウンロード レポート 作成 最終レポート(HTML)を保存 絶対もっといいやり方あるだろ

Slide 54

Slide 54 text

\ ありがとうございました! /