CodeCommit의 여러 이벤트 처리하기

CodeCommit

AWS는 CodeCommit을 “AWS CodeCommit은 안전한 Git 기반 리포지토리를 호스팅하는 완전관리형 소스 제어 서비스입니다.” 라고 소개하고 있습니다. 즉 GitHub의 AWS 버전입니다. CodePipeline등 AWS의 CI/CD 서비스와도 긴밀하게 연결되었고 후술할 여러 이벤트 Hook이 있어 자동화도 편리하기까지 합니다. 그래서 현재 프로젝트는 모두 CodeCommit으로 형상관리를 하고 있습니다.

서론

Devops 업무를 하다보면 CodeCommit의 여러 이벤트를 자동화하여 처리하여 효율을 높히는 방법을 고민하게 됩니다.

예를들어 PR이 생성되거나 새로운 브렌치가 생성되면 관계자에게 슬랙으로 알림을 전달하는 것 부터 보안이 철저한 회사라면 허용된 IP이외에서 레포를 다운받는걸 알람으로 받는다던지(예시입니다. 사실 이 경우는 IAM Policy를 통해 원천적으로 차단이 가능합니다.) 여러 가지 시나리오를 처리할 수 있겠지요.

CodeCommit에서는 이러한 이벤트 알람을 처리하는 방법은 크게 3가지가 있습니다.

  • CodeCommit에서 제공하는 알람을 통해 SNS호출
  • CloudWatch(EventBridge) Event Rule로 CodeCommit 이벤트를 잡아 SNS 호출
  • CloudWatch “AWS API Call via CloudTrail” 로 API 호출을 잡아 SNS호출

각 케이스에 대해서 간단히 살펴보겠습니다.

CodeCommit 자체 이벤트 알람

CodeCommit에서는 자체적으로 소스가 업데이트 되거나 브렌치의 생성같은 이벤트가 일어날때 알람을 설정할 수 있는 기능이 있습니다. 간단하게 좌측 메뉴에서 설정->알림->알림 규칙 생성에서 생성이 가능합니다. 여기서는 SNS를 생성할 수 있고 해당 SNS에 보낼 알림이 트리거 되는 조건을 선택할 수 있습니다.

자체적으로 제공하는 이벤트 알람 트리거

이 외에도 CodeCommit이 제공하는 여러 이벤트를 통해 CloudWatch(EventBridge) Event Rule을 생성해서 알람을 처리할 수 있습니다.

CloudWatch(EventBridge) Event Rule

AWS CodeCommit이 발생시키는 여러 Event 링크를 직접 CloudWatch Event Rule을 통해 잡아서 SNS를 호출할 수도 있습니다. 위에 언급한 자체 알람보다 더 많은 종류의 이벤트를 지원합니다.
CodeCommit Event 목록. 더 많은 이벤트를 지원합니다.

CloudWatch “AWS API Call via CloudTrail”

CodeCommit에서 모든 종류의 이벤트를 발생시키지는 않습니다. 예를들어 누군가가 Pull을 받거나 하는 행동에 대해서는 정의된 이벤트가 없습니다. 이 경우에는 AWS의 모든 API 호출에 대해서 이벤트 형식으로 잡아 사용할 수 있는 AWS API Call via CloudTrail Rule을 사용하면 됩니다. 링크

이 방법은 List*, Get*, Describe*를 제외한 모든 AWS의 API 호출은 일종의 이벤트 형식으로 잡아내서 CloudWatch Rule을 발생시키는 이벤트 처럼 사용할 수 있습니다. 즉 위에 Pull의 경우 CloudTrail에서는 codecommit:GitPull API로 Pull을 처리하는데, 이 API의 호출을 잡아내서 관련 내용을 보고 알람을 처리할 수 있습니다.

따라서 CodeCommit의 GitPush, GitPull API 등의 API 호출을 잡아서 해당 API가 발생했을대 알람을 생성할 수 있습니다.

CodeCommit:GitPush/GitPull API는 성공시 CloudTrail에 두번씩 기록됩니다.따라서 dataTransferred:true인 API 호출을 기준으로 이벤트를 생성합니다.

다음은 지정한 이메일주소로

  • 브렌치로 Push하였을때
  • 누군가 Pull을 받았을때
  • PR이 생성되었을때
  • 브렌치가 생성되었을때
  • PR이 머지되었을때

해당 내용을 알려주는 예시 CloudFormation 템플릿입니다.

템플릿에서는 간단한 문구만 전달하지만 실제로는 이벤트에서 다양한 정보(IP주소, AGENT 정보등)을 제공하기 때문에 원하는 작업을 수행할 수 있습니다.

다운로드

codecommit-events.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
Parameters:
EmailAddrees:
Type: String
Description: Email Address to be notified
Default: test@test.xyz

Resources:
AlarmTopic:
Type: AWS::SNS::Topic
Properties:
Subscription:
- Endpoint: !Ref EmailAddrees
Protocol: email
## - Endpoint:
## Fn::GetAtt: DeliverMessageToSlackLambdaFunction.Arn
## Protocol: lambda

