[CI/CD] ์ •์  ์ฝ”๋“œ ๋ถ„์„ ํˆด SonarQube์™€ Jenkins ์—ฐ๋™

2023. 6. 2. 13:14ใ†System ์ž‘์—…์‹ค/DevOps

728x90
๋ฐ˜์‘ํ˜•

 

 

 

 

 

 

 



๐Ÿ—‚ ๋ชฉ์ฐจ

โš ๏ธ ์•„๋ž˜ ๋ชฉ์ฐจ ์ค‘ ๋ช‡๋ช‡๊ฐœ์˜ ๋งํฌ๊ฐ€ ๊ฑธ๋ฆฌ์ง€ ์•Š๋Š” ๋ฌธ์ œ๋กœ ๊ธ€ ๋งจ ํ•˜๋‹จ์— ๋‹ค์Œ ๊ธ€๋กœ ์ด๋™ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด ๋‘์—ˆ์Šต๋‹ˆ๋‹ค.

โœ… [CI/CD] Jenkins์™€ Gitea ์—ฐ๋™
โœ… [CI/CD] Jenkins Trigger ์ •๋ณด Discord๋กœ ๋ณด๋‚ด๊ธฐ
โœ… [CI/CD] ์ •์  ์ฝ”๋“œ ๋ถ„์„ ํˆด SonarQube์™€ Jenkins ์—ฐ๋™
โœ… [CI/CD] SonarQube๋ฅผ ํ†ตํ•ด Code Convention ์ ์šฉ
โœ… [DevOps] JAVA Gradle JaCoCo (Code coverage) ์„ค์ •ํ•˜๊ธฐ 
โœ… [DevOps] JAVA Gradle JaCoCo (Code coverage) ์„ค์ •ํ•˜๊ธฐ (์ถ”๊ฐ€)(https://junyharang.tistory.com/392)

โœ… [CI/CD] Jenkins + Docker๋ฅผ ์ด์šฉํ•œ ๋ฌด์ค‘๋‹จ ๋ฐฐํฌ - โ‘  Application Linuxt(Ubuntu)์— SSH๋ฅผ ์ด์šฉํ•œ ํŒŒ์ผ ์ „์†ก
โœ… [CI/CD] Jenkins + Docker๋ฅผ ์ด์šฉํ•œ ๋ฌด์ค‘๋‹จ ๋ฐฐํฌ - โ‘ก Create Docker Image And BackUp
โœ… [CI/CD] Jenkins + Docker๋ฅผ ์ด์šฉํ•œ ๋ฌด์ค‘๋‹จ ๋ฐฐํฌ - โ‘ข Application Server Docker Job (โ‘  Application ๋„์ปค ์กด์žฌ ์—ฌ๋ถ€ ํ™•์ธ)
โœ… [CI/CD] Jenkins + Docker๋ฅผ ์ด์šฉํ•œ ๋ฌด์ค‘๋‹จ ๋ฐฐํฌ - โ‘ข Application Server Docker Job (โ‘ก Application Docker Run)(https://junyharang.tistory.com/406)
โœ… [CI/CD] Jenkins + Docker๋ฅผ ์ด์šฉํ•œ ๋ฌด์ค‘๋‹จ ๋ฐฐํฌ - โ‘ข Application Server Docker Job (โ‘ข Application Docker Health Check)
โœ… [CI/CD] Jenkins + Docker๋ฅผ ์ด์šฉํ•œ ๋ฌด์ค‘๋‹จ ๋ฐฐํฌ - โ‘ฃ NGINX Server Docker Job (โ‘  NGINX ๊ฐ ์ข… ์„ค์ •) 
โœ… [CI/CD] Jenkins + Docker๋ฅผ ์ด์šฉํ•œ ๋ฌด์ค‘๋‹จ ๋ฐฐํฌ - โ‘ฃ NGINX Server Docker Job (โ‘ก NGINX Docker ์กด์žฌ ์—ฌ๋ถ€ ํ™•์ธ) 
โœ… [CI/CD] Jenkins + Docker๋ฅผ ์ด์šฉํ•œ ๋ฌด์ค‘๋‹จ ๋ฐฐํฌ - โ‘ฃ NGINX Server Docker Job (โ‘ข NGINX Docker Run & Health Check)
โœ… [CI/CD] Jenkins + Docker๋ฅผ ์ด์šฉํ•œ ๋ฌด์ค‘๋‹จ ๋ฐฐํฌ - โ‘ฃ NGINX Server Docker Job (โ‘ข NGINX ์žฌ ์„ค์ •)



๐Ÿค” ๋‚ด๊ฐ€ ๋งŒ๋‚œ ๋ฌธ์ œ

โ›”๏ธ [Jenkins] java.lang.OutOfMemoryError: Java heap space

 

 

 

 

 

 

๋ฐฐํฌ ์ž๋™ํ™”์™€ ์ง€์†์  ์ธ๋„:๋„์ปค์™€ ์  ํ‚จ์Šค ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค๋กœ ๋งŒ๋“œ๋Š”

COUPANG

www.coupang.com

"์ด ํฌ์ŠคํŒ…์€ ์ฟ ํŒก ํŒŒํŠธ๋„ˆ์Šค ํ™œ๋™์˜ ์ผํ™˜์œผ๋กœ, ์ด์— ๋”ฐ๋ฅธ ์ผ์ •์•ก์˜ ์ˆ˜์ˆ˜๋ฃŒ๋ฅผ ์ œ๊ณต๋ฐ›์Šต๋‹ˆ๋‹ค."

 

 

๐Ÿš€ SonarQube์™€ Jenkins ์—ฐ๋™

    ๐Ÿ”ฝ ๊ฐœ์š”

        ๐Ÿ“ฆ ๊ตฌ์„ฑ๋„

CI/CD ๋ฌด์ค‘๋‹จ ๋ฐฐํฌ ๊ตฌ์„ฑ๋„

 

 

 

 

 

 

deploy Directory Path




        ๐Ÿ“ฆ ์†Œ๊ฐœ

์ด๋ฒˆ์—๋Š” ์ •์  ์ฝ”๋“œ ๋ถ„์„ ํˆด ์†Œ๋‚˜ํ๋ธŒ์™€ ์  ํ‚จ์Šค๋ฅผ ์—ฐ๋™ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์ •๋ฆฌํ•ด ๋ณด๋„๋ก ํ•˜๋ ค๊ณ  ํ•ด์š”.

์†Œ๋‚˜ํ๋ธŒ์— ๋Œ€ํ•œ ์†Œ๊ฐœ์™€ ์ฃผ๋‹ˆ๊ฐ€ ์„ค์น˜ํ•œ ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด์„œ๋Š” ์ด ๊ณณ์— ์ •์„ฑ์Šค๋Ÿฝ๊ฒŒ ์ค€๋น„ํ•ด ๋‘์—ˆ์–ด์š”.

 

[DevOps] Docker๋ฅผ ์ด์šฉํ•œ SonarQube ์„ค์น˜ํ•˜๊ธฐ

๐Ÿš€ SonarQube ์„ค์น˜ ๐Ÿ”ฝ ๊ฐœ์š” ๐Ÿ“ฆ ์†Œ๊ฐœ ์ด๋ฒˆ์—๋Š” Docker๋ฅผ ์ด์šฉํ•˜์—ฌ SonarQube๋ผ๋Š” ๊ฒƒ์„ ์„ค์น˜ํ•ด ๋ณด๋ ค๊ณ  ํ•ด์š”. ๋จผ์ € SonarQube๋ž€ ๋ฌด์—‡์ผ๊นŒ์š”? ์†Œ๋‚˜์†Œ์Šค๊ฐ€ ๊ฐœ๋ฐœํ•œ ์†Œ๋‚˜ํ๋ธŒ๋Š” ์ฝ”๋“œ ๋ฒ ์ด์Šค์˜ ์ฝ”๋“œ ํ’ˆ์งˆ ๋ฐ ๋ณด์•ˆ

junyharang.tistory.com

 



 

    ๐Ÿ”ฝ ๊ตฌ์„ฑ

        ๐Ÿ“ฆ SonarQube

์†Œ๋‚˜ํ๋ธŒ๋ฅผ ์„ค์น˜ํ•˜์˜€์œผ๋‹ˆ ์ด์ œ ์  ํ‚จ์Šค์™€ ์—ฐ๊ฒฐ์„ ์œ„ํ•ด ์†Œ๋‚˜ํ๋ธŒ์—์„œ ์ž‘์—…์„ ํ•ด ์ฃผ๋„๋ก ํ• ๊ฒŒ์š”.

Main -> Create Project -> Manually


์ตœ์ดˆ ๋ฉ”์ธ ํ™”๋ฉด์—์„œ ์œ„์™€ ๊ฐ™์ด ์„ ํƒ์„ ํ•ด ์ค„๊ฒŒ์š”.


Project display name
์—๋Š” ์›ํ•˜๋Š” ์ด๋ฆ„์„ ๋„ฃ์–ด์ฃผ๋ฉด ๋˜๊ณ ,
์ด๋ฆ„์„ ๋„ฃ์–ด์ฃผ๋ฉด key ๋ถ€๋ถ„์ด ์•Œ์•„์„œ ์ž…๋ ฅ๋˜๋Š” ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.

์ฃผ์˜ํ•  ์ ์€ ์  ํ‚จ์Šค์™€ ์—ฐ๋™ํ•  ๋•Œ,
์†Œ๋‚˜ํ๋ธŒ properties ์„ค์ •์—์„œ ํ•ด๋‹น key ๊ฐ’๊ณผ ์ด๋ฆ„์„ ์ž…๋ ฅํ•ด ์ค˜์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ž˜ ์ •๋ฆฌํ•ด ๋‘๋Š” ๊ฒƒ์ด ์ข‹๊ฒ ์–ด์š”.

Main branch name์—๋Š” ํ˜•์ƒ ๊ด€๋ฆฌ ํ”„๋กœ๊ทธ๋žจ์—์„œ Repository์˜ Main Branch ์ด๋ฆ„์„ ์ ์–ด์ฃผ๋ฉด ๋œ๋‹ต๋‹ˆ๋‹ค.

์ด์ œ Set Up ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ์ค„๊ฒŒ์š”.



์ด ์ฐฝ์ด ๋‚˜์˜ค๋ฉด Locally๋ฅผ ์„ ํƒํ•ด ์ฃผ๋„๋ก ํ• ๊ฒŒ์š”.



Token์„ ๋งŒ๋“ค์–ด ์ฃผ๋Š” ๋ถ€๋ถ„์ด์—์š”.

์œ„์™€ ๊ฐ™์ด ๊ธฐ์–ตํ•˜๊ธฐ ์‰ฌ์šด ํ† ํฐ ์ด๋ฆ„์„ ์ง€์ •ํ•˜๊ณ , ํ•ด๋‹น ํ† ํฐ์ด ๋งŒ๋ฃŒ๋˜๋Š” ์‹œ์ ์„ ์ •ํ•ด์ค„ ์ˆ˜ ์žˆ์–ด์š”.

์ฃผ๋‹ˆ๋Š” ๋งŒ๋ฃŒ๋˜์ง€ ์•Š๋„๋ก ํ•ด ์ค„๊ฑฐ์—์š”.

์ด์ œ ์ƒ์„ฑํ•˜๊ธฐ๋ฅผ ๋ˆŒ๋Ÿฌ์ค„๊ฒŒ์š”.



๊ทธ๋Ÿผ ์œ„์™€ ๊ฐ™์ด ํ† ํฐ์ด ๋ฐœ๊ธ‰๋œ ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.

์ด ํ† ํฐ์„ ์  ํ‚จ์Šค์— credentials์— ๋“ฑ๋กํ•ด ์ฃผ์–ด์•ผ ํ•ด์š”.

Continue๋ฅผ ๋ˆŒ๋Ÿฌ์ค€ ๋’ค ๋‹ค๋ฅธ ์ž‘์—…์„ ํ•˜์ง€ ์•Š๊ณ , ์ผ๋‹จ Main Page๋กœ ๋Œ์•„์™€ ์ค๋‹ˆ๋‹ค.



๊ทธ๋Ÿผ ์ด๋ ‡๊ฒŒ ๋ฐฉ๊ธˆ ๋งŒ๋“  ํ”„๋กœ์ ํŠธ๊ฐ€ ๋งŒ๋“ค์–ด์ง„๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.

 

ํ™˜๊ฒฝ์„ค์ • -> Webhooks


์ด๋ฒˆ์—” Webhook ์„ค์ •์„ ํ•ด์ฃผ๋„๋ก ํ•ด๋ณผ๊ฒŒ์š”.



์ด ๊ณณ์—์„œ ์ƒ์„ฑ ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ ์ค๋‹ˆ๋‹ค.


์ด ๊ณณ์—์„œ ์—ฐ๋™ํ•  ์  ํ‚จ์Šค ์ด๋ฆ„์„ ์ง€์ •ํ•˜๊ณ , ํ•ด๋‹น ์  ํ‚จ์Šค์™€ ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š” URL ์ •๋ณด๋ฅผ ์ž…๋ ฅํ•ด ์ฃผ๋ฉด ๋˜์š”.

URN์€ ์œ„์™€ ๊ฐ™์ด /sonarqube-webhook/์„ ๊ผญ ๋„ฃ์–ด์ฃผ์–ด์•ผ ํ•ด์š”.

์ด๋ ‡๊ฒŒ ํ•˜๊ณ , ์ƒ์„ฑ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๊ฒŒ ๋˜๋ฉด Global ์„ค์ •์œผ๋กœ ์†Œ๋‚˜ํ๋ธŒ ๋ชจ๋“  ํ”„๋กœ์ ํŠธ์— ํ•ด๋‹น webhook์ด ์ ์šฉ๋˜์–ด ์งˆ ๊ฑฐ์—์š”.

์ฃผ๋‹ˆ๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” ์  ํ‚จ์Šค๋Š” ํ•˜๋‚˜์ด๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ ‡๊ฒŒ ํด๋กœ๋ฒŒ ์„ค์ •์„ ํ•ด ์ฃผ์—ˆ์–ด์š”.

๋งŒ์•ฝ ํ”„๋กœ์ ํŠธ ๋‹น ๊ฐœ๋ณ„๋กœ Webhook ์„ค์ •์„ ์›ํ•˜๋Š” ๊ฒฝ์šฐ ํ•ด๋‹น ํ”„๋กœ์ ํŠธ ์•ˆ์—์„œ Project Setting - Webhook ์„ค์ •์—์„œ ํ”„๋กœ์ ํŠธ ๋ณ„๋กœ webhook์„ ๋‹ค๋ฅด๊ฒŒ ์„ค์ •ํ•ด ์ค„ ์ˆ˜๋„ ์žˆ์–ด์š”.

 

 

 

 

 

 

 

        ๐Ÿ“ฆ Jenkins

์ด๋ฒˆ์—๋Š” ์  ํ‚จ์Šค์—์„œ ์„ค์ •์„ ํ•ด ๋ณด๋„๋ก ํ• ๊ฒŒ์š”.

Jenkins ๊ด€๋ฆฌ -> PlugIn Manager


์ตœ์ดˆ PlugIn Manager์—์„œ ์œ„์˜ ๋‘ PlugIn์„ ์„ค์น˜ํ•ด ์ฃผ๋„๋ก ํ•ด์•ผ ํ•ด์š”.


Jenkins ๊ด€๋ฆฌ -> Credentials

 


์ด์ œ ์†Œ๋‚˜ํ๋ธŒ ์—ฐ๋™์„ ์œ„ํ•ด Credentials๋ฅผ ๋“ฑ๋กํ•ด ์ค„๊ฑด๋ฐ, ์œ„์™€ ๊ฐ™์ด Global ์„ค์ •์„ ํ•ด ์ฃผ๋ ค๊ณ  ํ•ด์š”.



์ด ๊ณณ์—์„œ ์ตœ์ดˆ kind๋Š” Secret text๋กœ ํ•ด ์ค„๊ฒŒ์š”.



Secret์—๋Š” ์†Œ๋‚˜ํ๋ธŒ์—์„œ ๋ฐœ๊ธ‰ ๋ฐ›์€ ํ† ํฐ ๊ฐ’์„ ์ž…๋ ฅํ•ด ์ฃผ์—ˆ์–ด์š”.

ID๋Š” ์  ํ‚จ์Šค ํŒŒ์ดํ”„๋ผ์ธ์—์„œ ์‚ฌ์šฉํ•  ID๋กœ ์ด ๊ฐ’์„ ํ†ตํ•ด Jenkins File์—์„œ ์†Œ๋‚˜ํ๋ธŒ ํ† ํฐ ๊ฐ’์„ ์ „๋‹ฌ ๋ฐ›๊ฒŒ ๋˜์š”.

Description์€ ํ•ด๋‹น Credentials์— ์„ค๋ช…์„ ์ ์–ด์ฃผ๋ฉด ๋œ๋‹ต๋‹ˆ๋‹ค.

Create๋ฅผ ๋ˆŒ๋Ÿฌ์ค„๊ฒŒ์š”.



Jenkins ๊ด€๋ฆฌ -> Configure System


์ด์ œ ์  ํ‚จ์Šค ์‹œ์Šคํ…œ ์„ค์ •์—์„œ ์œ„์™€ ๊ฐ™์ด ์†Œ๋‚˜ํ๋ธŒ ์ •๋ณด๋ฅผ ์ž…๋ ฅํ•ด ์ฃผ๋ฉด ๋˜์š”.

๊ทธ๋Ÿฐ ๋’ค ๊ณ ๊ธ‰ ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ ์ค๋‹ˆ๋‹ค.

๋ฐ˜์‘ํ˜•


๊ทธ๋Ÿผ ์œ„ ์„ค์ • ๋ถ€๋ถ„์ด ๋‚˜์˜ฌํ…๋ฐ, ์ด ๋ถ€๋ถ„์€ ์†Œ๋‚˜ํ๋ธŒ properties ์„ค์ •์„ ํ•˜๋Š” ๋ถ€๋ถ„์ด์—์š”.
์ฃผ๋‹ˆ๋Š” ์ด ๊ณณ์— project Key์™€ project Name์„ ์„ค์ •ํ•ด ์ค„ ์ˆ˜ ์žˆ์–ด์š”.

์ด๋ ‡๊ฒŒ ์†Œ๋‚˜ํ๋ธŒ์— ๋“ฑ๋ก์„ ํ•ด ์ค˜๋„ ๋˜๊ณ ,
์†Œ์Šค ์ฝ”๋“œ Project Root Directory์— sonar.properties๋ฅผ ๋งŒ๋“ค์–ด ๊ด€๋ฆฌํ•  ์ˆ˜๋„ ์žˆ์–ด์š”.

์ฃผ๋‹ˆ๋Š” ์ด ์„ค์ •์„ jenkins File์— ํ•ด ์ค„๊ฑฐ์—์š”.

ํ•ด๋‹น ๋‚ด์šฉ์€ ๋ฐ‘์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.

์—ฌ๊ธฐ๊นŒ์ง€ ๋˜์—ˆ๋‹ค๋ฉด ๋ฐ‘์— Apply๋ฅผ ๋ˆ„๋ฅธ ๋’ค Save๋ฅผ ๋ˆŒ๋Ÿฌ ์ €์žฅํ•ด ์ค๋‹ˆ๋‹ค.




 

 

 

 

   ๐Ÿ”ฝ ์„ค์ •

        ๐Ÿ“ฆ Sonar Scanner

์ด๋ฒˆ์—๋Š” Sonar Scanner ์„ค์ •์„ ํ•ด๋ณด๋ ค๊ณ  ํ•ด์š”.

์  ํ‚จ์Šค์—์„œ ์  ํ‚จ์Šค ๊ด€๋ฆฌ์˜ Global Tool Configuration์—์„œ ์ง„ํ–‰ ํ•ฉ๋‹ˆ๋‹ค.

Jenkins ๊ด€๋ฆฌ -> Global Tool Configuration



Sonar-Scanner PlugIn์ด ์ž˜ ์„ค์น˜ ๋˜์—ˆ๋‹ค๋ฉด ์œ„์— ํ•ญ๋ชฉ์ด ๋ณด์—ฌ์•ผ ํ•ด์š”.


Add SonarScanner for MSBuild ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ ์œ„์™€ ๊ฐ™์ด ์„ค์ •ํ•ด ์ฃผ์—ˆ์–ด์š”.

์—ฌ๊ธฐ์„œ ์ด๋ฆ„์€ ์ž„์˜์˜ ๊ฐ’์„ ์ง€์ •ํ•ด ์ฃผ๋ฉด ๋œ๋‹ต๋‹ˆ๋‹ค.


๊ทธ๋Ÿฐ ๋’ค Add SonarQube Scanner๋ฅผ ๋ˆŒ๋Ÿฌ ์œ„์™€ ๊ฐ™์ด ์„ค์ •ํ•ด ์ฃผ์—ˆ์–ด์š”.

์ด ๊ณณ์— ์‚ฌ์šฉ๋œ ์ด๋ฆ„ ๊ฐ’์„ ์ถ”ํ›„ Jenkins File์— Sonnar-analysis Stage ๋ถ€๋ถ„์—์„œ
Sonnar-Scanner tool ๋ถ€๋ถ„์— ๋ช…์‹œํ•ด ์ค˜์•ผ ํ•˜๋Š” ์ด๋ฆ„์ด์—์š”.

๋ฐ‘ ๋ถ€๋ถ„์— Apply๋ฅผ ๋ˆ„๋ฅด๊ณ , Save๋ฅผ ๋ˆŒ๋Ÿฌ ๋น ์ ธ ๋‚˜์™€ ์ค„๊ฒŒ์š”.


์ด์ œ Jenkins File์„ ์ˆ˜์ •ํ•ด ๋ณด๋„๋ก ํ• ๊ฑฐ์—์š”.


def SET_VARIABLE = "Jenkins File ๋ณ€์ˆ˜ ์„ค์ •"
def SONARQUBE_ANALYSIS = "์†Œ๋‚˜ํ๋ธŒ Analysis"

pipeline {
    agent any
    environment {
        WEBHOOK_URL = credentials("Total-Back-Office-BE-Discord-Webhook")
    }

    stages {
        stage(SET_VARIABLE) {
            steps {
                script {
                    // ๊ตฌ๋™ ํ™˜๊ฒฝ ์„ค์ • (์‚ผํ•ญ ์—ฐ์‚ฐ์ž๋กœ ๋ธŒ๋Ÿฐ์น˜ ์ด๋ฆ„์ด master๋ผ๋ฉด prod ํ™˜๊ฒฝ์ด๊ณ , ์•„๋‹ˆ๋ฉด dev ํ™˜๊ฒฝ
                    DRIVE_ENV = env.BRANCH_NAME.equals("master") ? "prod" : "dev"

                    // ์†Œ๋‚˜ํ๋ธŒ ์„ค์ •
                    SONARQUBE_SERVER_NAME = 'Jenkins SonarQube Server ์„ค์ •์˜ Name'
                    SONARQUBE_CREDENTIAL_ID = "Jenkins์—์„œ ๋“ฑ๋กํ•œ SonarQube Crendential ID"
                }
            }
        }
    }

    stage(SONARQUBE_ANALYSIS) {
        when {
            branch pattern: "(develop|master)", comparator: "REGEXP"
        }

        steps {
            script {
                def scannerHome = tool 'SonarQube-Scanner';
                withSonarQubeEnv(credentialsId: SONARQUBE_CREDENTIAL_ID, installationName: SONARQUBE_SERVER_NAME) {
                sh "${scannerHome}/bin/sonar-scanner \
                    -Dsonar.projectKey=BE-total-back-office \
                    -Dsonar.projectName=BE-total-back-office \
                    -Dsonar.branch.name=master \
                    -Dsonar.language=java \
                    -Dsonar.java.source=1.8 \
                    -Dsonar.sources=src/main/java \
                    -Dsonar.test=src/test/java \
                    -Dsonar.test.inclusion=**/*Test.java \
                    -Dsonar.issuesReport.console.enable=true \
                    -Dsonar.junit.reportPaths=build/test-results/test \
                    -Dsonar.java.binaries=build/classes \
                    -Dsonar.java.libraries.empty=true \
                    -Dsonar.sourceEncoding=UTF-8 \
                    -Dsonar.exclusions=**/dto/**,**/exception/**,**/constant/**,**/SpringInitProjectApplication.java,**/WebRestController.java,**/FileUploadYaml.java \
                    -Dsonar.java.checkstyle.reportPaths=build/reports/checkstyle-output/checkstyle-report.xml \
                    "
                }
            }
        }

        post {
            success {
                discordSend description: "์†Œ๋‚˜ํ๋ธŒ Scan ์ž‘์—… ์„ฑ๊ณต ํ•˜์˜€์–ด์š”. ๐Ÿ˜€",
                    footer: "Jenkins CI/CD Trigger Alarm",
                    link: env.BUILD_URL, result: currentBuild.currentResult,
                    title: "Jenkins CI/CD Trigger Discord๋ฅผ ํ†ตํ•ด ๋ฐ›๊ธฐ ์‹œํ—˜ ์ค‘ ์ž…๋‹ˆ๋‹ค.",
                    webhookURL: env.WEBHOOK_URL
            }

            failure {
                discordSend description: "์†Œ๋‚˜ํ๋ธŒ Scan ์ž‘์—… ์‹คํŒจ ํ•˜์˜€์–ด์š”. ๐Ÿ˜ข",
                    footer: "Jenkins CI/CD Trigger Alarm",
                    link: env.BUILD_URL, result: currentBuild.currentResult,
                    title: "Jenkins CI/CD Trigger Discord๋ฅผ ํ†ตํ•ด ๋ฐ›๊ธฐ ์‹œํ—˜ ์ค‘ ์ž…๋‹ˆ๋‹ค.",
                    webhookURL: env.WEBHOOK_URL
            }
        } // Discord Send Post ๋
    } // stage(SONARQUBE_ANALYSIS) ๋
}


Jenkins File์„ ์œ„์™€ ๊ฐ™์ด ์ˆ˜์ •ํ•ด ์ฃผ์—ˆ์–ด์š”.

์ตœ์ดˆ when ์ ˆ ๋ฐ‘์— branch ๋ถ€๋ถ„์€ Jenkins Build๊ฐ€ Develop Branch๋กœ Merge ๋˜๋Š” Push๊ฐ€ ์ผ์–ด๋‚  ๋•Œ๋งŒ, ํ•ด๋‹น Stage๊ฐ€ ์ž‘๋™ํ•˜๋„๋ก ํ•ด์ฃผ๋ ค๊ณ  ์ž‘์„ฑํ•œ ๋ถ€๋ถ„์ด์—์š”.

์šด์˜ ํ™˜๊ฒฝ(prod) ๋•Œ ๋ฐฐํฌ ์‹œ์—๋Š” ์ด๋ฏธ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์—์„œ ๋ชจ๋“  ๋ถ„์„๊ณผ ์ˆ˜์ •, ํ…Œ์ŠคํŠธ๊ฐ€ ๋๋‚˜๊ณ  ๋ฐฐํฌ๊ฐ€ ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ด ๋ถ€๋ถ„์„ ๋˜
๊ฑฐ์น  ํ•„์š”๊ฐ€ ์—†์–ด์š”.

๋˜ ๋‹ค๋ฅธ stage sh ๋ถ€๋ถ„์€ Shell Script๋ฅผ ์ž‘์„ฑํ•˜๊ฒ ๋‹ค๋Š” ์˜๋ฏธ์ธ๋ฐ,
-Dsonar. ์œผ๋กœ ์‹œ์ž‘ํ•˜๋Š” ์„ค์ •๋“ค์„ ํ†ตํ•ด ์†Œ๋‚˜ํ๋ธŒ ๋ถ„์„์‹œ ์‚ฌ์šฉ๋  ์„ค์ •๋“ค์„ ์„ค์ •ํ•˜๊ฒ ๋‹ค๊ณ  ์•Œ๋ ค์ค€ ๊ฑฐ์—์š”.

์œ„์—์„œ ์†Œ๋‚˜ํ๋ธŒ Project name๊ณผ Project Key๋ฅผ Jenkins File์— ๋‘๊ฒ ๋‹ค๊ณ  ํ•˜์˜€๋Š”๋ฐ, ๊ทธ ๋ถ€๋ถ„์ด ๋ฐ”๋กœ

jenkinsfile 61 ~ 64์ „์งธ ์ค„


63 ~ 64๋ฒˆ์งธ ์ค„์— ๋ช…์‹œํ•ด ์ค€ ๋ถ€๋ถ„์ด์—์š”.

๋ถ„์„ํ•  Package ์œ„์น˜๋„ ๋ช…์‹œ ํ•ด์ฃผ๊ณ , inclusion๊ณผ exclusion ์„ค์ •์„ ํ†ตํ•ด
SonarQube๋ฅผ ํ†ตํ•œ ๋ถ„์„ ์‹œ ํฌํ•จํ•  ํ•ญ๋ชฉ๊ณผ ๋ฐฐ์ œํ•  ํ•ญ๋ชฉ๋„ ์ง€์ •ํ•ด ์ค„ ์ˆ˜ ์žˆ์–ด์š”.

-Dsnoar.branch.name=master ๋ถ€๋ถ„์€ SonarQube์—์„œ ์ƒ์„ฑ๋œ
Project ๋ถ„์„ ๊ฒฐ๊ณผ๋ฅผ ๋“ฑ๋กํ•  Branch Name์„ ๋ช…์‹œํ•˜๋Š” ๊ณณ์ธ๋ฐ,

์†Œ๋‚˜ํ๋ธŒ ์„ค์ •์„ ํ†ตํ•ด Default Branch Name์„ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๋Š” ํ•œ main์œผ๋กœ ์žกํ˜€ ์žˆ์„ ๊ฑฐ์—์š”.
์ฃผ๋‹ˆ๋Š” master๋กœ ๋ณ€๊ฒฝํ–ˆ๋‹ต๋‹ˆ๋‹ค. ์ด ์„ค์ •์„ sonar-bot์˜ PR Comment๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ํ•„์š” ์—†์–ด์š”.

CheckStyle ๋ถ€๋ถ„์—์„œ Code Convention ๋ถ„์„ ๊ฒฐ๊ณผ๋ฅผ ์†Œ๋‚˜ํ๋ธŒ๋กœ ๋ณด๋‚ด๊ธฐ ์œ„ํ•ด ์ƒ์„ฑ๋œ xml File ์œ„์น˜๋ฅผ ๋ช…์‹œํ•ด ์ฃผ์—ˆ์–ด์š”.

-Dsonar.java.checkstyle.reportPaths=build/reports/checkstyle-output/checkstyle-report.xml \


.Dsonar. ์œผ๋กœ ์‹œ์ž‘ํ•˜๋Š” ์„ค์ •๋“ค์€ ์ฃผ๋‹ˆ๊ฐ€ ์  ํ‚จ์Šค์—์„œ ์†Œ๋‚˜ํ๋ธŒ ์„ค์ •์‹œ ์ด์•ผ๊ธฐํ•œ Project Root Directory์— sonar.properties๋ฅผ ๋”ฐ๋กœ ๋งŒ๋“ค์–ด ๊ด€๋ฆฌํ•  ์ˆ˜๋„ ์žˆ์–ด์š”.

์ด๋ฒˆ์—๋Š” ์†Œ๋‚˜ํ๋ธŒ์˜ Quality Gate ๊ธฐ๋Šฅ์„ ์ด์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์ •๋ฆฌํ•ด ๋ณผ๊ฒŒ์š”.

jenkinsfile 73 ~ 97๋ฒˆ์งธ ์ค„
jenkinsfile 99 ~ 116๋ฒˆ์งธ ์ค„

 

        stage(SONARQUBE_QUALITY_GATE) {
            when {
                branch pattern: "(develop|master)", comparator: "REGEXP"
            }

            steps {
                timeout(time: 5, unit: 'MINUTES') {
                    script {
                        echo "์†Œ๋‚˜ํ๋ธŒ Quality Gate ๊ฒ€์‚ฌ๊ฐ€ ์‹œ์ž‘ ๋˜์—ˆ์–ด์š”!"
                        def sonarQubeQualityGate = waitForQualityGate()
                        def qualityGateStatus = sonarQubeQualityGate.status
                        echo "Quality Gate ์ƒํƒœ: ${qualityGateStatus}"

                        if (qualityGateStatus != 'OK') {
                            echo "Quality Gate ๊ฒ€์ฆ ์ƒํƒœ: ${qualityGateStatus}"
                            error "Quality Gate ๊ฒ€์ฆ์— ์‹คํŒจ ํ•˜์˜€์–ด์š” ๐Ÿ˜ญ: ${qualityGateStatus}"

                        } else {
                         echo "Quality Gate ๊ฒ€์ฆ์— ์„ฑ๊ณต ํ•˜์˜€์–ด์š” ๐Ÿ˜€: ${qualityGateStatus}"
                        }

                        echo "Quality Gate ๊ฒ€์ฆ์„ ๋ชจ๋‘ ์™„๋ฃŒ ํ•˜์˜€์–ด์š” ๐Ÿ˜Ž"
                    }
                }
            }

            post {
                success {
                    discordSend description: "์†Œ๋‚˜ํ๋ธŒ Quality Gate ์ž‘์—… ์„ฑ๊ณต ํ•˜์˜€์–ด์š”. ๐Ÿ˜€",
                        footer: "Jenkins CI/CD Trigger Alarm",
                        link: env.BUILD_URL, result: currentBuild.currentResult,
                        title: "Jenkins CI/CD Trigger Discord๋ฅผ ํ†ตํ•ด ๋ฐ›๊ธฐ ์‹œํ—˜ ์ค‘ ์ž…๋‹ˆ๋‹ค.",
                        webhookURL: env.WEBHOOK_URL
                }

                failure {
                    discordSend description: "์†Œ๋‚˜ํ๋ธŒ Quality Gate ์ž‘์—… ์‹คํŒจ ํ•˜์˜€์–ด์š”. ๐Ÿ˜ข",
                        footer: "Jenkins CI/CD Trigger Alarm",
                        link: env.BUILD_URL, result: currentBuild.currentResult,
                        title: "Jenkins CI/CD Trigger Discord๋ฅผ ํ†ตํ•ด ๋ฐ›๊ธฐ ์‹œํ—˜ ์ค‘ ์ž…๋‹ˆ๋‹ค.",
                        webhookURL: env.WEBHOOK_URL
                }
            } // Discord Send Post ๋
        } // stage(SONARQUBE_QUALITY_GATE) ๋


Jenkins File์— ์œ„ ๋‚ด์šฉ์„ ์ถ”๊ฐ€ํ•ด ์ฃผ์—ˆ์–ด์š”.

sonarQubeQualityGate ๋ผ๋Š” ๋ณ€์ˆ˜์— waitForQualityGate()๋ฅผ ํ˜ธ์ถœํ•œ ๊ฒฐ๊ณผ๊ฐ’์„ ๋ฐ›๋„๋ก ํ•ด ์ฃผ์—ˆ๋Š”๋ฐ,
์ด ๋ถ€๋ถ„์€ ์†Œ๋‚˜ํ๋ธŒ Analysis๊ฐ€ ๋๋‚  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฐ ๋‹ค์Œ ๊ฒฐ๊ณผ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ํ•ด ์ฃผ๊ธฐ ์œ„ํ•œ ๋ถ€๋ถ„์ด์—์š”.


์—ฌ๊ธฐ๊นŒ์ง€ ์ž‘์—…ํ•˜๊ณ , Gitea์— Push๋ฅผ ํ•ด ์ฃผ์—ˆ์–ด์š”.



์  ํ‚จ์Šค์—์„œ ํ™•์ธํ•ด๋ณด๋‹ˆ ์ •์ƒ์ ์œผ๋กœ ์ž‘์—…์ด ์™„๋ฃŒ๊ฐ€ ๋˜์—ˆ์–ด์š”.

๋””์Šค์ฝ”๋“œ์—๋„ ์„ฑ๊ณตํ•œ ๋‚ด์—ญ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.


์†Œ๋‚˜ํ๋ธŒ์—์„œ ๋ณด๋ฉด ์œ„์™€ ๊ฐ™์ด ๊ฒ€์‚ฌ๊ฐ€ ์™„๋ฃŒ๋˜๊ณ , ํ•ด๋‹น ๋‚ด์šฉ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.



์ด๋ ‡๊ฒŒ ๋ฒ„๊ทธ(Bug), ์ทจ์•ฝ์ , ์ฝ”๋“œ ์•…์ทจ (Code Smell) ๋“ฑ์„ ๊ฒ€์ฆ ๋ฐ›์•„์„œ ๋ณด๋‹ค ์ข‹์€ ์ฝ”๋“œ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ฒŒ ๋„์™€์ฃผ๋Š”๊ฒŒ
๋ฐ”๋กœ ์†Œ๋‚˜ํ๋ธŒ์—์š”.


์œ„์—์„œ ์„ค์ •ํ–ˆ๋˜ Qulity Gate๋ฅผ ํ†ต๊ณผํ•˜๊ฒŒ ๋˜๋ฉด ์ •์ƒ์ ์œผ๋กœ CI/CD๊ฐ€ ์ง„ํ–‰๋˜๋Š” ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.



์†Œ๋‚˜ํ๋ธŒ -> Quality Gate(ํ’ˆ์งˆ ๊ฒŒ์ดํŠธ)


์†Œ๋‚˜ํ๋ธŒ์˜ Quality Gate๋Š” ์œ„์™€ ๊ฐ™์ด ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์žกํ˜€ ์žˆ๋Š” ์ƒํƒœ์—์š”.

๋งŒ์•ฝ ์ด ๋ถ€๋ถ„์„ ์šฐ๋ฆฌ ํ™˜๊ฒฝ์— ๋งž๊ฒŒ ์ข€ ๋” ๋†’์€ ๊ธฐ์ค€์น˜๋ฅผ ๋‘๊ฑฐ๋‚˜, ํ˜น์€ ๋‚ฎ์ถฐ์„œ ์„ค์ •ํ•ด ์ค„ ์ˆ˜๋„ ์žˆ์–ด์š”.

์ด๋ฒˆ์—๋Š” Quality Gate๋ฅผ ํ•œ๋ฒˆ ๋งŒ๋“ค์–ด ๋ณผ๊ฒŒ์š”.

 
์œ„ ํ™”๋ฉด์—์„œ ์ƒ์„ฑ์„ ๋ˆŒ๋Ÿฌ ์ค„๊ฒŒ์š”.



๊ทธ๋ฆฌ๊ณ  ์œ„์™€ ๊ฐ™์ด ์ด๋ฆ„์„ ์ •ํ•ด ์ฃผ๊ณ , ์ €์žฅ์„ ๋ˆŒ๋Ÿฌ ์ค๋‹ˆ๋‹ค.



์œ„ ํ™”๋ฉด์—์„œ ์กฐ๊ฑด ์ถ”๊ฐ€ (Add Condition)์„ ๋ˆŒ๋Ÿฌ์ค„๊ฒŒ์š”.



๊ทธ๋Ÿผ ์ด ๊ณณ์—์„œ ์šฐ๋ฆฌ ํ™˜๊ฒฝ์— ๋งž๋Š” Quality Gate๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ์—ฌ๋Ÿฌ๊ฐ€์ง€ ํ•ญ๋ชฉ์ด ์žˆ๋Š”๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.

์ด๋ ‡๊ฒŒ ๋งŒ๋“  Quality Gate๋ฅผ ํ†ตํ•ด ์šฐ๋ฆฌ์˜ Project Setting์—์„œ ๋งŒ๋“ค์—ˆ๋˜ Quality Gate๋ฅผ ์ง€์ •ํ•ด ์ฃผ๋ฉด ์ด ์„ค์ •์„ ๋‚ด์šฉ์„
ํ† ๋Œ€๋กœ ๋ถ„์„์„ ํ•˜๊ฒŒ ๋œ๋‹ต๋‹ˆ๋‹ค.

 

 

์ด์ „ ๊ธ€: [CI/CD] Jenkins Trigger ์ •๋ณด Discord๋กœ ๋ณด๋‚ด๊ธฐ


๋‹ค์Œ ๊ธ€:
[CI/CD] SonarQube๋ฅผ ํ†ตํ•ด Code Convention ์ ์šฉ



 

 

 

728x90
๋ฐ˜์‘ํ˜•