DockerのSonarQubeでTypeScriptの静的解析をローカル環境で行ったメモ

## 概要
SonarQubeを使ってTypeScriptをローカルで静的解析してみた。
[Windows上でDocker越しSonarQubeを起動して、ローカルソースをコード検証する][*1]の手順を基本的に踏襲する

[ソースコード](https://github.com/hibohiboo/Yakumi/blob/03cb53a32d0d8cb2f362a61699e08c2e9ee972b2/docs/sonarQube/docker-compose.yml)


## 環境
* Windows 11 Home `23H2 22631.3737 `
* Docker Desktop `Docker version 26.1.1, build 4cf5afa `

コードの構造

```
- app
  + src
- sonar-project.properties
- docs
  - sonarQube
    - docker-compose.yml
    - bin
      - .env
      - up.sh
      - cli.sh 
    + reports
```

## ソースコード
`postgresql:16`を利用している。
[参考](https://github.com/SonarSource/docker-sonarqube/blob/master/example-compose-files/sq-with-postgres/docker-compose.yml)の通りにしたら、`postgresql  | 2024-06-17 16:40:12.168 UTC [40] FATAL:  role "root" does not exist `のエラーがでるのでUオプションでユーザ名を指定している。

- version3.9未満の場合、depeneds_onを配列にすると動く

<details> <div>

[参考:eccube4がdocker-composeで立ち上がらない【services.ec-cube.depends_on contains an invalid type, it should be an array】とか出る](https://qiita.com/hatobeam75/items/d421411b89f9037def38)

```diff
- version: '3.9'
+ version: '3'

    depends_on:
-      sonarqube_db:
-        condition: service_healthy
+      - sonarqube_db
```

</div></details>


```yml:docs/sonarQube/docker-compose.yml
version: '3.9'
services:
  sonarqube:
    image: sonarqube:community
    hostname: sonarqube
    container_name: sonarqube
    depends_on:
      sonarqube_db:
        condition: service_healthy
    environment:
      SONAR_JDBC_URL: jdbc:postgresql://sonarqube_db:5432/sonar
      SONAR_JDBC_USERNAME: sonar
      SONAR_JDBC_PASSWORD: sonar
    volumes:
      - sonarqube_data:/opt/sonarqube/data
      - sonarqube_extensions:/opt/sonarqube/extensions
      - sonarqube_logs:/opt/sonarqube/logs
    ports:
      - "9000:9000"
  sonarqube_db:
    image: postgres:16
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U sonar"]
      interval: 10s
      timeout: 5s
      retries: 5
    hostname: postgresql
    container_name: postgresql
    environment:
      POSTGRES_USER: sonar
      POSTGRES_PASSWORD: sonar
      POSTGRES_DB: sonar
    volumes:
      - sonarqube_postgresql:/var/lib/postgresql
      - sonarqube_postgresql_data:/var/lib/postgresql/data

volumes:
  sonarqube_data:
  sonarqube_extensions:
  sonarqube_logs:
  sonarqube_postgresql:
  sonarqube_postgresql_data:
```

`docker-compose up`で起動すると http://localhost:9000 に立ち上がるので、手順に沿ってプロジェクトを作成したら環境変数を埋める。`Yakumi`プロジェクトを作成した。

```.env
SONAR_TOKEN=sqp_mytoken
SONAR_PASS=hoge
```

```sonar-project.properties
sonar.projectKey=Yakumi
sonar.sources=app/src
sonar.tests=app/tests
sonar.sourceEncoding=UTF-8
```

[参考にしている手順][*1]と異なる点として、cliもdockerで動かしている。なお、HOST_URLは`host.docker.internal`でローカルホストを指している。



```bash:docs/sonarQube/bin/cli.sh
#!/bin/bash

bin_dir=$(cd $(dirname $0) && pwd)
parent_dir=$(cd $bin_dir/.. && pwd)
work_dir=$(cd $bin_dir/../../.. && pwd)

source $bin_dir/.env
cd $work_dir

docker run \
    --rm \
     -v sonar_cache:/opt/sonar-scanner/.sonar/cache \
    -e SONAR_HOST_URL="http://host.docker.internal:9000/"  \
    -e SONAR_TOKEN="$SONAR_TOKEN" \
    -v ".:/usr/src" \
    sonarsource/sonar-scanner-cli

cd $parent_dir && curl -s -u admin:$SONAR_PASS -G -d "component=Yakumi" -d "metricKeys=cognitive_complexity" http://localhost:9000/api/measures/component_tree | jq '.baseComponent' > ./reports/cognitiveComplexity.json

```

<details><summary>wsl版dockerの場合はhost.docker.internalを使うために追加の設定が必要</summary><div>

```diff
#!/bin/bash

bin_dir=$(cd $(dirname $0) && pwd)
parent_dir=$(cd $bin_dir/.. && pwd)
work_dir=$(cd $bin_dir/../../.. && pwd)

source $bin_dir/.env
cd $work_dir

docker run \
    --rm \
     -v sonar_cache:/opt/sonar-scanner/.sonar/cache \
+   --add-host="host.docker.internal:host-gateway" \
    -e SONAR_HOST_URL="http://host.docker.internal:9000/"  \
    -e SONAR_TOKEN="$SONAR_TOKEN" \
    -v ".:/usr/src" \
    sonarsource/sonar-scanner-cli

cd $parent_dir && curl -s -u admin:$SONAR_PASS -G -d "component=Yakumi" -d "metricKeys=cognitive_complexity" http://localhost:9000/api/measures/component_tree | jq '.baseComponent' > ./reports/cognitiveComplexity.json

```

[参考: Dockerでコンテナ内のプロセスからホストのプロセスに接続する方法](https://qiita.com/silane1001/items/973f32e05defe254408c)

</div></details>

metricKeysについては[SonarQubeユーザーガイド - metrics_definition][*2]を参照

## 動作確認

静的解析の結果が表示された

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99876/cc8b2790-c7a3-c666-df77-526a5547333e.png)




## 参考
[Windows上でDocker越しSonarQubeを起動して、ローカルソースをコード検証する][*1]
[SonarQubeさんに怒られたら](https://qiita.com/gengen0719/items/d8f177d4b7809a10fa0c)
[SonarSource - docker-compose](https://github.com/SonarSource/docker-sonarqube/blob/master/example-compose-files/sq-with-postgres/docker-compose.yml)
[Docker - networking](https://docs.docker.com/desktop/networking/#use-cases-and-workarounds)
[sonarscanner-from-docker-image](https://docs.sonarsource.com/sonarqube/latest/analyzing-source-code/scanners/sonarscanner/#sonarscanner-from-docker-image)
[SonarQubeユーザーガイド - metrics_definition][*2]

[*1]:https://qiita.com/hoshimado/items/000df1b314e5759beb31
[*2]:https://docs.sonarsource.com/sonarqube/latest/user-guide/code-metrics/metrics-definition/