サントリーウエルネス DX推進部エンジニアリングGの青木です。
日々の業務でGithubを利用しているのですが、Github Actionsを使えば面倒なことを任せられることがわかり試行錯誤しながら導入しています。
今回はその第一弾として、Milestoneの期限通知をGithub Actionsで行う方法について紹介します。
Github Milestoneとは
Github Milestoneとは、対象リポジトリのバージョンに紐づく変更管理を容易にする機能です。
Milestoneに紐づけたIssueやPull Requestの進捗をパーセンテージ表示したり、リリース時になんの変更がそのMilestoneに紐づいているかを管理したりできます。
私のチームではセマンティック・バージョニングに基づいてMilestoneを作成しており、そのバージョンに含まれる変更管理をすべてMilestoneで行っています。
Milestoneは変更管理に強く、期限管理に弱い
Milestoneは変更管理には強いのですが、それに特化している機能であるとも言えると思います。期限に関してはカレンダーとして出るわけでもないですし、Milestoneにちょっと記載されているレベルです。これではぱっと見たときにいつがリリース日なのかがわかりません。 そのため、他のツールでスケジュール管理しておく必要が出てくるのですが、せめて期限通知くらいはできたら楽なのにな…と思いました。
そうだ、Github Actionsに任せよう
この期限通知はGithub Actionsを使って行えます。Milestoneの期限を取得する必要がありますが、同じGithubなので構築が楽です。
特にGithub Actionsごとに発行されるGITHUB_TOKEN
があるのでわざわざPATを発行しなくていい点も気軽だと思います。
構成
全体構成は下記の通りです。
週次でMilestoneの期限を確認しにいき、1ヶ月以内であれば事前に用意しておいたSlackアプリにPOSTするWorkflowを用意するだけです。非常に簡単な作りですが、これだけでMilestoneの期限通知を自動化できます。
Workflow
作成したWorkflowはこんな感じです。
毎週水曜日の朝9時にSlackチャンネルに通知させるようにします。
envに各リポジトリの情報をセットするように書けば横展開も楽なのでオススメです。
※Github Acitonsで立ち上がるコンテナはUTCなので注意。
name: Milestone Notifier
on:
schedule:
- cron: '0 0 * * 3' # UTCで毎週水曜日の0時(日本時間で毎週水曜日の9時)
workflow_dispatch:
jobs:
notify-milestones:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install requests
- name: Check Milestones and Notify Slack
env:
REPOSITORY: ${Organization}/${Repository}
SLACK_WEBHOOK_URL: ${SlackアプリのURL}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
APP_NAME: ${Applicaton名}
run: |
python .github/scripts/check_milestones.py
スクリプト
Workflow内でスクリプトを書く方法もあるのですが、可読性が低くなるので別ディレクトリで管理しています。
Workflowで定義しておいた環境変数を受け取って実行するように作成しているのでスクリプト自体はどのリポジトリでも使えます。
やっていることは、下記の通りです。
- Milestoneの情報をGET
- GETしたMilestoneの期限をチェックして取得日から30日以内であればメッセージに必要な変数をセット(取得したMilestone分繰り返す)
- 通知が必要なMilestoneがあれば変数を利用してメッセージラインを作成してSlackにPOST、されていなければPOSTせずに終了
import requests
from datetime import datetime, timedelta
import os
def get_milestones(repo, token):
url = f"https://api.github.com/repos/{repo}/milestones?state=open"
headers = {"Authorization": f"token {token}"}
response = requests.get(url, headers=headers)
return response.json()
def notify_slack(webhook_url, message):
payload = {"text": message}
requests.post(webhook_url, json=payload)
def main():
repo = os.environ["REPOSITORY"]
token = os.environ["GITHUB_TOKEN"]
webhook_url = os.environ["SLACK_WEBHOOK_URL"]
app_name = os.environ["APP_NAME"]
milestones = get_milestones(repo, token)
today = datetime.today()
upcoming_milestones = []
for milestone in milestones:
if milestone.get("due_on"):
due_date = datetime.strptime(milestone["due_on"], "%Y-%m-%dT%H:%M:%SZ")
if today <= due_date <= today + timedelta(days=30):
milestone_url = f"https://github.com/{repo}/milestone/{milestone['number']}"
upcoming_milestones.append({
"title": milestone["title"],
"due_on": milestone["due_on"][:10],
"url": milestone_url
})
if upcoming_milestones:
message_lines = ["<!subteam^${チームメンションID}>\n\n次のMilestoneの期限が30日以内です。\nご認識お願いします。\n"]
for milestone in upcoming_milestones:
message_lines.append(f"App:{app_name}\nMilestone:{milestone['title']}\nURL:{milestone['url']}\n期限:{milestone['due_on']}\n---\n")
message = "\n".join(message_lines) + "\n"
notify_slack(webhook_url, message)
if __name__ == "__main__":
main()
POST先のSlackアプリを作成する
SlackにはSlack APIが用意されており、開発者が柔軟性を持って比較的簡単にSlackのアプリを作成できます。
ここではGithub ActionsからPOSTされたらWebhookでSlackのチャンネルにそのままPOSTするアプリを作成します。
詳しい作成手順は公式サイトをご参照ください。
- Create New AppからScratchで新規アプリを作成する
- 作成できたら
Incoming Webhook
に移動し、Activate Incoming Webhhoks
をOnにする。
- 同ページ下部の
Webhook URLs for Your Workspace
にからAdd New Webhook to Workspase
を押下し、AppとWorkspaceの連携を許可する
- 許可できたら連携するSlackチャンネルを設定する。
- WebhookのURLをコピーして先ほど作成したGithub ActionsのWorkflowの
SLACK_WEBHOOK_URL
に設定する。- 不特定多数の人がリポジトリにアクセスできる環境であれば、Github Secretsを使ってWebhookURLを取得してきたほうが良い。
実行結果
これで準備が整いました。
実行結果を見てみましょう。
いい感じですね!
Milestoneが複数あった場合でも1メッセージでPOSTできていることが確認できました。
※複数件Milestoneがあった場合にその都度メッセージを送ると通知が飛びすぎて迷惑になるので1メッセージだけ送信したほうが良いです。
おわりに
Github Actionsを活用すれば面倒な確認作業を任せられることがわかりました。
スクリプトも呼び出せるのでWorkflow + lambdaみたいな感覚で扱えそうです。
今回はSlackアプリにPOSTしてWebhookさせるところまでで終わらせましたが、スケジュール管理アプリがあればそこに連携させて自動更新とかも全然できるなと思いました。
以上、参考になれば幸いです!