AWS

Slack-Codecommit 연동 :: 마이구미

mygumi 2018. 6. 29. 16:04
반응형

이 글은 슬랙(Slack) 과 코드커밋(Codecommit) 을 연동하는 과정을 다룬다.

코드커밋은 AWS 에서 제공하는 Github 이라고 보면 된다.

AWS 람다(Lambda) 학습의 기본 예제로 볼 수 도 있기에, 람다 학습이 필요하다면 도움을 줄 것이다.


슬랙과 코드커밋을 연동하는 목적과 방식은 여러가지가 존재한다.

이 글에서 다루는 연동은 코드커밋에서 어떤 이벤트라도 발생한다면, 슬랙에 알려주는 것을 목표로한다.

이를 위해 본인이 다루는 방식은 다음과 같다.



  • Codecommit - Git 저장소
  • SNS - 메시지 트리거
  • Lambda - 작성된 함수 호출
  • CloudWatch Logs - 함수 실행에 관련된 로그 확인

위 그림의 흐름대로 코드커밋에서 발생한 이벤트를 슬랙에 알려준다.

그 결과는 다음과 같은 모습으로 슬랙에 출력하게 할 수 있다.



이러한 결과를 얻기 위해서 단계별로 알아본다.


  1. 슬랙 설정
  2. AWS 람다 함수 생성
  3. SNS Topic 생성
  4. SNS - Lambda 연동
  5. Codecommit 설정


1. 슬랙 설정


슬랙에서는 외부 요청을 전송받기 위한 방법으로, Custom Integrations 중 Incoming WebHooks 을 제공한다.



관련 페이지에서 필요한 설정들을 입력한다.

그 중 Webhook URL 의 값을 추후에 사용할 것이다.

이 URL에 AWS 람다 함수의 결과값을 반환한다고 보면 된다.


2. 람다 함수 생성


실질적인 부분으로써, 코드커밋에서 발생한 이벤트를 넘겨 받아 원하는 출력 형태를 위해 코드를 작성한다.

관련 이름을 "CODECOMMIT-WEBHOOK" 연동 으로 지정하겠다.

람다 함수 생성 과정에서 추후 작업을 위한 역할에 lambda, codecommit, cloudwatch 관련 정책을 지정해준다.


이번 단계에서는 아무 설정없이 단순히 람다 함수를 생성한 것이다. (즉, 이 상태로는 동작할 수 없다.)

추후 작업은 4번 단계에서 진행한다.

(관련 람다 함수 예제 코드는 가장 하단에 배치하겠다.)


3. SNS Topic 생성


SNS는 Topic 을 사용하여 게시와 구독을 분리할 수 있다.

코드커밋과 슬랙을 위한 새로운 Topic 을 생성한다.

이 토픽은 "codecommit-slack" 이라고 이름을 지어주겠다.

생성된 토픽을 들어간 후, "create Subscription" 버튼을 통해 구독을 생성해준다.


람다 함수 실행을 위해 프로토콜은 람다로 설정해준다.

엔드포인트는 이전에 생성한 "CODECOMMIT-WEBHOOK" 를 설정해준다.

이로써, SNS 는 메시지를 통해 관련 람다 함수를 실행한다.


4. SNS - Lambda 연동


이 단계는 SNS 를 통해 람다 함수를 실행하기 위한 작업이다.

SNS 를 클릭하면 관련 트리거 설정에서 이전에 생성한 토픽 "codecommit-slack" 을 선택하여 지정한다.

아래와 같은 결과 이미지가 나올 것이다.



5. Codecommit 설정


지금까지의 작업으로, SNS 와 Lambda 는 서로 연결되어 있다는 것은 어느정도 파악할 수 있다.

하지만 실질적으로 이벤트를 SNS 에게 알려주게 되는 코드커밋과의 연결고리는 없다.

그것은 해당 저장소의 설정 메뉴에서 트리거를 지정할 수 있다.



보내는 방식에 있어, 이 글에서 사용하는 SNS 를 설정해준다.

이전 단계에서 생성한 SNS Topic 을 설정해준다.

아래에 존재하는 "Test trigger" 버튼을 통해 쉽게 테스트할 수 있다.

버튼을 클릭한다는 것은 지정된 람다 함수를 실행한다는 것이다.

상태는 cloudWatch log 를 통해 확인하면 된다.


작업이 완료되면, Test trigger 또는 코드커밋에 이벤트가 발생하면 슬랙에 출력되는 것을 볼 수 있다.

출력되는 형식은 아래 코드에서 slackMessgae 변수를 참고하면 된다.

자세한 가이드는 슬랙 공식 문서를 참고하자.

https://api.slack.com/docs/message-attachments


이 글은 AWS 에서 Slack 에 요청하는 방식이다.

다음 글에서는 반대로 Slack 에서 AWS 에 요청하는 방식을 알아볼 것이다.


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
const https = require("https");
const AWS = require("aws-sdk");
const url = require("url");
// to get the slack hook url, go into slack admin and create a new "Incoming Webhook" integration
const slack_url = "[Webhook URL]";
const slack_req_opts = url.parse(slack_url);
slack_req_opts.method = "POST";
slack_req_opts.headers = { "Content-Type""application/json" };
 
exports.handler = function(event, context) {
  (event.Records || []).forEach(function(rec) {
    if (rec.Sns) {
      var req = https.request(slack_req_opts, function(res) {
        if (res.statusCode === 200) {
          context.succeed("posted to slack");
        } else {
          context.fail("status code: " + res.statusCode);
        }
      });
 
      req.on("error"function(e) {
        console.log("problem with request: " + e.message);
        context.fail(e.message);
      });
 
      const codecommit = new AWS.CodeCommit({ apiVersion: "2015-04-13" });
      const records = JSON.parse(event.Records[0].Sns.Message).Records[0];
      let repository = records.eventSourceARN.split(":")[5];
      let commitId = records.codecommit.references[0].commit;
      let region = records.eventSourceARN.split(":")[3];
      const timestamp =
        new Date(event.Records[0].Sns.Timestamp).getTime() / 1000;
      let subject = event.Records[0].Sns.Subject;
 
      // Get the repository from the event and use it to get details of the commit
      codecommit.getCommit(
        {
          commitId: commitId,
          repositoryName: repository
        },
        function(err, data) {
          if (err) {
            context.fail(err);
          } else {
            console.log(data);
            const commit = data.commit;
            let color = "#36a64f";
            let branchName = records.codecommit.references[0].ref;
            let msg = commit.message;
            let authorName =
              commit.author.name + " <" + commit.author.email + ">";
            const slackMessage = {
              text: "*" + subject + "*",
              attachments: [
                {
                  color: color,
                  author_name: authorName,
                  title: "CodeCommit Notification",
                  title_link:
                    "https://ap-northeast-2.console.aws.amazon.com/codecommit/home?region=" +
                    region +
                    "#repository/" +
                    repository +
                    "/commit/" +
                    commitId,
                  fields: [
                    {
                      title: "Branch",
                      value: branchName,
                      short: false
                    },
                    {
                      title: "Message",
                      value: "`" + msg + "`",
                      short: false
                    }
                  ],
                  ts: timestamp
                }
              ]
            };
 
            req.write(JSON.stringify(slackMessage)); // for testing: , channel: '@vadim'
 
            req.end();
          }
        }
      );
    }
  });
};
 
cs


반응형