CodeBuild 빌드 결과를 Slack으로 알리기

2017-06-22 업데이트 에서 CodeBuild 빌드 결과를 CloudWatchEvents에서 캡처할 수 있습니다.
그대로 SNS로 통지해도 좋지만 Lambda에서 Incoming Webhook을 사용하여 Slack에 알리려고 생각합니다.

사전 준비



다음은 이미 완료된 전제로 이야기를 진행합니다.
  • CodeBuild 프로젝트 만들기
  • Slack Incoming Webhook 설정 (URL 게시)

  • 구현



    빨리 끝내고 싶기 때문에 Serverless 프레임워크 을 사용합니다.

    serverless.yml 설정



    글쎄, 언제 볼 수 있을까?

    serverless.yml
    service: notify-build-result
    provider:
      name: aws
      runtime: nodejs6.10
      timeout: 180
      stage: ${opt:stage, self:custom.defaultStage}
      #profileオプション追加
      profile: ${opt:profile, self:custom.defaultProfile}
      #regionオプション追加
      region: ${opt:region, self:custom.defaultRegion}
    custom:
      defaultStage: dev
      #何も指定がなければ default profile
      defaultProfile: default
      #何も指定がなければ 北バージニア
      defaultRegion: us-east-1
    
    functions:
      notify:
        handler: handler.notify
        memorySize: 128
        events:
          - cloudwatchEvent:
              event:
                source:
                  - "aws.codebuild"
                detail-type:
                  - "CodeBuild Build State Change"
                detail:
                  build-status:
                    - SUCCEEDED
                    - FAILED
                    - STOPPED
                  project-name:
                    - my-project-name
              enabled: true
    

    이벤트 설정



    이번 키모가 되는 events의 설정 항목은 상세하게 설명합니다.
    cloudwatchEvent를 지정하여 cloudwatch 이벤트를 트리거할 수 있습니다.
    cloudwatchEvent.event 다음 항목은


    항목 이름
    해설


    소스
    cloudwatch로 보는 대상 이번은 CodeBuild가 대상이므로 aws.codebuild에서 OK

    detail-type
    감지할 이벤트 유형 "CodeBuild Build State Change"를 지정하면 CodeBuild 상태가 변경될 때 이벤트가 발화됩니다.

    detail
    detail 다음은 CodeBuild 특유의 설정

    detail.build-status
    CodeBuild의 상태가 여기에 설정된 경우 이벤트가 발화됩니다. 준비되어 있는 것은 SUCCEEDED(성공), FAILED(실패), STOPPED(중단), PROGRESS(진행중)가 있습니다만, 이번은 결과를 가르쳐 주었으면 하므로 PROGRESS는 제외하고 있습니다.

    detail.project-name
    모니터링할 프로젝트 배열의 형태로 여러 개 지정할 수도 있습니다.

    enabled
    트리거 활성화/비활성화


    Lambda 함수



    payload 확인



    Lambda 함수를 구현하기 전에 cloudwatchEvent에서 Lambda를 호출 할 때 이벤트 인수에 전달되는 내용을 확인합니다.
    아니, 진짜로 트리거에 의해 인수 전혀 다르기 때문에 확인하지 않으면 죽는다.

    이벤트의 종류에 따라서는 Lambda의 콘솔의 테스트 이벤트의 설정으로부터 이런 느낌으로 볼 수 있습니다만,


    불행히도 CodeBuild의 cloudwatchEvent는이 방법으로는 볼 수 없었기 때문에 Lambda의 코드 내에서 console.log(event)
    그 결과는 여기

    event.json
    {
      "version": "0",
      "id": "50639ce0-1497-4911-baa0-79d9ca880a21",
      "detail-type": "CodeBuild Build State Change",
      "source": "aws.codebuild",
      "account": "account-number",
      "time": "2017-06-26T07:10:43Z",
      "region": "us-east-1",
      "resources": [
         "arn:aws:codebuild:us-east-1:account-number:build/my-project-name:9eb34205-9cba-40f2-a5d0-220497a9643a"
      ],
      "detail": {
        "build-status": "SUCCEEDED",
        "project-name": "my-project-name",
        "build-id": "arn:aws:codebuild:us-east-1:account-number:build/my-project-name:9eb34205-9cba-40f2-a5d0-220497a9643a",
        "current-phase": "COMPLETED",
        "current-phase-context": "[]",
        "version": "1"
      }
    }
    
    

    event.detail 이하를 보면 어떻게든 상당히 보이네요.

    기능 본체



    그럼 본체를 구현해 갑시다.
    정책으로는
  • 이벤트 인수에서 프로젝트 이름과 빌드 결과를 가져옵니다.
  • 미리 준비된 Slack의 webhook URL로 보내기

  • 이것뿐입니다.
    request 모듈로 POST하는 것만으로 간단한 일이군요.

    handler.js
    "use strict";
    const request = require('request');
    
    function sendRequest(url, message, callback){
    
        const post = {
            text: message
        };
        //ヘッダーを定義
        const headers = {
            "Content-Type":"application/json"
        };
    
        const options = {
            url: url,
            method: "POST",
            headers: headers,
            json: true,
            body: post
        };
        request(options,  (error, response, body) => {
            console.log(body);
            return callback();
        })
    }
    
    module.exports.notify = (event, context, callback) => {
      const url = "your-webhook-url";
      const buildDetail = event.detail;
      const message = `${buildDetail["project-name"]}のビルドが${buildDetail["build-status"]}デース!`;
      sendRequest(url, message, () => {
        callback(null);
      });
    };
    
    

    결과 확인



    성공





    실패





    왜 페가수스인가?


  • SUCCEEDED 나 FAILED 등 일부러 일본어로 고치는 것이 귀찮았다
  • 그렇다고 전부 영문으로 해서 「영어로 말해도 모르겠어」라든지 화내는 것도 싫었다.
  • 세야, 페가수스라면 영어와 일본어가 섞여도 위화감이 없다!

    구현 후 깨달은 것, 개선 방안


  • cloudwatchEvent의 발화가 매우 빠르다.
  • CodePipeline내에 설치한 CodeBuild에 넣었는데, 페가수스의 통지가 온 후 수십초간은 CodePipeline의 콘솔에서는 빌드중이라고 표시되고 있었다.

  • 멘션을 원할지도
  • CodePipeline의 수동 승인과 결합하면 담당자에게 멘션을 원합니다

  • 좋은 웹페이지 즐겨찾기