Server & Infra

SonarQube with Github Actions (PR Decoration)

리차드 2022. 8. 17. 04:52

 

EC2 인스턴스 생성부터 SonarQube 호스팅과 PR 데코레이션까지!
한 시간 내로 뚝딱! 

 

 

전체 오퍼레이션 과정은 아래 영상을 참고해주세요


https://www.youtube.com/watch?v=5uS4yyl_WCE 

 

 

 

SonarQube, SonarCloud


둘 다 정적 분석 도구입니다.
차이점은 직접 호스팅을 해야하는지 여부입니다.
직접 서버를 구축해야 하는 SonarQube는 Community Edition은 오픈소스입니다.
이미 구축되어 있는 서버를 이용하는 SonarCloud는 제한된 기능까지 무료로 사용 가능합니다.

처음엔 SonarCloud를 사용하고 싶었는데요,
woowacourse-teams 라는 하나의 Organization 안에 있는
하나의 Repository의 Collaborator로만 등록되어 있다보니 
SonarCloud를 사용하기에는 여러 한계가 존재했습니다.

우선 연동부터 직접 할 수가 없었어요.
owner와 collaborator의 권한 차이가 존재한다는 것을 처음 알게 됐습니다.
추가적으로 SonarCloud의 PR Decoration 기능이 매우 탐났지만 이 역시 포기했습니다.
PR Decoration은 Github PR에 코멘트로 정적 분석 결과를 알려주는 기능인데요,
PR 데코레이션을 클릭하여 상세 분석 결과를 볼 수가 없었습니다.
woowacourse-teams 하나의 Organization에 SonarCloud가 연동되어 있어서
이 계정에 직접 접근 권한이 없었기 떄문입니다.

그래서 최종 선택은 SonarQube를 직접 호스팅해서 사용하는 것이었습니다.

 

 

 

SonarQube도 PR 데코레이션이 가능!


SonarQube Community Edition은 오픈소스 무료이지만,
PR Decoration 기능은 공식 지원되지 않습니다.

대신 능력자분들이 만들어주신 플러그인을 사용하면
거의 유사한 기능을 누릴 수 있게 됩니다.

그럼 지금부터, 인스턴스 생성부터 PR 데코레이션까지! 달려보죠!

플러그인을 이용한 PR Decoration

 

 

 

swap memory, max process 설정, JDK 설치


# swap memory
touch /home/ubuntu/swapfile
sudo fallocate -l 2G /home/ubuntu/swapfile
sudo chmod 600 /home/ubuntu/swapfile
sudo mkswap /home/ubuntu/swapfile
sudo swapon /home/ubuntu/swapfile
sudo vi /etc/fstab

/home/ubuntu/swapfile swap swap defaults 0 0 # 이 내용을 맨 아레에 추가하고 저장

free -h # 적용 확인



sudo vi /etc/sysctl.conf 
#이하 내용을 아래에 붙여넣기
vm.max_map_count=524288
fs.file-max=131072
ulimit -n 131072
ulimit -u 8192

sudo vi /etc/security/limits.conf 
# 아래 내용 붙여넣기
*   -   nofile  131072
*   -   nproc   8192



# OpenJDK 11 설치
sudo apt update
sudo apt install openjdk-11-jdk -y

 

Ram이 적은 인스턴스를 사용하다보니 인스턴스를 만들 때마다 
swap memory 설정을 하는 것이 기본 절차가 되었네요!
이젠 해주고 나서야 편안 해집니다 ㅋ

그 다음은 max user process 상한 등을 올려주는 설정인데요,
SonarQube가 내부 검색에 Elastic Search를 사용하는데,
이를 기동하기 위해 필요한 설정입니다.

Elastic search 가 기동에 실패하면 SonarQube도 기동이 실패하는데요,
관련한 옵션을 미리 한 번에 설정하고 출발합시다.
해당 옵션이 정상 적용되지 않아 기동이 안된다면, 인스턴스 재부팅을 해보세요!

 

 

 

SonarQube 9.5 설치 및 접속


