Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Nxで構築するGoモノレポ

 Nxで構築するGoモノレポ

近年、Go界隈でモノレポの需要は増えています。Goでモノレポのビルド環境を構築するといえば、まずBazelを連想すると思いますが、Bazelは学習コストが高さが難点です。ただ、ビルドタスクの依存関係の解決、リモートキャッシュ、分散ビルド、といったBazelの機能はモノレポを構築するにあたって魅力的です。そこで、Bazelと類似の機能を備えつつも扱いが楽なNxを紹介します。ある程度の規模のモノレポでも通用するタスクランナーを利用したいがBazelは難しいという方々には、Nxは一考に値します。

KamikazeZirou

June 02, 2023
Tweet

More Decks by KamikazeZirou

Other Decks in Programming

Transcript

  1. 1.1 自己紹介 • ANDPADで働いています ◦ クラウド型建設プロジェクト管理サービスを提供してい ます • Goのバックエンドの開発を担当 •

    サブ業務としてGoモノレポを運用 ◦ モジュール数は12 ▪ サーバが8, 共通ライブラリが4 ◦ go.modが1つだけの構成 ◦ Nxを管理ツールとして利用 1.はじめに
  2. 1.2 用語 1.はじめに • 依存関係 ◦ (モジュールの)依存関係 • CIツール ◦

    GitHub Actionsのこと ▪ 他のCIツールでも大体同じことできるはず
  3. • Pros ◦ CIやLintなどの設定を統一しやすい ◦ 依存モジュールのバージョンを統一しやすい ◦ 共通モジュールを作りやすい ◦ 複数モジュールの変更を一括でできる

    • Cons ◦ ポリレポに比べるとビルドの設定の難易度が高い ◦ ファイル数が増えてくるとVCSが遅くなる 2.2 モノレポのPros/Cons 2.モノレポとは
  4. • Uberさん(2020/5/14時点) ◦ 管理対象 ▪ Goのバックエンドと共通ライブラリ ◦ 規模 ▪ 70,000以上のファイル

    ▪ 1ヶ月のActive Developer: 750人以上 ▪ 1ヶ月のコミット数: 9,000以上 ◦ ビルドツール ▪ GNU Make -> Bazel 2.3.2 Goモノレポの事例 2.モノレポとは
  5. • Mixiさん(2022/10/24時点) ◦ 管理対象 ▪ Goのコード(詳細は不明) ◦ ビルドツール ▪ Bazel

    -> GNU Make ◦ GNU Makeにした理由 ▪ Bazelの運用コストや学習コストが高い ▪ Bazelは立ち上がりが遅い ▪ Bazelには並列実行の制約がある ▪ GNU Makeでも意外と早かった 2.3.3 Goモノレポの事例 2.モノレポとは
  6. • CI/CDはモノレポ構築の難所の1つ ◦ 課題 ▪ コード変更時に、 全モジュールを直列でビルドすると時間がかかる ◦ 対処方法 ▪

    ビルド対象のモジュールを限定する ▪ 複数モジュールを並列ビルドする 3.1 モノレポのCI/CD 3. モノレポのCI/CD
  7. パスフィルタ Matrix Job モノレポツールの 分散ビルド 依存関係に基づくタスクの 実行の制御 △ ◯ ◎

    ビルドの効率(※) ◯ ◯ ◎ 全モジュールのCIのワーク フローを共通にできるか ✕ ◯ ◎ PC上で実行できるか ✕ ✕ △~◯ 環境構築のしやすさ ◎ ◯ ✕~◯ 学習コスト ◎ ◯ ✕~◯ ※同じビルド内容なら、CIのビルドの課金時間と全体の実行時間が低いほど ビルド効率は高いものとする 3.3 CI/CDのパターンの比較 3. モノレポのCI/CD
  8. 4.1 Nxとは • Typescript製のモノレポツール • モノレポに有用な機能を大体備えている ◦ タスクの実行順の調整 ◦ 変更の影響範囲の判別

    ◦ 分散ビルド ◦ リモートキャッシュ ◦ 依存関係の可視化 ◦ モジュールの雛形生成 ◦ 依存関係の制限 4. Nxとは
  9. • Web Frontに強いがGoモジュールも扱える • Nxという会社が開発している ◦ 分散ビルドやリモートキャッシュ以外 ▪ 無料で使える ◦

    分散ビルドやリモートキャッシュ ▪ 無料枠あり ▪ 所定の条件を満たせば完全無料 4.1 Nxとは 4. Nxとは
  10. 5.1 構築するGoモノレポ • 構築に使うツール ◦ Git/GitHub/GitHub Action/npm/node • 構築範囲 ◦

    2つモジュールを作る ◦ コード更新時に分散ビルドする • 所要時間 ◦ 10分以内 5. NxでGoモノレポを構築する
  11. 1. Nxのワークスペースを作成する (Nx Cloudを使うかの質問が出たらYesを選択) $ npx create-nx-workspace@latest nx-go-sample --preset=empty $

    cd nx-go-sample 2. go.modをルートに作る $ go mod init nx-go-sample 3. NxのGoプラグインを導入する $ npm install -D @nx-go/nx-go $ npx nx g @nx-go/nx-go:setup-nx-go-plugin 5.2 リポジトリを作成する 5. NxでGoモノレポを構築する
  12. 4. 実行可能なモジュールmainの雛形を生成する $ npx nx g @nx-go/nx-go:app main 5. 共通ライブラリlibの雛形を生成する

    $ npx nx g @nx-go/nx-go:lib lib 5.3 モジュールを生成する 5. NxでGoモノレポを構築する
  13. 5.4 ビルドタスクを記述する 6. apps/main/project.jsonの”test”の実行方法を変更する 5. NxでGoモノレポを構築する 変更前 "test": { "executor":

    "@nx-go/nx-go:test" } 変更後 "test": { "executor": "nx:run-commands", "options": { "commands": ["go test ./..."], "parallel": false, "cwd": "apps/main" } } “executor”に”nx:run-commands”を指定するとShellのコマンドが使える。 GoのPluginのexecutorより扱いやすいのでおすすめ。
  14. 8. GitHub Actionsのワークフローを生成する (名前の入力が求められるので何も入力しないでEnterを押す) $ npx nx g @nx/workspace:ci-workflow --ci=github

    9. 生成された.github/workflows/ci.ymlの内、以下の2行を消す parallel-commands: | npx nx-cloud record -- npx nx format:check 生成されたワークフローは、変更の影響を受けたモジュールのビルドタスク lint/test/buildを実行する 5.6 分散ビルドをする 5. NxでGoモノレポを構築する
  15. • Goのimport文から依存関係を判定してくれる • 各モジュールのタスクの 実行方法が統一される ◦ npx nx <task> <module-name>

    • CIのワークフローを共通化できたこと ◦ ビルドに使うGoのバージョンを 上げるといったCIのメンテが楽 6.1 便利だったこと 6. NxでGoモノレポを構築した感想
  16. 6.1 便利だったこと 6. NxでGoモノレポを構築した感想 • 変更の影響を受けたモジュールの タスクを実行するコマンド ◦ npx nx

    affected -t <target> • CIの課金時間を低く抑えられる ◦ CIのMatrix Job: 課金時間60m ◦ 分散ビルド: 課金時間30m • タスク実行時に.envを読み込んでくれる ◦ develop/productionといった環境ごとに.envも持てる
  17. • Go製でない • デフォルトのフォルダ構造を変えると、 設定の難易度が上がる • 初見だとCIのエラー時にどうしたら良いか 分かりづらい ◦ どこでログを確認できるのか分かりづらいらしい

    ◦ 再実行するときは、全Jobを再実行しないといけない が、初見だと分かりづらい 6.2 いまいちな点 6. NxでGoモノレポを構築した感想
  18. • go.modを1つだけにすると楽 ◦ Pros ▪ モジュールのバージョンを統一するのが容易 ▪ シンプル ◦ Cons

    ▪ 全モジュールのビルドが発生しやすい ◦ Note ▪ 他のモジュールに公開したくないコードは internalパッケージに置く 1. Goのモジュール構成について 付録 モノレポ運用Tips
  19. • 全モジュールで共通の設定 ◦ go.modと同じ場所に.golangci.ymlを置いている • sytle系のLinterはもめやすいので、 がちがちに設定しない • 有効にしているLinter ◦

    デフォルトで有効なもの ◦ bugs/complexity/performanceに分類されるもの 3. golang-ci-lintの設定 付録 モノレポ運用Tips
  20. 4. 開発フローについて 付録 モノレポ運用Tips • GitHub Flowがおすすめ ◦ サーバのデプロイトリガー ▪

    開発環境: mainブランチの更新時。一括 ▪ 本番環境: 手動でCI Jobを実行。モジュール別 ◦ Note ▪ hotfixをするときは、hotfixブランチを作り、 それに対してリリース用のCIのJobを手動実行する ▪ モノレポ => モジュールは一括デプロイするもの、と思って いる人もいるが、そんなことはない
  21. • コミットログはconventional commit ◦ 形式 ▪ type(scope): summary ▪ scopeにはモジュール名を入れる

    ◦ 例 ▪ feat(chat): reaction to message ◦ Note ▪ コミットログの1行目で変更モジュールが分かる ▪ Nxのプラグインで、リリースノートを自動生成できる 5. コミットログについて 付録 モノレポ運用Tips
  22. • CIの実行者を制限する(未実施) ◦ 動機 ▪ CIの権限が強くなりがちなので実行を制限したい ◦ 方法 ▪ 一般の開発者にはリポジトリをForkしてもらう

    ▪ 元のリポジトリを変更できるメンバーは限定する ◦ Note ▪ CI実行の承認者の設定、Secretの利用者の設定も使えそ う(GitHub Actions) 7. 統制について 付録 モノレポ運用Tips
  23. • テストの品質はとても重要 ◦ テストが不安定なモジュールがある => CI/CDが失敗する頻度が高くなる ◦ テストが遅いモジュールがある => CI/CDの全体の実行時間が遅くなる

    ◦ テストケースが不十分なモジュールがある => 外部モジュールのバージョンを上げたときに、バグ が起きる 9. テストについて 付録 モノレポ運用Tips
  24. 10. Nxとの付き合い方 付録 モノレポ運用Tips • 分散ビルドを使わないで、CIのMatrix Jobで CI/CDを構築することもできる ◦ Nxの変更の影響を受けたモジュールを

    検出する機能だけを使う ◦ Nxの有料プランに入らなくても良い ◦ 小規模リポジトリなら、 こちらの方が費用面では有利