Slide 1

Slide 1 text

10年もののAPIサーバーにおける CI/CDの改善の奮闘 株式会社エブリー 本丸

Slide 2

Slide 2 text

2 Copyright © 2015 every, Inc. All rights reserved. 目次 1. 自己紹介 2. デリッシュキッチンの紹介 3. 背景 4. やったこと 5. 結果 6. まとめ 7. 宣伝

Slide 3

Slide 3 text

3 Copyright © 2015 every, Inc. All rights reserved. 自己紹介 経歴 - 2021~ 株式会社ハウテレビジョン - 就活生向けのサービスのバックエンド - 2023~ 株式会社エブリー - サーバーサイドエンジニアとして入社 - サーバーサイドとインフラをメインにデリッシュキッチンの機能開発やヘルシカ (ヘルスケアアプ リ)の認証・課金基盤の開発などを担当 - 2024年10月からマネージャー

Slide 4

Slide 4 text

4 デリッシュキッチンの紹介

Slide 5

Slide 5 text

5 Copyright © 2015 every, Inc. All rights reserved. 『デリッシュキッチン』について レシピ提案 / レシピ検索 / 
 献立機能 
 買い物リスト / チラシ / 
 店頭ビーコン連動 
 調理手順動画/キッチンモード / 
 作った・レビュー / お気に入り 
 菅原千遥 
 デリッシュキッチン
 カンパニー長
 料理研究家
 斎藤 香織
 副編集長
 管理栄養士
 • 30名以上の食のプロが、蓄積 データに基づきオリジナル 
 レシピを日々考案 
 • 月間1,500本以上の動画配信 
 サービス・機能 
 レシピ検討 
 買い物
 料理中・料理後 
 専門家によるレシピ考案・監修 
 ■ 日本最大級のレシピ動画サービス 
 ■ 「誰でも簡単においしく作れるレシピ動画」毎日配信 
 ■ 全レシピ、管理栄養士が監修!蓄積データによるオリジナルレシピを考案 
 ■ SNS/APP/WEBを通じて延べ56,000本以上のレシピ動画を提供 


Slide 6

Slide 6 text

6 Copyright © 2015 every, Inc. All rights reserved.

Slide 7

Slide 7 text

7 デリッシュキッチンにおける CI/CDの改善

Slide 8

Slide 8 text

8 Copyright © 2015 every, Inc. All rights reserved. 技術スタック - Go - Echo - レイヤードアーキテクチャ - handler - service - repository - infra - model - Github Actions(CI) - gomock - ブランチ戦略は git-flow

Slide 9

Slide 9 text

9 Copyright © 2015 every, Inc. All rights reserved. 背景 - デリッシュキッチンのサーバー (delish-server)は9年目 - goのソースコードの行数は、約 70万行 - 1ヶ月で120時間、740回実行されている - CI/CDにかかっている時間 - master : 16分 - develop : 16分 - feature : 10分(deployを行わないため) CI/CDに時間がかかっていて、早くデプロイしたいのに待ち時間が発生する時があるので改 善したい!

Slide 10

Slide 10 text

10 Copyright © 2015 every, Inc. All rights reserved. 改善の体制 - CI/CD改善プロジェクトのメンバー - 人数: 3人 - 期間: 約1ヶ月 - Github Actionsの結果を見ながら、時間がかかっている箇所に対して高速化の案を出して いった

Slide 11

Slide 11 text

11 Copyright © 2015 every, Inc. All rights reserved. 検討した改善事項 - 検討したもの - デッドコードの削除 - テストの並列化の徹底 - 差分テスト - go tool系のキャッシュ - テストの際にbuildをやめてgo mod downloadにする+キャッシュさせる - 今回できていないこと - mockを使えていない箇所で使う - 依存関係の分離がうまくできていない箇所がある - グローバル変数を使用している箇所の並列化 - ツールで発見できないデッドコードの削除

Slide 12

Slide 12 text

