Whether you write code professionally or just as a hobby, static code analysis is an important tool for any developer to find bugs, security vulnerabilities, and opportunities to improve the quality of your code. The most popular tool is called Sonarqube which offers a free open-source community edition that can be installed locally and supports most of the popular languages. While it does not have all of the features of the paid Developer, Enterprise, and Data Center editions, it is more than enough to get you started with static code analysis and will help you become a better developer.
Before we begin setting up Sonarqube and the Sonar-Scanner on your Mac, let's talk about the different editions of Sonarqube. Available in Community, Developer, Enterprise, and Data Center editions, the primary difference between each version is the supported languages and other capabilities I'll call quality of life enhancements. Full customization, full pipeline support, nice-looking formatted pull requests, advanced detection of bugs, and the ability to scan any branch of a repo are the notable differences for me. Check out the official edition comparison page here for all the details, which also includes the SonarCloud service if you want to pay for a subscription to their cloud service alternative. Another version comparison chart is available on the download page here.
Is your language of choice supported in the Community Edition? For most, this is the only limiting factor to get started with the free version so I put together the list of "free" languages below.
Supported languages in Sonarqube Community Edition
- Azure Resource Manager
- CloudFormation
- C#
- CSS
- Docker
- Flex
- Go
- HTML
- Java
- JavaScript
- Kotlin
- Kubernetes
- PHP
- Python
- Ruby
- Scala
- Secrets (creds)
- Terraform
- TypeScript
- VB.NET
- XML
The language support in the Community Edition is quite comprehensive, but you will need to upgrade to the developer edition for C, C++, and TSQQL. The enterprise and data center editions provide access to Apex, VB6, RPG, and COBOL.
Understanding the Components of Sonarqube
There are two primary components of Sonarqube, the scanner utility and the server. The scanner utility is what we point at a directory or repo and it reads all your source code. The server hosts the interface we log into and interact with and processes the scanner results into different categories.
Installing Sonarqube and the Sonar-Scanner
I recommend using Homebrew to install Sonarqube and the Sonar-Scanner as it is the best way to install with all the required dependencies and provides easy updates going forward. If you don't already have Homebrew on your Mac, check out my guide here to get started.
Alternatively, you can download the Community Edition here (zip file) but you will need to extract the files, install the necessary Java dependencies, install the service, and update manually.
Back to the recommended approach, with Homebrew, you just need to run two commands:
brew install sonarqube
brew install sonar-scanner
The Sonarqube install will take a moment while a bunch of dependencies are downloaded and installed:
stevesinchak@tweaks dev % brew install sonarqube
==> Downloading https://formulae.brew.sh/api/formula.jws.json
################################################################################################################################### 100.0%
==> Downloading https://formulae.brew.sh/api/cask.jws.json
################################################################################################################################### 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/sonarqube/manifests/10.4.1.88267
################################################################################################################################### 100.0%
==> Fetching dependencies for sonarqube: giflib, libpng, freetype, fontconfig, pcre2, glib, xorgproto, libxau, libxdmcp, libxcb, libx11, libxext, libxrender, lzo, pixman, cairo, graphite2, icu4c, harfbuzz, jpeg-turbo, lz4, zstd, libtiff, little-cms2 and openjdk@17
==> Downloading https://ghcr.io/v2/homebrew/core/giflib/manifests/5.2.1
################################################################################################################################### 100.0%
==> Fetching giflib
==> Downloading https://ghcr.io/v2/homebrew/core/giflib/blobs/sha256:0810045224fbfa1ae8c5bbdfc44d454efcaf76606e865f8be4a46606369c44b1
################################################################################################################################### 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/libpng/manifests/1.6.43
################################################################################################################################### 100.0%
==> Fetching libpng
==> Downloading https://ghcr.io/v2/homebrew/core/libpng/blobs/sha256:37936ba5cd5a1e736908a26fd2a944e04d86694a55f99fe5e173bfacac90e2e8
################################################################################################################################### 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/freetype/manifests/2.13.2-1
################################################################################################################################### 100.0%
==> Fetching freetype
==> Downloading https://ghcr.io/v2/homebrew/core/freetype/blobs/sha256:8966d44484907e98ea2b0fa4b3708627285d0eae3ca0eeb5d3f158cc0437e3f7
################################################################################################################################### 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/fontconfig/manifests/2.15.0
################################################################################################################################### 100.0%
==> Fetching fontconfig
==> Downloading https://ghcr.io/v2/homebrew/core/fontconfig/blobs/sha256:4732e8c8cd6f940fa3ace12a5a5428baaef29bdccf9bc520fa4d37a1f0bf639c
################################################################################################################################### 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/pcre2/manifests/10.43
################################################################################################################################### 100.0%
==> Fetching pcre2
==> Downloading https://ghcr.io/v2/homebrew/core/pcre2/blobs/sha256:45c605d79f321f1afcab9192841fb6440f97693440ed6ccb8242edb3118303f3
################################################################################################################################### 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/glib/manifests/2.78.4
################################################################################################################################### 100.0%
==> Fetching glib
==> Downloading https://ghcr.io/v2/homebrew/core/glib/blobs/sha256:501d6eb669b7bcffceb11c1261562a8533e954eef22c60142e6e524853c5f678
################################################################################################################################### 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/xorgproto/manifests/2023.2
################################################################################################################################### 100.0%
==> Fetching xorgproto
==> Downloading https://ghcr.io/v2/homebrew/core/xorgproto/blobs/sha256:32a25261f78c125375872609316c2142f7b961617b7b7799b2ea11e818ced721
################################################################################################################################### 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/libxau/manifests/1.0.11
################################################################################################################################### 100.0%
==> Fetching libxau
==> Downloading https://ghcr.io/v2/homebrew/core/libxau/blobs/sha256:5af5678065c243a7d199b76facc8be615dd6aa6de65d03778e9b403e8b2827d6
################################################################################################################################### 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/libxdmcp/manifests/1.1.5
################################################################################################################################### 100.0%
==> Fetching libxdmcp
==> Downloading https://ghcr.io/v2/homebrew/core/libxdmcp/blobs/sha256:789326aa88d1b6dbe5dd565e9e70e5031bf63fac39d22cd30d11c1dfc49ffbfb
################################################################################################################################### 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/libxcb/manifests/1.16.1
################################################################################################################################### 100.0%
==> Fetching libxcb
==> Downloading https://ghcr.io/v2/homebrew/core/libxcb/blobs/sha256:59c243033b0a5515e65c81967116fb5852e8644f14b94dec3463140ecc6a2502
################################################################################################################################### 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/libx11/manifests/1.8.7
################################################################################################################################### 100.0%
==> Fetching libx11
==> Downloading https://ghcr.io/v2/homebrew/core/libx11/blobs/sha256:0894f5a7c09c10a989dc12b792cff2f1d1ae7d1d49f7c8c559e79b9d911ca998
################################################################################################################################### 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/libxext/manifests/1.3.6
################################################################################################################################### 100.0%
==> Fetching libxext
==> Downloading https://ghcr.io/v2/homebrew/core/libxext/blobs/sha256:50a9b29c594f9b93690466d66b52f2ac36461d956016b135a85d3dfbc883e336
################################################################################################################################### 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/libxrender/manifests/0.9.11
################################################################################################################################### 100.0%
==> Fetching libxrender
==> Downloading https://ghcr.io/v2/homebrew/core/libxrender/blobs/sha256:387261107110957df83504ec68c9328d84b3ce5a1f2a8e01f7d8f9112d8372ad
################################################################################################################################### 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/lzo/manifests/2.10
################################################################################################################################### 100.0%
==> Fetching lzo
==> Downloading https://ghcr.io/v2/homebrew/core/lzo/blobs/sha256:167749edd2052e4c577f27c79a41eb1cb4b79302b1e4bef1e4cfb29bd50aedd9
################################################################################################################################### 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/pixman/manifests/0.42.2-1
################################################################################################################################### 100.0%
==> Fetching pixman
==> Downloading https://ghcr.io/v2/homebrew/core/pixman/blobs/sha256:d355a294d3f9152479c2c0905efbeb329aef9cb27b9ae12e2a4ea6a4f41f2174
################################################################################################################################### 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/cairo/manifests/1.18.0
################################################################################################################################### 100.0%
==> Fetching cairo
==> Downloading https://ghcr.io/v2/homebrew/core/cairo/blobs/sha256:06c6aaadeca8f79c27867c56b8bb90fa9a7d00f84862cee7c837b611ffb8dbbc
################################################################################################################################### 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/graphite2/manifests/1.3.14
################################################################################################################################### 100.0%
==> Fetching graphite2
==> Downloading https://ghcr.io/v2/homebrew/core/graphite2/blobs/sha256:4cdee055db9958e12662c53661fab627057d3553974d15b289e2955b439f4a9d
################################################################################################################################### 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/icu4c/manifests/74.2
################################################################################################################################### 100.0%
==> Fetching icu4c
==> Downloading https://ghcr.io/v2/homebrew/core/icu4c/blobs/sha256:3facc22a7821e01d93a38e371e377f13275299d518929222ed34c77a4f4a65d3
################################################################################################################################### 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/harfbuzz/manifests/8.3.0_1
################################################################################################################################### 100.0%
==> Fetching harfbuzz
==> Downloading https://ghcr.io/v2/homebrew/core/harfbuzz/blobs/sha256:0e769ab84fe5ac3263691fd4c6210b9c03754291e554f25d4ac2b18352c3d33a
################################################################################################################################### 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/jpeg-turbo/manifests/3.0.1
################################################################################################################################### 100.0%
==> Fetching jpeg-turbo
==> Downloading https://ghcr.io/v2/homebrew/core/jpeg-turbo/blobs/sha256:89b1342d1dd69be94c1e293c8fc0ec5d324cd62f42bc8c3e9049bf5452957e01
################################################################################################################################### 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/lz4/manifests/1.9.4
################################################################################################################################### 100.0%
==> Fetching lz4
==> Downloading https://ghcr.io/v2/homebrew/core/lz4/blobs/sha256:5a8b7116d978e403c525e61794c60b43480d0afc83e499a763f7f14641bbc9b1
################################################################################################################################### 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/zstd/manifests/1.5.5-1
################################################################################################################################### 100.0%
==> Fetching zstd
==> Downloading https://ghcr.io/v2/homebrew/core/zstd/blobs/sha256:4712aabcc9f2710c0de2597aa9675ba95cd81fb59e27e8973b09a6ca5eabc2e6
################################################################################################################################### 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/libtiff/manifests/4.6.0
################################################################################################################################### 100.0%
==> Fetching libtiff
==> Downloading https://ghcr.io/v2/homebrew/core/libtiff/blobs/sha256:a9cafbce08b697fb25e326ea1dd3a0e01c3acc3f8f616e844940e49b33386ab3
################################################################################################################################### 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/little-cms2/manifests/2.16
################################################################################################################################### 100.0%
==> Fetching little-cms2
==> Downloading https://ghcr.io/v2/homebrew/core/little-cms2/blobs/sha256:d1ed5796de3f00d4b1301e9062cb54b2337c8e8dcf2ae9be8e03f3ed7af791e0
################################################################################################################################### 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/openjdk/17/manifests/17.0.10
################################################################################################################################### 100.0%
==> Fetching openjdk@17
==> Downloading https://ghcr.io/v2/homebrew/core/openjdk/17/blobs/sha256:0a5a6b5abdecc42b5fa0260bb4532c08258e573a78e2b392922c7d7bb0087e67
################################################################################################################################### 100.0%
==> Fetching sonarqube
==> Downloading https://ghcr.io/v2/homebrew/core/sonarqube/blobs/sha256:94434460f96aeaae2cff93aff9b7519801a79bceab598acc33eed9914792e98d
################################################################################################################################### 100.0%
==> Installing dependencies for sonarqube: giflib, libpng, freetype, fontconfig, pcre2, glib, xorgproto, libxau, libxdmcp, libxcb, libx11, libxext, libxrender, lzo, pixman, cairo, graphite2, icu4c, harfbuzz, jpeg-turbo, lz4, zstd, libtiff, little-cms2 and openjdk@17
==> Installing sonarqube dependency: giflib
==> Downloading https://ghcr.io/v2/homebrew/core/giflib/manifests/5.2.1
Already downloaded: /Users/stevesinchak/Library/Caches/Homebrew/downloads/51910e68b838a5c62c91c9352172d516e77a3c3c1a59a2cebaffc3f64f46adf4--giflib-5.2.1.bottle_manifest.json
==> Pouring giflib--5.2.1.arm64_sonoma.bottle.tar.gz
🍺 /opt/homebrew/Cellar/giflib/5.2.1: 19 files, 540KB
==> Installing sonarqube dependency: libpng
==> Downloading https://ghcr.io/v2/homebrew/core/libpng/manifests/1.6.43
Already downloaded: /Users/stevesinchak/Library/Caches/Homebrew/downloads/dd618b09b8d6d4b89203b771528951e5309631cc3afd8dc1236f0e98965f2b67--libpng-1.6.43.bottle_manifest.json
==> Pouring libpng--1.6.43.arm64_sonoma.bottle.tar.gz
🍺 /opt/homebrew/Cellar/libpng/1.6.43: 27 files, 1.3MB
==> Installing sonarqube dependency: freetype
==> Downloading https://ghcr.io/v2/homebrew/core/freetype/manifests/2.13.2-1
Already downloaded: /Users/stevesinchak/Library/Caches/Homebrew/downloads/8d6ca45fa8766fb544a5e6dbc76f0a68568656ab4fe1e837704491bb24e3035d--freetype-2.13.2-1.bottle_manifest.json
==> Pouring freetype--2.13.2.arm64_sonoma.bottle.1.tar.gz
🍺 /opt/homebrew/Cellar/freetype/2.13.2: 67 files, 2.4MB
==> Installing sonarqube dependency: fontconfig
==> Downloading https://ghcr.io/v2/homebrew/core/fontconfig/manifests/2.15.0
Already downloaded: /Users/stevesinchak/Library/Caches/Homebrew/downloads/33d176010dc9a105404ed23b6c0f8b853bf3a2df2e274876d412d7229a643320--fontconfig-2.15.0.bottle_manifest.json
==> Pouring fontconfig--2.15.0.arm64_sonoma.bottle.tar.gz
==> Regenerating font cache, this may take a while
==> /opt/homebrew/Cellar/fontconfig/2.15.0/bin/fc-cache -frv
🍺 /opt/homebrew/Cellar/fontconfig/2.15.0: 90 files, 2.4MB
==> Installing sonarqube dependency: pcre2
==> Downloading https://ghcr.io/v2/homebrew/core/pcre2/manifests/10.43
Already downloaded: /Users/stevesinchak/Library/Caches/Homebrew/downloads/4c12870adcfbf27eeeae4f44a420311ca3449f06a2fd8f6fcfe3d13db18087b4--pcre2-10.43.bottle_manifest.json
==> Pouring pcre2--10.43.arm64_sonoma.bottle.tar.gz
🍺 /opt/homebrew/Cellar/pcre2/10.43: 234 files, 6.3MB
==> Installing sonarqube dependency: glib
==> Downloading https://ghcr.io/v2/homebrew/core/glib/manifests/2.78.4
Already downloaded: /Users/stevesinchak/Library/Caches/Homebrew/downloads/aef5bf088596f6a37eb7ae224416357a2769019fea7a8a82896a6065e374f754--glib-2.78.4.bottle_manifest.json
==> Pouring glib--2.78.4.arm64_sonoma.bottle.tar.gz
🍺 /opt/homebrew/Cellar/glib/2.78.4: 456 files, 22.5MB
==> Installing sonarqube dependency: xorgproto
==> Downloading https://ghcr.io/v2/homebrew/core/xorgproto/manifests/2023.2
Already downloaded: /Users/stevesinchak/Library/Caches/Homebrew/downloads/8740825bd79ba6441c86fb430f955cb3d08f4693dd2947fe877c11c7c8122343--xorgproto-2023.2.bottle_manifest.json
==> Pouring xorgproto--2023.2.arm64_sonoma.bottle.tar.gz
🍺 /opt/homebrew/Cellar/xorgproto/2023.2: 267 files, 3.9MB
==> Installing sonarqube dependency: libxau
==> Downloading https://ghcr.io/v2/homebrew/core/libxau/manifests/1.0.11
Already downloaded: /Users/stevesinchak/Library/Caches/Homebrew/downloads/7faff26297b2e07682655beaa529cff7b3de0ad1abc013863ca3d03602b79ee7--libxau-1.0.11.bottle_manifest.json
==> Pouring libxau--1.0.11.arm64_sonoma.bottle.tar.gz
🍺 /opt/homebrew/Cellar/libxau/1.0.11: 21 files, 123.5KB
==> Installing sonarqube dependency: libxdmcp
==> Downloading https://ghcr.io/v2/homebrew/core/libxdmcp/manifests/1.1.5
Already downloaded: /Users/stevesinchak/Library/Caches/Homebrew/downloads/8713e53f73d0be64780dbea522b0ee07027e6cc7828ff1a4fa0a6596f14cfe25--libxdmcp-1.1.5.bottle_manifest.json
==> Pouring libxdmcp--1.1.5.arm64_sonoma.bottle.tar.gz
🍺 /opt/homebrew/Cellar/libxdmcp/1.1.5: 11 files, 136.4KB
==> Installing sonarqube dependency: libxcb
==> Downloading https://ghcr.io/v2/homebrew/core/libxcb/manifests/1.16.1
Already downloaded: /Users/stevesinchak/Library/Caches/Homebrew/downloads/8770f5784e17b45567a2910cdf1ce0b535f85fc18cea509377ca1a6549ad6168--libxcb-1.16.1.bottle_manifest.json
==> Pouring libxcb--1.16.1.arm64_sonoma.bottle.tar.gz
🍺 /opt/homebrew/Cellar/libxcb/1.16.1: 2,462 files, 7.5MB
==> Installing sonarqube dependency: libx11
==> Downloading https://ghcr.io/v2/homebrew/core/libx11/manifests/1.8.7
Already downloaded: /Users/stevesinchak/Library/Caches/Homebrew/downloads/4d15c929e0532c9a908dcb7d562929ecc5dd3a0a0cd4c19cf50683c06282fd7f--libx11-1.8.7.bottle_manifest.json
==> Pouring libx11--1.8.7.arm64_sonoma.bottle.tar.gz
🍺 /opt/homebrew/Cellar/libx11/1.8.7: 1,042 files, 7.0MB
==> Installing sonarqube dependency: libxext
==> Downloading https://ghcr.io/v2/homebrew/core/libxext/manifests/1.3.6
Already downloaded: /Users/stevesinchak/Library/Caches/Homebrew/downloads/fedb843acbfcf682fb451396914bfc096f9ea2748376d4c43ce2af7ce1b766b7--libxext-1.3.6.bottle_manifest.json
==> Pouring libxext--1.3.6.arm64_sonoma.bottle.tar.gz
🍺 /opt/homebrew/Cellar/libxext/1.3.6: 87 files, 450.9KB
==> Installing sonarqube dependency: libxrender
==> Downloading https://ghcr.io/v2/homebrew/core/libxrender/manifests/0.9.11
Already downloaded: /Users/stevesinchak/Library/Caches/Homebrew/downloads/134c11be8346a1b116e04983c2da6366f29c4f4c2abc17604dcdb80d0475ae9d--libxrender-0.9.11.bottle_manifest.json
==> Pouring libxrender--0.9.11.arm64_sonoma.bottle.tar.gz
🍺 /opt/homebrew/Cellar/libxrender/0.9.11: 12 files, 214.2KB
==> Installing sonarqube dependency: lzo
==> Downloading https://ghcr.io/v2/homebrew/core/lzo/manifests/2.10
Already downloaded: /Users/stevesinchak/Library/Caches/Homebrew/downloads/d4aa5b0c239912c53bc857d1012c6b7feb4acb509618f5e100f95bf8521f08e7--lzo-2.10.bottle_manifest.json
==> Pouring lzo--2.10.arm64_sonoma.bottle.tar.gz
🍺 /opt/homebrew/Cellar/lzo/2.10: 31 files, 565.5KB
==> Installing sonarqube dependency: pixman
==> Downloading https://ghcr.io/v2/homebrew/core/pixman/manifests/0.42.2-1
Already downloaded: /Users/stevesinchak/Library/Caches/Homebrew/downloads/2b0d8f2c63712ce503fa54309b732051a7ca5cd31bd561aa4aaba331bf26bcef--pixman-0.42.2-1.bottle_manifest.json
==> Pouring pixman--0.42.2.arm64_sonoma.bottle.1.tar.gz
🍺 /opt/homebrew/Cellar/pixman/0.42.2: 11 files, 1.3MB
==> Installing sonarqube dependency: cairo
==> Downloading https://ghcr.io/v2/homebrew/core/cairo/manifests/1.18.0
Already downloaded: /Users/stevesinchak/Library/Caches/Homebrew/downloads/1b8b7f19e38cb0e029497dfe0ad3f3557f605025c5575bdfe86c17b889c6e6d1--cairo-1.18.0.bottle_manifest.json
==> Pouring cairo--1.18.0.arm64_sonoma.bottle.tar.gz
🍺 /opt/homebrew/Cellar/cairo/1.18.0: 52 files, 2.2MB
==> Installing sonarqube dependency: graphite2
==> Downloading https://ghcr.io/v2/homebrew/core/graphite2/manifests/1.3.14
Already downloaded: /Users/stevesinchak/Library/Caches/Homebrew/downloads/bbb4dd2ef1846301d1eb08053e19e11ca9c780f93f4d3b2d638fd94a9bf54a0c--graphite2-1.3.14.bottle_manifest.json
==> Pouring graphite2--1.3.14.arm64_sonoma.bottle.tar.gz
🍺 /opt/homebrew/Cellar/graphite2/1.3.14: 18 files, 281.9KB
==> Installing sonarqube dependency: icu4c
==> Downloading https://ghcr.io/v2/homebrew/core/icu4c/manifests/74.2
Already downloaded: /Users/stevesinchak/Library/Caches/Homebrew/downloads/3e5230e726e5548db28bc0cf75710d6405903b742f941113d3dbe7483fad72a4--icu4c-74.2.bottle_manifest.json
==> Pouring icu4c--74.2.arm64_sonoma.bottle.tar.gz
🍺 /opt/homebrew/Cellar/icu4c/74.2: 270 files, 77.9MB
==> Installing sonarqube dependency: harfbuzz
==> Downloading https://ghcr.io/v2/homebrew/core/harfbuzz/manifests/8.3.0_1
Already downloaded: /Users/stevesinchak/Library/Caches/Homebrew/downloads/7d4da56c776328321b12bea7aeb54e250f01ac761171a71571a9376b13c3447e--harfbuzz-8.3.0_1.bottle_manifest.json
==> Pouring harfbuzz--8.3.0_1.arm64_sonoma.bottle.tar.gz
🍺 /opt/homebrew/Cellar/harfbuzz/8.3.0_1: 76 files, 9.5MB
==> Installing sonarqube dependency: jpeg-turbo
==> Downloading https://ghcr.io/v2/homebrew/core/jpeg-turbo/manifests/3.0.1
Already downloaded: /Users/stevesinchak/Library/Caches/Homebrew/downloads/abe7baf77a474e831f940214d72e8d72182373e6ea726884670f2d90f47525a7--jpeg-turbo-3.0.1.bottle_manifest.json
==> Pouring jpeg-turbo--3.0.1.arm64_sonoma.bottle.tar.gz
🍺 /opt/homebrew/Cellar/jpeg-turbo/3.0.1: 44 files, 3.4MB
==> Installing sonarqube dependency: lz4
==> Downloading https://ghcr.io/v2/homebrew/core/lz4/manifests/1.9.4
Already downloaded: /Users/stevesinchak/Library/Caches/Homebrew/downloads/379e59b981667f9585b33a2ff318769d8edca3ce6fd2e9a67ed291ae3e0cc872--lz4-1.9.4.bottle_manifest.json
==> Pouring lz4--1.9.4.arm64_sonoma.bottle.tar.gz
🍺 /opt/homebrew/Cellar/lz4/1.9.4: 22 files, 636.0KB
==> Installing sonarqube dependency: zstd
==> Downloading https://ghcr.io/v2/homebrew/core/zstd/manifests/1.5.5-1
Already downloaded: /Users/stevesinchak/Library/Caches/Homebrew/downloads/fc13698599720a53800064b40cddd854399651cf8760d9b0e46092f2e8da701a--zstd-1.5.5-1.bottle_manifest.json
==> Pouring zstd--1.5.5.arm64_sonoma.bottle.1.tar.gz
🍺 /opt/homebrew/Cellar/zstd/1.5.5: 31 files, 2MB
==> Installing sonarqube dependency: libtiff
==> Downloading https://ghcr.io/v2/homebrew/core/libtiff/manifests/4.6.0
Already downloaded: /Users/stevesinchak/Library/Caches/Homebrew/downloads/9c8455a2f6bcea7bf3e3461218fba309141b0b0553b6e1afc5fe64e63caccff3--libtiff-4.6.0.bottle_manifest.json
==> Pouring libtiff--4.6.0.arm64_sonoma.bottle.tar.gz
🍺 /opt/homebrew/Cellar/libtiff/4.6.0: 414 files, 6.7MB
==> Installing sonarqube dependency: little-cms2
==> Downloading https://ghcr.io/v2/homebrew/core/little-cms2/manifests/2.16
Already downloaded: /Users/stevesinchak/Library/Caches/Homebrew/downloads/c4e2b31b0daade62da1f3c2e57d69f74987bac35310011b87220145fa60b3558--little-cms2-2.16.bottle_manifest.json
==> Pouring little-cms2--2.16.arm64_sonoma.bottle.tar.gz
🍺 /opt/homebrew/Cellar/little-cms2/2.16: 22 files, 1.4MB
==> Installing sonarqube dependency: openjdk@17
==> Downloading https://ghcr.io/v2/homebrew/core/openjdk/17/manifests/17.0.10
Already downloaded: /Users/stevesinchak/Library/Caches/Homebrew/downloads/ee1df1b01e71fa292d43f615af961345d8643a607499c1beef7f2be586bb2f22--openjdk@17-17.0.10.bottle_manifest.json
==> Pouring [email protected]_sonoma.bottle.tar.gz
🍺 /opt/homebrew/Cellar/openjdk@17/17.0.10: 635 files, 304.9MB
==> Installing sonarqube
==> Pouring sonarqube--10.4.1.88267.arm64_sonoma.bottle.tar.gz
==> Caveats
Data: /opt/homebrew/var/sonarqube/data
Logs: /opt/homebrew/var/sonarqube/logs
Temp: /opt/homebrew/var/sonarqube/temp
To start sonarqube now and restart at login:
brew services start sonarqube
Or, if you don't want/need a background service you can just run:
/opt/homebrew/opt/sonarqube/bin/sonar console
==> Summary
🍺 /opt/homebrew/Cellar/sonarqube/10.4.1.88267: 313 files, 490.6MB
==> Running `brew cleanup sonarqube`...
Disable this behaviour by setting HOMEBREW_NO_INSTALL_CLEANUP.
Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).
==> `brew cleanup` has not been run in the last 30 days, running now...
Disable this behaviour by setting HOMEBREW_NO_INSTALL_CLEANUP.
Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).
Pruned 1 symbolic links and 2 directories from /opt/homebrew
==> Caveats
==> sonarqube
Data: /opt/homebrew/var/sonarqube/data
Logs: /opt/homebrew/var/sonarqube/logs
Temp: /opt/homebrew/var/sonarqube/temp
To start sonarqube now and restart at login:
brew services start sonarqube
Or, if you don't want/need a background service you can just run:
/opt/homebrew/opt/sonarqube/bin/sonar console
When completed, don't forget to run the command to install sonar-scanner
.
Setting Up the Server
You have two different options to run the Sonarqube server:
- Set up the server as a service so that it starts up every time you boot up your Mac.
- Run the server manually on-demand when you want to use it.
To install the Sonarqube server as a service run: brew services start sonarqube
Alternatively, run this command to start up the Sonarqube server on-demand: /opt/homebrew/opt/sonarqube/bin/sonar console
CAUTION: No matter which option you choose, you must wait a long time for Sonarqube to start for the first time. It can take several minutes for the server to start up and begin listening and responding to HTTP traffic on port 9000. I wasted a lot of time reviewing logs, changing dependency versions, and removing & re-installing simply because I was not expecting such as long delay (with low CPU usage) on the initial startup.
Once you are ready, open up your browser and head over to http://localhost:9000 to give the server console a try. If the page doesn't load, just wait longer per my note above.
When the login prompt is displayed, login with the default admin
user and admin
as the password. You will be prompted to change the password to something else immediately.
After login, you will be taken to the "How do you want to create your project?" screen. While you can import a project from one of the listed devops platforms, for this guide about local static analysis, we will select Create a local project
.
Type in a name for your project, the project key will be generated for you automatically but you can customize it to your preference. When finished, hit Next
.
In most cases, you will want to select Use the global setting
and then hit Create project
.
On the Analysis Method screen, select Locally
as we are going to use Sonar-Scanner to scan a local folder. Don't worry, this folder can and usually is a local cloned repo which works great.
Click the Generate
button to create a token for your project.
Next, click Continue
.
Under "Run analysis on your project," select Other
to cover most cases of local code scanning, and then select macOS
.
In the "Execute the Scanner" section, click on the Copy
button to copy the entire command to your clipboard that we will use in the next section of this guide.
Running Sonar-Scanner
Open up Terminal, and cd
over to the root of your project folder you want to analyze.
Paste in the sonar-scanner command you copied from the previous section and hit return.
stevesinchak@tweaks tweaks11ty % sonar-scanner \
-Dsonar.projectKey=First-Project \
-Dsonar.sources=. \
-Dsonar.host.url=http://localhost:9000 \
-Dsonar.token=sqp_e16f22c5d1b9aaf2d50c37a6b2c00c75b339df72
INFO: Scanner configuration file: /opt/homebrew/Cellar/sonar-scanner/5.0.1.3006/libexec/conf/sonar-scanner.properties
INFO: Project root configuration file: NONE
INFO: SonarScanner 5.0.1.3006
INFO: Java 21.0.2 Homebrew (64-bit)
INFO: Mac OS X 14.2.1 aarch64
INFO: User cache: /Users/stevesinchak/.sonar/cache
INFO: Analyzing on SonarQube server 10.4.1.88267
INFO: Default locale: "en_US", source code encoding: "UTF-8" (analysis is platform dependent)
INFO: Load global settings
INFO: Load global settings (done) | time=35ms
INFO: Server id: 147B411E-AY4Ln7QRODV-Lck6PYKu
INFO: User cache: /Users/stevesinchak/.sonar/cache
WARN: sonar.plugins.downloadOnlyRequired is false, so ALL available plugins will be downloaded
INFO: Loading all plugins
INFO: Load plugins index
INFO: Load plugins index (done) | time=25ms
INFO: Load/download plugins
INFO: Load/download plugins (done) | time=904ms
INFO: Process project properties
INFO: Process project properties (done) | time=3ms
INFO: Execute project builders
INFO: Execute project builders (done) | time=0ms
INFO: Project key: First-Project
INFO: Base dir: /Volumes/External/Dev/tweaks11ty
INFO: Working dir: /Volumes/External/Dev/tweaks11ty/.scannerwork
INFO: Load project settings for component key: 'First-Project'
INFO: Load project settings for component key: 'First-Project' (done) | time=8ms
INFO: Load quality profiles
INFO: Load quality profiles (done) | time=58ms
INFO: Load active rules
INFO: Load active rules (done) | time=3043ms
INFO: Load analysis cache
INFO: Load analysis cache (404) | time=7ms
INFO: Preprocessing files...
INFO:
INFO: 7 languages detected in 6867 preprocessed files
INFO: 2699 files ignored because of scm ignore settings
INFO: Load project repositories
INFO: Load project repositories (done) | time=10ms
INFO: Indexing files...
INFO: Project configuration:
INFO: 4191 files indexed
INFO: Quality profile for css: Sonar way
INFO: Quality profile for js: Sonar way
INFO: Quality profile for json: Sonar way
INFO: Quality profile for py: Sonar way
INFO: Quality profile for web: Sonar way
INFO: Quality profile for xml: Sonar way
INFO: ------------- Run sensors on module First-Project
INFO: Load metrics repository
INFO: Load metrics repository (done) | time=9ms
INFO: Sensor Python Sensor [python]
WARN: Your code is analyzed as compatible with all Python 3 versions by default. You can get a more precise analysis by setting the exact Python version in your configuration via the parameter "sonar.python.version"
INFO: Starting global symbols computation
INFO: 3 source files to be analyzed
INFO: 3/3 source files have been analyzed
INFO: Starting rules execution
INFO: 3 source files to be analyzed
INFO: 3/3 source files have been analyzed
INFO: The Python analyzer was able to leverage cached data from previous analyses for 0 out of 3 files. These files were not parsed.
INFO: Sensor Python Sensor [python] (done) | time=480ms
INFO: Sensor Cobertura Sensor for Python coverage [python]
INFO: Sensor Cobertura Sensor for Python coverage [python] (done) | time=142ms
INFO: Sensor PythonXUnitSensor [python]
INFO: Sensor PythonXUnitSensor [python] (done) | time=115ms
INFO: Sensor JaCoCo XML Report Importer [jacoco]
INFO: '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
INFO: No report imported, no coverage information will be imported by JaCoCo XML Report Importer
INFO: Sensor JaCoCo XML Report Importer [jacoco] (done) | time=1ms
INFO: Sensor IaC CloudFormation Sensor [iac]
INFO: 0 source files to be analyzed
INFO: 0/0 source files have been analyzed
INFO: Sensor IaC CloudFormation Sensor [iac] (done) | time=158ms
INFO: Sensor IaC AzureResourceManager Sensor [iac]
INFO: 0 source files to be analyzed
INFO: 0/0 source files have been analyzed
INFO: Sensor IaC AzureResourceManager Sensor [iac] (done) | time=58ms
INFO: Sensor JavaScript/TypeScript analysis [javascript]
INFO: Detected os: Mac OS X arch: aarch64 alpine: false. Platform: DARWIN_ARM64
INFO: Using embedded Node.js runtime
INFO: Using Node.js executable: '/Users/stevesinchak/.sonar/js/node-runtime/node'.
INFO: Memory configuration: OS (32768 MB), Node.js (4144 MB).
INFO: Found 0 tsconfig.json file(s): []
INFO: Creating TypeScript program
INFO: TypeScript configuration file /var/folders/fd/pphd6p_11rs88rtkys6v746c0000gn/T/tmp-29512-Ono6skX9paJN
INFO: 7 source files to be analyzed
INFO: Creating TypeScript program (done) | time=392ms
INFO: Starting analysis with current program
INFO: Analyzed 7 file(s) with current program
INFO: 7/7 source files have been analyzed
INFO: Hit the cache for 0 out of 7
INFO: Miss the cache for 7 out of 7: ANALYSIS_MODE_INELIGIBLE [7/7]
INFO: Sensor JavaScript/TypeScript analysis [javascript] (done) | time=7265ms
INFO: Sensor JavaScript inside HTML analysis [javascript]
INFO: 63 source files to be analyzed
ERROR: Failed to parse file [node_modules/hamljs/test/fixtures/filter.cdata.whitespace.html] at line 1: Unexpected token (1:8)
ERROR: Failed to parse file [node_modules/hamljs/test/fixtures/filter.cdata.html] at line 1: Unexpected token (1:8)
INFO: 63/63 source files have been analyzed
INFO: Hit the cache for 0 out of 63
INFO: Miss the cache for 63 out of 63: ANALYSIS_MODE_INELIGIBLE [63/63]
INFO: Sensor JavaScript inside HTML analysis [javascript] (done) | time=1168ms
INFO: Sensor CSS Rules [javascript]
INFO: 64 source files to be analyzed
INFO: 64/64 source files have been analyzed
INFO: Hit the cache for 0 out of 0
INFO: Miss the cache for 0 out of 0
INFO: Sensor CSS Rules [javascript] (done) | time=297ms
INFO: Sensor CSS Metrics [javascript]
INFO: Sensor CSS Metrics [javascript] (done) | time=1054ms
INFO: Sensor C# Project Type Information [csharp]
INFO: Sensor C# Project Type Information [csharp] (done) | time=9ms
INFO: Sensor C# Analysis Log [csharp]
INFO: Sensor C# Analysis Log [csharp] (done) | time=16ms
INFO: Sensor C# Properties [csharp]
INFO: Sensor C# Properties [csharp] (done) | time=0ms
INFO: Sensor HTML [web]
INFO: Sensor HTML [web] (done) | time=602ms
INFO: Sensor XML Sensor [xml]
INFO: 3 source files to be analyzed
INFO: 3/3 source files have been analyzed
INFO: Sensor XML Sensor [xml] (done) | time=55ms
INFO: Sensor TextAndSecretsSensor [text]
INFO: 448 source files to be analyzed
INFO: 448/448 source files have been analyzed
INFO: Sensor TextAndSecretsSensor [text] (done) | time=3577ms
INFO: Sensor VB.NET Project Type Information [vbnet]
INFO: Sensor VB.NET Project Type Information [vbnet] (done) | time=2ms
INFO: Sensor VB.NET Analysis Log [vbnet]
INFO: Sensor VB.NET Analysis Log [vbnet] (done) | time=5ms
INFO: Sensor VB.NET Properties [vbnet]
INFO: Sensor VB.NET Properties [vbnet] (done) | time=0ms
INFO: Sensor IaC Docker Sensor [iac]
INFO: 0 source files to be analyzed
INFO: 0/0 source files have been analyzed
INFO: Sensor IaC Docker Sensor [iac] (done) | time=16ms
INFO: ------------- Run sensors on project
INFO: Sensor Analysis Warnings import [csharp]
INFO: Sensor Analysis Warnings import [csharp] (done) | time=0ms
INFO: Sensor Zero Coverage Sensor
INFO: Sensor Zero Coverage Sensor (done) | time=865ms
INFO: SCM Publisher SCM provider for this project is: git
INFO: SCM Publisher 79 source files to be analyzed
INFO: SCM Publisher 78/79 source files have been analyzed (done) | time=885ms
WARN: Missing blame information for the following files:
WARN: * src/assets/theme.css
WARN: This may lead to missing/broken features in SonarQube
INFO: CPD Executor 62 files had no CPD blocks
INFO: CPD Executor Calculating CPD for 11 files
INFO: CPD Executor CPD calculation finished (done) | time=5ms
INFO: Analysis report generated in 51ms, dir size=490.3 kB
INFO: Analysis report compressed in 518ms, zip size=191.3 kB
INFO: Analysis report uploaded in 21ms
INFO: ANALYSIS SUCCESSFUL, you can find the results at: http://localhost:9000/dashboard?id=First-Project
INFO: Note that you will be able to access the updated dashboard once the server has processed the submitted analysis report
INFO: More about the report processing at http://localhost:9000/api/ce/task?id=800f4a0d-e5c7-4659-8d85-e5b346f33eae
INFO: Analysis total time: 59.780 s
INFO: ------------------------------------------------------------------------
INFO: EXECUTION SUCCESS
INFO: ------------------------------------------------------------------------
INFO: Total time: 1:01.395s
INFO: Final Memory: 36M/148M
INFO: ------------------------------------------------------------------------
Reviewing the output log, you can see the analysis of my project took just about a minute. The report is automatically uploaded to the server where it is processed. On the "ANALYSIS SUCCESSFUL" line of the output, you will find a link directly to the report.
Viewing Results in Sonarqube
It's time to go back over to the Sonarqube server web interface to view the results of the scan and see what "opportunities" we have to improve our code. Head over to the URL displayed in the sonar-scanner output, in my case it is http://localhost:9000/dashboard?id=First-Project
.
I like to jump to Security issues first. Head over there by clicking on the number of open issues (in my case, the number 3).
Uh oh, looks like I have some saved creds in my code! To view the details, click on the title of the issue.
The detailed issue view will show you the exact lines of code that have the problem. In my case, a connection string with a database password in clear text.
Hit back and let's explore a different category such as Intentionality under Clean Code Attribute. Here you can see a "Code Smell" issue where I didn't follow the best practice and properly declare the variable in this Javascript file. This code runs fine since Javascript is an incredibly forgiving language, but it is not quality code, you could say it smells.
Again, click on the title to view the detailed results and you can see my naked variable.
If you have any questions about an issue, click on the "Why is this an issue?" tab for a detailed example of what is wrong and what is the right way to do it. Here is a good example of a bug in my Javascript code and the explanation.
If you want to understand who is to blame for an issue, click on the "Activity" tab and it will show who and when the change was made that introduced the issue.
What a nice Christmas Eve present to myself!
How to stop Sonarqube from running in the background
If you set up Sonarqube to run as a service, you may want to consider stopping the service when you are not using it as it will eat up over 1GB of RAM with the various Java processes.
To stop the service, run the following at terminal: brew services stop sonarqube
Final Thoughts
While we only covered a tiny portion of Sonarqube in this article, I encourage you to explore the interface and play around with the advanced features to learn and grow. When viewing issues, always make sure to visit the "Why is this an issue?" tab to validate and learn. While static code analysis does not catch everything, and sometimes it can even make mistakes, it is without a doubt a valuable tool to help you write better and more robust code.