この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
私のいるチームでは、毎日10時30分からデイリースクラムをしています。 最近、「ファシリテーターを変えてみよう」という事になりました。 当初はデイリースクラムの最後に「次の人を指名する」という運用を数日していましたが、忘れたり時間切れで決めれない場合がありました。
そこで、ランダムでファシリテーターを決める仕組みを作ってみました。
おすすめの方
- Slack Botを作りたい方(通知動作)
- AWS SAMでAWS Lambdaをデプロイしたい方
Slackアプリの作成と通知先URLの取得
Slackアプリの作成
下記にアクセスして、Slackアプリを作成します。
Incoming Webhooksの設定
Incoming Webhooksを選択し、ON
にします。
ページの下側にある「Add New Webhook to Workspace」を選択し、任意のチャンネルを許可します。
追加完了したあとは、URLをメモしておきます。
AWS Systems ManagerのパラメータストアにSlack通知先を追加
下記コマンドでAWS Systems Managerのパラメータストアに追加します。
URLの先頭にhttps://
があると、AWS CLIコマンド実行に失敗するため除去しています。
aws ssm put-parameter \
--type 'String' \
--name '/Slack/DailyScrumChannelUrl' \
--value 'hooks.slack.com/services/xxxxx/yyyyy/zzzzz'
Slack Botを作成する
sam init
sam init \
--runtime python3.9 \
--name Daily-Scrum-Facilitator-Bot \
--app-template hello-world \
--package-type Zip
SAMテンプレート
通知先のURLは、AWS Systems Managerのパラメータストアから直接取得しています。 また、10時30分からデイリースクラムを開始するので、1分前の10時29分に起動させます。
template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Daily-Scrum-Facilitator-Bot
Parameters:
DailyScrumChannelUrl:
Type: AWS::SSM::Parameter::Value<String>
Default: /Slack/DailyScrumChannelUrl
Resources:
NotifyDailyScrumFacilitatorFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: src/
Handler: app.lambda_handler
Runtime: python3.9
Timeout: 10
Architectures:
- x86_64
Environment:
Variables:
DAILY_SCRUM_CHANNEL_URL: !Ref DailyScrumChannelUrl
Events:
Notify:
Type: Schedule
Properties:
Schedule: "cron(29 1 ? * MON-FRI *)" # 月-金の10時29分(JST)
NotifyDailyScrumFacilitatorFunctionLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub /aws/lambda/${NotifyDailyScrumFacilitatorFunction}
Lambdaコード
メンションをしたいので、メッセージのtype
をmrkdwn
にしています。plain_text
だとメンションされませんでした。
app.py
import json
import os
import urllib.request
import random
NOTIFY_SLACK_URL = os.environ['DAILY_SCRUM_CHANNEL_URL']
HIT_USERS_NUMBER = 4
USERS = [
{'userId': 'aaa', 'name': 'Aさん'},
{'userId': 'bbb', 'name': 'Bさん'},
{'userId': 'ccc', 'name': 'Cさん'},
{'userId': 'ddd', 'name': 'Dさん'},
{'userId': 'eee', 'name': 'Eさん'},
{'userId': 'fff', 'name': 'Fさん'},
]
def lambda_handler(event, context):
payload = make_payload()
post_slack(payload)
def make_payload():
hit_users = random.sample(USERS, HIT_USERS_NUMBER)
main_user_id = hit_users.pop()['userId']
sub_user_names = '\n'.join([x.get('name') for x in hit_users])
return {
'blocks': [
{
'type': 'section',
'text': {
'type': 'mrkdwn',
'text': f'今日のファシリテーターは、 <@{main_user_id}> です!'
}
},
{
'type': 'section',
'text': {
'type': 'mrkdwn',
'text': f'不在の場合は、次の人にお任せしましょう。 ```{sub_user_names}```'
}
}
]
}
def post_slack(payload):
try:
res = post(f'https://{NOTIFY_SLACK_URL}', data=payload)
except requests.exceptions.RequestException as e:
print(e)
raise
else:
print(res.status)
def post(url: str, data: dict, headers: dict = {}):
req = urllib.request.Request(url,
data=json.dumps(data).encode('utf-8'),
headers=headers,
method='POST')
return urllib.request.urlopen(req)
メンバーIDは、Slackのプロフィールで取得できます。
デプロイ
sam package \
--output-template-file packaged.yaml \
--s3-bucket cm-fujii.genki-deploy
sam deploy \
--template-file packaged.yaml \
--stack-name daily-scrum-facilitator-bot-stack \
--s3-bucket cm-fujii.genki-deploy \
--capabilities CAPABILITY_NAMED_IAM \
--no-fail-on-empty-changeset
動作確認
朝10時29分になると、無事に通知が来ました!
なお、「開始ギリギリすぎて近況トークの準備に困る」とのフィードバックをもらったので、10時に通知するように変更したいと思います。