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

Goで作る、開発・CI環境

 Goで作る、開発・CI環境

Avatar for Shinpei Mine

Shinpei Mine

July 01, 2025
Tweet

Other Decks in Programming

Transcript

  1. 開発における定型タスク リント デプロイ 自動生成 開発サイクルの中で繰り返し行われる作業 (時間をまたいでの重複) ビルド テスト 自動整形 etc.

    開発効率向上のため、 スクリプトやタスクランナーに 定型タスクを切り出し (よくあるパターン) 5
  2. 環境をまたいで実行される定型タスク 開発時(ローカル環境) 統合時(リモート CI環境) 専用のファイルでワークフローを定義 ローカル/リモートで共通する作業も多い pushなど で発火 開発フェーズをまたいで繰り返される作業 (空間をまたいでの重複)

    • リント • テスト • ビルド • 自動生成 • デプロイ • タグづけ etc. 手動実行 / スクリプト / タスクランナー • リント • フォーマット • テスト • ビルド • 自動生成 etc. PF/ツール例 6
  3. 環境ごとに独立してタスク定義する場合 似たような作業が個別に定義されていると以下の点でつらい • 認知負荷の増加 • ワークフローの実装が膨らむ ◦ 構文理解の必要やテストのしづらさ • ローカルとリモートの環境差異

    ◦ バージョンや処理の違い • 変更時に複数のファイルを修正する必要 ローカルとリモート間で共通の処理を定義したくなってくる → タスクランナーによる共通タスク定義 8
  4. タスクランナーとは 開発における定型的なタスクの自動化を行うためのツール ex. ビルド, リント, テスト, デプロイ, ドキュメント生成 … •

    言語によってはデフォルトで同梱されている場合も ◦ Node.js なら npm scripts, deno なら deno task • Goの場合は標準のタスクランナーはなし → 要外部ツール ◦ ビルドなどは標準の仕組みが存在 • ツールによってはIDEやエディタとも連携可 9
  5. 手軽なタスクランナーとしての「 make」 • ファイル間の依存関係や更新履歴に基づいて 効率的なコンパイル・ビルドを実現 • Makefileにコマンドを記述 • 十分枯れてるので参考資料は多い •

    大体のLinux環境に入っており可搬性が高い • .PHONYをつけることでタスクの定義も可能 (ファイルをターゲットとして使用しないことの明示) 自分のプロジェクトでも当初、makeをタスクランナーとして使用 → 後に別の仕組みに移行 GNU make 10
  6. makeのつらみ • 複雑な処理を書こうとすると辛い ◦ 条件分岐や繰り返し、正規表現など ◦ 細かいコメント書きづらい • 属人化しやすい ◦

    makeやシェルスクリプトの構文知識が必要 ◦ (AIが使えてずいぶん楽にはなってきた) • ドキュメント化しづらい • 本来、ビルドプロセス自動化を目的としており タスクランナーとしての利用は目的外という見方も ◦ Goにはビルドの仕組みが内蔵されている 11
  7. make以外のタスクランナーという選択肢 Task (⭐13k) Mage (⭐4.4k) xc (⭐1.3k) • YAMLでタスク定義 •

    プリプロセッサとして text/templateを利用 • クロス環境動作 • Goでタスク定義 • 複雑な処理を書きやすい • クロス環境動作 • Markdownでタスク定義 • シェルスクリプト記載 • ドキュメントとタスクを一体管理 12
  8. make以外のタスクランナーという選択肢 Task (⭐13k) Mage (⭐4.4k) xc (⭐1.3k) • YAMLでタスク定義 •

    プリプロセッサとして text/templateを利用 • クロス環境動作 • Goでタスク定義 • 複雑な処理を書きやすい • クロス環境動作 • Markdownでタスク定義 • シェルスクリプト記載 • ドキュメントとタスクを一体管理 モノレポ開発で複雑な処理も多くなりがちだったので Mageを試してみることに 13
  9. Go製タスクランナー 「mage」 • Goでタスク定義できるタスクランナー ◦ like Rake (Ruby), Gulp (Node.js)

    • OSによらずGoが導入されていれば動作 (Linux / Windows間で利用可) • CLIコマンドの実行やmake-likeなファイルの 変更検知をサポートするヘルパーパッケージ mage 14
  10. Why mage? Makefileは読みにくく、書きにくい。 主な理由は、 Makefileが本質的に、 大量の空白と make関連の構文が追加された、 凝ったbashスクリプトだからです。 Mageでは複数の magefileを作成でき、

    ファイル名も自由に設定できます。 また、複数の OS向けにカスタマイズも簡単です。 MageはGo言語以外に依存しないため、 主要なOSで問題なく動作します。 一方、makeは一般的に bashを使用しますが、 これはWindowsではサポートが不十分です。 分岐やループなど、コマンドを直線的に実行する以外 の複雑なタスクでは、 Go言語の方が bashよりも優れています。 プロジェクトが Go言語で書かれているのであれば、 わざわざbashのような特殊な言語を導入する必要はありません。 貢献者が既に使い慣れている言語を使うのは良い考えです。 Mage :: Mage - Why? • Goでタスクが記述できるので Go開発者にやさしい ◦ 独自の構文が少ないので学習コストを抑えられる ◦ タスクのリスト表示もデフォルトで搭載 (makeでは自前で定義する必要) • 複雑な処理も書きやすい ◦ 型安全性が保てる ◦ タスク自体のテストが書ける • 可読性を保ちやすい ◦ 細かいコメントも書きやすい • Go製ツールをタスク内で利用する場合、 バイナリでなくパッケージから直接関数を利用可能 • 複数プロジェクトで共通のタスクを Goのパッケージとして公開可 • CIとの統合オプション ◦ ex. 静的バイナリ出力 , Zero Install Option 15
  11. mageの基本的なタスク定義方法 ① mageの管理対象  “mage” というビルドターゲットを指定した  “main” パッケージ  ファイルはプロジェクトルート or “magefiles”

     ディ レクトリに配置  (magefiles以下ではビルドタグ設定は任意) ② タスク定義  公開された関数がタスクとして登録  contextを引数として受けることも可 16
  12. mageの基本的なコマンド     $ mage or mage -l     $ mage <ターゲット名>     $

    mage -h <ターゲット名> タスクの実行 タスクのヘルプ表示 タスク一覧 ターゲット名 = 公開関数名 (大文字小文字は判別されない) 追加実装の手間なく タスクと説明の一覧を表示可 名前空間も反映(後述)  タスクは実行時にバイナリとしてコンパイル (再実行時にはキャッシュを利用) 同時に複数のターゲットを 指定することも可能 → 直列に実行 17
  13. 自分のプロジェクトにおける開発・ CI体制 プラットフォーム (CI) Github Actions タスクランナー Mage 実行内容 リント,

    テスト, ビルド, 自動整形, 自動生成 etc. 方針 • ローカル/リモートで 共通のタスクを使用 • タスク内で使用するツール はなるべくgo.mod管理に寄 せる(専用モジュール) • LefthookでCI以前の品質 チェック ローカル 開発時のタスク実行 プッシュ前に CI相当のチェック CIでのタスク実行 mageで共通タスク定義 各環境で同じ verを強制でき るようにmage内で使用する ツールも専用モジュールの go.mod管理に寄せる 23 先に紹介したCI用のタスクの静的バイナリ化 まではまだ未対応...
  14. 自身のプロジェクトに導入してみて タスクランナーでのタスク共通化 + CI統合 mageの導入 GOOD • 環境差異の減少 • ワークフローの実装コスト減少

    • AIエージェントからの活用 • LefthookによるCI以前の品質チェック • 複雑な処理を追加しやすくなった • コメントやファイル分割で 可読性は保てている • (Go製ツールは専用モジュールの go.modでバージョン管理を統一) MORE • 環境固有の実装も混在 • 完全な統一は難しい • CI上でのツールのインストール やキャッシュの必要 • CLIコマンドラップしてるだけのタス クも多い • コード量は増えがち • CIでの静的バイナリ利用は未対応 (インストールやキャッシュの手間は減るが別途管理コスト) 24
  15. • 共通タスク化で環境差異が減った 👌 • 実装コスト・認知負荷が減った 👌 • 他ツールとも統合しやすくなった 👌 •

    完全な共通化はまだ難しい 🤔 • 簡単なタスクは makeやWF個別実装でも十分 🤔 ただし... プロジェクトやチームの状況に合わせた構成を採用すべき (今回の紹介パターンは、その一例 ) 25 今だったらclaudeなどのhooksへの 利用目的でタスクを整理しておく のもいいかも 所感