Github Action, Slack 연동

최더디·2022년 5월 19일
7
post-thumbnail

📍 서론

Github Action은 설정했지만, main or develop 브랜치에 push 할 때마다 Github Action 페이지에 들어가서 확인하기는 매우 번거롭다. PUSH 후 Build & Deploy가 성공하게 된다면 Slack Channel로 메시지를 보내는 기능을 구현해보려고 한다.

📍 참고

📍 개발

slack-send 사용

Github Marketplace에서 제공하는 slack-send를 사용해 설정.

Slack으로 데이터를 보내는 3가지 방법을 알려주는데, 유로 Slack 요금제를 사용 중인 경우 추천하는 방법인 "Slack의 Workflow Builder로 데이터를 보내는 방법"을 사용하려고 한다.

WebHook URL 얻기

"Slack의 Workflow Builder로 데이터를 보내는 방법"을 사용하기 위해서는 Slack Workflow Builder 설정을 해야한다.(당연한 소리)

1) slack 좌측 상단 팀명 클릭 → 도구 → 워크플로 빌더

2) 생성 버튼을 눌러 새로운 워크플로를 생성

3) 워크플로 이름 지정 → 다음

4) 웹 후크 선택 후 우선 "다음" 클릭 (변수를 만들지 않았으므로)

5) 아래 사진처럼 만들어졌지만, 아직 게시 버튼이 비활성화 되어있다.
("게시"를 해야 WebHook URL을 얻을 수 있음)

6) "단계 추가"를 눌러 자신이 원하는 것을 추가한다. 나는 "메시지 보내기"를 선택했다.

7) "이 메시지 보내기" 선택 및 "메시지 텍스트" 작성 후 "저장" 버튼 클릭

8) 단계를 추가했다면 이처럼 "게시" 버튼이 활성화 됨

9) "게시" 버튼을 클릭하게 되면 WebHook URL을 얻을 수 있음

Github Repository Secret 설정

위를 통해 얻은 WebHook URL을 Github Repository Secrets에 넣어준다.

자신의 Repository → Settings → Secrets-Action 탭 클릭 → New repository secret 클릭 → Key-Value 입력(Key=SLACK_WEBHOOK_URL, Value={아까 만든 WebHook URL})

Workflow YAML 파일 수정

yaml 파일을 수정해보자.

name: Build and Deploy
on:
  push:
    branches:
      - main
      - develop

jobs:
  deploy-dev:
		if: ${{ github.ref == 'refs/heads/develop' }}
    ...
			      
  deploy-prod:
    if: ${{ github.ref == 'refs/heads/main' }}
		...

	# Slack 알림 관련 Job
  slack-notification:
    if: ${{ always() }}
    needs: [deploy-dev, deploy-prod]
    runs-on: ubuntu-latest
    steps:
      - name: Set CUSTOM_STATUS Env Variable
        run: |
          if [ "${{ needs.deploy-dev.result }}" = "failure" ] || \
             [ "${{ needs.deploy-prod.result }}" = "failure" ];
          then
            CUSTOM_STATUS="❌ 실패"
          elif [ "${{ needs.deploy-dev.result }}" = "cancelled" ] || \
            [ "${{ needs.deploy-prod.result }}" = "cancelled" ];
          then
            CUSTOM_STATUS="⚠️ 취소"
          else
            CUSTOM_STATUS="✅ 성공"
          fi
          
          echo "CUSTOM_STATUS=${CUSTOM_STATUS}" >> $GITHUB_ENV

      - name: slack-send
        uses: slackapi/slack-github-action@v1.19.0
        with:
          payload: |
            {
              "custom_status": "${{ env.CUSTOM_STATUS }}",
              "workflow": "${{ github.workflow }}",
              "job_deploy_dev": "deploy_dev",
              "status_deploy_dev": "${{ needs.deploy-dev.result }}",
              "job_deploy_prod": "deploy_prod",
              "status_deploy_prod": "${{ needs.deploy-prod.result }}",
              "actor": "${{ github.actor }}",
              "ref_name": "${{ github.ref_name }}",
              "head_commit_url": "${{ github.event.head_commit.url }}",
              "action_run_url": "${{ env.ACTION_RUN_URL }}"
            }
        env:
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
          ACTION_RUN_URL: "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"

1) Slack 알림은 성공, 실패, 취소 하는 등 모든 액션에 있어 실행되어야 하기 때문에 always() 를 넣어준다.

