이전 노션 블로그의 소나큐브와 Jacoco로 코드를 깨끗하게 유지하기 (2023.09.07)로부터 마이그레이션된 글입니다.
touch ~/swapfile
sudo fallocate -l 2G ~/swapfile
sudo chmod 600 ~/swapfile
sudo mkswap ~/swapfile
sudo swapon ~/swapfile
sudo yum install java-17-amazon-corretto-headless
/etc/fstab
~/swapfile swap swap defaults 0 0
/etc/sysctl.conf
vm.max_map_count=524288
fs.file-max=131072
ulimit -n 131072
ulimit -u 8192
/etc/security/limits.conf
* - nofile 131072
* - nproc 8192
비효율적임을 느끼고, 도커 기반 자동화 설정 시작
sudo yum install docker
sudo service docker start
sudo usermod -a -G docker ec2-user
// auto-start에 docker 등록
sudo chkconfig docker on
sudo yum install docker-compose
sudo chmod +x /usr/local/bin/docker-compose
sckwon770/sonarqube:9.9.1-community
: SonarQube + PR decoration 플러그인이 합쳐진 커스텀 도커 이미지version: "3"
services:
sonarqube:
image: sckwon770/sonarqube:9.9.1-community
container_name: sonar
ports:
- "8080:9000"
ulimits:
nofile:
soft: "262144"
hard: "262144"
networks:
- sonarnet
environment:
SONAR_JDBC_URL: jdbc:postgresql://db:5432/sonar
SONAR_JDBC_USERNAME: sonar
SONAR_JDBC_PASSWORD: sonar
volumes:
- sonarqube_conf:/opt/sonarqube/conf
- sonarqube_data:/opt/sonarqube/data
- sonarqube_extensions:/opt/sonarqube/extensions
- sonarqube_logs:/opt/sonarqube/logs
db:
image: postgres:13
container_name: postgres
ports:
- "5432:5432"
networks:
- sonarnet
environment:
- POSTGRES_USER=sonar
- POSTGRES_PASSWORD=sonar
volumes:
- postgresql:/var/lib/postgresql
- postgresql_data:/var/lib/postgresql/data
networks:
sonarnet:
driver: bridge
volumes:
sonarqube_conf:
sonarqube_data:
sonarqube_extensions:
sonarqube_logs:
postgresql:
postgresql_data:
docker-compose up -d
docker logs sonarqube -f
flow.yaml
에 추가build.gradle
에서 plugins
부분은 지시사항과 다르게 아래의 버전으로 추가해야 함. SonarQube 3버전이 최근 버전인 Gradle 8에서 deprecated된 그루비 문법을 사용하고 있기 때문에, Github Actions에서 빌드 오류 발생함flow.yaml
에 있는 secrets.GITHUB_TOKEN
은 신경쓰지 않아도 됨앱에 설치할 봇 사용자가 없습니다.
이 발생함. 주의SLACK_BE_PR_ANALYSIS_ALARM_WEBHOOK
)action-slack:
if: ${{ always() }}
needs: build
runs-on: ubuntu-latest
steps:
- name: Slack Alarm
uses: 8398a7/action-slack@v2
with:
status: ${{ job.status }}
author_name: GitHub-Actions development automation
fields: repo,message,commit,author,ref,job,took
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_BE_PR_ANALYSIS_ALARM_WEBHOOK }}
if: always() # Pick up events even if the job fails or is canceled.
Jacoco가 없으면 SonarQube PR Comment에서 테스트 커버리지가 첨부되지 않기 때문에, Jacoco로 디펜던시에 추가해야 함.
Jacoco를 추가하면 jacocoTestReport
과 jacocoTestCoverageVerification
가 추가되는데, 테스트 실행과 함께 진행되야 하므로 실행할 테스크가 너무 많다. 커스텀 그레이들 테스크 testCoverage로 한 번에 실행할 수 있다. Jacoco 빌드 결과 HTML은 build/jacocoHtml/index.html
에 있다.
plugins {
id "jacoco"
}
jacoco {
toolVersion = '0.8.7'
}
jacocoTestReport {
dependsOn test
mustRunAfter test
reports {
xml.required = false
csv.required = false
html.outputLocation = layout.buildDirectory.dir('jacocoHtml')
}
afterEvaluate {
classDirectories.setFrom(
files(classDirectories.files.collect {
fileTree(dir: it, excludes: [
'**/ReviewMateApplication*',
'**/*Formatter*',
'**/*Interceptor*',
'**/GlobalControllerAdvice*',
'**/SwaggerConfig*',
'**/MultipartJackson2HttpMessageConverter*',
'**/StaticRoutingConfiguration*',
'**/*BaseEntity*'
])
})
)
}
}
jacocoTestCoverageVerification {
mustRunAfter jacocoTestReport
violationRules {
rule {
element = 'CLASS'
limit {
counter = 'BRANCH'
value = 'COVEREDRATIO'
minimum = 0.0
}
limit {
counter = 'LINE'
value = 'COVEREDRATIO'
minimum = 0.00
}
limit {
counter = 'METHOD'
value = 'COVEREDRATIO'
minimum = 0.0
}
}
rule {
element = 'METHOD'
excludes = [
"*"
]
limit {
counter = 'LINE'
value = 'TOTALCOUNT'
maximum = 200
}
}
}
}
task testCoverage(type: Test) {
group 'verification'
description 'Runs the unit tests with coverage'
dependsOn('test',
'jacocoTestReport',
'jacocoTestCoverageVerification')
}
⚠️ 주의할 점: 개발 블로그에 올라와 있는 많은 양의 Jacoco 포스팅이 Jacoco 혹은 그레이들 최근 버전들과 호환되지 않음. 특히, 테스트 커버리지에서 제외 할 클래스 설정하는 것은 아래를 따라야 함.
jacocoTestReport {
afterEvaluate {
classDirectories.setFrom(
files(classDirectories.files.collect {
fileTree(dir: it, excludes: [
'**/ReviewMateApplication*',
'**/*Formatter*',
'**/*Interceptor*',
'**/GlobalControllerAdvice*',
'**/SwaggerConfig*',
'**/MultipartJackson2HttpMessageConverter*',
'**/StaticRoutingConfiguration*',
'**/*BaseEntity*'
])
})
)
}
}
https://sungsan.oopy.io/1d6e3f0c-7a3e-48f2-bb62-ad0e37e3c888
프로젝트의 루트 경로에 lombok.config
파일을 생성하고 다음 내용을 추가하면 된다.
lombok.addLombokGeneratedAnnotation = true
슬픈 개구리가 분석이 완료되면, 해당 PR의 변경점을 한정으로 통과 여부와 코드 퀄리티, 테스트 커버리지를 작성해준다. 사진에서 Failed된 이유는 사용하지 않는 import문 하나가 있어서 발생했다. 이 정도로 빡빡하므로, 애초에 IDE에서 SonarLint를 설치해서 Push하기도 전에 미리 체크해두는 것이 좋을듯 싶다.
분석하고 PR 코멘트가 생성되는데 시간이 꽤 걸리므로, 아래처럼 슬랙 알림을 설정하는 것도 좋다.
$ docker ps -a
Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.40/containers/json?all=1: dial unix /var/run/docker.sock: connect: permission denied
원인
Docker 명령어 사용에 필요한 docker.sock을 실행할 권한이 없는 상태
해결 방법
/var/run/docker.sock
파일의 권한을 666으로 변경하여 그룹 내 다른 사용자도 접근 가능하게 변경sudo chmod 666 /var/run/docker.sock
sudo chown root:docker /var/run/docker.sock
원인
docker-compose.yml
에서 포트 설정이 잘못외었음
(ex. 포트포워딩이 잘못된 경우)
services:
sonarqube:
ports:
- "8080:8080"
해결방법
posts
설정은 다음과 같이 이루어져 있음
services:
sonarqube:
ports:
- "컨테이너가_요청받는_포트:요청을_포트포워딩_할_포트"
그리고 소나큐브의 기본 접속 포트는 9000
입니다. 따라서 외부에서 8080
포트로 들어오기로 설정했다면, 그 포트를 9000
포트로 포워딩해줘야 됨.
(ex. 정상 설정)
services:
sonarqube:
ports:
- "8080:9000"
docker-compose.yml
에서 vm.max_map_count
늘리는 부분이 빠졌거나, 가상 메모리 설정이 잘못될 경우 발생
해결방법
docker-compose.yml
에 해당 부분이 빠졌다면, 추가
ulimits:
nofile:
soft: "262144"
hard: "262144"
그래도 되지 않는 경우, EC2 커널의 메모리 설정 재시도
https://creampuffy.tistory.com/196
https://gblee1987.tistory.com/105