본문 바로가기

개발/CI CD

SonarQube & Jenkins

오늘은 Jenkins 과 SonarQube를 이용하여 Pull Request Decoration을 진행해보려고 합니다. 추가로 docker 를 사용할 계획이에요.

먼저 전체적인 흐름은 아래와 같아요.

  1. 개발자의 Push
  2. Github webhook이 Jenkins로 전송
  3. Jenkins 내에서 SonarQube Scanner 실행
  4. SonarQube에서 main 브랜치와 PR 브랜치에 대해 분석 후 젠킨스로 전송
  5. 개발자의 Pull Request 작성
  6. SonarQube 봇의 Github App을 통한 체크

위와 같은 흐름을 숙지해주세요.

1. Docker & Jenkins

소나큐브에 관한 내용은 여기에 정리되어 있으니 소나큐브에 대해 궁금하신 분들은 참고하시길 바래요 :)

1.1 Docker

도커는 리눅스의 응용 프로그램들을 프로세스 격리 기술, 즉 컨테이너화 하여 실행하고 관리할 수 있는 어플리케이션입니다. 오늘 저희는 도커 내에 젠킨스와 SonarQube컨테이너를 올려서 작업을 진행할 계획이에요.

링크를 통해 도커를 다운받을 수 있어요!

저는 mac os 에서 진행하고 있기 때문에 .dmg 파일을 받아 Applications에 옮겨주는 방식으로 설치를 진행했어요!

1.2 Jenkins

Jenkins is a self-contained, open source automation server which can be used to automate all sorts of tasks related to building, testing, and delivering or deploying software. -

Jenkins

젠킨스란 소프트웨어의 빌드, 테스트, 배포 등과 관련된 모든 종류의 작업을 자동화해주는 독립형 오픈 소스 자동화 서버에요. 젠킨스는 대표적인 CI 툴이라고 해요. CI란 무엇일까요? CI는 소스 관리, 빌드, 테스트, 배포 등의 단계에 자동화를 도입하여 소프트웨어의 질적 향상과 소프트웨어를 배포하는데 걸리는 시간을 줄이는 것입니다.

젠킨스는 Docker에 검색창에 검색을 하면 위와 같이 나오는데요, Pull 버튼을 누르셔도 되고 보이는 명령어를 통해 설치하셔도 됩니다.

그럼 위와 같이 Image가 생겨있을 거에요. 위와 같이 Docker 앱에서 직접 실행시켜도 되고,

직접 위와 같이 터미널에서 실행시킬 수도 있어요.

초기 실행시 위와 같은 화면이 나와요. 그러면 빨간색 부분에 경로로 찾아가서 Password를 확인하고 입력해주면 돼요.

저는 위 사진과 같이 jenkins 컨테이너 내에서 해당 파일을 출력해서 확인했어요.

처음 실행할 때 위와 같은 화면을 마주치게 되는데, 둘 중 아무 버튼이나 클릭해도 상관 없어요! 하지만  Install suggested plugins 옵션은 자주 사용되는 plugins들을 한 번에 설치해주기 때문에 저는 해당 옵션을 선택했어요.

2. Jenkins 초기 설정

2.1 Item

설치가 성공적으로 완료되면 위와 같은 화면을 만날 수 있어요. 왼쪽 메뉴에서 새로운 Item을 눌러볼게요.

item name을 입력해주고, 저는 Freestyle project으로 item을 생성해줄게요.

2.2 소스코드 관리

생성을 하면 Configure 화면을 만나요. 먼저 소스 코드 관리 부분에 자신의 PR Decoration을 사용할 Repository URL을 입력해주시고, Credentials를 Add해주세요.

Credentials는 Kind에서 Username with password로 자신의 Github ID 와 Password를 입력해도 되고,

Secret text에 Secret 부분에 Github에서 발급받은 토큰, ID에 Github ID를 입력해서 추가할 수도 있어요.

토큰은 깃허브에 Settings에서 위와 같이 발급받을 수 있어요.

2.3 빌드 유발

다음은 빌드 유발 부분이에요. 우리는 Github에서 Push나 Pull Request가 일어났을 때 Webhook을 받아 Build Trigger로 사용할 것이기 때문에 GitHub hook trigger for GITScm polling 만 체크해주도록 할게요.

2.4 Ngrok

지금은 Jenkins를 localhost에서 사용하고 있지만, Github webhooks를 받기 위해서는 외부에서도 접속할 수 있게 해줘야 해요. 그래서 ngrok를 사용하여 Jenkins 서버를 인터넷으로 공유해보도록 할게요. 사실 사용방법은 쉬워요 !

먼저 위 명령어로 ngrok를 입력하고 기다리면,

