본문 바로가기

끄적끄적

[CI/CD] Jenkins, Github webhook을 이용해서 CI/CD 구축하기

[CI/CD] Jenkins, Github webhook을 이용해서 CI/CD 구축하기

이번 포스팅에서는 Jenkins, Github webhook을 이용해 CI/CD를 구축 해보겠다.

흐름은 다음과 같다.

1. 클라이언트가 깃 브랜치에 커밋을 하고 pull-request를 보낸다.

2. 깃허브는 젠킨스에 web-hook을 날린다.

3. 젠킨스는 깃허브에서 프로젝트를 가져와 빌드하고 성공여부를 깃허브에 응답한다.

4. 깃허브는 브랜치에 빌드의 성공여부를 표현한다.

5. 클라이언트가 브랜치의 pull-request를 main으로 merge한다.

6. 깃허브는 젠킨스에 web-hook을 날린다.

7. 젠킨스는 빌드하고 성공했다면 파일을 production 서버로 보낸다.

 

위 과정을 그림으로 나타내면 아래와 같다. (위 목차로 읽는게 더 편할듯 싶음)


[테스트 환경]

 

- [CI/CD server]

- - ubuntu 20.04

- - Jenkins version 2.346.3

- - Docker version 20.10.14

 

- [Production server]

- - macOS 12.5

- - Docker version 20.10.17

 

(마침 집에 놀고있는 라떼판다가 있어서 CI/CD 서버로 사용하기로 했다.)

젠킨스는 기본적으로 설치되어 있다고 생각하고 젠킨스 설치부분은 다루지 않겠다.

또한, 이 글에서는 테스트를 위해 java11, springboot 2.7.3을 이용해 web application server를 구축하는데, 이 글을 따라하며 다른 개발 환경을 이용하는 사람들에게 혼선을 주지 않기위해서 자세히 설명하지 않겠다.


1. Github repository 만들기와 개발환경 설정

우선 이 글에서 사용할 테스트용 private 레포지토리를 만들어준다. 

이제 로컬 개발환경에서 레포지토리를 pull 받자

git init
git pull https://github.com/devxb/CI_CD_Test.git

이제 로컬 개발환경에 본인의 웹 애플리케이션 개발 환경을 세팅한다.

(cicd가 내 애플리케이션 개발 환경이다)

간단하게 hello글자만을 출력하는 페이지를 만들어줬다.


2. Jenkins와 Github repository webhook 연결

사전세팅이 끝났으니 이제 이 글의 주제인 Jenkins와 github repository의 webhook을 연결하자.

우선, Github Pull Request Builder 와 Github integration 플러그인을 설치해주자.

아래 그림에서 "새로운 Item" 을 누른다.

그후 아래와 같은 그림에서, Freestyle project를 설정하고 프로젝트 이름을 타이핑후 OK를 누른다.

 

그후 나타난 창에서 아래 사진과 같이 설정해준다. 

설명에 프로젝트의 설명을 적고, Github project를 선택후 url을 입력한다.(이 과정은 안해도 상관없음)

그 후, 소스코드 관리탭에서 Git을 선택후 

Repository URL에 레포지토리를 pull받는 경로를 입력한다. 여기까지하면 Failed to connected ... 라고 빨간글씨가 뜰것인데, Credentials을 설정안해줘서 그렇다. 깃허브에서 Personal access token을 발급받고 토큰 번호를 기억하자. 
Personal access token을 발급받을때는 repo와 repo hook부분을 모두 체크하면된다.

이제 다시 젠킨스로 돌아와 Credentials부분의 add 를 누르고 Jenkins를 선택한 후 다음과 같이 입력한다.

kind : Username with password

username : 깃허브 id

id : 깃허브 id

password : 이전에 발급받은 personal access token

그 후 credentials를 설정해주면 아래 사진과 같은 상태가 될 것이다.

그 후, branches to build를 */main으로 바꿔준다.

 

이제, 빌드 유발 탭으로 넘어가서

Github pull request builder를 체크한 후, admin list에 Pull request 유발시 빌드할 계정의 이름을 적어주자.

그 후, Use github hooks for build triggering에 체크하고 저장을 누른다.

최종 설정화면

이제 Github에 webhook을 설정해서 pull request 발생시 jenkins로 요청을 전송하도록 설정해줘야한다.

