[AWS] amplify 배포 / 빌드 현황 슬랙 웹훅(slack webhook) 알람봇 구현 (lambda)
Code/Dev environment

[AWS] amplify 배포 / 빌드 현황 슬랙 웹훅(slack webhook) 알람봇 구현 (lambda)

반응형
반응형

현재 담당하고 있는 서비스는 amplify 를 통해 master 와 staging 브랜치를 기준으로 배포 환경 구성이 되어있다.

그동안은 프론트를 혼자 담당하고 있었고 마스터 배포가 잦은 편은 아니었기에 직접 aws amplify 에 접속해 배포 현황을 보고 배포가 완료되면 팀 채널에 공유하는 식으로 업무를 진행했었는데, 조금씩 마스터 배포가 훨씬 자주 일어나게 되자 amplify 접속하는 것도 귀찮아져서 슬랙 알람 봇을 구현해야겠다는 생각을 했다.

amplify 는 이메일 알람 이외 다른 notification은 제공하지 않았기에 이메일 트리거를 사용하는 방법을 택했다.


그렇게 찾은 두 가지 방법

  1. 개인용 슬랙 메일 주소로 알람 받는 법
  2. amplify의 이메일 노티를 감지해 lambda 함수로 슬랙 웹훅에 전달하기 


1. 개인용 슬랙 메일 주소로 알람 받는 법

우선 1의 경우를 설명하자면 슬랙 계정의 preferences -> Messages & Media 탭 하단을 보면 개인용 이메일 계정을 확인할 수 있다.

 

개인용 이메일 주소를 aws Amplify -> notifications 의 이메일로 등록한다.

그럼 이제 아래와 같이 slack-bot 앱을 통해 메일을 받을 수 있게 된다.

이렇게 간단하게 본인만 확인 가능한 alert 구현이 가능하다.


그런데... 이 방법은 내게 2가지 정도의 문제가 있었다

우선 프론트엔드로써.. 저렇게 빌드 상태 구분조차 힘든 UI 를 용납할 수 없었다.

그리고 그 전까지는 FE 1인 체계였기에 알림을 개인 이메일 슬랙봇으로 받아도 무방했으나, 새 팀원 분의 합류로 이제는 배포 현황에 대한 알람 채널이 필요하다는 생각이 들었다.

그래서 2의 방법을 시도했다.


2.  amplify의 이메일 노티를 감지해 lambda 함수로 슬랙 웹훅에 전달

조금 더 자세 하게 말하자면 amplify에 이메일 주소를 등록해 놓게 되면 amplify 는 빌드 상태가 변경될 때마다 해당 이메일 주소로 이벤트를 실행 시켜 이메일을 발송하게 되어있는데,

이 이벤트를 AWS SNS 를 통해 감지하고 이를 트리거로 갖는 AWS lambda 함수를 만들어 슬랙 API 를 사용, 알람을 받을 수 있도록 구현하는 것이다.

 

세부 설정 방법은 아래 링크를 참고했다.

참고 : https://betterprogramming.pub/how-to-send-slack-notifications-for-aws-amplify-deployments-99278a778ff7

 

How to Send Slack Notifications for AWS Amplify Deployments

Save time and set up Slack notifications for your front-end projects

betterprogramming.pub

나의 경우 위 링크에서의 함수 코드를 그대로 넣으니 작동이 안되어 보니 lambda 함수 실행 파일이 .mjs 의 형식으로 기본 셋팅 되어있어 발생한 문제라 index.js로 파일명 수정 후 정상 작동 되는 것을 확인했다.

 

위 함수 그대로 웹훅에 연결하게 되면 아래와 같이 1번의 방법을 사용했던 이메일로 오던 message 를 그대로 보내주고 있는 것을 확인할 수 있다.

하지만 영 맘에 드는 구조가 아니었기에 받을 수 있는 데이터를 탐색하기 시작했다.

Amplify event 객체 (일부 마스킹처리)