slack-notification: 
	if: ${{ always() }}

2) deploy-dev, deploy-prod 작업이 끝난 후 실행되어야 하고, 결과 값을 가져와야 하기 때문에 needs 설정

slack-notification: 
	if: ${{ always() }}
	needs: [deploy-dev, deplpy-prod]

3) 작성된 모든 Job들의 결과 상태에 따라 값을 다르게 주도록 설정한다.
마지막에는 저장된 결과 상태 값(=CUSTOM_STATUS)을 환경 변수에 넣어준다.

...

steps:
  - name: Set CUSTOM_STATUS Env Variable
    run: |
      if [ "${{ needs.deploy-dev.result }}" = "failure" ] || \
         [ "${{ needs.deploy-prod.result }}" = "failure" ];
      then
        CUSTOM_STATUS="❌ 실패"
      elif [ "${{ needs.deploy-dev.result }}" = "cancelled" ] || \
        [ "${{ needs.deploy-prod.result }}" = "cancelled" ];
      then
        CUSTOM_STATUS="⚠️ 취소"
      else
        CUSTOM_STATUS="✅ 성공"
      fi
      
      echo "CUSTOM_STATUS=${CUSTOM_STATUS}" >> $GITHUB_ENV

4) Github Marketplace에 있는 slack-send를 사용.
해당 링크를 통해 필요한 값들을 JSON 형식으로 payload 에 넣어준다.

💡 [주의사항]
github.event.head_commit.message 를 사용하려면 commit message 제목만 작성해야 한다. 본문까지 작성한다면 JSON 형식에 맞지 않는다는 오류가 발생한다. (문자열 분리를 통해 값을 가져오려고 시도했지만, 실패..)

...

- name: slack-send
  uses: slackapi/slack-github-action@v1.19.0
  with:
    payload: |
      {
        "custom_status": "${{ env.CUSTOM_STATUS }}",
        "workflow": "${{ github.workflow }}",
        "job_deploy_dev": "deploy_dev",
        "status_deploy_dev": "${{ needs.deploy-dev.result }}",
        "job_deploy_prod": "deploy_prod",
        "status_deploy_prod": "${{ needs.deploy-prod.result }}",
        "actor": "${{ github.actor }}",
        "ref_name": "${{ github.ref_name }}",
        "head_commit_url": "${{ github.event.head_commit.url }}",
        "action_run_url": "${{ env.ACTION_RUN_URL }}"
      }
  env:
    SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
    ACTION_RUN_URL: "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"

Slack Workflow Builder 변수 설정

Workflow YAML 파일을 수정했다면, payload에 작성한 값을들 받을 수 있도록 slack workflow builder에서 변수 설정을 해줘야 한다.

1) 편집 → 변수 추가 클릭

2) 위에서 작성한 YAML 파일 payload에 해당하는 KEY 값들을 추가해줍니다.

메시지 형식 작성

변수 설정이 끝났다면 설정한 채널에 어떤 형식으로 보낼지 작성해야 합니다.

1) 메시지 보내기 편집 클릭

2) 채널을 선택한 후, "메시지 텍스트"를 작성한다.
"변수 삽입"을 통해 설정한 변수를 사용할 수 있다.(변수에 굵기, 코드 삽입도 가능함)
"미리 보기" 부분을 통해 확인 후, 설정 및 확인했다면 "저장"

게시

모두 설정을 완료 했다면 변경사항 게시 클릭하게 되면 설정된 값이 저장된다.

Github Action 실행 및 결과

모든 준비는 끝났다. 이제 아무 파일이나 수정을 한 후, Github Action이 실행되도록 해보자!

성공!

📍 이슈

commit 메시지에 제목 + 본문을 작성하면 오류 발생

[오류 상황]

head_commit_message 값은 commit message를 받아오는 데이터이다.
해당 값이 JSON 형식에 맞지 않아 오류가 발생

