วิเคราะห์ NodeJs source code ด้วย SonarQube
ในบทความนี้เราจะมาทำการรู้จักกับ SonarQube เครื่องมือที่ช่วยในการวิเคราะห์ source code ตลอดไปถึงการทดลองวิเคราะห์ NodeJs application ด้วย library ง่ายๆ เริ่มกันเลยครับ
SonarQube คืออะไร
อย่างที่เกริ่นไปแล้ว SonarQube คือ tool ตัวนึงที่ช่วยเราวิเคราะห์ source code และสร้างเป็นรายงานคุณภาพของโค้ดเรา SonarQube ถูกพัฒนาขึ้นโดยบริษัท SonarSource ซึ่ง SonarQube ให้บริการทั้ง Community Edition(CE) ซึ่งฟรี และแบบที่ต้องจ่ายเงินที่จะเพิ่ม features และภาษาที่ support เข้ามา
ในที่นี้เราจะอ้างอิงถึง SonarQube CE กันนะครับ ซึ่งภาษาการเขียนโปรแกรมที่เวอร์ขั่นนี้รองรับคือ Java, C#, JavaScript, TypeScript, CloudFormation, Terraform, Kotlin, Ruby, Go, Scala, Flex, Python, PHP, HTML, CSS, XML และ VB.NET
SonarQube วิเคราะห์อะไรบ้าง
สิ่งที่ SonarQube วิเคราะห์ source code ของเรามีดังนี้
- Bugs ช่องโหว่และข้อผิดพลาดต่างๆที่อาจทำให้ซอร์ฟแวร์ไม่ทำงานคลาดเคลื่อนไปจากที่คาดหวัง
- Code smells ซอสโค้ดที่ไม่เป็นไปตาม standard ซึ่งอาจจะส่งผลให้ยากต่อการ maintainence หรือก่อให้เกิดปัญหาใหญ่ได้ในอนาคต
- Vulnerabilities ช่องโหว่ในการถูกโจมตี
- Code duplications โค้ดที่มีการถูกเขียนซ้ำๆโดยไม่จำเป็น (ซึ่งจะขัดกับหลัก DRY หรือ Don't repeat yourself)
- Test coverage ความคลอบคลุมในการเขียนเทส (Sonarqube ไม่ได้รัน coverage test เองแต่จะอ่านจาก report ของ library อื่น)
ลง SonarQube CE บนเครื่อง local machine
เราจะมาลง SonarQube Community Edition ของเราเพื่อทดลองทำการแสกน source code กันนะครับในที่นี้เราจะลงผ่าน Docker ด้วย docker-compose ถ้าเครื่องใครยังไม่มีให้ไป install ก่อนนะ
อันดับแรกสร้าง directory เปล่าเพื่อทำการทดลองก่อนจะได้จักการไฟล์ได้ง่าย
1mkdir sonarqube-demo && cd sonarqube-demo
หลังจากนั้นสร้างไฟล์ชื่อ docker-compose.yml และ copy เนื้อหาข้างล่างลงไปครับ
4 image: sonarqube:community
8 SONAR_JDBC_URL: jdbc:postgresql://db:5432/sonar
9 SONAR_JDBC_USERNAME: sonar
10 SONAR_JDBC_PASSWORD: sonar
12 - sonarqube_data:/opt/sonarqube/data
13 - sonarqube_extensions:/opt/sonarqube/extensions
14 - sonarqube_logs:/opt/sonarqube/logs
21 POSTGRES_PASSWORD: sonar
23 - postgresql:/var/lib/postgresql
24 - postgresql_data:/var/lib/postgresql/data
เสร็จแล้ว build และรัน container ได้เลย (ในที่นี้จะมี container สองลูก ตัวนึงคือ SonarQube CE และอีกลูกคือ Postgres database ที่ SonarQube เอาไว้ใช้เก็บข้อมูล)
1docker-compose up -d && docker-compose logs -f
รอดู log จนกว่าจะเห็นคำว่า SonarQube is operational
แสดงว่าในทำการ launch เสร็จแล้ว ให้กด Ctrl+C เพื่อออกมาได้เลยครับ
ในกรณีที่เจอ error เกี่ยวกับ memory ที่ต้องใชักับ Elastic Search และไม่สามารถรัน SonarQube ได้ ให้เซทค่าตามที่ error message บอกไว้ใน official document เช่น รันคำสั่งเหล่านี้ใน Linux และรัน docker-compose ใหม่
1sysctl -w vm.max_map_count=524288
2sysctl -w fs.file-max=131072
หลังจากติดตั้งเสร็จเรียบร้อย ลองเข้า browser ไปที่ url http://localhost:9000 ก็จะเห็นหน้า login ของ SonarQube
เรียบร้อยครับ ณ ตอนนี้เรามี SonarQube ไว้ทดลองบนเครื่อง local ของเราแล้ว
สร้างโปรเจคใน SonarQube
ในขั้นตอนนี้ก็จะเป็นการสร้าง project ใน SonarQube เพื่อเอาไว้เก็บ report ของ NodeJs application ที่เราจะทำการแสกนในขั้นตอนต่อไป
ก่อนอื่นล้อคอินด้วย username: admin
, password: admin
ก่อนพอเข้าไปแล้วระบบจะให้ทำการเปลี่ยน password ก็เปลี่ยนตามใจชอบได้เลย
หลังจากนั้นสร้าง Manual project คลิ้กตามรูปได้เลย
หลังจากนั้นให้ตัวชื่อโปรเจคว่า javascript-demo
แล้วคลิก setup ระบบจะถามว่าจะวิเคราะห์ code จากทางไหน ให้คลิ้ก Locally
ต่อไประบบจะให้ตั้งชื่อ token ในที่นี้ผมจะใช้ชื่อว่า local-demo
เสร็จแล้วระบบจะสร้าง token ให้ copy เก็บไว้ใช้ในขั้นตอนถัดๆไป
ถึงตอนนี้ระบบจะให้กด continue เพื่อสอบถามข้อมูลเพิ่มเติมและให้เราดาวโหลดไฟล์มารันบนเครื่อง เราไม่จำเป็นต้อง continue ต่อครับ เนื่องจากเราจะใช้ javascript library ในการ submit code ไปยัง SonarQube จึงไม่จำเป็นต้องลง binary บนเครื่องให้ยุ่งยาก
ทดลองแสกน NodeJs โปรเจคด้วยโมดูล 'sonarqube-scanner'
ในขั้นตอนนี้เราจะลองเขียน NodeJs ง่ายๆเพื่อทดลองให้ SonarQube แสกนดู
เริ่มแรกสร้าง directory และ initialize โปรเจคก่อน
1mkdir nodejs-sonar-demo && cd nodejs-sonar-demo && npm init -y
Library ที่เราจะใช้ชื่อ sonarqube-scanner และเราจะใช้ Jest เพื่อทำ unit test ให้ install ได้เลยครับ
1npm install --save-dev --save-exact sonarqube-scanner jest
ภายในโปรเจคเราจะมี 2 sub-folders ด้วยกัน folder src
เอาไว้เก็บ source code และ folder tests
เอาไว้เขียน test สร้างเตรียมไว้ได้เลย
ขั้นตอนถัดไปจะทำการสร้างไฟล์ src/hello.js
เพื่อที่จะทำไปใช้ในไฟล์หลักของเรา สร้างไฟล์แล้วใส่เนื้อหาด้านล่างลงไป
3 sayHello: (user, country) => `Hello ${user}!`,
4 helloFoo: () => `Hello Foo!`,
5 helloBar: () => `Hello Bar!`,
หลังจากนั้นสร้างไฟล์หลักชื่อ src/index.js
เพื่อทดลองนำโมดูลไปใช้
2const hello = require('./hello');
4console.log(hello.sayHello('Somchai');
5console.log(hello.helloFoo());
6console.log(hello.helloBar());
ต่อไปสร้างไฟล์เทส เราจะเทสแค่ 2 methods นะครับลองดูว่า SonarQube จะว่าอย่างไร
สร้างไฟล์ tests/hello.test.js
ด้วยเนื้อหาด้านล่างเลย
2const hello = require('../src/hello');
4test('Say hello to Somchai', () => {
5 expect(hello.sayHello('Somchai')).toBe('Hello Somchai!');
8test('Say hello to Foo', () => {
9 expect(hello.helloFoo()).toBe('Hello Foo!');
ต่อไปสร้างไฟล์ชื่อ sonar-scan.js
เพื่อที่จะส่งโค้ดทั้งหมดไปยัง Sonarqube ให้ใส่ token ที่เรา copy ไว้ในขั้้นตอนก่อนลงไปด้วยนะครับ
4 serverUrl : 'http://localhost:9000',
5 token : "<token ที่สร้างใน SonarQube>",
7 'sonar.projectName': 'javascript-demo',
8 'sonar.projectDescription': '',
9 'sonar.sources': 'src',
10 'sonar.tests': 'tests'
สุดท้าย แก้ไขไฟล์ package.json
ใส่ script เข้าไปดังนี้
3 "test": "jest --coverage tests/*",
4 "start": "node src/index.js",
5 "sonar": "node sonar-scan.js"
คราวนี้มาลองรัน script ของเราได้เลยครับ เริ่มจาก application หลัก
ถ้าไม่มี error อะไรคราวนี้เรารัน test ดู
Jest จะสร้าง folder ชื่อ coverage
และเก็บผลลัพธ์ไว้ในนั้น ต่อไปส่งโค้ดของเราเข้า sonar ได้เลยครับ
ถ้า scan สำเร็จระบบจะแสดงข้อความ 'EXECUTION SUCCESS' ก็ถือว่าเป็นอันเรียบร้อยครับ
กลับไปดูที่โปรเจคของเราจะเห็นว่า SonarQube รายงานว่ามี code smell 1 ตัวเนื่องจากเรา declare parameter ที่ไม่ได้ถูกใช้ไว้ใน method sayHello
และ unit test ของเราไม่ cover เนื่องจากเราไม่ได้ได้เทส method helloBar
เรียบร้อยครับ การทดลองของเราสำเสร็จแล้ว
สรุป
ในบทความนี้เราก็ได้เรียนรู้ว่า SonarQube คืออะไรและได้ทดสองติดตั้งลงบนเครื่อง อีกทั้งเรายังได้ทดลอง NodeJs ง่ายๆให้ SonarQube ได้แสกนและรายงานคุณภาพดู หวังว่าบทความนี้จะมีประโยชน์ไม่มากก็น้อย
สอบถาม ติชม เสนอแนะ ได้ที่ช่อง comment ด้านล่างเลยครับ