지난 INRTO에서 어떻게 CI/CD 파이프라인을 만들지 얘기했었습니다.
그림과 함께 더 자세하게 볼까요?
- 개발자가 깃 허브의 feat * 브랜치에서 코드를 push 하고 pr 을 생성한다
- 깃 허브의 웹훅이 젠킨스에서 post 요청을 보내 web hook trigger을 작동 시킨다.
2-2. 젠킨스 웹훅은 설정한 조건에 해당한다면 빌드 파이프 라인을 작동 시킨다.- 설정한 파이프라인을 작동 시킨 후 파이프라인의 결과(빌드 성공, 실패)를 pr의 코멘트로 달아 리뷰하기 전 올바른 코드를 올린지 먼저 체크한다.
지금부터 그림의 과정을 직접 구현해보겠습니다.
가장 먼저 해야할 것은 젠킨스가 깃 허브의 리포지토리에 접근할 수 있도록 하는 것 입니다.
깃 허브에서 발급받은 access token을 젠킨스 환경변수의 credentials에 미리 세팅해둠으로서 제킨스가 해당 리포에 접근할 수 있도록 합니다.
(단순히 clone 하는 작업에 credentials가 필요하진 않지만 이후 빌드 결과를 코멘트로 남기기 위해 세팅하겠습니다.)
깃 허브의 리포에 접근하려면 Access token이 필요합니다.
깃 허브 페이지의 오른쪽 상단 자신의 프로필 클릭 → Settings → Developer settings → Personal access tokens → Tokens(classic) → Generate new token(classic) 선택 후
그림에서 다음을 입력해 줍니다.
- Note : 토큰 이름
- Expiration : 만료 기간
- Select scopes : 접근 권한
- 리포지토리와 훅의 권한이 필요하므로 아래와 같이 선택해 줍니다.
- repo 탭 모두
- admin: repo_hook 탭 모두
설정을 완료 했으면 맨 밑의 Generate Token 버튼을 클릭하면 토큰을 확인할 수 있습니다.
ex. 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
**토큰은 발급했을 때 위와 같은 문자열을 꼭 어딘가에 저장하기 바랍니다. 까먹으면 새로 발급받고 기존 토큰을 사용한 곳 모두 수정해야 합니다.
젠킨스로 돌아가겠습니다.
젠킨스 메인화면 → 젠킨스 관리 → 시스템 설정 → GitHub 탭 → Credentials에 add를 누릅니다.
그림과 같은 입력창을 볼 수 있는데요.
Kind를 Secret text로 설정한다면 다음과 같이 설정하고 바로 Connection을 테스트 해볼 수 있습니다.
- Secret : 깃 허브에서 발급받은 Access Token
- ID : 젠킨스에서 사용할 Credential 이름
그림의 빨간 박스와 같이 나왔다면 발급한 토큰으로 연결에 성공한 것입니다.
하지만 이후 연결에서는 깃 허브의 ID 등이 필요하므로 Kind를 Username with password로 설정하고 옵션에 다음과 같이 입력합니다.
- Username : 깃 허브 아이디
- Password : 깃 허브에서 발급받은 Access Token
- ID : 젠킨스에서 사용할 Credential 이름
등록한 Credential은 젠킨스 메인 → Jenkins 관리 → Manage Credentials에서 확인할 수 있습니다.
지금 한 것은 젠킨스 환경변수에 토큰을 등록한 것인데요.
미리 예고하자면 pipeline script를 작성할 때 credentialsI : ~~ 라든가 withCredentials() 등으로 꺼내쓸 수 있습니다.
이제 젠킨스에서 깃 허브의 리포로 접근은 가능해졌으니 내가 어떤 CI를 만들지 고민하고 Pipeline을 통해 만들어 보겠습니다.
젠킨스 메인 → 새로운 Item을 눌러보면 다양한 옵션들이 많은데 간단히 살펴볼까요?
- FreeStyle project : 쉬운 사용과 간단한 파이프라인 구축 가능
- Pipeline : Pipeline script를 활용한 세세한 설정 가능
- Multibranch Pipeline: 한 프로젝트에서 여러 브랜치를 관리 가능
젠킨스가 처음이라면 혹은 CI/CD 구축이 처음이라면 FreeStyle로 간단하게 배포를 해볼 수 도 있습니다.
하지만 앞선 Intro 발견한 CI/CD는 다음과 같은 문제점이 있었습니다.
- 모든 push 이벤트에 대해 CI/CD가 작동한다.
- CI와 CD가 분리되지 않아 CI 직후 (잘못된 코드 포함) 모든 코드가 원격 서버로 배포된다.
깃 허브에 push 하면 원격 서버에 바로 배포 되는건 좋아보이지만 굳이 이 과정을 위해 서버를 하나 더 만들어가면서 젠킨스를 설치했어야 할까요?
이 문제점을 해결하기 위해 젠킨스의 Pipeline을 이용해 아래의 요구사항을 만족해 보겠습니다.
- CI 와 CD가 분리되어야 한다.
- 모든 push 이벤트에 대해 빌드가 일어날 필요 없다.
- pr을 생성한 브랜치를 기준으로 코드의 빌드 테스트가 일어나야 한다.
- 코드 리뷰 전 빌드 결과를 알 수 있어야 한다.
- test 코드에 대한 검증이 일어난다(옵션)
- 컨벤션에 대한 검증이 일어난다(옵션)
요구사항을 만족해 지속적으로 코드를 push 하고 하나의 pr단위가 만들어졌을 때 pr을 생성하면 자동으로 테스트를 합니다.
테스트에 대한 결과를 바탕으로(빌드 성공/실패) 코드 리뷰가 이루어지고 main 혹은 master 브랜치로 병합을 할 수 있습니다.
여기까지가 구축하려는 CI의 단계입니다. 이후 CD는 완성된 코드를 바탕으로 원격 서버에 배포된다면 되겠죠.
처음 소개한 그림과 같이 말이죠.
자 그럼 CI를 만들어 볼까요?
프로젝트의 이름을 입력하고 Pipeline을 선택 후 OK를 누릅니다.
처음 화면은 그림과 같을 겁니다.
우리는 Build Triggers 탭을 볼건데요.
여기서 Generic Webhook Trigger을 이용할 것 입니다.
만약 해당 옵션이 안보인다면 다음과 같이 해주세요.
젠킨스 메인 → Jenkins 관리 → 플러그인 관리 → Available plugins → Generic Webhook Trigger 검색 후 설치
설치가 되었다면 Generic Webhook Trigger을 체크 후 Post content parameters에 추가 버튼을 눌러주세요.
Post content parameters란?
- 깃 허브 저장소에 웹훅에서 설정한 이벤트가 일어났을 때 젠킨스의 Generic Webhook Trigger(Token으로 구분)로 post 요청을 날립니다.
이 때 요청의 payload에 다양한 값들이 저장되어 있습니다. 이 값 들의 상태에 따라 트리거를 작동 시킬지 여부를 선택할 수 있습니다.
이렇게 말로만 하면 더 헤깔리니 직접 설정하며 확인 해봅시다.
Post content parameters의 Variable에 그림과 같이 설정해 줍니다.
Post content parameters의 Variable에 그림과 같이 설정해 줍니다.
- Name of variable : 변수로 쓸 이름
- Expression : 깃 허브 웹훅이 post 요청한 payload에서 사용할 값 ($. 으로 시작하고 각 구분마다 . 으로 구분)
- JSONPath 로 설정
그림의 설정은 pull_request의 state를 이 파이프라인에서 PR_OPEN이라는 변수로 사용하겠다는 의미와 같습니다.
그리고 paramter를 두 개 더 추가 후 다음과 같이 설정합니다.
- REQUEST_BRANCH / $.pull_request.head.ref / JSONPath
- NUMBER / $.number / JSONPath
다음과 같이 설정 했다면 이게 무슨 뜻인지 아리송 할테니 깃 허브의 웹훅에서 보낸 post 요청을 맛보기로 볼까요?
아! 웹훅이 POST 요청을 보냈고, 변수로 설정한 pull_request의 state 라는 값도 보이네요.
실제로 내려보면 엄청 많은 값들이 Payload에 들어가 있습니다.
이제 웹훅의 다양한 조건을 활용해 내가 원하는 조건에서 젠킨스를 작동시킬 수 있겠죠?
다시 젠킨스로 돌아오겠습니다.
이제 Generic Webhook Trigger에서 파라미터 설정은 끝났고 쭉 내려가다보면 Token이 있습니다.
Token은 깃 허브의 웹훅이 post 요청을 보낼 endpoint 입니다. 이전 그림 Headers의 Request URL을 보면
[http://젠킨스_주소/generic-webhook-trigger/invoke?token=SLACK_TOKEN]이 보이죠?
젠킨스에서 설정한 Token의 이름일 뿐입니다.
(이름이 SLACK_TOKEN인 이유는 기존의 슬랙 알림을 위한 프로젝트를 가져왔을 뿐입니다.)
토큰을 설정했다면 깃 허브에서 웹훅을 만들어 보겠습니다.
깃 허브 프로젝트 리포 → Settings → Webhooks → Add webhook 클릭
이제 그림과 같은 화면을 볼 수 있습니다.
- Payload URL : http://{젠킨스_주소}/generic-webhook-trigger/invoke?token={바로 위에서 설정한 토큰 이름}
- Content type : application/json
- Secret : 공백
그 다음이 중요한데요.
이전 그림의 빨간 박스를 보면 Just the push event라는 탭에 체크가 되어 있는것이 보입니다.
Intro에서 push 할 때 마다 발생했던 문제가 바로 이 웹훅 설정에 있었습니다.
그럼 Let me select individual events. 탭을 클릭해볼까요?
클릭하면 많은 옵션들이 보일겁니다. 이 옵션들을 활용해서 다양한 트리거를 작동시킬 수 있겠죠?
이번에 만들 CI는 pr을 생성했을 때 작동시킬 것 이기 때문에
그림과 같이 Pull requests에 클릭을 해주겠습니다. Pushes는 체크를 풀어주세요.
웹훅을 생성 했다면 다시 젠킨스로 돌아오겠습니다.
Generic web hook trigger의 Token도 설정 했으니 조금만 더 내려가볼까요?
Optional filter가 보입니다.
필터로 트리거 작동 조건을 더 상세하게 조정할 수 있습니다.
그림과 같이 설정합니다.
- Expression : 정규 표현식으로 ?는 변수 =.*{value}로 특정 조건에 해당할 때 트리거를 작동시킬 수 있습니다.
- Text : Post content parameters에서 선언한 변수명들을 Expression의 ? 순차대로 사용할 수 있습니다.
- ex. Expression : (?=.open). / Text : $PR_OPEN 이라면 웹훅이 post 요청으로 보낸 payload에 이전에 설정한 pull_request.state 가 open 인 경우에만 트리거가 작동해 파이프라인을 실행합니다.
CI/CD 분리를 위해 웹훅과 트리거를 사용해 pr이 생성되었을 때 이 파이프라인이 작동하도록 했습니다.
이로써 개발자가 열심히 코드를 작성 후 pr 단위가 갖춰졌을 때 pr을 생성할 것이고, 젠킨스 파이프라인 스크립트에 맞는 빌드와 테스트가 이루어져 리뷰를 할 수 있는 상태가 될 것입니다.
이제 거의 다 왔습니다. 남은건 파이프라인 스크립트를 통해 빌드와 테스트만 한다면 CI는 완성됩니다.
** 파이프라인 스크립트 편에서 계속...