목록 보기
AWS CodeCommit 어디까지 써봤니?
기타

AWS CodeCommit 어디까지 써봤니?

브랜디
브랜디
2022년 5월 26일

안녕하세요. B2C 랩유닛 APPS실 커머스개발팀 백엔드파트 손수정입니다. 이 글은 웹서비스팀 개발문화 만들기 를 먼저 읽는걸 권장합니다. 저희 팀은 AWS CodeCommit 을 이용하여 형상관리를 하고 있습니다. 그리고 CodeCommit 의 Pull Request(이하 pr) 를 이용하여 코드 리뷰를 진행하고 있습니다. PR 생성, 업데이트, 병합, 닫힘, 코멘트 생성의 이벤트에 대한 알림을 슬랙을 통해 받고 있었습니다. (위에 링크한 글의 Slack Bot + Lambda + CloudWatch Event을 통한 알림을 사용합니다.) 팀원이 많아지고, PR 문화가 활성화되면서 기존에는 느끼지 못했던 불편함을 느끼기 시작했습니다. 리뷰를 받기 위해 대기하는 시간이 늘어나고, 리뷰를 위해 들여야 하는 시간도 늘어나면서 팀원들의 피로감이 증가하고 있었습니다. 그래서, 코드 리뷰를 더 효율적으로 하기 위해 작은 것부터 편리하게 만든 기록을 공유합니다. AWS CodeCommit 은 다른 형상 관리 툴보다 편의적인 기능 제공에 다소 부족함이 있습니다. 외부 툴 integration 이 쉽지 않다 파일의 소스 길이가 너무 길면 볼 수 없다 메서드 간 이동이 되지 않는다 파일별 변경 점을 찾아다니며 봐야 한다 좋은 툴을 사용하는 것도 방법이지만, 현재 사용하고 있는 툴을 이관하는 것은 많은 시간이 필요한 작업입니다. 당장 팀원들의 효율을 높이기 위해 AWS CodeCommit 을 이용할 때의 불편한 점들을 해결하기로 했습니다. 현재의 문제점은? pr 을 생성하고, 생성 알림은 오지만 해당 알림의 스레드로 리뷰를 직접 요청해야 한다. 2. pr에 코멘트가 생성되면 코멘트 내용을 보기 위해서는 직접 console 에 들어가서 확인해야 한다. 3. 리뷰어가 현재 리뷰 상태인지 알 수 없다. (코멘트를 달거나 승인을 하기 전까지) 문제점 해결하기 pr을 생성하고 스레드로 직접 멘션을 걸던 작업을 자동화하면 어떨까? 라고 생각했습니다. pr이 생성되면, 스레드로 작성자에게 리뷰를 요청하도록 했습니다. 요청하기 버튼을 클릭하면 리뷰어를 지정할 수 있는 모달이 생성됩니다. 슬랙 app 의 modal 기능을 사용하여, 리뷰어를 지정할 수 있게 하였습니다. blocks = ( "title": ( "type": "plain_text", "text": "리뷰어를 지정해주세요" ), "submit": ( "type": "plain_text", "text": "요청하기" ), "blocks": [ ( "type": "input", "element": ( "type": "users_select", "action_id": "user-1", "placeholder": ( "type": "plain_text", "text": "Select a user" ), ), "label": ( "type": "plain_text", "text": "첫번째 리뷰어를 지정해주세요" ) ), ( "type": "input", "element": ( "type": "users_select", "action_id": "user-2", "placeholder": ( "type": "plain_text", "text": "Select a user" ), ), "label": ( "type": "plain_text", "text": "두번째 리뷰어를 지정해주세요" ) ), ], "type": "modal" ) 슬랙의 modal 은 message 에 사용하는 modal 과 비슷한 block입니다. (슬랙의 block kit 생성 기능으로 생성 가능합니다.) type 만 modal 로 지정해주면 됩니다. 슬랙의 views_open 기능을 이용해서 모달을 띄울 수 있습니다. call_result = slack_client.views_open( trigger_id=trigger_id, # 슬랙 action 에서 전달받은 trigger_id view=json.dumps(blocks) # 위에서 생성한 block ) 이때의 trigger_id 는 위에서 리뷰 요청하기 버튼 클릭 시 슬랙에서 전달받은 trigger_id 입니다. (button 액션 시 받은 body 값에 있습니다.) 슬랙의 modal 은 trigger_id 가 유효하지 않으면 정상 작동하지 않습니다. 저희 팀에서는 한사람에게 리뷰가 치우치는 것을 방지하기 위해 스크립트를 통해 랜덤으로 리뷰어를 지정하고 있었습니다. 또한 팀원들이 하는 작업이 스쿼드 별로 다르기 때문에, 필수 리뷰어가 달라야 했습니다. 형평성 있는 분배와 작업 별 기본 리뷰어를 디폴트로 지정하는 일, 두 가지 기능을 추가하기로 했습니다! 지정된 리뷰어를 리뷰어 지정 모달에서 초깃값으로 설정하기 위해서는 initial_user 옵션을 사용하면 됩니다. blocks = ( "title": ( "type": "plain_text", "text": "리뷰어를 지정해주세요" ), "submit": ( "type": "plain_text", "text": "요청하기" ), "blocks": [ ( "type": "input", "element": ( "type": "users_select", "action_id": "user-1", "placeholder": ( "type": "plain_text", "text": "Select a user" ), ), "label": ( "type": "plain_text", "text": "첫번째 리뷰어를 지정해주세요" ) ), ( "type": "input", "element": ( "type": "users_select", "action_id": "user-2", "placeholder": ( "type": "plain_text", "text": "Select a user" ), ), "label": ( "type": "plain_text", "text": "두번째 리뷰어를 지정해주세요" ) ), ], "type": "modal" ) 위처럼 blocks 를 설정하면 초깃값 지정 없이 모달이 생성됩니다. blocks["blocks"][0]["element"]["initial_user"] = "user" # 슬랙의 USER ID 위처럼 각 element 에 initial_user 를 지정해주면, 아래처럼 user select box 에 초깃값을 설정할 수 있습니다. pr 을 생성하면, 리뷰어 지정 스크립트를 실행하고, 리뷰어를 지정해서 알림을 보냅니다. 요청하기 버튼을 클릭하면 지정된 리뷰어가 보이고, 물론 리뷰어를 변경할 수 있습니다. 2. pr 에 작성된 코멘트 내용을 보이게 하자. ( 'version': '0', 'id': '41', 'detail-type': 'CodeCommit Comment on Pull Request', 'source': 'aws.codecommit', 'account': '', 'time': '2022-05-04T08:39:47Z', 'region': 'ap-northeast-2', 'resources': ['arn:aws:codecommit:ap-northeast-2::brandi-api'], 'detail': ( 'afterCommitId': 'be', 'beforeCommitId': 'f2', 'callerUserArn': 'arn:aws:iam:::user/sohnsj', 'commentId': 'ea', 'event': 'commentOnPullRequestCreated', 'inReplyTo': 'e7', 'notificationBody': 'A pull request event occurred in the following AWS CodeCommit repository: brandi-api. The user: arn:aws:iam:::user/s made a comment or replied to a comment. The comment was made on the following Pull Request: 4213. For more information, go to the AWS CodeCommit console, 'pullRequestId': '4213', 'repositoryId': '9**', 'repositoryName': 'brandi-api' ) ) CloudWatch 로 부터 받는 event 정보인데, 한계가 있어 코멘트 내용까지는 받지 못했었습니다. 하지만, pullRequestId 와 commentId 는 알 수 있으니, CodeCommit 에 요청을 보내 코멘트 내용을 가져올 수 있었습니다. # event 는 cloudwatch 로 부터 전달받은 event client = boto3.client('codecommit')

event_detail_info = event['detail'] comment_response = client.get_comment(commentId=event_detail_info['commentId'])

if comment_response.get('comment'): comment_content = comment_response['comment']['content'] aws codecommit 에서 get_comment 메서드를 이용하여서 comment 내용을 가져올 수 있습니다! 코멘트 내용이 보이니, pr 작성자가 아닌 사람도 코멘트 내용을 볼 수 있었고, 좋은 피드백은 모두 공감하여 적용할 수 있었습니다. 이렇게, PR 작성자와 코멘트 작성자 외에 모든 팀원이 코멘트를 확인하고, 의견을 공유할 수 있게 됐습니다. cloudwatch event 에서 이 코멘트가 다른 코멘트의 reply 코멘트인지 여부도 확인할 수 있었습니다. inReplyTo 키로 기존 코멘트의 id를 전달해주고 있어, 그 id 로 기존 코멘트 내용도 조회하도록 했습니다. if event_detail_info.get('inReplyTo'): is_reply = True comment_response = client.get_comment(commentId=event_detail_info['inReplyTo']) if comment_response.get('comment'): reply_content = comment_response['comment']['content'] 코멘트의 답글을 다는 경우도, 원래 코멘트의 내용도 가져와 기존 코멘트 내용과 코멘트 답글 내용도 함께 볼 수 있게 됐습니다. 3. 리뷰어가 더 이상 코멘트를 남길 것이 없는지, 리뷰를 시작했는지 알지 못하고 계속 기다리기만 하는 시간을 줄이기 위해, 리뷰 시작/리뷰 종료에 대한 이벤트를 받기로 했습니다. 리뷰 요청하기를 누르고, 리뷰어를 지정하면, 리뷰어들을 태그하고 각각 리뷰어들이 리뷰를 시작했을 때 누를 수 있는 버튼을 만들어 주었습니다. 이제, 리뷰이는 리뷰어가 리뷰를 시작했는지, 리뷰를 완료 했는지 알림을 받아볼 수 있게 됐습니다! 추가 기능 넣기 불편함을 해결하고 나니, 원하는 기능들이 생겼습니다. (상상 속에 있는 걸 현실로 옮기기로 했습니다.) 피드백을 반영하고 난 후, 소스가 업데이트되면 지정되었던 리뷰어에게 재 알림을 주면 좋겠다. 리뷰어로 할당된 pr들을 모아서 보고 싶다. 소스 업데이트 시 리뷰어에게 재 알림 보내기 기존에는 pr 생성과 리뷰어 지정이 함께 연동되지 않았습니다. (소스 업데이트 시 pr 요청자가 지정되었던 리뷰어를 기억하고 태그를 해야 했었습니다.) pr 에 지정된 리뷰어를 유지하는 방법을 찾아보다가, pr 의 승인 규칙을 적용하기로 했습니다. pr 의 필수 승인자로 리뷰어를 지정하면, 소스를 업데이트하여도 승인 규칙을 조회해서 기존의 리뷰어를 찾을 수 있을 것 같았습니다. 리뷰어 지정하고 리뷰를 요청하면, 슬랙으로부터 view_submission type의 액션을 받게 됩니다. ( "type":"view_submission", "team":( "id":"T*", "domain":"b*" ), "user":( "id":"U*", "username":"p*", "name":"p*", "team_id":"T*" ), "api_app_id":"A*", "token":"1*", "trigger_id":"3*", "view":( "id":"V*", "team_id":"T*", "type":"modal", "blocks":[...], "private_metadata":"", "callback_id":"", "state":( "values":( "JqX":( "user-1":( "type":"users_select", "selected_user":"U*" ) ), "x8eSC":( "user-2":( "type":"users_select", "selected_user":"U*" ) ), "C1Bo":( "emergency-selct":( "type":"static_select", "selected_option":( "text":( "type":"plain_text", "text":":x:", "emoji":True ), "value":"e*" ) ) ) ) ), "hash":"1*", "title":(...), "clear_on_close":False, "notify_on_close":False, "close":None, "submit":( "type":"plain_text", "text":"*0", "emoji":True ), "previous_view_id":None, "root_view_id":"V*", "app_id":"A*", "external_id":"", "app_installed_team_id":"T*", "bot_id":"B*" ), "response_urls":[], "is_enterprise_install":False, "enterprise":None ) view['state']['values'] 에서 선택된 값들을 받을 수 있습니다. values 객체 안의 키값은 계속 변경되는 값입니다! answer_blocks = payload['view']['state']['values'] answer_keys = answer_blocks.keys()

first_reviewer = None second_reviewer = None emergency_answer = False

for key in answer_keys: answer_keys = answer_blocks[key] if answer_keys.get('user-1'): first_reviewer = answer_keys['user-1']['selected_user'] elif answer_keys.get('user-2'): second_reviewer = answer_keys['user-2']['selected_user'] 그래서 loop 를 돌려, 지정한키 (user-1, user-2) 를 찾아 리뷰어를 찾아오도록 했습니다. 이때 지정한 키는, 위에서 blocks 를 생성할 때 각 element 에 지정한 action_id 입니다. 이제 codecommit 의 create_pull_request_approval_rule 를 이용하여, 선택된 리뷰어가 필수 승인자로 지정되게 합니다. codecommit 의 pull_request_approval_rule 은 필수 승인자 수와, 필수 승인자 (Approval pool) 을 지정할 수 있습니다. aws_client = boto3.client('codecommit')

code_commit_approver = f'arn:aws:iam::(domain_id):user/' first_user = USER_NAME.get(first_reviewer).get('aws_name') # aws 의 username second_user = USER_NAME.get(second_reviewer).get('aws_name') # aws 의 username

rule_content = ( 'Version': '2018-11-08', 'Statements': [ ( 'Type': 'Approvers', 'NumberOfApprovalsNeeded': 2, # 승인자 수 'ApprovalPoolMembers': [] # 필수 승인자 ) ] )

rule_content['Statements'][0]['ApprovalPoolMembers'].append(f'(code_commit_approver)(first_user)') rule_content['Statements'][0]['ApprovalPoolMembers'].append(f'(code_commit_approver)(second_user)')

result = aws_client.create_pull_request_approval_rule( pullRequestId=pull_request_id, approvalRuleName=f'(pull_request_id)_commerce_dev_approval_rule', # 승인 룰 이름 approvalRuleCon

댓글 0

댓글을 작성하려면 로그인이 필요합니다.

댓글을 불러오는 중...