Github Action과 Github API를 이용하여 Trigger를 구성하고, 이를 통해 간단한 CI 구축해봅니다!
Github에는 Github Action 이라는, Github repository를 기반으로 일정한 Workflow를 자동화할 수 있는 툴이 있습니다. 각 repository에 들어가면 상단 탭에서 확인할 수 있습니다.
이 것을 이용하여 Github의 특정 branch에 push하면, unit test를 실행한다거나, 빌드하여 원하는 서버로 업로드한다거나 하는 것을 자동화할 수 있습니다.
오늘은 기존에 작성해놓은 API Server 토이프로젝트를, Heroku 서버로의 deploy 후 API Test까지 자동으로 실행하는 흐름을 만들어보고자 합니다.
제가 원하는 흐름은 아래와 같습니다.
1. Local에서 작업후 에 Github master
브랜치에 push를 하면,
2. heroku에 다시 push를 해주고, push가 완료되면
3. Test code가 있는 다른 repository로 POST
API를 호출하여
4. 해당 repository의 Github action을 이용해 heroku에 배포되어있는 서버 코드에 대해 API Test
를 실행
하는 흐름입니다.
repository_dispatch
Event that trigger Github actionGithub action를 발동시키는 트리거에는 몇가지가 있습니다. 일단 널리 알려진대로는 push
, pull request
, 그리고 schedule
이 있습니다. 이 이벤트들이라면 대부분의 경우에 대응할 수 있긴할 것 입니다. 그러나 외부에서의 다른 이벤트를 이용해 Github action을 실행시키고 싶을 수 있을텐데요, 이럴 때 사용하는 것이 repository_dispatch
(Github webhook의 한 종류)입니다.
위 이벤트를 발동시키기 위해서는, 아래 endpoint로 POST
Request를 보내야합니다.
https://api.github.com/repos/:owner/:repo/dispatches
위 Endpoint는, 특정 repository로 repository_dispatch
를 발생시키는 endpoint이긴 합니다만, 만일 위 endpoint를 이용한 여러개의 Github action이 있다면 event_type
이라는 파라미터를 이용하여 구분해야할 필요가 있습니다.
상세 파라미터는 아래와 같습니다.
Name | Type | In | Description |
---|---|---|---|
Accept | string | header | Setting to application/vnd.github.v3+json |
owner | string | path | |
repo | string | path | |
event_type | string | body | Required. A custom webhook event name |
client_payload | object | body | JSON payload with extra information about the webhook event that your action or workflow may use. |
https://docs.github.com/ja/rest/reference/repos#create-a-repository-dispatch-event
저는 Github A repo의 Github action에서 curl
을 이용하여 해당 endpoint로 request를 날려 실행시키고자 합니다.
일단 A
repo와 B
repo에 각각 test용 action을 만들고, 그 이후 heroku 배포용 action도 추가해보겠습니다.
Github에서 프로필 사진을 누르고, Settings
로 이동합니다.
이후 좌측 메뉴에서 Developer settings
를 선택하시고 Personal access tokens
를 발급받습니다.
이미 Github로의 push를 이용하기 위해 토큰을 발급받으셨다면, 그것을 이용하셔도 되고 새로 발급받으셔도 됩니다.
발급하실 때의 권한 설정은 아래 정도를 해주셔도 될 것 같습니다.
admin:repo_hook, repo, workflow
이렇게 발급 받으신 토큰은 어딘가 안전한 곳에 복사해서 붙여넣기해놓습니다.
Endpoint를 실행할, A
repo에 Access token 정보를 입력해야합니다.
Repo의 Settings에서 Secrets로 이동하시면, 각종 중요정보를 입력할 수 있는 창이 뜹니다. 여기에 ACESS_TOKEN
으로 입력합니다. (사실 key값은 편하신대로 입력하시면 됩니다.)
value값으로는 username:token
의 형태로 입력합니다.
일단 A
repo의 action은 master
branch에 push할 때 마다 실행시킬 것이므로, 먼저 trigger당하는 B
repo의 action을 생성해보겠습니다.
일단 만드는 방법은 다른 분들께서도 잘 작성해주셔서 생략하나.. 적당히 어느 한 분의 글을 링크해드립니다.
https://jonnung.dev/devops/2020/01/31/github_action_getting_started/
# /.github/workflows/~~.yml
# 파일명은 임의이며, Github repository에서 action을 만들 경우,
# 보통은 branch이름으로 생성됩니다.
name: Triggering test
on:
repository_dispatch:
types: [TRIGGER_API_TEST]
#repository_dispatch가 발생할 때, 이 Action이 실행됩니다.
#여기서 types란, 위에서 설명한 endpoint의 payload의 event_type입니다.
#받는 쪽에서 지정한 특정 event_type을 가진 request가 있다면, 실행합니다.
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Check Github action trigger
run: |
echo "Event '${{ github.event.action }}' received from '${{ github.event.client_payload.repository }}'"
일단 간단하게, Trigger를 받아 실행된 action에서 간단한 문자열을 출력해보도록 합니다.
여기서 action
이란 event_type을 뜻하고, client_payload
는 제가 임의로 보내는 데이터를 의미합니다.
다음으로는 A
Repo에서의 action을 생성해봅니다.
name: Deploy to heroku
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
# Trigger Test repository
- name: Send Trigger
run: |
curl -X POST https://api.github.com/repos/:owner/:repo/dispatches \
-H 'Accept: application/vnd.github.v3+json' \
-u ${{ secrets.ACCESS_TOKEN }} \
-d '{"event_type": "TRIGGER_API_TEST", "client_payload": { "repository": "'"$GITHUB_REPOSITORY"'" }}'
A
에서 curl
을 사용하여 trigger를 발생시켜줍니다.
:owner
에는 Github username:repo
에는 B
repository의 이름을 기재하면 됩니다.
여기서 secrets.ACCESS_TOKEN
이, 나중에 실행하면 2. Setting access token repository
에서 등록한 ACCESS_TOKEN
값이 들어가게 됩니다.
이후 local에서 작업하셨다면 Github로 push하시거나, Github에서 직접 action을 작성하셨다면 commit change
하시면 기본적으로 master
나 main
branch로 커밋될 것이고, Action에 정의한 on
조건으로 인하여 자동으로 실행될 것 입니다.
잘 실행되는 것을 확인할 수 있었습니다.
잘 동작하는 것을 확인하였으니, 저의 원래 목적인 Heroku 배포 액션을 추가해봅니다.
Github action marketplace에 올라와있는 heroku-deploy
을 사용해 보았습니다.
name: Deploy to heroku
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
#########################
- name: Deploy to Heroku
uses: AkhileshNS/heroku-deploy@v3.12.12
with:
heroku_api_key: ${{secrets.HEROKU_API_KEY}}
heroku_app_name: "practice-flask-restful-dh"
heroku_email: ${{secrets.HEROKU_EMAIL}}
#########################
# Trigger Test repository
- name: Send Trigger
run: |
curl -X POST https://api.github.com/repos/:owner/:repo/dispatches \
-H 'Accept: application/vnd.github.v3+json' \
-u ${{ secrets.ACCESS_TOKEN }} \
-d '{"event_type": "TRIGGER_API_TEST", "client_payload": { "repository": "'"$GITHUB_REPOSITORY"'" }}'
HEROKU_API_KEY
와 HEROKU_EMAIL
역시 A repo의 Secret에 등록해주었습니다.
Action은 기본적으로 위에서 아래로 실행되기 때문에, 각각의 step
의 순서를 고려해야합니다. 저는 배포가 완료되면, 그 다음 trigger를 발동시켜야 하므로 Trigger의 전 단계에 기재하였습니다.
# /.github/workflows/~~.yml
# 파일명은 임의이며, Github repository에서 action을 만들 경우,
# 보통은 branch이름으로 생성됩니다.
name: Triggering test
on:
repository_dispatch:
types: [TRIGGER_API_TEST]
#repository_dispatch가 발생할 때, 이 Action이 실행됩니다.
#여기서 types란, 위에서 설명한 endpoint의 payload의 event_type입니다.
#받는 쪽에서 지정한 특정 event_type을 가진 request가 있다면, 실행합니다.
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Check Github action trigger
run: |
echo "Event '${{ github.event.action }}' received from '${{ github.event.client_payload.repository }}'"
- name: Set up JDK 14
if: github.event.action == 'TRIGGER_API_TEST'
uses: actions/setup-java@v1
with:
java-version: 14
- name: Test project with Maven
run: mvn test
저는 API Test code를 JAVA
로 작성하였고, dependency관리로 maven
을 사용하였기에 관련 내용을 작성해주었습니다.
참고로 중간에 if
문이 보이는데, on
에서 조건을 명시하지 않아도, if
를 이용하여 특정 조건인 경우에 실행할 step
도 나누어줄 수 있습니다.
mvn test
를 이용하여 관련 library의 설치 및 테스트까지 한 번에 실행합니다.
이제 A를 push한 후 B Action의 실행결과를 확인합니다.
Heroku 배포하는데에 46
초가 걸렸습니다.
저는 Unit test code를 작성하지 않았지만, 배포 전 단계에서 build후 Unit test 실행 후 배포의 흐름을 만든다면 더욱 완벽할 것 같습니다.
Build 및 Test단계에서, API Testcode의 build 후 Test완료까지 16.365
초가 소요되었고, 해당 step종료는 총 19
초 가 걸린 것을 알 수 있습니다.
간단하게 Github Action을 이용하여 API server의 배포 및 API Test까지 실행해보았습니다. 혼자서 포트폴리오를 만드려하니, Circle CI 나 Travis CI 는 결제를 해야하거나 체험판기간이 있어서 조금 부담되더라구요.
어쩌다보니 공부 차 AWS EC2에 Jenkins를 설치해놓은 Instance가 있긴한데, 이번에는 Github action을 사용하게 되었습니다.
yaml
파일에 정의해주는 방법도 공부할 수 있어서 좋았습니다.
Jenkins를 이용하면 각종 Add-on 들 덕분에 이쪽도 쉽게했을지도 모르겠습니다만...
이번 포스트를 통해서 API test code를 이용한 Integration Test까지 실행해보았습니다. 이후에 Marketplace의 여러 action을 이용하여 Test결과 혹은 Action실행 결과등을 Slack이나 Email로 받아볼 수 있으면 좋을 것 같습니다.
IT가 완료되면 Production Server로의 배포까지 실행시켜, CI/CD 환경 또한 구축해볼 수 있을 것 같습니다.
(Dev -> UT/IT 실행 -> QA 서버로의 연속적인 배포라던지)
Ref.
유익한 글이네요. 잘 읽었습니다.