この記事は「traP 夏のブログリレー」2024年、7日目の記事です。
こんにちは。いくら・はむ(@ikura-hamu)です。主にSysAd班でサーバーサイドのプログラムを書いています。が、最近は「芸術C」という授業で、Unityでゲームを作ったりもしました。 (作ったゲームはこちら)
この記事は、GitHubのOrganizationのメンバー管理を楽にするためにいろいろやった(やっている)話です。
結論から言うと、この記事を書いている2024年8月時点までで、手動→Terraform→部内SNSのbotというように管理方法が変わってきています。これらの方法について詳細に書いていきます。
背景
traPには2つのGitHub Organizationがあります。1つは部内向けサービスの開発・運用を行っているSysAd班が管轄する@traPtitech、もう1つはtraPの役員会が管理する@traP-jpです。(よかったらどっちもフォローしてください!)今回は後者の@traP-jpについてです。
@traP-jpでは、定期的に部内で開催されるハッカソンと、半年に1回設立されるプロジェクトのリポジトリを主に管理しています。もともとはハッカソンのチームやプロジェクトごとにOrganizationを作っていたのを、一か所にまとめたいというモチベーションで作られました。ハッカソンのチームやプロジェクトごとにOrganization内でTeamを作っています。
初めは、役員会のGitHub Organization担当が他の部員の依頼を受けて手動でメンバーを追加したり、Teamを作ったりしていました。しかし、ハッカソンの直前などは依頼が多くなり、担当者の手が回らなくなってきました。そのため、自動化が検討されました。
Terraformによる自動化
担当者はBotなどによる自動化を提案しましたが、@ikura-hamu(筆者)(別に担当者ではない)はTerraformによる管理を提案しました。
Terraformは宣言的に記述するIaC(Infrastructure as Code)ツールです。AWSなどクラウドのリソースを管理することに使うことが多いイメージですが、GitHubのintegrationも用意されており、だいたいのことはできます。
インターン先でTerraformを初めて使ったばかりだった@ikura-hamuは、外から口を出してTerraformでの管理を提案し、採用されました。その結果がこのリポジトリです。
https://github.com/traP-jp/members
以下のような流れで運用することにして、実装しました。
- 部員がメンバー追加などのPRを出す
- GitHub Actionsで
terraform plan
などを実行し、その結果をPRにコメントする - OrganizationのAdminはそれを確認し、PRを承認・マージする
- マージされたらGitHub Actionsで
terraform apply
を実行し、Organizationへの招待などを実行する
これを今年(2024年)の6月の春ハッカソンで使いましたが、以下のような問題が発生しました。
- リポジトリに対する権限が無いと直接pushできないので、部員がPRを作れない
- リポジトリをフォークすればPRを作れるが、フォークからのPRのGitHub ActionsはSecretsの値を読むことができず、実行に失敗してしまう
- traPの活動でTerraformを使う場面は少ないので、環境が手元に無い人が多く、
terraform fmt
などでGitHub Actionsの実行が失敗する
などです。辛いところが多かったので、部内SNSのtraQのbotでの管理に移行することになりました。
traQ Botによる実装
Terraformを提案した責任を取って、 @ikura-hamuが開発しました。
以下のような仕様としました。
- 部員が
@BOT /invite <traQID> <GitHubID>...
のように、Organizationに追加したい人のtraQ IDとGitHub IDをBotに送る。 - Botは、GitHubのユーザー存在確認などをして、管理者に通知する。
- 管理者は通知を受け取ったら、承認・却下をメッセージへのスタンプで示す。
- 管理者からの承認が一定数集まったら、BotがGitHubのAPIを使ってOrganizationへの招待を送る。
また他の方法に変える可能性もあるので、Organizationへの招待という最低限の機能のみ実装し、Teamの作成などは設定でメンバーならだれでもできるようにしました。
GitHubの認証はGitHub Appを使っています。Terraformのときは管理者のPersonal Access Tokenを使っていたのですが、学生サークルという性質上頻繁に管理者が変わることが想定されたので、今回はGitHub Appにしました。
実装
この記事の本質ではないですが、何かを作ったらその中身について語らずにはいられないプログラマーなので、書かせてください。
普段から使っているGo言語を使いました。traPtitech/traq-ws-botという便利なライブラリがあり、これを使うとWebSocketを用いたtraQのBotを簡単に作ることができます。
DB(MariaDB)との接続にはuptrace/bunを使いました。一時期Xとかで話題になってJavaScriptの方のbunと混同されてた記憶があります。ORMなんですが、SQLに近い書き方ができて、かなり直感的で嬉しかったです。
GitHubの認証はインストールアクセストークンを使った GitHub App インストールとしての認証を用いています。よくわからない名前をしていますが、GitHub側が生成した秘密鍵を使ってJWTを作り、それを使ってインストールアクセストークンを取得して、そのトークンで様々なリクエストを送ります。
このトークンの有効期限は1時間、JWTの有効期限も10分以内なので、かなり面倒です。トークン取得の流れを自分で実装するのは嫌だなあと思っていたところ、google/go-githubのドキュメントのAuthenticationの章にbradleyfalzon/ghinstallationというライブラリへの言及がありました。このライブラリを使うと、このGitHub App インストールのトークン取得をいい感じにやってくれるhttp.Transport
を作ってくれます。とてもうれしい。内部ではhttp.RoundTripper
という機能を使っているらしいです。初めて知ったのですが、便利ですね。
テスト用のモックには、matryer/moqを使いました。Goのモックライブラリと言えばgo.uber.org/mock (gomock) が有名だと思いますが、最近はmoqを使うのにはまっています。gomockと比べて、引数のバリデーションが楽で、手軽にモックできると感じています。
今後
まだ新しく作ったbotを使う場面は来てないので、冬ハッカソンに期待という感じです。ここでいい感じであれば、チームの管理など、追加機能なども考えていきたいです。うまくいくことを祈ります。
明日は@ch4tlaと@Takeno_hitoです。