Jenkins
수정·

[Webhook] Github Webhook을 통한 빌드/배포 자동화[1]

by Dohoon Kim · 23년 08월 21일 09:00:00

Github Webhook을 통한 빌드 / 배포 자동화 1편


Github Webhook Credential 발급

  • Github에서 hook 을 이용할 수 있는 권한을 준 token을 발급받아 저장한다.
  • 해당 토큰을 Manage Jenkins -> Credentials 에 secret text 형식으로 저장한다.
  • Manage Jenkins-> System 에서 Github 란에 가서 API를 이용할 수 있는지 확인한다. 성공했다면 아래와 같은 화면이 뜬다.

imageURL

Github Username/Password Credential 추가 생성

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

Jenkins Pipeline 생성

imageURL

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

imageURL

Jenkins Generic Webhook Trigger Plugin 설치

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

imageURL

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

imageURL

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

imageURL

application/json 형식으로 데이터를 전달받을 것이라면, k8s 사용시 많이 이용하게 되는 JSONPath 형식을 이용하여 파라미터를 읽어올 수 있다. 위 예제에서는 pull_request event가 발생하였고, merged 필드를 IF_MERGED 필드에 세팅하는 것이다.

Github Webhook events and Payloads 위 링크를 참조하자.

이제 Pull Request가 생성되었을 때 Unit Test 를 실행하는 설정을 해보자. 우선 Github Webhook 을 받기 위한 Token을 먼저 생성하도록 하자.

imageURL

Generic Webhook Trigger 이하 Token 필드를 세팅해준다. 텍스트 필드를 직접 입력해도 되고, Manage Jenkins -> Credentials 에서 생성해서 이용해도 된다.

Github Webhook 생성

  • Github에 로그인 후 웹훅 적용 대상 레포지토리로 이동
  • Settings -> Webhooks로 이동 후 Add Webhook 선택

imageURL

위와 같은 화면에서 Payload URL 에는 현재 구동중인 Jenkins의 URL을 입력한다. 하부 Which events would you like to trigger this webhook? 에서는 Let me select individual events. 를 선택한 뒤 Pull Request를 선택하도록 하자.

설정 후 정상적으로 Github 에서 Webhook을 발송했다면 다음과 같은 메시지를 볼 수 있다.

imageURL

Test Pull Request 생성

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

imageURL

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

imageURL

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

imageURL

Unit Test 실행

PR 이 생성될 경우, Unit Test를 실행하도록 파이프라인을 작성한다. 우선 Generic Webhook Trigger 에 변수를 세팅한다.

두개의 post content 를 설정한다.

name : branch expression : .pullrequest.head.refname:PRACTIONexpression:.pull_request.head.ref name : PR_ACTION expression : .action

또한 post content 하단부에 optional filter 가 있는데 PR이 생성된 경우에만 실행할 것이기 때문에 아래와 같이 작성해준다.

imageURL

이제 파이프라인을 작성한다.

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에 대해서 파이프라인이 동작함을 알 수 있다.

imageURL

실행 결과

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