# sonarqube-9.5.0.56709 다운
sudo wget https://binaries.sonarsource.com/Distribution/sonarqube/sonarqube-9.5.0.56709.zip

# unzip 설치
sudo apt install unzip

# 압축 풀기
unzip sonarqube-9.5.0.56709.zip

# 권한 설정
sudo chown -R ubuntu sonarqube-9.5.0.56709

# 포트 설정
sudo vi sonarqube-9.5.0.56709/conf/sonar.properties
# 107번 라인의 sonar.web.port=8081로 설정

# 실행 스크립트 만들기
vi sonar.sh
nohup java -jar sonarqube-9.5.0.56709/lib/sonar-application-9.5.0.56709.jar &

 

SonarQube는 실행, 실행중단을 위한 쉘 파일을 제고하고 있는데요,
ARM 아키텍처 기반의 인스턴스여서 그런지 이슈가 다소 있었습니다.
그래서 jar 파일을 이용해 직접 기동하는 방식을 사용하게 됐습니다.

설치는 별 내용 없이 다운 받고, 압축 풀면 완료입니다.
다만 포트를 8081로 수정을 해주었습니다.

기동을 완료했다면 publicIp:8081 로 접속하여 정상 기동을 확인합니다.
최초 로그인 계정은 admin/admin 입니다.

SonarQube 첫 화면

 

 

 

로컬 분석 결과를 SonarQube 서버로


SonarQube 접속 후 첫 화면 중앙에 보이는 Add a project를 눌러 첫 프로젝트를 시작해봅시다.
Manually를 선택하고, 프로젝트 키와 토큰을 생성합니다.

그리고 나면 build.gradle에 sonarqube 플러그인을 추가하는 스크립트와,
터미널에서 수행해야할 gradle 명령어를 자동으로 생성해서 보여줍니다.

이를 수행하면 로컬에서 정적 코드 분석을 수행하고, 그 결과를 서버로 전송하게 됩니다.
서버에서는 통합적으로 코드 스멜, 버그 또는 보안 위협 등을 손쉽게 탐지할 수 있습니다.

윈도우라면 git bash를 이용하면 편리하실 거에요!

plugins {
  id "org.sonarqube" version "3.0"
}

./gradlew sonarqube \
  -Dsonar.projectKey=rich-pickpick \
  -Dsonar.host.url=http://13.209.72.70:8081 \
  -Dsonar.login=defd6500c7ba1825e0557dd1b42d89827ad03b1a

git bash sonarqube
SonarQube

 

 

 

H2에서 PostgreSQL로


SonarQube는 기본적으로 H2를 내장 DB로 사용합니다.
인스턴스를 재부팅하더라도 정적 분석 결과가 사라지지 않는 걸로 보아
인 메모리는 아니고 파일 형태로 저장을 하는 것 같습니다.

하지만 공식 문서에서는 테스트 용도로만 H2를 사용하라고 권장하고 있습니다

The embedded H2 database is used by default.
It is recommended for tests but not for production use.
Supported databases are Oracle, PostgreSQL, and Microsoft SQLServer.

 

사용중인 DB는 Administration -> System -> Database 에서 확인할 수 있습니다.

H2 on SonarQube

 

 

 

PostgreSQL 설치 및 SonarQube 연동


# postgresql-12 설치 
# 8.9의 소나큐브는 postgresql 13버전까지만 지원됨 
# postgresql 설치 시, 버전명시 안하면 14설치됨
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
sudo apt-get update
sudo apt-get -y install postgresql-12

systemctl status postgresql # 설치하면 자동으로 실행됨
sudo lsof -i:5432 # postgresql은 기본포트 5432 에서 동작

--------------------------------------------------------

# postgresql 초기 비밀번호 변경 - id:postgres pw:pickpick
sudo passwd postgres # 비밀번호 세팅 pickpick
sudo su - postgres
createuser richsonar # 유저 생성
psql

alter user richsonar with encrypted password 'rich1234';
# 생성한 유저에 비밀번호 세팅
# ALTER ROLE 이라고 나옴

create database sonarqube owner richsonar; 
# 소나큐브용 데이터베이스 생성
# CREATE DATABASE 라고 나옴