위와 같이 성공적으로 설치되었다는 문구를 확인할 수 있어요. 이제 그냥 그대로 사용해도 되지만 추가 설정 없이는 세션 제한 시간이 필요하고 그때마다 다시 실행해줘야 하는 번거로움이 있어서 추가 설정을 해주도록 할게요. 먼저 ngrok 공식 홈페이지에서 회원가입을 진행해주세요. 그리고 링크에 들어가면 자신의 Authtoken을 확인할 수 있어요.

그리고 위와 같이 ngrok authtoken [authtoken] 으로 설정을 진행할 수 있어요.

저는 도커에서 젠킨스 컨테이너를 localhost에 8085 포트로 사용하고 있기 때문에

위와 같이 명령어를 입력해주었어요. 8085에 도커에서 설정한 포트를 입력해주시면 돼요.

그러면 위 사진 처럼 나오면 정상적으로 실행이 된거에요 :)

Forwarding 부분에서 외부에서 접속할 수 있는 자신의 domain을 확인할 수 있어요. 이 도메인을 기억해주세요.

2.5 Github webhook

Github에 Settings에 들어가주세요. (계정 Settings이 아닌 Repository Settings)

위와 같이 자신의 Repository에서 오른 쪽 위에 Setting을 통해 들어갈 수 있어요.

그리고 왼쪽 메뉴에서 Webhooks을 선택해주세요. 그리고 나오는 화면에서 Add webhook 버튼을 눌러주세요.

그리고 아까 ngrok에서 기억해둔 도메인을 위 Payload URL에 /github-webhook/을 붙여서 넣어주세요.

Which events would you like to trigger this webhook? 에서 세 번째 항목을 선택해주세요.

Pull requests와 Pushes 만 선택을 해주시고 webhook을 등록해주시면 돼요!

그리고 Recent Deliveries에 가보면,

위와 같이 초기에 ping을 보내는데 저 같은 경우 Payload URL을 잘못 입력해서 한 번 실패했어요. 정상적으로 진행되었다면, 초록색 체크표시가 나와야 해요. 꼭 github-webhook뒤에 /가 붙어있어야 합니다!!!!!!

Jenkins 설정은 여기까지 하고 나머지 설정을 마친 후에 다시 돌아오도록 할게요 !

3. SonarQube 설정

3.1 Community Branch Plugin - With Docker Image

도커를 이용한다면 Plugin이 이미 설치되어 있는 Image를 이용하면 돼요.

 

 

그러나 m1 칩에서는 poor performance를 보이기 때문에 글쓴이는 사용하지 못했어요. (너무 느림) 도커를 이용하는 유저는 그냥 저 이미지를 다운받아서 실행하면 아래의 설정 없이 바로 사용할 수 있으니 참고해주세요:)

3.2 Community Branch Plugin - Without Docker Image

이 링크에 들어가면 자신의 SonarQube 맞는 Plugin Version이 명시되어 있어요. 이제 그 버전에 맞추어서 설치를 진행해보도록 할게요.

wget <https://github.com/mc1arke/sonarqube-community-branch-plugin/releases/download/1.14.0/sonarqube-community-branch-plugin-1.14.0.jar>

위 명령어를 통해 플러그인을 받을 수 있어요. 그리고 받은 jar 파일을 extensions/plugin 폴더로 이동해주어야 해요.

mv sonarqube-community-branch-plugin-1.14.0.jar {sonarDirectory}/extensions/plugins/

위 명령어로 이동 시키고 이제 conf/sonar.properties를 수정해주어야 하는데 mac 환경의 Docker에서는 권한 문제로 잘 안될 수 있어요. 권한 문제가 생길 시

docker exec -it -u root ${소나큐브 컨테이너 이름} /bin/bash

을 통해 root 로 소나큐브 컨테이너를 실행하고 sonar.properties를 권한 문제 없이 설정할 수 있어요.

sonar.web.javaAdditionalOpts=-javaagent:./extensions/plugins/sonarqube-community-branch-plugin-1.14.0.jar=web
sonar.ce.javaAdditionalOpts=-javaagent:./extensions/plugins/sonarqube-community-branch-plugin-1.14.0.jar=ce

위 설정을 conf/sonar.properties에 추가해주고 소나큐브를 재시작해주세요. 그러면 외부 플러그인 사용에 대한 문구가 나오는데 accept 해주면 설치가 완료됩니다!

그러면 소나큐브 메인에서 Administration > marketplace 에 들어가서 installed 창을 확인하면 위와 같이 Community Branch Plugin이 생겨있고, 이를 통해 정상적으로 설치됐음을 확인할 수 있어요.

3.3 Github App

SonarQube에서 분석 결과를 PR 시에 받기 위해서 Github App을 만들어보도록 할게요. 깃허브에서 settings > Developer settings > GitHub Apps 로 이동하여 New GitHub App을 눌러주세요.