[오류 원인]

  • head_commit_message 값 때문에 오류 발생.
  • """ 을 사용해도 오류 발생 " 를 사용해서 값을 넣어줘도 오류 발생.
  • 문자열을 \n 으로 나눠봤는데도 오류 발생 → \n 이 없는 값 같인가..?

[해결 방법]

  • 해결 하지 못함..
  • Commit Message Title만 가져오고 싶은데... 해결하지 못해 우선 Commit URL을 넘겨주도록 수정

이모티콘이 나오지 않는 이슈

[오류 상황]

아래의 스크립트 명령어를 실행하면 계속해서 echo ${EMOTICON} 을 하게 되면 값이 출력 되지 않음.

run: |
	if [ "${{ needs.set-python-and-test.result }}" = "failure" ] || \
	   [ "${{ needs.deploy-dev.result }}" = "failure" ] || \
	   [ "${{ needs.deploy-prod.result }}" = "failure" ];
	then
	  echo "❌ FAIL"
	  EMOTICON="❌"
	else:
	  echo "✅ Success"
	  EMOTICON="✅"
	fi

[오류 원인]

else에 :(콜론)을 붙임..

[해결 방법]

제거하니까 바로 됨

echo 로 출력된 값을 넣어줄 때 오류

payload에 값을 넣어줄 때 ${{ env.{value} }} 이처럼 값을 출력하기 때문에 아래처럼 작성하게 되면 환경변수에 넣어질 줄 알았음 → 하지만 오류 발생

echo "CUSTOM_STATUS=${CUSTOM_STATUS}" >> ${{ env }}

이처럼 넣어줘야 함.

echo "CUSTOM_STATUS=${CUSTOM_STATUS}" >> $GITHUB_ENV

payload 로 넘겨준 값이 Slack Workflow Builder 변수 설정에 없다면 오류 발생.

해당 이슈를 통해 생각한 작업 방식.

YAML 파일 수정 → Slack Workflow Builder 변수 설정 → Workflow Builder 메시지 수정

텍스트에 링크 삽입하기

커밋 메시지, workflow 텍스트에 링크를 삽입해 링크를 눌러 쉽게 접근할 수 있도록 하고 싶었다.
하지만 도저히 어떻게 하는지 모르겠다.

Slack Workflow Builder 메세지 작성하는 부분에서 변수에 링크를 넣는 기능을 현재 제공하지 않는다고 한다.

찾아보니 변수에 링크를 넣고 싶다면 Slack API를 사용해야 가능하다고 한다. 그렇다면 내가 선택한 slack-send에서 추천한 1번 방법으로는 사용할 수 없다는 뜻이 된다.

📍 마무리

해당 작업을 하면서 YAML, Linux 문법이 부족하다는 것을 느꼈다. 꾸준히 하면서 익숙해져야 할 것 같다.

아쉬운 점은 Github Action을 쉽게 테스트 하는 방법을 못 찾았다는 것이다. 내가 이벤트 트리거 설정을 PUSH 로 해놓긴 했지만, 계속해서 Push를 하면서 테스트를 진행했다.

그렇기 때문에 나는 이번 작업을 하는데만 75 commits 을 했다..ㅎㅎ
PUSH 하지 않고 어떻게 테스트를 진행할지 생각해봐야겠다. (지금 생각해보니 쉬울 것 같기도? 아닌가..?)

해당 글은 Github Marketplace 에서 제공하는 slack-send를 사용해서 진행한 프로젝트다.
하지만 해당 링크를 통해 보면 slack-send 보다 Slack Notify, action-slack이 스타가 더 많고 많이 사용한다는 것을 볼 수 있다.

내가 slack-send를 선택한 이유는 공식 인증인 파란 체크가 달려있었기 때문이였는데, action-slack을 사용해보니 확실히 slack-send보다 편한 느낌이 있었다. 알아서 만들어주는 느낌이랄까?

만약 slack-send 사용이 어렵다고 판단되면 Slack Notify, action-slack 사용도 생각해보면 좋을 것 같다.

action-slack을 잠깐 사용한 후기는 편하게 보여주기는 하지만 나에게는 커스텀하는데 약간 불편했고, 내가 원하는 정보를 가져올 수 없었다. 하지만 내가 가장 원했던 "커밋 메시지를 보여주는 기능"과 "텍스트에 링크를 삽입하는 기능"이 자동으로 해주기 때문에 너무 좋았다.

간단한 작업일 줄 알았는데, 생각보다 오래 작업했던 것 같다...
내가 개발에 재능이 있는 줄 알았는데, 절대 아니다. 역시 개발은 이런 재미지. 분발해라 최더디.

profile
focus on why

1개의 댓글

comment-user-thumbnail
2023년 12월 28일

소중한 지식 공유 감사합니다.

답글 달기