Lambda로 CodeCommiit 알림을 Teams로 건너뛰기
개시하다
다음 기사에 의해 촉발되어 Lambda에서python에서 CodeCommiit에 알림을 보내는 것을 실현하였다.zip바p가 귀찮아서pythn3.이루어지다
통지의 설정 등 세부 사항은 아래의 보도 내용을 확인해 주십시오.
일단 람다에서 이벤트 내용을 확인합니다.
lambda_handler()
이벤트에 전달된 내용은 Object로 전달됐는데 어떤 형태로 왔는지 알 수 없다.코드Commiit의 PR 관련 트리거는 이벤트에서 어떤 정보가 유출되는지 먼저 확인했다.
Sns의 이벤트 확인 코드
다음 코드를 통해 Sns에서 전송된 이벤트를 확인했습니다.
event['Records'][0]['Sns']['Message']
는 유니버설 문자열로 식별되어 dict로 순조롭게 읽을 수 없기 때문에 끼워 넣기json.loads()
.CloudWatchLogs에서 logger를 여러 줄로 바뀐 로그 출력 대신 기록 출력으로 설정합니다.
lambda deploy로 이쪽을 통과한 후 코드commiit에서 알림 내용을 확인하고 싶은 처리를 실시하고 클라우드 왓 로그를 확인하면 알림의 이벤트 내용을 확인할 수 있습니다.
import json
import os
import re
import requests
import sys
from logging import getLogger, INFO ,StreamHandler
logger = getLogger(__name__)
logger.setLevel(INFO)
def lambda_handler(event, context) -> None:
sns_dict = event['Records'][0]['Sns']
sns_dict['Message'] = json.loads(sns_dict['Message'])
sns_dict_str = json.dumps(sns_dict, ensure_ascii=False)
logger.info('sns message:')
logger.info(sns_dict_str)
모든 조작 모델을 조사하는 것은 매우 어려워서 3개만 조사한다.(조사가 까다로워 설명서를 요구한다)
이벤트 확인: PR 제작
{
"Type": "Notification",
"MessageId": "aaaaa-aaaaa-aaaaa-aaaa", #mask
"TopicArn": "arn:aws:sns:ap-northeast-1:aaaaa:codcommit-notification", # mask
"Subject": null,
"Message": {
"account": "aaaaa", #mask
"detailType": "CodeCommit Pull Request State Change",
"region": "ap-northeast-1",
"source": "aws.codecommit",
"time": "2021-10-31T16:20:26Z",
"notificationRuleArn": "arn:aws:codestar-notifications:ap-northeast-1:aaaaa:notificationrule/aaaaa", # mask
"detail": {
"sourceReference": "refs/heads/feature/notification_test2",
"lastModifiedDate": "Sun Oct 31 16:20:18 UTC 2021",
"author": "arn:aws:iam::aaaaa:user/iam_user_name", #mask
"isMerged": "False",
"pullRequestStatus": "Open",
"notificationBody": "A pull request event occurred in the following AWS CodeCommit repository: test-repository. User: aarn:aws:iam::aaaaa:user/iam_user_name. Event: Created. Pull request name: 12. Additional information: A pull request was created with the following ID: 12. The title of the pull request is: notification test 2. For more information, go to the AWS CodeCommit console {repogitory_link}",
"description": "notification desictiption",
"destinationReference": "refs/heads/master",
"callerUserArn": "arn:aws:iam::aaaaa:user/iam_user_name", #mask
"creationDate": "Sun Oct 31 16:20:18 UTC 2021",
"pullRequestId": "12",
"title": "notification test 2",
"revisionId": "aaaaaa", # mask
"repositoryNames": [
"test-repogitory"
],
"destinationCommit": "423f021893fa3233cf956f287ece47d0987be441",
"event": "pullRequestCreated",
"sourceCommit": "bcda8ac3245cf63388d61df6a16769f32b2de590"
},
"resources": [
"arn:aws:codecommit:ap-northeast-1:aaaaa:test-repogitory" #mask
],
"additionalAttributes": {
"numberOfFilesAdded": "0",
"numberOfFilesDeleted": "1",
"numberOfFilesModified": "0",
"changedFiles": [
{
"changeType": "D",
"filePath": "test2.txt"
}
]
}
},
"Timestamp": "2021-10-31T16:20:28.873Z",
"SignatureVersion": "1",
"Signature": "aaaaa", # mask
"SigningCertUrl": "{pem_link}", #mask
"UnsubscribeUrl": "{link}", #mask
"MessageAttributes": {}
}
이벤트 확인: PR 병합
{
"Type": "Notification",
"MessageId": "aaaaa-aaaaa-aaaaa-aaaa", #mask
"TopicArn": "arn:aws:sns:ap-northeast-1:aaaaa:codcommit-notification", #mask
"Subject": null,
"Message": {
"account": "aaaaa", #mask
"detailType": "CodeCommit Pull Request State Change",
"region": "ap-northeast-1",
"source": "aws.codecommit",
"time": "2021-10-31T16:03:49Z",
"notificationRuleArn": "arn:aws:codestar-notifications:ap-northeast-1:aaaaa:notificationrule/aaaaa", #mask
"detail": {
"sourceReference": "refs/heads/feature/notification_test",
"lastModifiedDate": "Sun Oct 31 16:03:39 UTC 2021",
"author": "arn:aws:iam::aaaaa:user/iam_user_name",#mask
"isMerged": "True",
"pullRequestStatus": "Closed",
"notificationBody": "A pull request event occurred in the following AWS CodeCommit repository: test-repogitory. User: arn:aws:iam::aaaa:iam_user_name. Event: Updated. Pull request name: 11. Additional information: The pull request merge status has been updated. The status is merged. For more information, go to the AWS CodeCommit console {repogitory_link}",#mask
"description": "# notification実装テスト用PRの説明セクション\ntest\n## test\n- test\n - test",
"destinationReference": "refs/heads/master",
"callerUserArn": "arn:aws:iam::aaaaa:user/iam_user_name", #mask
"creationDate": "Sun Oct 31 14:46:05 UTC 2021",
"pullRequestId": "11",
"title": "notification実装テスト用PR",
"revisionId": "aaaaa", # mask
"repositoryNames": [
"test-repogitory"
],
"destinationCommit": "1da430df4696193ce4883bd029d7fa650606a078",
"event": "pullRequestMergeStatusUpdated",
"mergeOption": "SQUASH_MERGE",
"sourceCommit": "ae1dd8f163e45e150d6074f78357d1ce6c030ab8"
},
"resources": [
"arn:aws:codecommit:ap-northeast-1:aaaaa:test-repogitory" #mask
],
"additionalAttributes": {}
},
"Timestamp": "2021-10-31T16:03:51.808Z",
"SignatureVersion": "1",
"Signature": "aaaaa", # mask
"SigningCertUrl": "{pem_link}", #mask
"UnsubscribeUrl": "{link}", #mask
"MessageAttributes": {}
}
이벤트 확인: PR 리뷰 추가
{
"Type": "Notification",
"MessageId": "aaaaa", # mask
"TopicArn": "arn:aws:sns:ap-northeast-1:aaaaa:codcommit-notification", # mask
"Subject": null,
"Message": {
"account": "909287433301",
"detailType": "CodeCommit Comment on Pull Request",
"region": "ap-northeast-1",
"source": "aws.codecommit",
"time": "2021-10-31T15:20:36Z",
"notificationRuleArn": "arn:aws:codestar-notifications:ap-northeast-1:aaaaa:notificationrule/aaaaa", #mask
"detail": {
"beforeCommitId": "1da430df4696193ce4883bd029d7fa650606a078",
"notificationBody": "A pull request event occurred in the following AWS CodeCommit repository: test-repository. The user: arn:aws:iam::aaaaa:user/iam_user_name made a comment or replied to a comment. The comment was made on the following Pull Request: 11. For more information, go to the AWS CodeCommit console {repogitory_link}", # mask
"repositoryId": "aaaaa", # mask
"commentId": "aaaaa", # mask
"afterCommitId": "c98211927b2d78bc7bad803b08221a0e0329ce20",
"callerUserArn": "arn:aws:iam::aaaaa:user/iam_user_name", #mask
"event": "commentOnPullRequestCreated",
"pullRequestId": "11",
"repositoryName": "test-repository"
},
"resources": [
"arn:aws:codecommit:ap-northeast-1:aaaaa:test-repogitory" # mask
],
"additionalAttributes": {
"commentedLine": null,
"resourceArn": "arn:aws:codecommit:ap-northeast-1:aaaaa:test-repogitory", # mask
"comments": [
{
"authorArn": "arn:aws:iam::aaaaa:user/iam_user_name", #mask
"commentText": "変更に対するコメントテスト13"
}
],
"commentedLineNumber": null,
"filePath": null
}
},
"Timestamp": "2021-10-31T15:20:39.578Z",
"SignatureVersion": "1",
"Signature": "aaaaa", # mask
"SigningCertUrl": "{pem_link}", #mask
"UnsubscribeUrl": "{link}", #mask
"MessageAttributes": {}
}
Teams 발언 형식
다음 함수에 정의된 발언 형식에 따라 실현되었습니다.
지정할 수 있는 포맷 옵션이 많았지만 쉽게 구현하고 싶어 실장 경험이 있는 포맷으로 구현했다.
def post_teams(title: str, detail: list, link: list) -> None:
payload = {
'@type': 'MessageCard',
"@context": "http://schema.org/extensions",
"themeColor": "0076D7",
"summary": f'{AWS_ACCOUNT}: {title}',
"sections": [{
"activityTitle": f'{AWS_ACCOUNT}: CodeCommit Notifiction',
"activitySubtitle": f'{title}',
"activityImage": f'{link["icon_url"]}',
"facts": detail,
"markdown": 'true',
"potentialAction": [{
"@type": "OpenUri",
"name": f'{link["name"]}',
"targets": [{
"os": "default",
"uri": f'{link["url"]}'
}]
}]
}]
}
logger.info('post message:')
logger.info(json.dumps(payload))
try:
response = requests.post(TEAMS_WEBHOOK_URL, data=json.dumps(payload))
except requests.exceptions.RequestException as e:
print(e)
else:
print(response.status_code)
최종 완성된 코드
상부의 환경 변수를 별도로 설정하면 동작한다.
get_message()
에서 각 이벤트 알림 모드에 대해 Teams 발언 데이터 형식에 따라 성형한 후 Teams에 투고했다.여전히 아이콘 설정에 감각이 없어 아이콘을 모집 중입니다.
import json
import os
import re
import requests
import sys
from logging import getLogger, INFO ,StreamHandler
logger = getLogger(__name__)
logger.setLevel(INFO)
# SLACK_WEBHOOK_URL = os.environ['SLACK_WEBHOOK_URL']
TEAMS_WEBHOOK_URL = os.environ['TEAMS_WEBHOOK_URL']
AWS_ACCOUNT = os.environ['ACCOUNT_NAME']
def lambda_handler(event, context) -> None:
sns_dict = event['Records'][0]['Sns']
sns_dict['Message'] = json.loads(sns_dict['Message'])
sns_dict_str = json.dumps(sns_dict, ensure_ascii=False)
logger.info('sns message:')
logger.info(sns_dict_str)
title, detail, link = get_message(sns_dict['Message'])
post_teams(title, detail, link)
def get_message(message: dict) -> (str, list, dict):
title = message['detailType']
https_pattern = "https?://[\w/:%#\$&\?\(\)~\.=\+\-]+"
if title == 'CodeCommit Comment on Pull Request':
# title
title_fixed = title
# detail
user_arn = message['detail']['callerUserArn']
user_name = user_arn.split('/')[1]
repo_name = message['detail']['repositoryName']
comment_line = message['additionalAttributes']['commentedLine'] or '---'
comment_filepath = message['additionalAttributes']['filePath'] or '---'
comment_text = message['additionalAttributes']['comments'][0]['commentText']
detail = [
{'name':'user', 'value':user_name},
{'name':'repo_name', 'value':repo_name },
{'name':'comment_filepath', 'value':comment_filepath},
{'name':'comment_line', 'value':comment_line},
{'name':'comment_text', 'value':comment_text}
]
# link
url_list = re.findall(https_pattern, message['detail']['notificationBody'])
url = url_list[0]
url = url[:-1] if url[-1] == '.' else url
link = {
'icon_url': 'https://img.icons8.com/external-flatart-icons-outline-flatarticons/64/000000/external-comment-chat-flatart-icons-outline-flatarticons-2.png',
'name': 'PullRequest',
'url': url
}
elif title == 'CodeCommit Pull Request State Change':
if message['detail']['event'] == "pullRequestCreated":
# title
title_fixed = 'CodeCommit Pull Request Created'
# detail
repo_name = message['detail']['repositoryNames'][0]
src_branch = message['detail']['sourceReference']
dst_branch = message['detail']['destinationReference']
author_arn = message['detail']['author']
author_name = author_arn.split('/')[1]
description = message['detail']['description']
detail = [
{'name':'repo_name', 'value':repo_name },
{'name':'src_branch', 'value':src_branch},
{'name':'dst_branch', 'value':dst_branch},
{'name':'author', 'value':author_name},
{'name':'description', 'value':description}
]
# link
url_list = re.findall(https_pattern, message['detail']['notificationBody'])
url = url_list[0]
url = url[:-1] if url[-1] == '.' else url
link = {
'icon_url': 'https://cdn-icons-png.flaticon.com/512/3659/3659866.png',
'name': 'PullRequest',
'url': url
}
elif message['detail']['isMerged'] == "True":
# title
title_fixed = 'CodeCommit Pull Request Mereged'
# detail
repo_name = message['detail']['repositoryNames'][0]
src_branch = message['detail']['sourceReference']
dst_branch = message['detail']['destinationReference']
merge_option = message['detail']['mergeOption']
detail = [
{'name':'repo_name', 'value':repo_name},
{'name':'src_branch', 'value':src_branch},
{'name':'dst_branch', 'value':dst_branch}
]
# link
url_list = re.findall(https_pattern, message['detail']['notificationBody'])
url = url_list[0]
url = url[:-1] if url[-1] == '.' else url
link = {
'icon_url': 'https://cdn0.iconfinder.com/data/icons/octicons/1024/git-pull-request-512.png',
'name': 'PullRequest',
'url': url
}
else:
# title
title_fixed = title
# detail
detail = [
{'name':'notificationBody', 'value':message['detail']['notificationBody']}
]
# link
url_list = re.findall(https_pattern, message['detail']['notificationBody'])
url = url_list[0]
url = url[:-1] if url[-1] == '.' else url
link = {
'icon_url': 'https://cdn-icons.flaticon.com/png/512/2076/premium/2076218.png?token=exp=1635696056~hmac=6f323fa1adc2e6d6de8d2b961c96984b',
'name': 'PullRequest',
'url': url
}
return title_fixed, detail, link
def post_teams(title: str, detail: list, link: list) -> None:
payload = {
'@type': 'MessageCard',
"@context": "http://schema.org/extensions",
"themeColor": "0076D7",
"summary": f'{AWS_ACCOUNT}: {title}',
"sections": [{
"activityTitle": f'{AWS_ACCOUNT}: CodeCommit Notifiction',
"activitySubtitle": f'{title}',
"activityImage": f'{link["icon_url"]}',
"facts": detail,
"markdown": 'true',
"potentialAction": [{
"@type": "OpenUri",
"name": f'{link["name"]}',
"targets": [{
"os": "default",
"uri": f'{link["url"]}'
}]
}]
}]
}
logger.info('post message:')
logger.info(json.dumps(payload))
try:
response = requests.post(TEAMS_WEBHOOK_URL, data=json.dumps(payload))
except requests.exceptions.RequestException as e:
print(e)
else:
print(response.status_code)
끝맺다
이벤트 패턴이 무한해서 하나하나 조사하기 힘들어서 샘플을 원합니다.
Reference
이 문제에 관하여(Lambda로 CodeCommiit 알림을 Teams로 건너뛰기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/antyuntyun/articles/codecommit_notification텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)