아까 만들어둔 깃허브에 테스트 레포지토리로 돌아가서 settings -> webhook으로 들어간다. 그 후, add webhook을 클릭하고

아래와 같이 설정한다.

1. payload url

-> 자신이 사용하는 프로토콜(http or https)://젠킨스 주소/ghprbhook/

만약 안된다면 webhook설정이 안된다면 다음처럼 입력하자.

-> 자신이 사용하는 프로토콜(http or https)://젠킨스주소/jenkins/ghprbhook/

* (ghprbhook는 github pullrequest builder hook의 약어임)

 

2. Content-type은 알아보기 쉬운 json으로 선택하자.

 

3. Which events would you like to trigger this webhook? Let me select individual events.을 선택하고 Pull request를 선택하자.

 

마지막으로 add webhook을 누른다. 잘 설정이 되었다면 추가된 webhook옆에 체크표시가 나올 것이다.이제 깃허브 레포지토리의 settings -> branches에 들어가 branch protection rules를 추가한다.

앞으로 생성될 모든 branch에 대해 적용하기 위해서 branch name pattern에 와일드카드 * 를 입력하고 아래와 같이 설정을 해준다.

 

이제 Github PullRequest Builder 플러그인의 설정을 해줘야 하는데, Jenkins에서 아래처럼 타고 들어간다.

Jenkins -> Jenkins관리 -> 시스템 설정 -> GitHub Pull Request Builder탭으로 스크롤을 내린다.

1. GitHub Pull Request Builder의 Credentials부분에 앞서 발급한 Credential을 입력한다.

2. GitHub Server API URL 에는 https://api.github.com 입력하고 저장해준다.


3. 동작 확인

이제 로컬 개발환경으로 돌아가 testbranch를 만들어주고 변경사항을 github repository에 push해보자.

성공적으로 동작한다 ! 

여기서 merge시 젠킨스에서 merge된 브랜치 기준으로 다시한번 빌드하도록 하고싶으면, 젠킨스 설정의 "Github hook trigger for GITScm polling"을 체크해주면 된다.

 

그렇다면, 실패한경우는 어떻게 될까? build에 실패하는 코드를 작성하고 브랜치에 커밋한다음 pull request를 전송해보자. 아마 그대로 성공한다고 나올 것이다. 그 이유는 아직 Jenkins에 빌드 설정을 안해줘서 그렇다. 

이제 빌드 설정을 해보자.


4. Jenkins build명령어 설정

다시 Jenkins로 돌아가 아까 만든 프로젝트를 클릭하고 구성을 들어가서 프로젝트 설정페이지로 들어가자.

build탭에서 Add build step으로 자신이 원하는 옵션을 선택하자.

나는 excute shell을 선택하고 직접 명령어를 입력해서 실행하겠다.

나는 설정하다가 안되는부분이 좀 있어서 디버깅용으로 --stacktrace 옵션을 주고 빌드했는데, 빌드 옵션에 대한 부분은 터미널에 가서 찾아보자. 대체로 clean을 통해 이전 build를 지우고 빌드하는 것 같다.

최종적으로 아래와 같은 상태가 되면 된다.

이제 저장을 하고 다시 결과를 확인해보자.


5. 결과확인

다시 빌드에 실패하는 코드를 고의적으로 Pull request해보자.

성공적으로? 실패하는 모습을 볼 수 있다. 


6. 중간점검 및 로깅

여기까지... CI환경 구성이 끝났다. 많이 어설프지만 구색은 갖춘 모습이다.

만약 따라하다 안되는 부분이 있다면 아래 사항을 체크하며 스스로 고쳐보자.

1. github의 webhook에서 recent deliveries를 확인한다. Jenkins서버로 잘 전달되는지 확인 할 수 있다.

2. Jenkins의 로그를 확인해보자. Jenkins검색창에 log를 입력하면 Jenkins에 찍힌 로그를 손쉽게 확인 할 수 있다.


7. CD구축 

이제 자동 배포를 위해서 Jenkins에 publish over ssh 플러그인을 설치해준다.

설치가 완료되면, Jenkins 관리 -> 시스템 설정 -> publish over ssh 탭으로 스크롤을 내리자.

이제 publish over ssh탭을 설정해줘야하는데, 젠킨스의 ?설명을 읽으며 자신에게 맞는 설정을 하는것이 베스트이다. 잘 안된다면 아래 목차를 따라가도록하자. (내 ip주소등이 노출되므로 사진은 없다.)

