• Slack-Codecommit 연동 :: 마이구미
    AWS 2018. 6. 29. 16:04

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

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

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


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

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

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


    서비스 구조


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

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

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


    git slack 연동


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


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


    1. 슬랙 설정


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


    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" 을 선택하여 지정한다.

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


    slack-lambda


    5. Codecommit 설정


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

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

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


    codecommit trigger


    보내는 방식에 있어, 이 글에서 사용하는 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


    댓글 0

Designed by Tistory.