AlarmTopicpolicy:
Type: AWS::SNS::TopicPolicy
Properties:
PolicyDocument:
Id: AlarmTopicpolicy
Version: "2012-10-17"
Statement:
- Sid: state1
Effect: Allow
Principal:
Service:
- events.amazonaws.com
Action: sns:Publish
Resource: "*"
Topics:
- !Ref AlarmTopic
CodeCommitGitPushEvent:
Type: AWS::Events::Rule
Properties:
Description: CodeCommitGitPushEvent
EventPattern:
source:
- aws.codecommit
detail-type:
- AWS API Call via CloudTrail
detail:
eventSource:
- codecommit.amazonaws.com
eventName: [GitPush]
additionalEventData:
dataTransferred: [true]
Targets:
- Arn:
Ref: AlarmTopic
Id: CodeCommitGitPushEvent
InputTransformer:
InputTemplate: |
" <UserIdentity> 님께서 <Repo> 레포지토리의 '<Branch>' 브렌치에 푸시하였습니다."
InputPathsMap:
Repo: "$.detail.additionalEventData.repositoryName"
Branch: "$.detail.requestParameters.references[0].ref"
UserIdentity: "$.detail.userIdentity.userName"
CodeCommitGitPullEvent:
Type: AWS::Events::Rule
Properties:
Description: CodeCommitGitPushEvent
EventPattern:
source:
- aws.codecommit
detail-type:
- AWS API Call via CloudTrail
detail:
eventSource:
- codecommit.amazonaws.com
eventName: [GitPull]
additionalEventData:
dataTransferred: [true]
Targets:
- Arn:
Ref: AlarmTopic
Id: CodeCommitGitPullEvent
InputTransformer:
InputTemplate: |
" <UserIdentity> 님께서 <Repo> 레포지토리를 받았습니다."
InputPathsMap:
Repo: "$.detail.additionalEventData.repositoryName"

UserIdentity: "$.detail.userIdentity.userName"

CodeCommitCreatePullRequestEvent:
Type: AWS::Events::Rule
Properties:
Description: CodeCommitCreatePullRequestEvent
EventPattern:
source:
- aws.codecommit
detail-type:
- AWS API Call via CloudTrail
detail:
eventSource:
- codecommit.amazonaws.com
eventName: [CreatePullRequest]
Targets:
- Arn:
Ref: AlarmTopic
Id: CodeCommitCreatePullRequestEvent
InputTransformer:
InputTemplate: |
" <UserIdentity> 님께서 <Repo> 레포지토리에 <Title>(<Source> → <Destination>) Pull Request를 생성하였습니다."
InputPathsMap:
Repo: "$.detail.requestParameters.targets[0].repositoryName"
Source: "$.detail.requestParameters.targets[0].sourceReference"
Destination: "$.detail.requestParameters.targets[0].destinationReference"
UserIdentity: "$.detail.userIdentity.userName"
Title: "$.detail.requestParameters.title"

CodeCommitCreateBranchRequestEvent:
Type: AWS::Events::Rule
Properties:
Description: CodeCommitCreateBranchRequestEvent
EventPattern:
source:
- aws.codecommit
detail-type:
- AWS API Call via CloudTrail
detail:
eventSource:
- codecommit.amazonaws.com
eventName: [CreateBranch]

Targets:
- Arn:
Ref: AlarmTopic
Id: CodeCommitCreateBranchRequestEvent
InputTransformer:
InputTemplate: |
" <UserIdentity> 님께서 <Repo> 레포지토리에 <BranchName> 브렌치를 생성하였습니다."
InputPathsMap:
Repo: "$.detail.requestParameters.repositoryName"
BranchName: "$.detail.requestParameters.branchName"
UserIdentity: "$.detail.userIdentity.userName"
CodeCommitMergePullRequestByFastForwardEvent:
Type: AWS::Events::Rule
Properties:
Description: CodeCommitMergePullRequestByFastForwardEvent
EventPattern:
source:
- aws.codecommit
detail-type:
- AWS API Call via CloudTrail
detail:
eventSource:
- codecommit.amazonaws.com
eventName:
[
MergePullRequestByFastForward,
MergePullRequestBySquash,
MergePullRequestByThreeWay,
]
Targets:
- Arn:
Ref: AlarmTopic
Id: CodeCommitMergePullRequestByFastForwardEvent
InputTransformer:
InputTemplate: |
" <UserIdentity> 님께서 <Repo> 레포지토리에 <Title>(<Source> → <Destination>) PR을 머지하였습니다."
InputPathsMap:
Repo: "$.detail.requestParameters.repositoryName"
BranchName: "$.detail.requestParameters.branchName"
Source: "$.detail.responseElements.pullRequest.pullRequestTargets[0].sourceReference"
Destination: "$.detail.responseElements.pullRequest.pullRequestTargets[0].destinationReference"
Title: "$.detail.responseElements.pullRequest.title"
UserIdentity: "$.detail.userIdentity.userName"


결론

CodeCommit의 여러 이벤트를 통해 자동화 처리로 업무를 효율적으로 처리할 수 있습니다. 다음에는 CodePipeline과 연계하여 CI/CD 파이프라인을 구축하는 내용에 대해 포스트를 써볼 까 합니다.

WRITTEN BY
Dev Lead | Certified Professional AWS Solutions Architect/Devops Engineer

댓글