grant all privileges on database sonarqube to richsonar; 
# richsonar 계정에 소나큐브용 데이터베이스 권한 부여
# GRANT 라고 나옴

\q
exit
sudo systemctl restart postgresql # postgresql 재실행
systemctl status postgresql # 재실행 확인

--------------------------------------------------------

sudo vi /home/ubuntu/sonarqube-9.5.0.56709/conf/sonar.properties

sonar.jdbc.username=richsonar
sonar.jdbc.password=rich1234
sonar.jdbc.url=jdbc:postgresql://localhost:5432/sonarqube

# 8081 포트 kill 후 nohup 재기동 또는 인스턴스 재부팅 후 소나큐브 재실행 및 재접속

 

PostgreSQL은 버전을 명시하지 않으면 14가 설치되는데,
현재 13버전까지 호환되므로 버전을 명시하여 설치하길 권장드립니다.

SonarQube 설정파일에 이미 DB별 설정이 주석처리되어 작성되어있기 때문에,
주석을 해제하고 일부 값을 입력하는 정도로 간단히 설정이 가능합니다.

설정이 완료되었다면 재실행하여 PostgreSQL로 DB가 변경되었는지 확인합니다.
정상 변경시, 로그인 계정도 admin/admin 으로 초기화되어있는 점 참고하세요.

PostgreSQL on SonarQube

 

 

 

PR 데코레이션을 위한 플러그인 설치


# 소나큐브 버전별 지원되는 플러그인 버전이 다르므로 반드시 확인!
# 참고로 소나큐브 8.9가 LTS여서 이에 맞는 1.8.2를 시도했으나 PR 데코레이션이 적용 안됨
# https://github.com/mc1arke/sonarqube-community-branch-plugin/releases
wget https://github.com/mc1arke/sonarqube-community-branch-plugin/releases/download/1.12.0/sonarqube-community-branch-plugin-1.12.0.jar

# 파일 이동
mv sonarqube-community-branch-plugin-1.12.0.jar sonarqube-9.5.0.56709/extensions/plugins/

# 소나큐브 설정파일에 플러그인 등록을 위한 파일 수정
sudo vi sonarqube-9.5.0.56709/conf/sonar.properties

# 96번 라인
sonar.web.javaAdditionalOpts=-javaagent:./extensions/plugins/sonarqube-community-branch-plugin-1.12.0.jar=web
# 247번 라인
sonar.ce.javaAdditionalOpts=-javaagent:./extensions/plugins/sonarqube-community-branch-plugin-1.12.0.jar=ce

# Administration -> System -> Restart Server 
# 재실행

 

플러그인 설치 후 접속 화면

 

플러그인을 다운받고, 특정 경로로 이동시키고,
SonarQube 설정 파일에서 일부 설정을 추가한 뒤 재실행하는 것으로 플러그인 설치는 완료됩니다.

 

 

 

Github App 생성


https://github.com/settings/apps/new 에 접속하여 Github App을 생성합시다.
Github App은 SonarQube와 연동하여 PR에 코멘트를 작성할 수 있는 권한을 부여하는 데 사용됩니다.