위와 같은 창을 만날 수 있어요. App이라곤 하지만, 설정할 것은 많지 않아요.

  • App Name
  • Homepage URL
  • Callback URL
  • Webhook URL

을 설정해주어야 해요. 여기서 App Name과 Homepage URL은 중요하지 않아요. 아무렇게나 설정해주어도 돼요. 중요한 것은 Callback과 Webhook URL 이 두가지에요. 소나큐브 역시 깃허브 앱과의 통신이 필요하므로 위에서 젠킨스를 ngrok로 인터넷에 공개한 것과 같은 작업이 필요한데, 젠킨스에서 했던 것과 동일하게 소나큐브에 적용해주면 돼요.

(ngrok 유료 회원이 아니라면 1개의 도메인 밖에 제공되지 않으므로, localtunnel 과 같은 ngrok와 비슷한 툴들이 있으니 참고해주세요!)

Callback 과 Webhook URL에 ngrok 혹은 localtunnel에서 알려준 소나큐브의 도메인을 넣어주면 돼요.

그리고 Permissions 부분에 Repository permission에서

  • Checks > Read and write
  • Commit statuses > Read-only
  • Pull requests > Read and write

로 설정해주세요.

이 부분은 Jenkins에서 사용할 repository에만 설치가 되면 되기 때문에 자신이 원하는 옵션을 선택하고 깃허브 앱을 생성해주세요!

그리고 Install App 부분으로 이동하여 App을 사용할 account에 설치를 해주세요.

위와 같이 Installed 가 나오면 돼요.

그리고 다시 General로 이동해주세요. 먼저 사용할 항목들은 다음과 같아요

  • App ID
  • Client ID
  • Client secrets
  • Private keys

Client secrets를 Generate a new client secret를 클릭하여 위와 같이 생성해주시고 복사해두세요! 한 번 나가면 위와 같이 다시 볼 수 없어요.

Private key도 위 항목에서 Generate를 눌러서 생성해주세요. Private key는 생성시 .pem 파일로 다운받아지는 파일이 있을거에요. 이 파일을 꼭 기억해주세요. 이제 소나큐브로 다시 돌아가볼게요!

3.4 SonarQube와 Github App 연동

소나큐브에서 Administration > Configuration > General Settings > DevOps Platform Integrations로 이동해주세요. 저는 이미 설정을 완료해두었기 때문에 위와 같이 초록색 체크 박스를 확인할 수 있어요. Github App을 사용하기 때문에 Github 항목에서 Create configuration을 선택해주세요.

그러면 위와 같은 화면이 나오고 name을 설정해주시고, GitHub API URL은 https://api.github.com/을 을 그대로 넣어주시면 돼요. 그리고 마지막 Webhook Secret칸은 비워두시고 나머지 칸들을 아까 Github App을 생성하면서 기억해뒀던 것들을 넣어주면 돼요. 이 때 Private Key는 아까 받은 .pem 파일을 보면돼요.

이런 형식인데 주의할점은 --- BEGIN RSA --- 와  ---END RSA--- 부분도 꼭 !!! 넣어주셔야 합니다!!

그리고 설정을 저장한 뒤 Check configuration을 누르면 valid 한 설정인지 확인할 수 있어요.

이제 Authentication으로 이동해주세요. Github 항목으로 가서 Enabled를 활성화 해주시고 아래의 Client ID와 Client Secret을 마찬가지로 작성해주세요!

4. SonarQube 와 Jenkins 연동

4.1 SonarQube 프로젝트 생성

이제 소나큐브에서 프로젝트를 생성해볼게요.

Projects로 이동하여 Create Project에서 Manually를 선택해서 프로젝트를 생성해볼게요.

프로젝트의 Project Settings > General Settings > DevOps Platform Integeration으로 이동해주세요. 그리고 아까 추가해놨던 configuration이 있을거에요. 그걸 선택해주세요!

4.2 Jenkins 추가 설정

다시 젠킨스로 이동할게요. Jenkins에 Dashboard > Jenkins 관리 > 플러그인 관리 로 이동해주세요.

그리고 Available plugins 로가서 SonarQube Scanner for jenkins를 설치해주세요. 저는 이미 설치가 되어 있기 때문에 검색 결과에 나오지 않은 거에요. 그리고 Parameterized Trigger라는 플러그인을 하나 더 설치해주세요! 이 플러그인은 설치하지 않아도 괜찮아요. 설치하지 않는다면 Jenkins 내에 환경변수를 추가해서 사용하는 방법도 있어요.

설치가 완료되었다면 다시 Dashboard > Jenkins 관리 > Global Tool Configuration으로 이동해주세요.

그리고 SonarQube Scanner 항목에서 Add SonarQube Scanner로 위와 같이 추가해주면 돼요.

