codecommitのPullRequestをredmineのチケットに連携する


概要

これのシリーズもの
codecommitでpullrequestしたときに、関連するredmineのチケットのコメントに通知を出したくてごにょごにょした記録。
手順にはなってませんが、ヒントにはなるかな、と。
こんな感じで。

やりたい構成図

ざっくりこんなかんじ

やったこと概要

前提

codecommitでブランチを切るときに必ずredmineのチケット番号を記載する運用ルールにしていたので、更新対象のチケット番号はブランチ名からとってくることにした

redmine側の設定

APIを有効にする
  • adminで入って「管理」→「設定」から

AWS側の設定

Lambdaの設定をする
  • snsから通知されたメッセージを拾ってredmineのrestAPIをたたくpythonを書く
  • python_redmineを使えるようにLambdaLayerを設定した
  • 参考にさせて頂いたサイトはこちら
  • 宛先がオンプレサーバのためVPC経由で通信できるようにする必要があり、LambdaがVPC起動できるようにする
codecommitに通知ルールを設定し、codecommit上で何かイベントがあったときにSNSにメッセージが飛ぶようにする
  • 今回は以下の設定とした

苦労した点

  • snsから受け取ったデータ(jsonフォーマット)の中の"Message"はcodecommitが発したjsonだと思われ、ここから必要なものをredmineに投げたかったのだが、これを取得するのに難儀した。
  • 以下のようにしたらいけた ※ここについていい方法やメカニズムがわかればぜひ教えてください

    # このような取り出しをしたら「TypeError: string indices must be integers」になった
    # eventName = event['Records'][0]['Sns']['Message']['detail']['event']

    # どうも"Message"は単なるstringみたいなので、
    # 仕方ないので一度json形式に変換して必要なキーを取り出した

    Message_str = event['Records'][0]['Sns']['Message'] 
    Message = json.loads(Message_str)
    eventName = Message['detail']['event']

Lambdaのコード

import json
from redminelib import Redmine
import re

def lambda_handler(event, context):

    # SNSのメッセージからcodecommitのメッセージを抜き出す
    # ただしstringになってしまうので、最後にjson.loadsをする
    Message_str = event['Records'][0]['Sns']['Message']
    Message = json.loads(Message_str)
    # print("Message " +str(Message))

    # redmineに投げるリクエストに必要な要素を取り出す
    branchName = Message['detail']['sourceReference'].split('/')[2]
    eventName = Message['detail']['event']
    notificationBody = Message['detail']['notificationBody']

    #print("branchName " +str(branchName))
    #print("eventName " +str(eventName))
    #print("notificationBody "+str(notificationBody))


    # redmineを更新する

    # 対象チケット番号をブランチ名から取得する
    m = re.search(r'#\d+', branchName)
    issueNo_str = str(m.group())

    # もしも対象チケット番号がなかったら処理しない、あったら処理する
    if issueNo_str:
        issueNo = int(issueNo_str[1:])

        redmine = Redmine('http://<redmineurl>/', username='admin', password='xxxxxx')
        issue = redmine.issue.get(issueNo)
        issue.notes = notificationBody
        issue.save()

        #print(issue)
        #print(issue.notes)