GitHub API / Slack API / AWS Lambda + EventBridge
GitHub API を使用して Contributions やコミット数を取得し、Slack に通知する sh スクリプトを書く。
LambdaはCustom Amazon Linux2をRuntimeに使用する。
また、EventBridgeを使用して定期的に実行させる。
Prerequisites
- GitHub のアクセストークンを発行し
repo
とuser
のスコープに許可を付与する。トークンはここから作成できる。 - Slack のアプリを作成し任意のチャンネルに追加する。また OAuth のトークンを控えておく。アプリはここから作成できる。
以下の解説ではLambda Functionの環境変数に下記の4つを登録している。
GITHUB_TOKEN=your_github_token
GITHUB_USERNAME=your_github_username
SLACK_TOKEN=your_slack_token
SLACK_GITHUB_CHANNEL=your_slack_channel_name
ローカルで使用する場合は.zshrc
に登録しておくとよい。
cat << EOF >> ~/.zshrc
#github
export GITHUB_TOKEN=your_github_token
export GITHUB_USERNAME=your_github_username
#slack
export SLACK_TOKEN=your_slack_token
export SLACK_GITHUB_CHANNEL=your_slack_channel_name
EOF
GitHub からデータを取得する
Contributions の情報は GitHub API v4(GraphQL)で取得できる。
GraphQL API の Explorerから実際のデータをもとに試すことができる。
エンドポイントにhttps://api.github.com/graphql
を指定し、クエリを POST する。
response=$(curl -H "Authorization: bearer $GITHUB_TOKEN" -X POST -d '{"query":"query { user(login: \"'$GITHUB_USERNAME'\") { name contributionsCollection(from: \"'$from_date'\", to: \"'$to_date'\") { commitContributionsByRepository(maxRepositories: 100) { repository { name } contributions { totalCount } } contributionCalendar { totalContributions } } } }"}' https://api.github.com/graphql)
ここでは取得日の範囲は先週(日曜 00:00〜土曜日 23:59)とした。なお最大の日付範囲は1年以内である。
from_date=$(date -d "last Sunday - 1 week" +"%Y-%m-%dT00:00:00Z")
to_date=$(date -d "last Saturday" +"%Y-%m-%dT23:59:59Z")
なお、もしMacOSで実行する場合はdate
のオプションは下記のように記述する。
from_date=$(date -v-sunday -v-1w +"%Y-%m-%dT00:00:00Z")
to_date=$(date -v-saturday +"%Y-%m-%dT23:59:59Z")
jq を使った JSON データの解析
API のレスポンスから必要なデータを抽出するために、jq を利用する。ローカルで実行する場合はjq
は brew 等でインストールしておく。
brew install jq
LambdaのLinux環境でjq
を使用するために、最新版のjqをダウンロードし実行権限を付与した上で、zipに固める。
LambdaでLayerを新しく作成し、このjq_layer.zip
をアップロードする。RuntimeにはCustom runtime on Amazon Linux 2
を選択する。
mkdir bin
cd bin
curl -L https://github.com/stedolan/jq/releases/download/jq-1.7/jq-linux64 -o jq
chmod +x jq
cd ..
zip -r jq_layer.zip bin
Layerが作成できたらLambdaに追加しておく。
取得したレスポンスから下記の3つのデータを抜き出す。
commitContributionsByRepository
の返り値は空配列の場合があるので、// 0
としてデフォルトを設定しておくとよい。
total_contributions=$(echo $response | jq -r '.data.user.contributionsCollection.contributionCalendar.totalContributions')
total_commits=$(echo $response | jq -r '.data.user.contributionsCollection.commitContributionsByRepository | map(.contributions.totalCount) | add // 0')
total_repositories=$(echo $response | jq -r '.data.user.contributionsCollection.commitContributionsByRepository | length')
もし、このスクリプトをローカルで(例えば)CronJobから使用する場合は、jq
コマンドが参照されないため、/usr/local/bin/jq
という風にフルパスを指定する必要がある。
Slack への通知
取得した情報を Slack に送信する。
改行コード\n
が、そのままだと\\n
としてエスケープされてしまうため、replace する必要がある。
temp="*Last week's contributions:*\ntotal contributions: \`$total_contributions\`, commits: \`$total_commits\`, repositories: \`$total_repositories\`"
text=$(echo $temp | sed -e 's/\\n/\'$'\n''/g')
エンドポイントにhttps://slack.com/api/chat.postMessage
を指定して POST する。
$SLACK_GITHUB_CHANNEL
には先ほど作成したアプリのボットを追加したチャンネル名を入れる。
curl -d "text=$text" -d channel="$SLACK_GITHUB_CHANNEL" -H "Authorization: Bearer $SLACK_TOKEN" -X POST https://slack.com/api/chat.postMessage > /dev/null
これで実行すれば slack に通知が来る。
./function.sh
Lambda Functionへのアップロード
下記のファイルに実行権限を付与する。
chmod +x function.sh bootstrap
これらをzipに固めてLambdaにアップロードする。またはS3等にアップロードしてURLを指定する。
zip function.zip function.sh bootstrap
定期実行の設定
EventBridgeを設定することで、Lambdaを定期的に実行することができる。
例えば、毎週月曜の9:00AMに実行する場合、Cron expressionは下記のように設定する。
0 9 ? * 2 *
ローカルで簡易的にCronJob を設定し、このスクリプトを毎週月曜日に実行させる場合はcrontabに記述する。
crontab -e
crontab のエディタが立ち上がるので編集する。
CronJob実行時に.zshrcの環境変数を読み込み、スクリプトのディレクトリに移動して実行する。
# 毎週月曜日の9:00AMに実行する場合
0 9 * * 1 . ~/.zshrc; cd /path/to/directory && ./function.sh
まとめ
参考までにソースコードを github に置いています。
AWS Lambda版
ローカル(CronJob)版
Discussion