🤖

部会の連絡を GitHub Actions で自動化したい

2024/03/07に公開

わたしは所属する名古屋工業大学コンピュータ倶楽部 NITMic に所属しています.今回,この NITMic における毎週のミーティング(部会)の連絡を GitHub Actions により自動で Discord に配信するシステムを作りました.

1. はじめに

NITMic では,コロナ禍を受けて部会の実施形態が以下のように変化していきました:

  1. 毎週水曜日のお昼に部室に集合して実施
  2. 毎週水曜日のお昼に Discord のボイスチャンネルで実施
  3. 毎週水曜日のお昼に連絡事項をまとめたスライドを送信
  • GitHub で管理
  • Marp を利用してマークダウンから PDF に変換

こうした中で,連絡事項を決まった時間に自動で送信するようにしたいという需要が生まれました.しかし,そうこうしている間にコロナ禍が落ち着き,部長の交代を機にオフライン開催へ変更しつつある今日この頃です.

じゃあ一体なんでまだ今更こんなものを作ったのかということですが,端的に言えば作ってみたかったからですね.GitHub Actions とかを触ってみたかったので,いい題材になったというわけです.ただ言い訳すれば,連絡事項を GitHub で管理し自動で Discord に送信したいという需要はまだ残っていると思います:

  • 全員が部室に集まることは難しい
  • 部会の日に全員講義があるとも限らない
  • 自動化されるに越したことはない

2. 機能

機能として以下のようなものがあるとよいと考えました:

  • 部会の日に連絡事項を自動でリリースする機能
    • Discord の部会チャンネルに送信
    • ついでに GitHub Releases にも公開
  • 来週の分のファイルを自動で用意する機能
  • 幹部が部会をすっぽかしたときに,その旨を Discord に送信する機能

3. 実装

3.1. ワークフローの分割

柔軟な運用を可能にする観点から,機能を以下の 2 つのワークフローに分割して実装することにしました:

  • Release ワークフロー
    • 毎日 12:00 に実行
    • もしその日に対応するディレクトリに meeting.md が存在したら以下の処理を実行
      • GitHub Releases に公開
      • Discord に送信
  • Add Next Weekly Meeting ワークフロー
    • 毎週水曜日 12:00 に実行
    • 来週の部会用のファイルを作成

これにより,たとえば以下のような運用が可能になります:

  • 不定期で連絡したいことが発生したときは,その日に応じたディレクトリを作成すればよい
  • 部会のスケジュールが変わったときは,Add Next Weekly Meeting ワークフローのみを変更すればよい

3.2. テンプレートファイル

Add Next Weekly Meeting ワークフローは,テンプレートファイルを複製して来週の分として用意する仕組みにしました.そして,このテンプレートファイルに,幹部が部会をすっぽかしたとき用のメッセージを仕込むことにしました:

https://github.com/fjktkm/auto-meeting-announcements/blob/main/templates/meeting.md

3.3. 決まった時刻に GitHub Actions の実行する方法

わたしは GitHub Actions は Push イベントなどをトリガーとしてワークフローを実行する者しか今まで触ったことがありませんでした.そのため,次のような疑問がありました:

GitHub Actions で毎週 hh 時 mm 分にワークフローを実行するみたいな設定って可能なの?

おそらく同じように思っている人も多いのではないかと思います.調べてみたところ,これは可能でした.具体的には,以下のように設定すればいいようです:

name: Add Next Weekly Meeting

on:
  workflow_dispatch:
  schedule:
    - cron: '0 3 * * 3'

https://github.com/fjktkm/auto-meeting-announcements/blob/main/.github/workflows/add_next_weekly_meeting.yml#L1-L6

これは Add Next Weekly Meeting ワークフローで,毎週水曜日の 12:00(日本時間)にワークフローを実行する設定になっています.便利ですね.

3.4. Discord への送信

Discord への送信は,Discord の Webhook を利用しました.処理は Python でスクリプトを記述して,GitHub Actions の中で実行するようにしました:

def send_discord_message(webhook_url, message):
    data = {"content": message}
    response = requests.post(webhook_url, json=data)
    response.raise_for_status()

https://github.com/fjktkm/auto-meeting-announcements/blob/main/.github/scripts/send_to_discord.py

https://stackoverflow.com/questions/70631696/discord-webhook-post-to-channel-thread

工夫点としては,Discord にはメッセージに文字数の上限があるのですが,マークダウンの見出しレベルごとにメッセージを分割して送信するようにしたことがあります.メッセージの分割の基準を文字数ではなく見出しごとに設定したのは,以下の理由によります:

  • 見栄えを気にした
  • 文字数でメッセージを分けると,見出しや箇条書きなどの途中で分割される恐れがある

見出しごとに分割することにより,現実的な運用の中で文字数の問題が発生することはまずないだろうと思われます.一応,コードブロックの中で # によるコメントアウトなどがあると,見出しと誤認識してメッセージを分割してしまうという問題があるのですが,このへんが現実的な落としどころなのかなと考えています.

https://qiita.com/GrapeColor/items/58189f81b6e64f48d8ba

ただこの方法にも落とし穴があります.というのも,Discord には文頭や文末の空白文字や改行が無視されるという仕様があって,見出しごとに分割すると Discord 上の表示の見栄えが悪くなってしまうのです.この問題は,すべての行末にゼロ幅スペースを追加することで解決しました.ゼロ幅スペースは Discord 的には空白文字ではないようです.

4. 実行例

完成したシステムはこちらです:

https://github.com/fjktkm/auto-meeting-announcements

実行例は以下の通りです:

実際の部会の様子は独断で公開するわけにもいかないので,ここでは開発中のものを提示していますが,イメージとしてはこんな感じです.実際の部会では,このテンプレートを GitHub であらかじめ編集してもらうという形式になっています.マークダウンをいじるだけなので,github.dev でも編集できるのがよい点ですね.

5. 考察

GitHub Actions の時間指定はかなりルーズみたいです.はじめ部会は 12:15 スタートなので 12:15 に実行されるように設定していたのですが,実際には 12:24 に実行されました.15 分程度のずれは考慮しておくのがよさそうです.

https://qiita.com/tommy_aka_jps/items/5f4fe384008ffc9fa794

それから,GitHub Actions は UTC 基準なので,日本時間で設定したい場合すこし問題が発生する場合もあります.ここらへんはもう少し柔軟性があってもいいような気がするんですけどねー.

https://zenn.dev/blancpanda/articles/github-actions-cron-timezone-jst

6. おわりに

今後の展望としては,現在 Discord そのままメッセージとしてに送信しているのを,以前のように Marp を使って変換した画像にすることでしょうか.今回 GitHub Actions は思ったよりもいろんなことができることがわかったので,おそらくこれも技術的には可能だと思います.ただ,画像にすることに意味があるのかには疑問があって,現状労力に見合った価値があるようには感じられていません.そもそも自分はすでに引退の身の上なので,ここから先の改善は後輩たちに任せたいですね.

願はくは,このシステムが後輩たちの役に立ちますように.先輩より愛をこめて~

GitHubで編集を提案
NITMic Tech Blog

Discussion