12 Copyright © 2015 every, Inc. All rights reserved. 改善の結果 最初: 16分 最終: 10分 - キャッシュなし - フルテスト: 13分 - 部分テスト: 8分 - キャッシュあり - フルテスト: 10分 - 部分テスト: 5分

Slide 13

Slide 13 text

13 Copyright © 2015 every, Inc. All rights reserved. デッドコードの削除

Slide 14

Slide 14 text

14 Copyright © 2015 every, Inc. All rights reserved. デッドコードの削除(作業) - デッドコードの検出 - https://pkg.go.dev/golang.org/x/tools/cmd/deadcode - 偽陽性があることに注意! - ツールで抽出したデッドコードを本当に削除して良いか、確認し つつ削除

Slide 15

Slide 15 text

15 Copyright © 2015 every, Inc. All rights reserved. issueでチェックリスト作成 pkgごとのチェックリスト

Slide 16

Slide 16 text

16 Copyright © 2015 every, Inc. All rights reserved. デッドコードの削除(結果) - テストの時間はほとんど変化なし - 約11,000行を削除(全体が70万行なので 1/70) 余談ですが、他のプロダクト (トモニテ)では135,000行のデッドコードを削除でき、 2~3分ほどはテストの時間を削減 (不要なテーブルやエンドポイントの削除まで対応した結果 )

Slide 17

Slide 17 text

17 Copyright © 2015 every, Inc. All rights reserved. テストの並列化の徹底

Slide 18

Slide 18 text

18 Copyright © 2015 every, Inc. All rights reserved. テストの並列化の徹底 (準備) - 対応が必要な pkgを抽出 - 直近のテストコードの結果をもとに確認

Slide 19

Slide 19 text

19 Copyright © 2015 every, Inc. All rights reserved. issueでチェックリスト作成 チェックリスト

Slide 20

Slide 20 text

20 Copyright © 2015 every, Inc. All rights reserved. テストの並列化の徹底 (実装) - t.Parallel()を使用することでテストを並列実行できるようにする - 230/4,800のテストでは元々利用していた - DBへのアクセスがあるものなどは t.Parallel()を使用する際に注意が必要なので対応し ない

Slide 21

Slide 21 text

21 Copyright © 2015 every, Inc. All rights reserved. time.Now()を使用するテストの並列化 - 並列化をするにあたって Now()を利用するテストへの対応が必要になった util/time.go campaign_test.go(変更前)

Slide 22

Slide 22 text

22 Copyright © 2015 every, Inc. All rights reserved. time.Now()を使用するテストの並列化 - テストの時に util/time.goに渡すTimeを 固定値にすることでも対応可能 - 今回はsynctestを使ってみる - util/time.goはテスト用に作成されたも のなので、わざわざ使用する必要がなく なる - せっかくなので使ってみたかった campaign_test.go(変更後)

Slide 23

Slide 23 text

23 Copyright © 2015 every, Inc. All rights reserved. テストの並列化の徹底 (結果) - テストの時間が約 1分短縮 - テストの数 約4,800 - t.Parallel()に対応した数 約220-> 約2,200

Slide 24

Slide 24 text

24 Copyright © 2015 every, Inc. All rights reserved. テストの並列化の徹底 (今後のための対応) - golangci-lintでt.Parallel()を利用しているか検知 - https://golangci-lint.run/docs/linters/configuration/#paralleltest - configファイルに linters/enableにparalleltestを追加 - 並列化できないものは //nolint:paralleltestをつける

Slide 25

Slide 25 text

25 Copyright © 2015 every, Inc. All rights reserved. 差分テスト対応

Slide 26

Slide 26 text

26 Copyright © 2015 every, Inc. All rights reserved. 差分テスト対応(準備) - delish-serverのCI(/CD)のタイミング - featureブランチ(CI) - developブランチ(CI/CD) - masterブランチ(CI/CD) - 差分テストの方針について - 全てフルでテストするか差分のみテストするかは悩ましいところ - 今回はCI/CDを高速化しつつ、安全に運用できるラインを目指した - developブランチ以降のdeployまで動く環境ではフルでテストを行う - リスクの高い変更がある場合はフルでテストをするようにする - go listを利用して、差分ファイルに依存関係がある pkgまでカバーするようにする