1. Name에는 이 설정을 기억할 이름을 저장하자. (마음대로)

2. HostName에는 배포받는 서버(Production server)의 ip주소 혹은 도메인 네임을 입력한다. 

3. username에 ssh로 접속할 유저 이름을 입력한다.

4. Remote Directory에 작업할 base 디렉토리를 적는다. 

5. Use password authentication, or use a different key에는 접속할 유저의 비밀번호(있다면)를 설정해주면된다. 

중요! -> 이 과정에서 두가지 선택지가 있는데, 첫번째는 비대칭 키를 이용해서 ssh연결을 하는 방법이고 두번째는 ssh에 접속하는 비밀번호를 이용해서 ssh연결을 하는 방법이다. 나는 첫번째 방법으로 시도하다가, 맥북(Production server가 맥북임)에서 비대칭 키를 이용한 ssh 자동 로그인 방식을 세팅하기 힘들어서 두번째 방법으로 로그인을 진행했다.

비밀번호로 진행하는경우, Passphrase / password 입력란에 비밀번호만 입력해주면 된다.

 

설정을 다 했다면 좀 더 내려서 Test Configuration을 눌러보자. Success가 뜬다면 연결 성공이고 배포할 준비가 되었다는 것이다.

 

이제, 배포할 파일과 배포 후 동작을 지정해줘야한다.

다시 이전에만든 Jenkins 프로젝트로 넘어가서 구성을 눌러 Jenkins 프로젝트 설정 페이지로 넘어가자.

쭉 내리면 빌드 후 조치 탭이 있는데, 여기서 "빌드 후 조치 추가를 선택 후" Send build artifacts over ssh를 선택한다.

설정은 아래와 같이 해주면된다.

1. SSH-Server Name에는 이전에 설정한 ssh서버를 선택한다. (아마 배포 서버추가가 처음이라면 자동으로 되어있을 것이다.)

2. Transfer Set탭의 Source files에 전송할 파일을 경로를 포함해 입력하면된다. 경로의 root는 프로젝트의 워크스페이스다. 

3. Remove prefix는 선택사항으로 2번에 설정한 경로를 없애고 파일만 전송하고싶을때 설정한다.(설정하지 않으면 폴더도 같이 보내진다.)

4. Remote directory는 배포되는 파일 앞에 만들어줄 경로다. 이 칸을 입력하면 배포된 파일이 Remote directory에 설정한 경로에 저장된다.

5. Exec command는 전송 완료후 실행할 커맨드다. 나같은경우 테스트 목적이니 이 칸은 적지 않았다. 실제 배포서버라면 여기서 실행 스크립트를 작성하거나 실행 스크립트 트리거를 발동시켜주면 될듯 하다.

최종적으로 아래 그림과 같이 나오면 된다.

 

 

이제 저장하고 테스트를 해보자.


8. 중간 테스트

다시 로컬 개발환경으로 돌아와 파일을 조금 수정해 다시 빌드에 성공하게 만든후 커밋과 Pull request를 전송하자.

젠킨스 CI 테스트에 성공했다. 

이제 파일이 Production server에 잘 전송되었는지 확인해보자.

production server로 들어와 파일이 배포되었을 위치로 이동후 확인해본다.

파일이 잘 전송된 모습!

 

이렇게 CI/CD환경 구축이 끝났다.

근데, 글 처음에 설명과 다르게 지금은 pull request시마다 build파일이 전송되고 있다. 이제 조금 수정해서 merge시마다 build파일이 전송되게 바꿔보자.


9. merge시 build로 바꾸기

우선, 기존에 설정한 pull request용 jenkins프로젝트의 '빌드 후 조치'부분을 없애고, merge용 jenkins프로젝트를 만들자.

그 후, 깃허브 레포지토리로 들어가서 다음과 같이 web-hook을 새로 만들어준다.

아래 부분 Let me select individual events에서 pushes를 선택하고 저장하자. 

 

이제 다시 merge용 젠킨스 프로젝트로 돌아와서 빌드유발을 제외한 모든 설정을 Pull request때와 동일하게 하고 빌드 유발을 아래와 같이 변경한다.

그 후, 빌드 후 조치를 추가한다음 저장을 하면 merge시 마다 파일이 배포되는것을 볼 수 있다.