callback URL과 webhook URL은 SonarQube 서버 주소를 입력하고, (ex: http://1.1.1.1:8081)
Repository permissions에서는 Checks에 Read and write, Commit statuses 에 Read-only,
Metadata에 Read-only, Pull requests 에 Read and write를 줍니다.

마지막으로 Any account를 선택해야 woowacourse-teams Organization에도 설치가 가능해집니다.
App 생성이 완료되었다면 General 메뉴에서 Client Secret, private key를 생성한 뒤,
잘 보관해둡니다.

 

 

 

SonarQube에 Github App 등록


SonarQube 우상단의 Create project 선택 후 Github 을 선택합니다.
그리고 앞서 잘 챙겨두었던 Github App 정보들을 기입해줍니다.

그 다음엔 Github Action으로 연동하는 버튼을 선택합니다.
그러면 SONAR_TOKEN, SONAR_HOST_URL을 생성해주고,
build.gradle 파일에 추가할 내용과 Github Action으로 사용할 yml파일을 자동 생성해줍니다.

SONAR_TOKEN과 SONAR_HOST_URL은 Repository Secret으로 등록해줍니다.

SonarQube에서 Administration -> Configuration -> General -> Server base URL도 설정해줍니다.
이 값은 PR Decoration에 링크 주소로 사용됩니다.

여기까지가 하셨다면, 이제부터 PR Decoration이 적용될 겁니다!

 

 

 

Jacoco 연동을 통한 테스트 커버리지 정보 추가


Sensor JaCoCo XML Report Importer [jacoco] 'sonar.coverage.jacoco.xmlReportPaths' is not defined.
Using default locations: target/site/jacoco/jacoco.xml,
target/site/jacoco-it/jacoco.xml,build/reports/jacoco/test/jacocoTestReport.xml
No report imported, no coverage information will be imported by JaCoCo XML Report Importer

 

jacoco 관련 설정이 없다면, PR 데코레이션에 테스트 커버리지 정보가 표시되지 않습니다.
위에 있는 영어 문구는 Github Action 수행 시 테스트 커버리지 정보가 없을 때 표기되는 메시지 입니다.

 

plugins {
    # ...
    id "jacoco"
}

test {
		# ...
    finalizedBy 'jacocoTestReport'
}

jacoco {
  toolVersion = '0.8.8'
}

jacocoTestReport {
  reports {
    xml.enabled true
  }
}

 

Jacoco 관련 설정은 이번 포스팅에선 깊이있게 다루지 않습니다.
위와 같은 형태로 build.gradle에 jacoco 설정을 추가해주면,
SonarQube의 PR Decoration에도, 정적 분석 결과에도 코드 커버리지가 함께 표기됩니다.

우와 드디어 정상이네요!

 

 

 

이래저래 삽질기


시간이... 너무 오래 걸렸습니다.
같은 기수 크루인 조조그린, 이프가 가이드를 작성해 공유해주지 않았더라면
아마 지금쯤에도 완료하지 못했을지도 모르겠습니다.

너무 많은 변수들에 대해 무지할 때에
하나씩 차근히 이해하려 노력하며 시도한 방법들을 소거해나가고,
시도하지 않은 방법들을 꾸준히 시도해야하는데
마음이 급하다보니 우당탕탕 이것저것 우다다다 시도해보면서
오히려 미궁속에 빠져버렸던 것 같습니다.
물론 실제 쉽지 않았던 것도 맞는 것 같습니다.

우선 ARM 아키텍처로 인해 도커 기반으로 SonarQube를 사용하지 못한다는 점에서 1차 이슈가 있었고,
ulimit 설정 등이 정상적으로 적용되지 않고 오류가 발생하는 이슈가 있었습니다.
그 이후엔 LTS 최신버전인 8.9를 사용하여 이를 호환하는 플러그인 1.8.2버전을 사용했는데
원인을 알 수 없지만 해당 버전은 PR 데코레이션이 정상 동작하지 않는 이슈가 있었습니다.
성공 모델을 따라 버전까지 맞춰서 SonarQube 9.5와 플러그인 1.12.0으로 시도하니 잘 되었습니다.

그 외에는 Github Action으로 동작하는 것을 확인해야 하다 보니
한 번 돌릴 때마다 5분씩 기다려야 하는 이슈가 있었고,
SonarCloud, SonarQube의 개념에 대해 제대로 이해하지 못해서 헤메는 시간이 있었습니다.

저의 경우 많은 케이스에 인스턴스 재부팅이 문제를 해결(?)해주었고,
PR 데코레이션은 라이브러리가 1.8.2버전이 그냥 이슈가 있는 거라 생각되어
SonarQube 9.5 버전을 사용하신다면 라이브러리 1.12.0 을 쓰셔야 하니 큰 이슈 없으실 것 같습니다.

 

 

SonarQube 붙잡고 있는다고 지난 주부터 내내 거의 개발은 못하고 이것만 했는데...
오래 기다려준 팀원들에게 미안하고 고맙습니다.. ;ㅅ;

 

 

참고 자료