Slide 27

Slide 27 text

27 Copyright © 2015 every, Inc. All rights reserved. 差分テスト対応(実装) - 差分テストの流れ - develop/masterのテストはフルで実行 - featureのテストは下記のフローで処理する 1. 実行対象のpkgを抽出 2. フルでテストなのか差分のみテストなのか判定 - 下記のようなリスクが高いケースではフルでテストする - go.modの変更 - migrationファイルの変更 - model/utilファイルの変更 - ci/cdのワークフロー関連の変更 - 関連するpkgが多い場合はフルでテストする - doc系のみの変更の場合はテストをスキップする 3. go test pkg名を実行することで差分があるパッケージだけをテストする

Slide 28

Slide 28 text

28 Copyright © 2015 every, Inc. All rights reserved. 差分抽出(メインの処理のみ抜粋 )

Slide 29

Slide 29 text

29 Copyright © 2015 every, Inc. All rights reserved. 差分テスト対応(結果) - featureブランチでのテストの時間が 8~10分→3~5分程度に - develop, masterブランチではフルでのテスト実行なので変化なし

Slide 30

Slide 30 text

30 Copyright © 2015 every, Inc. All rights reserved. その他の対応

Slide 31

Slide 31 text

31 Copyright © 2015 every, Inc. All rights reserved. その他の対応と結果 - 不要なビルドをやめて go mod downloadにする - デプロイと関係ないところでgo buildを行っていた - go buildの時に必要なパッケージのダウンロードを行っていた → 1分短縮 - ダウンロードしたパッケージをキャッシュにのせる → 1分短縮 - テストが失敗した時に即終了するように変更 - go testのfailtestオプションを利用 - 複数failになる場合に一度のCIで確認できないのは許容 → 失敗時により早く気づけるように

Slide 32

Slide 32 text

32 Copyright © 2015 every, Inc. All rights reserved. 今回行った対応と結果 改善施策 概要 効果 短縮時間 デッドコード削除 ツールを利用して検出したデッドコードの削 除 ❌ ほぼ変わらず テストの並列化 t.Parallel()を利用できていない箇所で利用す るように変更 ⭕ 1分短縮 差分テスト対応 featureブランチのテストを変更した差分のみ 実行するように変更 ⭕ featureブランチ 最大7分程度の短縮 不要なビルドをやめて go mod downloadに する テスト時には不要なデプロイを行っており、ダ ウンロードのみで十分だったため変更 ⭕ 1分短縮 pkgのバイナリキャッ シュ ダウンロードしたpkgをキャッシュしていな かったためキャッシュするように変更 ⭕ 1分短縮 failfastにする テスト失敗時にCIが早く終了するように変更 ⭕

Slide 33

Slide 33 text

33 Copyright © 2015 every, Inc. All rights reserved. まとめ

Slide 34

Slide 34 text

34 Copyright © 2015 every, Inc. All rights reserved. まとめ まとめ - CIの時間が16分→10分に改善! - よくあるCI/CDの改善ではあったと思うが、整備できていない点も多かったのでこの機会 に対応できてよかった - 想定よりデッドコードが少なく、違いを見せられなかったのは残念 今後の課題 - mockを使ってテストしているが依存を分離できていない箇所があり、そこまでは手が回 らなかった - ツールで発見できないデッドコードの削除までは手が回らなかった

Slide 35

Slide 35 text

35 Copyright © 2015 every, Inc. All rights reserved. エブリーからのお知らせ Go Conference 2025 スポンサー 5社共催 アフターイベント開催します 🎉 🔍 compass go bash vol.2 🔍 エブリー オウンドメディア 🔍 エブリー テックブログ

Slide 36

Slide 36 text

No content