깃헙 액션으로 gcp run에 배포를 하고 있었고 성공여부를 슬랙 메세지로 받고 싶었습니다. 전체 코드는 게시글 마지막에 첨부되어 있습니다. 우선 단계별로 진행 과정을 확인해시면 이해하는데 도움이 되리라 생각합니다.
1. 슬랙 앱 기본 셋팅
우선 배포시작 알림 메세지를 슬랙에 보내봅시다. 배포가 완료되고 나면 이 메세지에 o , x 이모지로 성공 여부를 표시하려고 합니다. 배포시작 메세지를 보내는것은 curl명령어를 통해 슬랙 앱 api를 호출하면 되는데요. 우선 슬랙 앱을 만들어야겠죠?
- https://api.slack.com/apps 이곳에서 슬랙 api 앱을 생성할 수 있습니다.
앱이 생성되면 토큰을 설정하고 권한을 부여합니다. 아래 이미지에서 토큰생성과 권한을 참고해주세요.
OAuth 토큰 확인
권한 설정
2. 배포 시작 메세지 보내기
이 코드는 curl 명령어로 좀 전에 만든 슬랙 앱 api를 호출하는 명령어입니다. 최종적으로 깃헙 액션 워크플로우에서 실행시키게 할 예정입니다.
RESPONSE=$(curl -H "Content-type: application/json; charset=utf-8" \
--data "$JSON_DATA" \
-H "Authorization: Bearer $SLACK_TOKEN" \
-X POST https://slack.com/api/chat.postMessage)
$SLACK_TOKEN: 슬랙 앱을 만들고 확인할 수 있는 토큰입니다. 저의 경우 깃헙 오가니제이션 시크릿 키에 등록해두고 불러와서 사용하였습니다.
$JSON_DATA: 배포 시작 메세지에 담아 보내는 데이터 입니다. 아래와 같이 설정해 주었습니다. SLACK_CHANNEL_ID만 어떤 채널에 보내야 할지 필요하니 필수이고 나머지는 정보성 데이터 입니다.
JSON_DATA=$(jq -n \
--arg channel "$SLACK_CHANNEL_ID" \
--arg site "$SITE" \
--arg env "$ENV" \
'{channel: $channel, blocks: [
{type: "section", fields: [
{type: "mrkdwn", text: ("*사이트:* " + $site)},
{type: "mrkdwn", text: ("*배포환경:* " + $env)}
]},
]}')
3. TIMESTAMP 추출하기
curl 명령어의 RESPONSE 가 중요합니다. 슬랙 웹훅 url을 사용하지 않고 슬랙 api를 사용한 이유이기도 합니다. RESPONSE에는 메세지의 TIMESTAMP가 담겨있습니다. 이 TIMESTAMP를 기억해 두었다가 이모지를 달아야 하는 메세지를 찾을 수 있습니다.
아래처럼 jq를 활용하여 RESPONSE에서 TIMESTAMP를 추출할 수 있습니다
TIMESTAMP=$(echo $RESPONSE | jq -r '.ts
그 후 TIMESTAMP를 깃헙 액션의 출력값으로 지정합니다.
echo "message_timestamp=$TIMESTAMP" >> $GITHUB_OUTPUT
3. 워크플로우로 message_timestamp를 보내봅시다.
outputs:
message_timestamp:
description: 'message timestamp'
value: ${{ steps.notify_deploy_start.outputs.message_timestamp }}
message_timestamp라는 키값으로 깃헙 워크플로우에서 사용할 수 있게 되었습니다. message_timestamp를 통해 배포 시작 메세지를 찾고 이모지를 달 수 있는 준비를 마쳤습니다.
전체코드를 보며 맥락을 이해해 봅시다.
1) github composite를 사용하여 워크플로우에서 사용할 수 있게 모듈 형태로 작성했다는 것을 참고해주세요.
2) 이 코드를 .github/workflows/deploy.yml에서 불러와서 사용할 수 있습니다.
// .github/actions/deploy-start/action.yml
name: 'Notify Deploy to Slack'
description: 'Sends a notification to Slack'
outputs: // 워크플로우로 message_timestamp를 보냅니다.
message_timestamp:
description: 'message timestamp'
value: ${{ steps.notify_deploy_start.outputs.message_timestamp }}
runs:
using: 'composite'
steps:
- name: Notify Slack Deployment
id: notify_deploy_start
shell: bash
run: |
if [[ "$ENV" != "development" ]]; then
if [ -z "$PURPOSE" ]; then
PURPOSE_TEXT=""
else
PURPOSE_TEXT="${PURPOSE}"
fi
CURRENT_BRANCH="${GITHUB_REF#refs/heads/}"
BRANCH_URL="https://github.com/$GITHUB_REPOSITORY/tree/$CURRENT_BRANCH"
DIFF_URL="https://github.com/$GITHUB_REPOSITORY/compare/$D1_ENV...$CURRENT_BRANCH"
WORKFLOW_URL="https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID"
JSON_DATA=$(jq -n \
--arg channel "$SLACK_CHANNEL_ID" \
--arg branch "$CURRENT_BRANCH" \
--arg diffUrl "$DIFF_URL" \
--arg actor "$GITHUB_ACTOR" \
--arg url "$WORKFLOW_URL" \
--arg purposeText "$PURPOSE_TEXT" \
--arg site "$SITE" \
--arg env "$ENV" \
'{channel: $channel, blocks: [
{type: "section", fields: [
{type: "mrkdwn", text: ("*사이트:* " + $site)},
{type: "mrkdwn", text: ("*배포환경:* " + $env)}
]},
{type: "section", fields: [
{type: "mrkdwn", text: ("*브랜치:* <" + $diffUrl + "|" + $branch + ">")},
{type: "mrkdwn", text: ("*목적:* " + $purposeText)}
]},
{type: "context", elements: [
{type: "mrkdwn", text: ("배포자: " + $actor)},
{type: "mrkdwn", text: ("진행상황: " + "<" + $url + "|Workflow>")}
]}
]}')
RESPONSE=$(curl -H "Content-type: application/json; charset=utf-8" \
--data "$JSON_DATA" \
-H "Authorization: Bearer $SLACK_TOKEN" \
-X POST https://slack.com/api/chat.postMessage)
TIMESTAMP=$(echo $RESPONSE | jq -r '.ts') // RESPONSE에서 TIMESTAMP를 추출합니다.
if [[ $(echo $RESPONSE | jq -r '.ok') != "true" ]] || [[ "$TIMESTAMP" == "null" ]]; then
echo "Error: Failed to retrieve timestamp from Slack API response."
else
echo "message_timestamp=$TIMESTAMP" >> $GITHUB_OUTPUT //message_timestamp 출력으로 담습니다.
fi
fi
정리해보겠습니다.
1. 슬랙에 메세지를 보낼 앱 기본셋팅
2. 슬랙에 메세지를 보내고 해당 메세지를 찾을 수 있는 TIMESTAMP 추출하기
3. TIMESTAMP를 워크플로우에서 사용할 수 있게 만들기
이 3가지를 이번 게시글에서 설명해보았습니다.
다음 게시글에서는 이 composite 코드를 깃헙 워크플로우에서 어떻게 불러와서 사용하는지, 그리고 어떻게 이모지를 다는지 작성해보겠습니다 :)