const event = {
  Records: [
    {
      Sns: {
        Type: 'Notification',
        MessageId: '보안',
        TopicArn: 'arn:aws:sns:보안',
        Subject: null,
        Message:
          '"Build notification from the AWS Amplify Console for app: https://master.보안.com/. Your build status is STARTED. Go to https://console.aws.amazon.com/amplify/보안/master/47 to view details on your build. "',
        Timestamp: '2023-09-13T07:16:42.890Z',
        SignatureVersion: '1',
        Signature: '보안',
        SigningCertUrl: 'https://##보안.pem',
        UnsubscribeUrl: 'https://##보안',
        MessageAttributes: {},
      },
    },
  ],
};

Message만 추출해서 보여주던 이유가 있었다.

그것 말고는 정보가 딱히 없었기 때문에.....

더 많은 정보를 보여주고 싶어 이런 저런 방법을 찾아봤는데 직접 shell script를 짜거나 무엇인가를 하라고 했는데 잘 모르는 분야이기도 하고 당장 필요한 기능은 아닌 듯 하여 좀 더 세밀한 개발 환경 구축이 필요할 때 학습하여 도입하고, 그 전까지는 우선 위 이벤트 객체를 활용하는 쪽을 택했다.

일단 쓸 수 있는 데이터를 파악한 뒤 아래와 같이 js 의 exports.handler 이벤트 함수 코드를 수정했다.

exports.handler = async event => {
  const message = event.Records[0].Sns.Message.slice(1, -1);

  const buildStatus = message.includes('STARTED')
    ? 'STARTED'
    : message.includes('FAILED')
    ? 'FAILED'
    : 'SUCCEED';

  const urlRegex = /https:\/\/[^\s]+/g;
  const urlMatches = message.match(urlRegex);

  const branchNameMatches = urlMatches[0].includes('master')
    ? '마스터'
    : urlMatches[0].includes('staging')
    ? '스테이징'
    : '알 수 없는 브랜치';

  const deployHistory = urlMatches[1].split('/').pop();

  const title =
    buildStatus === 'STARTED'
      ? `🚀 ${branchNameMatches} ${deployHistory}번째 빌드 시작!\n`
      : buildStatus === 'FAILED'
      ? `👿 ${branchNameMatches} 배포 실패!\n`
      : `🌼 ${branchNameMatches} ${deployHistory}번째 배포 성공!\n`;

  const timestamp = new Date(event.Records[0].Sns.Timestamp).getTime() / 1000;

  const slackMessage = {
    attachments: [
      {
        title,
        title_link:
          buildStatus === 'SUCCEED' ? 'https://www.hoolzzuk.com/' : undefined,
        color:
          buildStatus === 'STARTED'
            ? 'info'
            : buildStatus === 'FAILED'
            ? 'danger'
            : 'good',

        fields: [
          {
            title: '브랜치',
            value: branchNameMatches,
            short: true,
          },
          {
            title: '배포 현황',
            value: urlMatches[1],
          },
        ],
        ts: timestamp,
      },
    ],
  };

  await postRequest(slackMessage);
};

정규 표현식을 사용해(gpt 최고) message에서 Url만 추출한 뒤 url에 존재하는 빌드 히스토리 스택과 브랜치 이름을 식별할 수 있도록 했고, 빌드 상태를 좀 더 시각적으로 분명하게 보여주기 위해 상태 별 타이틀과 컬러의 핸들링을 진행했다. 

 

오늘의 결과물

나름 로켓도 달고 악마도 넣고 꽃도 넣었다

팀장님이 보시더니 "와~ 힙해요~"라고 호응해주셨다. ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ

 

담당하는 서비스가 계속 커지면서 안정적이고 편한 개발 환경은 무엇일지에 대해 많은 고민을 하고 있는데 이번 기회를 통해 lambda 라는 존재에 대해서 조금 더 알게 된 것 같아 좋은 경험이었다고 생각한다. 

반응형