알고리즘 스터디를 하면서, 깃허브에서 제공하는 자체 웹후크를 사용하여 디스코드로 PR 알림을 받고 있었다.
그런데, 깃허브 자체 웹후크는 PR과 관련된 모든 작업(라벨 바꾸기 등)에 이벤트가 발생하다보니 가끔 호출 제한을 초과하여 알림이 오지 않는 현상이 발생했다. reopen을 해도 상세 정보가 표시되지 않는 불편함도 있었다.
그래서 PR이 open/reopen될 때만 이벤트를 처리하는 웹후크를 스스로 만들어보기로 했다.
Discord Embed Builder - Autocode 에서 디스코드 임베드를 만들어볼 수 있다.
만들어야 할 기능은 PR 알림, PR에서 문제 링크 추출, 링크 이동 버튼 만들기 정도이다.
PR이 open/reopen될 때마다 작업을 자동으로 처리하기 위해 GitHub Actions를 만들어준다.
name: Discord Notification
on:
pull_request:
types: [opened, reopened]
jobs:
PR:
runs-on: ubuntu-latest
steps:
- run: echo "Hello, World!"
이렇게 main.yml을 저장하고 PR을 올리면 Actions 탭에서 echo "Hello, World!" 명령이 실행됨을 확인할 수 있다.
디스코드 채널 편집 - 연동 - 웹후크 - 웹후크 만들기를 한 후 웹후크 URL을 복사하자.
깃허브 Settings - Security - Secrets and variables - Actions - New repository secret 으로 새 secret을 만들어 복사한 디스코드 웹후크 URL을 붙여넣는다. Name은 편한대로 설정하면 된다.
name: Discord Notification
on:
pull_request:
types: [opened, reopened]
jobs:
PR:
runs-on: ubuntu-latest
steps:
- run: >
curl -X
POST -H 'Content-type:application/json'
-d '{"content":"Hello, World!"}'
${{ secrets.DISCORD_WEBHOOK_URL }}
main.yml을 수정하고, PR을 닫았다가 다시 열면 디스코드로 알림이 온다.
name: Discord Notification
on:
pull_request:
types: [opened, reopened]
jobs:
PR:
runs-on: ubuntu-latest
steps:
- env:
DATA: >
{
"embeds": [
{
"title": "23-Munbin-Lee",
"description": "새로운 PR이 도착했습니다!\n\nhttps://www.acmicpc.net/problem/1756",
"url": "https://github.com/Munbin-Lee/test/pull/1"
}
]
}
run: >
curl -X
POST -H 'Content-type:application/json'
-d "$DATA"
${{ secrets.DISCORD_WEBHOOK_URL }}
autocode에서 작성한 양식의 코드를 참조하여 main.yml을 수정하고, PR을 닫았다가 다시 열면 디스코드로 알림이 온다.
이제 PR의 내용에 맞게 임베드의 내용을 수정하자.
name: Discord Notification
on:
pull_request:
types: [opened, reopened]
jobs:
PR:
runs-on: ubuntu-latest
steps:
- run: >
PROBLEM=$(
echo ${{ toJson(github.event.pull_request.body) }} |
grep -Pio 'http[\w\:\/\.-]+' |
head -1
);
echo "PROBLEM=$PROBLEM" >> $GITHUB_ENV
- env:
DATA: >
{
"username": ${{ toJson(github.event.sender.login) }},
"avatar_url": ${{ toJson(github.event.sender.avatar_url) }},
"embeds": [
{
"title": ${{ toJson(github.event.pull_request.title) }},
"description": "새로운 PR이 도착했습니다!\n\n${{ env.PROBLEM }}",
"url": ${{ toJson(github.event.pull_request.html_url) }},
"color": 6847432
}
]
}
run: >
curl -X
POST -H 'Content-type:application/json'
-d "$DATA"
${{ secrets.DISCORD_WEBHOOK_URL }}
임베드의 타이틀과 내용, 링크를 PR에 맞게 생성하고, PR 작성자의 이름과 프로필 사진도 가져오도록 만들었다.
이 action에는 몇가지 문제가 있지만, 아래 내용과 겹치기 때문에 따로 수정하지는 않았다.
잘 작동하는 것을 볼 수 있다.
이 actions를 여러 레포지토리에 적용하려하는데, 단순히 적용하면 수정사항이 발생할 때마다 모든 레포지토리의 파일을 수정해야하는 불편함이 발생한다.
그래서 actions를 배포하기로 했다.
새로운 레포지토리를 만들고, README.md와 action.yml 파일을 추가한다.
action.yml 파일의 내용은 아래와 같다.
name: 'PR to Discord'
author: 'Munbin-Lee'
description: 'sends PR notifications to Discord.'
branding:
icon: 'award'
color: 'blue'
inputs:
discord_webhook_url:
description: 'webhook URL of a Discord channel.'
required: true
pull_request:
description: 'Pull request json.'
required: false
default: ${{ toJson(github.event.pull_request) }}
runs:
using: 'composite'
steps:
- shell: bash
env:
BODY: ${{ toJson(fromJson(inputs.pull_request).body) }}
USERNAME: ${{ toJson(fromJson(inputs.pull_request).user.login) }}
AVATAR_URL: ${{ toJson(fromJson(inputs.pull_request).user.avatar_url) }}
TITLE: ${{ toJson(fromJson(inputs.pull_request).title) }}
URL: ${{ toJson(fromJson(inputs.pull_request).html_url) }}
run: >
PROBLEM=$(
echo $BODY |
grep -Pio 'http[\w\:\/\.-]+' |
head -1 ||
echo "$URL" |
tr -d '"'
);
echo "PROBLEM=$PROBLEM" >> $GITHUB_ENV;
echo "USERNAME=$USERNAME" >> $GITHUB_ENV;
echo "AVATAR_URL=$AVATAR_URL" >> $GITHUB_ENV;
echo "TITLE=$TITLE" >> $GITHUB_ENV;
echo "URL=$URL" >> $GITHUB_ENV;
- shell: bash
env:
DATA: >
{
"username": ${{ env.USERNAME }},
"avatar_url": ${{ env.AVATAR_URL }},
"embeds": [
{
"title": ${{ env.TITLE }},
"description": "새로운 PR이 도착했습니다!\n\n${{ env.PROBLEM }}",
"url": ${{ env.URL }},
"color": 6847432
}
]
}
run: >
curl -X
POST -H 'Content-type:application/json'
-d "$DATA"
${{ inputs.discord_webhook_url }}
다른 action에서 이 action을 실행하기 때문에 github.event를 참조할 수 없다. 따라서 실행 시의 인자로 github.event.pull_request object를 json으로 변환하여 보내고, 사용할 때는 다시 object로 변환한 후 자식을 다시 json으로 변환하여 사용한다. 또한, 문제 링크 검색에 실패했을 때에는 문제 링크 대신 PR 링크로 대체하도록 만들었다.
상세한 내용은 Munbin-Lee/PR-to-Discord (github.com) 에서 확인할 수 있다.
원래는 임베드 밑에 버튼을 만들고 싶었지만, 뭐가 문제인 것인지 잘 작동하지 않는다.
좀 더 공부해야겠다.
참고한 자료
Discord Developer Portal — Documentation — Webhook
https://docs.github.com/en/webhooks/webhook-events-and-payloads
How to read environment variables in env section of github action workflow - Stack Overflow
'Web' 카테고리의 다른 글
온라인 저지 사이트 만들기 - 4 (2) | 2023.01.06 |
---|---|
온라인 저지 사이트 만들기 - 3 (0) | 2023.01.05 |
온라인 저지 사이트 만들기 - 2 (0) | 2023.01.05 |
온라인 저지 사이트 만들기 - 1 (0) | 2023.01.05 |