GitHub Enterprise Jenkins Pipeline 자동 빌드 이슈 해결

개요

회사에서 Gerrit 사용 중 GitHub Enterprise로 넘어오게 되었는데, push시 빌드하도록 설정하였는데도 빌드가 안되는 이슈 발생

 

사용 버전

GitHub Enterprise Server 3.7.3

Jenkins 2.243

 

기존 설정

Jenkins

item - 구성 - Build Triggers - GitHub hook trigger for GITScm polling 체크박스 체크

 

GitHub

GitHub Repository - Settings - Hooks - Add webhook

Payload URL (jenkins url 뒤에 /github-webhook/ 추가) 입력

Content type: application/json

Just the push event. 라디오 버튼 선택

Active 선택

 

 

문제해결

"github webhook pipeline not working" 키워드로 검색 중 링크 발견

링크 내용 중 3번 내용 참고하여 내용 정리

  1. Jenkins에서 webhook Log 확인을 위한 Logger 추가
  2. pipeline 스크립트에서 사용중인 git 명령어의 url이 webhook Request 안의 url과 동일한지 확인
  3. Jenkins 스크립트 콘솔을 사용하여 DefaultPushGHEventSubscriber.java 파일에서 빌드 발생시킬 때 호출하는 메서드 return 값 확인
  4. pipeline 스크립트에서 사용중인 git 명령어의 url과 스크립트 콘솔에서 보여지는 host가 다를경우 해당 아이템 빌드 (pipeline 스크립트에서 git url 수정 후 빌드 한번 해줘야 url 바뀜)
  5. 자동 빌드 테스트시 GitHub webhook의 Redeliver버튼으로는 Trigger가 안되니, 반드시 직접 push하여 테스트

 

Jenkins에서 webhook Log 확인을 위한 Logger 추가

Jenkins Dashboard - Jenkins 관리 - System Log - 신규 로그 기록기 추가

이름: DefaultPushGHEventSubscriberLogger

Loggers 추가

Logger: org.jenkinsci.plugins.github.webhook.subscriber.DefaultPushGHEventSubscriber

Log level: ALL

 

입력 후 SAVE

 

// GitHub이 호출한 webhook Push 이벤트 Request Jenkins가 수신
Aug 29, 2023 7:13:42 PM INFO org.jenkinsci.plugins.github.webhook.subscriber.DefaultPushGHEventSubscriber onEvent
Received PushEvent for https://github.com/webgori/lolien-api from 1.2.3.4 ⇒ http://localhost:8080/github-webhook/

// Jenkins에 등록된 lolien-api 아이템의 git 정보가 수신한 정보와 동일한지 확인
// 동일하여 빌드
Aug 29, 2023 7:13:42 PM FINE org.jenkinsci.plugins.github.webhook.subscriber.DefaultPushGHEventSubscriber$1 run
Considering to poke lolien-api
Aug 29, 2023 7:13:42 PM INFO org.jenkinsci.plugins.github.webhook.subscriber.DefaultPushGHEventSubscriber$1 run
Poked lolien-api

// Jenkins에 등록된 lolien-web 아이템의 git 정보가 수신한 정보와 동일한지 확인
// 동일하지 않아 Skip
Aug 29, 2023 7:13:42 PM FINE org.jenkinsci.plugins.github.webhook.subscriber.DefaultPushGHEventSubscriber$1 run
Considering to poke lolien-web
Aug 29, 2023 7:13:42 PM FINE org.jenkinsci.plugins.github.webhook.subscriber.DefaultPushGHEventSubscriber$1 run
Skipped lolien-web because it doesn't have a matching repository.

webhook Request 후 기록된 로그 확인

 

pipeline 스크립트에서 사용중인 git 명령어의 url이 webhook Request 안의 url과 동일한지 확인

{
  "repository": {
    "html_url": "https://github.com/webgori/lolien-api",
    "url": "https://github.com/webgori/lolien-api"
  }
}

위의 Json은 webhook Request 중 Jenkins GitHub 플러그인이 사용하는 정보이다.

 

        URL repoUrl = push.getRepository().getUrl();
        final String pusherName = push.getPusher().getName();
        LOGGER.info("Received PushEvent for {} from {}", repoUrl, event.getOrigin());
        GitHubRepositoryName fromEventRepository = GitHubRepositoryName.create(repoUrl.toExternalForm());

        if (fromEventRepository == null) {
            // On push event on github.com url === html_url
            // this is not consistent with the API docs and with hosted repositories
            // see https://goo.gl/c1qmY7
            // let's retry with 'html_url'
            URL htmlUrl = push.getRepository().getHtmlUrl();
            fromEventRepository = GitHubRepositoryName.create(htmlUrl.toExternalForm());
            if (fromEventRepository != null) {
                LOGGER.debug("PushEvent handling: 'html_url' field "
                        + "has been used to retrieve project information (instead of default 'url' field)");
            }
        }

        final GitHubRepositoryName changedRepository = fromEventRepository;

        if (changedRepository != null) {
            // run in high privilege to see all the projects anonymous users don't see.
            // this is safe because when we actually schedule a build, it's a build that can
            // happen at some random time anyway.
            ACL.impersonate(ACL.SYSTEM, new Runnable() {
                @Override
                public void run() {
                    for (Item job : Jenkins.getInstance().getAllItems(Item.class)) {
                        GitHubPushTrigger trigger = triggerFrom(job, GitHubPushTrigger.class);
                        if (trigger != null) {
                            String fullDisplayName = job.getFullDisplayName();
                            LOGGER.debug("Considering to poke {}", fullDisplayName);
                            if (GitHubRepositoryNameContributor.parseAssociatedNames(job)
                                    .contains(changedRepository)) {
                                LOGGER.info("Poked {}", fullDisplayName);
                                trigger.onPost(GitHubTriggerEvent.create()
                                        .withTimestamp(event.getTimestamp())
                                        .withOrigin(event.getOrigin())
                                        .withTriggeredByUser(pusherName)
                                        .build()
                                );
                            } else {
                                LOGGER.debug("Skipped {} because it doesn't have a matching repository.",
                                        fullDisplayName);
                            }

Jenkins GitHub 플러그인이 자동 빌드 시키는 DefaultPushGHEventSubscriber.java 파일 내용 중 일부이다. (원본 파일은 링크를 확인)

코드를 보면 Repository의 url을 가지고 changedRepository를 선언한다.

그리고 changedRepository는 빌드 발생 여부 확인하는 부분 (아래의 if문) 에서 사용된다.

if (GitHubRepositoryNameContributor.parseAssociatedNames(job).contains(changedRepository))

빌드가 안되는 원인을 확인해보려면 GitHubRepositoryNameContributor.parseAssociatedNames(job)가 어떤값이 나오는지를 알아야 하는데 이 부분은 아래의 스크립트 콘솔에서 스크립트 실행으로 확인할 수 있다.

 

Jenkins 스크립트 콘솔을 사용하여 DefaultPushGHEventSubscriber.java 파일에서 빌드 발생시킬 때 호출하는 메서드 return 값 확인

import com.cloudbees.jenkins.GitHubRepositoryNameContributor;

for (Item job : Jenkins.getInstance().getAllItems(Item.class)) {
  def gitHubRepositoryName = GitHubRepositoryNameContributor.parseAssociatedNames(job)
  
  if (gitHubRepositoryName.size() == 0) {
    continue
  }
  
  println(job.getName())
  println(gitHubRepositoryName)
  println()
}

Jenkins - Jenkins 관리 - Script Console

빌드를 발생 시킬지, 안시킬지 확인하는 if문에서 사용하는 메서드 return 값 확인 하기 위해 위의 스크립트 실행

(가독성을 위해 serverfault 링크에 있는 스크립트를 git을 사용하는 item만 나오도록 수정함)

 

lolien-api
[GitHubRepositoryName[host=gerrit.com,username=webgori,repository=lolien-api]]

lolien-web
[GitHubRepositoryName[host=gerrit.com,username=webgori,repository=lolien-web]]

스크립트 실행 결과

결과와 if문으로 유추해볼 때 Jenkins에 등록되어 있는 아이템들 중 git을 사용하고 있는 아이템들의 정보 (host, username (확실하지 않음), repository)를 webhook Request 받은 정보와 비교하여 (contains) 맞으면 빌드 발생 trigger.onPost() 시키는 것 같다.

 

pipeline 스크립트에서 사용중인 git 명령어의 url과 스크립트 콘솔에서 보여지는 host가 다를경우 해당 아이템 빌드

나의 경우는 해당 이슈가 원인이었는데, pipeline 스크립트에서 git url을 Gerrit에서 GitHub으로 수정하였는데 빌드를 안해서 인식을 못한것이었다.

수동 빌드 진행 후 push 해보니 자동 빌드가 잘 되었다.

 

자동 빌드 테스트시 GitHub webhook의 Redeliver버튼으로는 Trigger가 안되니, 반드시 직접 push하여 테스트

자동 빌드 확인 후 몇번 더 테스트 해보려고 Redeliver버튼 눌렀는데 빌드가 안되서 깜짝 놀랐는데 실제로 push 하니 잘 되었다. Redeliver로 왜 안되는지는 잘 모르겠음