Jenkins Webhook
현재 진행하고 있는 프로젝트는 Github Push -> Webhook -> Jenkins Build 과정으로 자동화된 CI 환경을 구축했다.
아래 포스트에서 진행한 내용이다.
AWS EKS Jenkins 환경 구축하기 [2/2]
하나의 포스트로 담기에는 분량이 너무 많을 것 같아 2개로 나누었다. 이전 포스트에 이어 진행된다. https://imsongkk.tistory.com/75 AWS EKS Jenkins 환경 구축하기 [1/2] Jenkins란? Jenkins는 가장 널리 사용되
imsongkk.tistory.com
그렇게 CI 환경을 구축하고 프로젝트를 개발하던 중, 슬랙에 예상치 못한 메세지들이 날아왔다.
dev 브랜치가 아닌 다른 곳에서의 push
슬랙으로 날아온 메세지를 보았을 때, Docker 이미지 push 실패라고 되어있었다.
맨 처음에는 ECR Authentication에 문제가 생긴것인가 하고 생각했지만,
직접 젠킨스에 들어가 로그를 확인해보니 프론트에서 사용하고 있는 next.js의
빌드 과정에서 오류가 생겨서 Docker 이미지 빌드까지 오류가 발생한것이었다.
이 문제는 젠킨스 문제가 아니기에 프론트 팀원과 해결이 되었지만, 가만 생각해보니 문제는 따로 있었다.
dev 브랜치에 push 안했는데...?
그렇다.
프론트 레포에도 CI 자동화를 위해 웹훅을 설정하였고, Jenkins 내에 생성한 Job은 dev 브랜치를 빌드하도록 설정했다.
따라서 dev 이외의 브랜치 push는 Job을 trigger하지 않아야 했는데, 예상치 못하게 계속 빌드가 일어나고 있었다.
문제를 해결하기 위해 CI 과정을 천천히 생각해보았다.
- 개발자는 feature 브랜치에 작업하면서 dev 브랜치로 PR을 생성한다.
- PR는 review 이후 dev 브랜치로 merge 및 push된다.
- Github은 기존 Webhook의 미리 지정한 Jenkins 서버 url로 push event를 보낸다.
- Jenkins 서버는 해당 Webhook을 수신하여 Job을 실행한다.
여기서 처음으로 의심한 부분은 3번 Webhook 부분이었다.
Webhook의 정보를 설정하는 화면에서, 어느 부분에서도 브랜치에 관한 내용이 없다.
즉, Webhook은 dev 브랜치의 push만을 보내는것이 아닌 모든 브랜치의 push 이벤트를 보내는 것이었다.
이 부분을 자세히 말하기전에 아래 그림을 보자.
현재 대략적인 파이프라인은 다음과 같다.
만약 프로젝트가 One Repo - One Job이면 push event가 들어오면 바로 Job을 실행하면 되지만,
우리 프로젝트는 여러 개의 레포와 여러 개의 Job이 있었다.
그렇다면 현재 Auth-Service Repo가 발생 시킨 Webhook으로 Auth-Service Job을 Trigger 하고 있는데,
각 repo-job 관계를 resolve 해주는건 누구일까?
그림을 보면 알겠지만 Github Plugin이 대신 해준다.
Job을 구성하는 설정 중에, 다음과 같은 설정을 볼 수 있다.
아래 SCM section에서 정의한 Repo URL이 발생시킨 Webhook만 수신한다는 뜻이다.
지금까지의 상황을 보다 자세하게 그림으로 나타내면 다음과 같다.
이제서야 왜 dev 브랜치가 아닌 다른곳에서 push가 일어나도 Job이 실행되는지 알게 되었다.
Webhook은 specific한 브랜치가 아닌 모든 브랜치의 push event를 보내고 있었고,
Jenkins는 각 Webhook이 발생한 URL을 가져와 알맞은 Job에 매핑 해주고 있었지만
정작 dev 브랜치만 빌드 하고 있었던 것이다.
어떻게 해결할 수 있을까?
맨 처음 든 생각은 Webhook을 커스텀하게 바꿀수 없을까였다.
이 옵션들은 push 이외의 이벤트들을 포함시킬뿐, 브랜치 명을 특정할 수 없었다.
게다가 구글링을 더 해보니 Github측에 여러 유저들이 요청하고 있었지만 아직 까지 지원 계획은 없다고 한다...
Trigger의 기준을 Custom하게
Webhook을 바꿀 수 없다면, Trigger의 기준을 좀 더 세분화 하면 되지않을까 생각했다.
현재 Gihtub Plugin의 Trigger 설정 목록은
push event가 발생했을 때, checkout할 브랜치 이름만 정할 수 있었다.
Github Plugin만으로는 해결할 수 없는 부분이었다.
따라서 새로운 Trigger를 도입하기로 했다.
Generic Webhook Trigger
Generic Webhook Trigger는 이름에서 알 수 있듯이 뭔가 더 Generic할 것 같다.
플러그인 설치 페이지에서 간편하게 설치 가능하며, 설치 한 이후 Job 설정에 들어가 보면 다음과 같은 화면이 나온다.
Build Triggers 항목에 새롭게 추가된것을 볼 수 있다.
이때 Post content parameters를 이용해 Build에 사용할 variable을 지정할 수 있다고 되어있다.
그렇다면 content는 어디에서 오는것일까?
바로 Webhook의 Body이다.
나름 친절하게도 Plugin 측에서 Webhook body를 Jsonpath를 통해 가져오는 예시들을 써놓았다.
Webhook body에는 다행히도 브랜치명이 들어있어 우리가 목표로 하는 Multi-branch pipeline이 가능할 것 같다.
Generic Webhook Trigger의 변수를 설정하는것은 그렇게 어렵지 않았다.
먼저 $.ref라는 Jsonpath를 이용해 브랜치명이 포함된 문자열을 branch라는 variable로 가져온다.
그런 다음, Generic webhook trigger가 Repo에 맞는 Job을 resolve하기 위한 Token을 미리 지정했다.
예시가 친절하게 되어있어, Webhook의 URL param에 token을 지정해주면 된다는것을 알 수 있었다.
Expression은 해당 브랜치만 빌드하기 위해 필요한 설정이다. 정규표현식을 이용한다.
Text는 Expression을 적용시킬 변수를 지정한다. 위에서 branch라는 이름으로 variable을 생성했으므로 똑같이 써준다.
Jenkins 파일 수정
Jenkinsfile에서 위에서 지정한 branch 라는 variable을 사용하기 위해 조금 수정해주었다.
branch가 'dev'로 하드코딩 되어있는 상태였는데, 이를 주석처리 하고 branch variable을 사용할 수 있게 해주었다.
이때, branch는 ref/heads/test, ref/heads/dev, ref/heads/prod 와 같이 구성되어 있는데
이를 그대로 사용하니 Git 명령어가 제대로 동작하지 않았다.
따라서 '/'를 기준으로 split 해준 다음 마지막 브랜치명만 가져오도록 설정했다.
마지막 정리
모든 작업은 끝났다!
다시 그림을 통해 정리해보자
깔끔하게 나타내기 위해 나머지 Repo들과 Job들은 표시하지 않았지만 구성은 동일하다.
- 개발자는 feature 브랜치에 작업하면서 dev 브랜치로 PR을 생성한다.
- PR는 review 이후 dev 브랜치로 merge 및 push된다.
- Github은 기존 Webhook의 미리 지정한 Jenkins 서버 url로 token과 함께 push event를 보낸다.
- Jenkins 서버는 해당 Webhook을 수신하여 Body로 부터 branch variable을 추출한다.
- URL에 매핑된 Token을 확인하여 알맞은 Job으로 resolve한다.
이로써 완벽하게 Webhook을 통해 Multiple branch 빌드가 가능해졌다.
배포 이전에 발견해서 참 다행이다!
'Trouble Shooting' 카테고리의 다른 글
AWS EKS ArgoCD 환경 구축하기 [2/2] (0) | 2023.08.29 |
---|---|
AWS EKS ArgoCD 환경 구축하기 [1/2] (0) | 2023.08.28 |
ALB Ingress Controller로 여러 개의 Ingress 처리하기 (0) | 2023.08.11 |
MSA 환경에서 Swagger 서버 구축하기 (0) | 2023.08.05 |
AWS EKS Jenkins 환경 구축하기 [2/2] (0) | 2023.07.31 |