Dashboard > Jenkins 관리 > Configure System 에서 SonarQube servers 항목으로 이동해주세요.

그리고 위와 같이 소나큐브 프로젝트에서 key를 발급받아 Server authentication token에 추가해주시고, Server URL도 설정해주어 소나큐브 서버를 추가해주세요!

4.3 Jenkins 프로젝트 설정

다시 젠킨스에서 아까 만들었던 프로젝트 Configuration으로 와주세요. 그리고 빌드 시 매개변수를 추가해줄게요. 아까 설치한 Parameterized Trigger 플러그인을 사용하게 돼요.

Configuration에 General에서 이 빌드는 매개변수가 있습니다 항목을 체크해주세요.

그러면 매개변수의 이름과 Value를 설정하는 창이 나와요. 저희는 세 개의 값을 추가해줄거에요.

  • ghprbPullId >> PR 키값 (Integer Value이어야 합니다)
  • ghprbSourceBranch >> PR이 작성된 브랜치 이름
  • ghprbTargetBranch >> PR이 받아들여져 머지 될 브랜치 이름

그리고 다시 소스 코드 관리 부분으로 돌아가서 Branches to build에 브랜치를 ghprbSourceBranch로 설정해줄게요.

Build Steps로 이동해서 Excute SonarQube Scanner를 두 개 추가해줄게요. PR 분석을 위해서는 머지될 브랜치를 먼저 분석하고 PR 브랜치를 분석해야 한다고 해요.

이런 창이 생기는데요 SonarQube Installation에서 아까 설정한 소나큐브를 선택해주세요. 그리고 첫 번째 Analyasis properties 목록은 다음과 같아요.

  • sonar.host.url=${소나큐브 URL}
  • sonar.projectName=opensource-test-pr
  • sonar.projectKey=opensource-test-pr
  • sonar.branch.name=${머지될 브랜치}
  • sonar.sources=src/main
  • sonar.issuesReport.console.enable=true
  • sonar.tests=src/test
  • sonar.language=java
  • sonar.java.binaries=build/libs
  • sonar.sourceEncoding=UTF-8
  • sonar.login=${소나큐브에서 생성한 토큰}
  • sonar.scm.provider=git

이게 첫 번째 소나큐브 분석에 필요한 properties에요. 이제 두 번째, PR 이 작성될 브랜치에 대한 properties에요.

  • sonar.host.url=${소나큐브 URL}
  • sonar.projectName=opensource-test-pr
  • sonar.projectKey=opensource-test-pr
  • sonar.pullrequest.key=${ghprbPullId}
  • sonar.pullrequest.base=${ghprbTargetBranch}
  • sonar.pullrequest.branch=${ghprbSourceBranch}
  • sonar.issuesReport.console.enable=true
  • sonar.sources=src/main
  • sonar.tests=src/test
  • sonar.language=java
  • sonar.java.binaries=build/libs
  • sonar.sourceEncoding=UTF-8
  • sonar.scm.provider=git

이렇게 작성을 했으면 Apply를 눌러주세요.

그리고 젠킨스로 분석을 끝낸 훈에 결과를 보낼 수 있게 웹훅을 날릴 거에요. Administration > Configuration > Webhooks 로 이동해주세요. 그리고 Create Webhook 을 눌러 ${젠킨스 도메인}/sonarqube-webhook/을 URL 칸에 넣어서 만들어주세요.

이후 일련의 과정이 완료되면 위 사진과 같이 Last delivery에 초록색 체크박스가 표시된다면 정상적으로 Webhook이 전달된 것이에요.

5. 결과 확인

개발자가 소스 코드를 작성해서 Repository로 Push를 진행하면 자동으로 젠킨스에서 위 사진처럼 빌드가 진행돼요.

그리고 위와 같이 PR을 작성해볼까요?

 

 

그러면 위와 같이 성공적으로 분석이 된 것을 볼 수 있어요.

마치며

오늘은  Jenkins 과 SonarQube를 이용해서 PR Deco를 진행해봤어요. 해주어야 할 것이 많기 때문에 하나의 설정만 잘못되어도 결국 하나도 작동되지 않으니 하나하나 꼼꼼히 체크해서 진행해야 해요:)

참고자료

🔗 - https://docs.sonarqube.org/9.6/analyzing-source-code/pull-request-analysis/

🔗 -  https://mangkyu.tistory.com/229

🔗 - https://ko.wikipedia.org/wiki/지속적_통합

🔗 - https://github.com/mc1arke/sonarqube-community-branch-plugin#compatibility

🔗 - https://docs.sonarqube.org/9.6/devops-platform-integration/github-integration/

'개발 > CI CD' 카테고리의 다른 글

Git Actions  (0) 2023.06.27
SonarQube & Jacoco  (0) 2023.06.27