[Webhook] Github Webhook을 통한 빌드/배포 자동화[1]
Github Webhook을 통한 빌드 / 배포 자동화 1편
Github Webhook Credential 발급
- Github에서 hook 을 이용할 수 있는 권한을 준 token을 발급받아 저장한다.
- 해당 토큰을 Manage Jenkins -> Credentials 에 secret text 형식으로 저장한다.
- Manage Jenkins-> System 에서 Github 란에 가서 API를 이용할 수 있는지 확인한다. 성공했다면 아래와 같은 화면이 뜬다.

Github Username/Password Credential 추가 생성
Manage Jenkins -> Credentials 에 Username/password 형태의 Credential을 추가 생성한다. Username은 Github 아이디이며, Password 는 token이다.
Jenkins Pipeline 생성

우선 Webhook 트리거를 사용하기 전에 간단한 git clone 을 수행하는 파이프라인을 작성한다. 파이프라인을 동작시켜보면 정상 동작할 경우 아래와 같이 파이프라인 스테이지가 성공한다.

Jenkins Generic Webhook Trigger Plugin 설치
- Manage Jenkins -> Plugins -> Available Plugins 에서 Generic Webhook Trigger Plugin 검색 후 설치

이제 Webhook을 이용하여 트리거 시킬 파이프라인의 토큰을 생성해야한다. 파이프라인의 설정으로 이동해보면 Build Triggers에 Generic Webhook Trigger 가 생성된 것을 확인할 수 있다.

클릭해보면 여러가지 필드가 존재하는 것을 확인할 수 있는데 주로 사용할 것은 Post content parameter이다. Webhook을 통해 데이터를 전달 받은 경우, 이것을 파싱하여 데이터를 변수로 만들기 위해 사용한다. 해당 옵션을 선택하면 아래와 같은 화면이 뜬다.

application/json 형식으로 데이터를 전달받을 것이라면, k8s 사용시 많이 이용하게 되는 JSONPath 형식을 이용하여 파라미터를 읽어올 수 있다. 위 예제에서는 pull_request event가 발생하였고, merged 필드를 IF_MERGED 필드에 세팅하는 것이다.
Github Webhook events and Payloads 위 링크를 참조하자.
이제 Pull Request가 생성되었을 때 Unit Test 를 실행하는 설정을 해보자. 우선 Github Webhook 을 받기 위한 Token을 먼저 생성하도록 하자.

Generic Webhook Trigger 이하 Token 필드를 세팅해준다. 텍스트 필드를 직접 입력해도 되고, Manage Jenkins -> Credentials 에서 생성해서 이용해도 된다.
Github Webhook 생성
- Github에 로그인 후 웹훅 적용 대상 레포지토리로 이동
- Settings -> Webhooks로 이동 후 Add Webhook 선택

위와 같은 화면에서 Payload URL 에는 현재 구동중인 Jenkins의 URL을 입력한다. 하부 Which events would you like to trigger this webhook? 에서는 Let me select individual events. 를 선택한 뒤 Pull Request를 선택하도록 하자.
설정 후 정상적으로 Github 에서 Webhook을 발송했다면 다음과 같은 메시지를 볼 수 있다.

Test Pull Request 생성
테스트용 브랜치를 하나 생성한 뒤, Github에 Push를 하고 PR을 생성해보자.

PR을 생성 한 뒤, Webhook Recent Delivery 를 확인해보면 다음과 같이 발송 된 것을 확인할 수 있다.

또한 Jenkins Pipeline도 동작한 것을 확인할 수 있다.

Unit Test 실행
PR 이 생성될 경우, Unit Test를 실행하도록 파이프라인을 작성한다. 우선 Generic Webhook Trigger 에 변수를 세팅한다.
두개의 post content 를 설정한다.
name : branch expression : .action
또한 post content 하단부에 optional filter 가 있는데 PR이 생성된 경우에만 실행할 것이기 때문에 아래와 같이 작성해준다.

이제 파이프라인을 작성한다.
pipeline {
agent any
stages {
stage("Print Branch name") {
steps {
echo "branch : ${branch} triggered this pipeline. action : ${PR_ACTION}"
}
}
stage("Git") {
steps {
git branch: "$branch", credentialsId: 'webhook-test',
url : 'https://github.com/dhkim92-dev/multibranch-test.git'
}
}
stage("Unit Test") {
steps {
script {
echo "Unit test run"
sh '''./gradlew :test --tests "kr.dohoonkim.demo.jenkins.demo.units.*"'''
}
}
}
}
}
이렇게 한 뒤 PR을 생성시켜보면 action이 opened PR에 대해서 파이프라인이 동작함을 알 수 있다.

실행 결과
Generic Cause
[Pipeline] Start of Pipeline
[Pipeline] node
Running on Jenkins in /Users/terrapin/.jenkins/workspace/Webhook
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Print Branch name)
[Pipeline] echo
branch : feature/calculator triggered this pipeline. action : opened
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (Git)
[Pipeline] git
The recommended git tool is: NONE
Warning: CredentialId "webhook-test" could not be found.
> git rev-parse --resolve-git-dir /Users/terrapin/.jenkins/workspace/Webhook/.git # timeout=10
Fetching changes from the remote Git repository
> git config remote.origin.url https://github.com/dhkim92-dev/multibranch-test.git # timeout=10
Fetching upstream changes from https://github.com/dhkim92-dev/multibranch-test.git
> git --version # timeout=10
> git --version # 'git version 2.39.2 (Apple Git-143)'
> git fetch --tags --force --progress -- https://github.com/dhkim92-dev/multibranch-test.git +refs/heads/*:refs/remotes/origin/* # timeout=10
> git rev-parse refs/remotes/origin/feature/calculator^{commit} # timeout=10
Checking out Revision 72d3c3a786e3f79128f69cdda4c4270c97b07a05 (refs/remotes/origin/feature/calculator)
> git config core.sparsecheckout # timeout=10
> git checkout -f 72d3c3a786e3f79128f69cdda4c4270c97b07a05 # timeout=10
> git branch -a -v --no-abbrev # timeout=10
> git branch -D feature/calculator # timeout=10
> git checkout -b feature/calculator 72d3c3a786e3f79128f69cdda4c4270c97b07a05 # timeout=10
Commit message: "feature : LongCaculatorService 추가"
> git rev-list --no-walk 72d3c3a786e3f79128f69cdda4c4270c97b07a05 # timeout=10
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (Unit Test)
[Pipeline] script
[Pipeline] {
[Pipeline] echo
Unit test run
[Pipeline] sh
+ ./gradlew :test --tests 'kr.dohoonkim.demo.jenkins.demo.units.*'
Starting a Gradle Daemon (subsequent builds will be faster)
> Task :compileKotlin UP-TO-DATE
> Task :compileJava NO-SOURCE
> Task :processResources UP-TO-DATE
> Task :classes UP-TO-DATE
> Task :compileTestKotlin UP-TO-DATE
> Task :compileTestJava NO-SOURCE
> Task :processTestResources NO-SOURCE
> Task :testClasses UP-TO-DATE
> Task :test UP-TO-DATE
BUILD SUCCESSFUL in 4s
4 actionable tasks: 4 up-to-date
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS