วิเคราะห์ NodeJs source code ด้วย SonarQube

โลโก้ของ 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 เปล่าเพื่อทำการทดลองก่อนจะได้จักการไฟล์ได้ง่าย

1
mkdir sonarqube-demo && cd sonarqube-demo

หลังจากนั้นสร้างไฟล์ชื่อ docker-compose.yml และ copy เนื้อหาข้างล่างลงไปครับ

1
version: "3"
2
services:
3
sonarqube:
4
image: sonarqube:community
5
depends_on:
6
- db
7
environment:
8
SONAR_JDBC_URL: jdbc:postgresql://db:5432/sonar
9
SONAR_JDBC_USERNAME: sonar
10
SONAR_JDBC_PASSWORD: sonar
11
volumes:
12
- sonarqube_data:/opt/sonarqube/data
13
- sonarqube_extensions:/opt/sonarqube/extensions
14
- sonarqube_logs:/opt/sonarqube/logs
15
ports:
16
- "9000:9000"
17
db:
18
image: postgres:12
19
environment:
20
POSTGRES_USER: sonar
21
POSTGRES_PASSWORD: sonar
22
volumes:
23
- postgresql:/var/lib/postgresql
24
- postgresql_data:/var/lib/postgresql/data
25
26
volumes:
27
sonarqube_data:
28
sonarqube_extensions:
29
sonarqube_logs:
30
postgresql:
31
postgresql_data:

เสร็จแล้ว build และรัน container ได้เลย (ในที่นี้จะมี container สองลูก ตัวนึงคือ SonarQube CE และอีกลูกคือ Postgres database ที่ SonarQube เอาไว้ใช้เก็บข้อมูล)

1
docker-compose up -d && docker-compose logs -f

รอดู log จนกว่าจะเห็นคำว่า SonarQube is operational แสดงว่าในทำการ launch เสร็จแล้ว ให้กด Ctrl+C เพื่อออกมาได้เลยครับ

screenshot แสดงการรัน sonarqube บน docker เสร็จสิ้น

ในกรณีที่เจอ error เกี่ยวกับ memory ที่ต้องใชักับ Elastic Search และไม่สามารถรัน SonarQube ได้ ให้เซทค่าตามที่ error message บอกไว้ใน official document เช่น รันคำสั่งเหล่านี้ใน Linux และรัน docker-compose ใหม่

1
sysctl -w vm.max_map_count=524288
2
sysctl -w fs.file-max=131072
3
ulimit -n 131072
4
ulimit -u 8192

หลังจากติดตั้งเสร็จเรียบร้อย ลองเข้า browser ไปที่ url http://localhost:9000 ก็จะเห็นหน้า login ของ SonarQube

เรียบร้อยครับ ณ ตอนนี้เรามี SonarQube ไว้ทดลองบนเครื่อง local ของเราแล้ว

หน้า login ของ SonarQube

สร้างโปรเจคใน SonarQube

ในขั้นตอนนี้ก็จะเป็นการสร้าง project ใน SonarQube เพื่อเอาไว้เก็บ report ของ NodeJs application ที่เราจะทำการแสกนในขั้นตอนต่อไป
ก่อนอื่นล้อคอินด้วย username: admin, password: admin ก่อนพอเข้าไปแล้วระบบจะให้ทำการเปลี่ยน password ก็เปลี่ยนตามใจชอบได้เลย

หลังจากนั้นสร้าง Manual project คลิ้กตามรูปได้เลย

สร้าง SonarQube 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 โปรเจคก่อน

1
mkdir nodejs-sonar-demo && cd nodejs-sonar-demo && npm init -y

Library ที่เราจะใช้ชื่อ sonarqube-scanner และเราจะใช้ Jest เพื่อทำ unit test ให้ install ได้เลยครับ

1
npm install --save-dev --save-exact sonarqube-scanner jest

ภายในโปรเจคเราจะมี 2 sub-folders ด้วยกัน folder src เอาไว้เก็บ source code และ folder tests เอาไว้เขียน test สร้างเตรียมไว้ได้เลย

1
mkdir src tests

ขั้นตอนถัดไปจะทำการสร้างไฟล์ src/hello.js เพื่อที่จะทำไปใช้ในไฟล์หลักของเรา สร้างไฟล์แล้วใส่เนื้อหาด้านล่างลงไป

1
// ไฟล์ src/hello.js
2
const hello = {
3
sayHello: (user, country) => `Hello ${user}!`,
4
helloFoo: () => `Hello Foo!`,
5
helloBar: () => `Hello Bar!`,
6
}
7
8
module.exports = hello;

หลังจากนั้นสร้างไฟล์หลักชื่อ src/index.jsเพื่อทดลองนำโมดูลไปใช้

1
// ไฟล์ src/index.js
2
const hello = require('./hello');
3
4
console.log(hello.sayHello('Somchai');
5
console.log(hello.helloFoo());
6
console.log(hello.helloBar());

ต่อไปสร้างไฟล์เทส เราจะเทสแค่ 2 methods นะครับลองดูว่า SonarQube จะว่าอย่างไร
สร้างไฟล์ tests/hello.test.js ด้วยเนื้อหาด้านล่างเลย

1
// ไฟล์ tests/hello.test.js
2
const hello = require('../src/hello');
3
4
test('Say hello to Somchai', () => {
5
expect(hello.sayHello('Somchai')).toBe('Hello Somchai!');
6
});
7
8
test('Say hello to Foo', () => {
9
expect(hello.helloFoo()).toBe('Hello Foo!');
10
});

ต่อไปสร้างไฟล์ชื่อ sonar-scan.js เพื่อที่จะส่งโค้ดทั้งหมดไปยัง Sonarqube ให้ใส่ token ที่เรา copy ไว้ในขั้้นตอนก่อนลงไปด้วยนะครับ

1
// ไฟล์ ./sonar-scan.js
2
scanner(
3
{
4
serverUrl : 'http://localhost:9000',
5
token : "<token ที่สร้างใน SonarQube>",
6
options: {
7
'sonar.projectName': 'javascript-demo',
8
'sonar.projectDescription': '',
9
'sonar.sources': 'src',
10
'sonar.tests': 'tests'
11
}
12
},
13
() => process.exit()
14
)

สุดท้าย แก้ไขไฟล์ package.json ใส่ script เข้าไปดังนี้

1
...
2
"scripts": {
3
"test": "jest --coverage tests/*",
4
"start": "node src/index.js",
5
"sonar": "node sonar-scan.js"
6
},
7
...

คราวนี้มาลองรัน script ของเราได้เลยครับ เริ่มจาก application หลัก

1
npm start

ถ้าไม่มี error อะไรคราวนี้เรารัน test ดู

1
npm test

Jest จะสร้าง folder ชื่อ coverage และเก็บผลลัพธ์ไว้ในนั้น ต่อไปส่งโค้ดของเราเข้า sonar ได้เลยครับ

1
npm run sonar

ถ้า scan สำเร็จระบบจะแสดงข้อความ 'EXECUTION SUCCESS' ก็ถือว่าเป็นอันเรียบร้อยครับ

รัน SonarQube scan สำเร็จ

กลับไปดูที่โปรเจคของเราจะเห็นว่า SonarQube รายงานว่ามี code smell 1 ตัวเนื่องจากเรา declare parameter ที่ไม่ได้ถูกใช้ไว้ใน method sayHello และ unit test ของเราไม่ cover เนื่องจากเราไม่ได้ได้เทส method helloBar

รัน SonarQube scan สำเร็จ

เรียบร้อยครับ การทดลองของเราสำเสร็จแล้ว

สรุป

ในบทความนี้เราก็ได้เรียนรู้ว่า SonarQube คืออะไรและได้ทดสองติดตั้งลงบนเครื่อง อีกทั้งเรายังได้ทดลอง NodeJs ง่ายๆให้ SonarQube ได้แสกนและรายงานคุณภาพดู หวังว่าบทความนี้จะมีประโยชน์ไม่มากก็น้อย

สอบถาม ติชม เสนอแนะ ได้ที่ช่อง comment ด้านล่างเลยครับ

Copyright © 2024. All rights reserved - Ninenote.net