GitLab Merge Request + SonarQube:构建可量化的 .NET Core 代码评审体系
本文需要启动的服务如下:

因为sonar最新版本不支持扫描多分支,所以本次演示使用了最新版本和支持多分枝扫描的老旧版本,演示环境为windows的docker-desktop。
先安装一下gitlab,这里不推荐做挂载,在docker-desktop上会有文件读写的权限导致运行出问题。
docker run -d -p 443:443 -p 80:80 -p 222:22 ^ --hostname mygitlab.local --name gitlab --restart always ^ gitlab/gitlab-ce:18.5.0-ce.0
在本地的C:\Windows\System32\drivers\etc目录的hots下面提前配置一下域名,这是gitla安装需要的: 127.0.0.1 mygitlab.local
然后可以使用 mygitlab.local登录本地的git,默认的账号是root,密码看这里

还有一个gitlab.rb文件,跟初始密码是同一个目录下,配置一下下面的变量


也可以使用下面命令拷贝出来改完后再拷贝进去然后重启服务
docker cp gitlab:/etc/gitlab/gitlab.rb D:\work\docker/gitlab.rb 拷贝出来然后替换
docker cp D:\work\docker\gitlab.rb gitlab:/etc/gitlab/gitlab.rb
下面就是安装runner,首先拿到需要注入到runner中的token

下面就是启动服务的命令:
docker run -d --name gitlab-runner ^ --restart always ^ -v d:/dwz/docker-volume/gitlab-runner/config:/etc/gitlab-runner ^ -v /var/run/docker.sock:/var/run/docker.sock ^ gitlab/gitlab-runner:v13.2.4
然后需要注册一个runner,这里的registration-token就是gitlab拷贝出来的,url也是gitlab的地址
docker exec -it gitlab-runner gitlab-runner register -n ^ --url http://172.17.0.2 ^ --registration-token Tca8wkxwbjswexxtE_ij ^ --executor docker ^ --description "Docker Runner" ^ --docker-image "sonarsource/sonar-scanner-cli:latest"

以上就是完整的gitlab和ci/cd的搭建了。注意一下docker中默认使用的网关bridge,否则都要指定一下同一个,如果网关gateway:172.17.0.2不一致就需要各种网络假如等等操作,所以安装制定好就行。上面的有默认就不需要额外配置。
下面继续sonar安装:
services: postgres: image: postgres:13 container_name: postgres ports: - "15432:5432" volumes: - postgres_data:/var/lib/postgresql/data environment: POSTGRES_USER: sonar POSTGRES_PASSWORD: sonar POSTGRES_DB: sonar network_mode: bridge sonar: image: sonarqube:9.9-community container_name: sonar depends_on: - postgres ports: - "9000:9000" environment: SONARQUBE_JDBC_USERNAME: sonar SONARQUBE_JDBC_PASSWORD: sonar # 内部容器互访请用服务名:port(不要用容器 IP) SONARQUBE_JDBC_URL: jdbc:postgresql://postgres:5432/sonar volumes: - sonarqube_extensions:/opt/sonarqube/extensions - sonarqube_logs:/opt/sonarqube/logs - sonarqube_data:/opt/sonarqube/data - sonarqube_conf:/opt/sonarqube/conf network_mode: bridge volumes: postgres_data: sonarqube_extensions: sonarqube_logs: sonarqube_data: sonarqube_conf:
使用docker-compose 安装完后需要手动配置一下数据库相关,还是社区版的插件安装配置等。首先安装旧版本,最后再试试新版本。
第一个插件可以就可以将 sonarQube 的审查结果以评论的试发布到 gitlab 上面
https://github.com/javamachr/sonar-gitlab-plugin
第二个插件可以实现增强 sonarQube 多分支包括MR的代码检测
https://github.com/mc1arke/sonarqube-community-branch-plugin
第一个插件就固定一个最新的,第二个需要根据镜像版本来安装对应的插件和配置了。

docker cp "D:\work\docker\sonar-gitlab-plugin-5.4.0.jar" 67ccc284b64a:/opt/sonarqube/extensions/plugins/ (67ccc284b64a 是容器名)
docker cp "D:\work\docker\sonarqube-community-branch-plugin-25.9.0.jar" 67ccc284b64a:/opt/sonarqube/extensions/plugins/ (67ccc284b64a 是容器名)
下面需要拷贝一下配置文件然后改好覆盖进去:有五行改动,分别是数据库的配置,和第二个插件。如果配置不对或者插件版本不对都会导致服务启动不了。
docker cp 容器名:/opt/sonarqube/conf/sonar.properties "D:\work\docker\sonar.properties"
docker cp "D:\work\docker\sonar.properties" 容器名:/opt/sonarqube/conf/sonar.properties



sonar.jdbc.username=sonar sonar.jdbc.password=sonar sonar.jdbc.url=jdbc:postgresql://172.17.0.4:5432/sonar sonar.web.javaAdditionalOpts=-javaagent:./extensions/plugins/sonarqube-community-branch-plugin-1.14.0.jar=web sonar.ce.javaAdditionalOpts=-javaagent:./extensions/plugins/sonarqube-community-branch-plugin-1.14.0.jar=ce
可以看到我这个文件的插件是针对老版本sonarqube:9.9-community的配置,而拷贝插件命令是最新版本的sonarqube:community的配置,最新版最后说。
下面就可以通过9000端口进入sonar了, 默认账号密码admin,需要进入后改掉密码。
老版本比新版本多了这个分支管理功能


下面就是如何配置sonar和gitlab的交互了,这里不配置gitlab可以通过sonar继承登录 和分组权限功能,直接最高权限来做配置。




上面权限看着勾选,前面几个read少不了的。

点击创建项目会提示你输入gitlab的personal access token,然后选择要导入的项目到gitlab,然后就关联上项目了。
在gitlab配置一下sonar的回调地址和权限即可,否则sonar拿不到runner扫描的结果


下面就可以配置项目的cicd的yml文件




上面的第一步需要.NET,第二步就是需要在gitlab配置两个变量



这里都是按照sonar的步骤来创建SONAR_TOKEN变量和值,然后按照要求勾选Visibility,Flags。
下面截图的gitlab的配置地址是sonar新的对外的ip没改过来,实际是172.17.0.5



上面的SONAR_TOKEN这里的token来自

或者来自下面



以上配置都完成了,下面就是在gitlab的项目中创建一个.gitlab-ci.yml文件,这个文件可以从sonar刚才的配置中拷贝也可以自己写
image: mcr.microsoft.com/dotnet/sdk:8.0 variables: SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar" GIT_DEPTH: "0" JAVA_VERSION: "17" SONAR_PROJECT_KEY: "root_testsonar_AZqR29AXIQF2ktGMbFvi" SONAR_HOST_URL: "http://172.17.0.5:9000" workflow: rules: - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "main"' - if: '$CI_PIPELINE_SOURCE =~ /merge_request/' stages: - sonar sonar_scan: stage: sonar rules: - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "main"' - if: '$CI_PIPELINE_SOURCE =~ /merge_request/' before_script: - apt-get update && apt-get install -y --no-install-recommends openjdk-${JAVA_VERSION}-jdk - export JAVA_HOME=$(update-alternatives --query java | grep "Best" | awk '{print $5}' | sed 's/bin\/java//') - export PATH="$JAVA_HOME/bin:$PATH" - dotnet tool install --global dotnet-sonarscanner - export PATH="$PATH:$HOME/.dotnet/tools" - java -version - dotnet tool list -g - command -v dotnet-sonarscanner || true script: - | if [ -n "${CI_MERGE_REQUEST_IID}" ]; then # MR / Pull Request 分析 dotnet sonarscanner begin \ /k:"${SONAR_PROJECT_KEY}" \ /d:sonar.host.url="${SONAR_HOST_URL}" \ /d:sonar.token="${SONAR_TOKEN}" \ /d:sonar.pullrequest.key="${CI_MERGE_REQUEST_IID}" \ /d:sonar.pullrequest.branch="${CI_COMMIT_REF_NAME}" \ /d:sonar.pullrequest.base="${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}" \ /d:sonar.qualitygate.wait=true \ /d:sonar.projectBaseDir="${CI_PROJECT_DIR}" \ /d:sonar.exclusions="**/bin/**,**/obj/**,**/Properties/**" else # 普通分支(例如 main)分析 dotnet sonarscanner begin \ /k:"${SONAR_PROJECT_KEY}" \ /d:sonar.host.url="${SONAR_HOST_URL}" \ /d:sonar.token="${SONAR_TOKEN}" \ /d:sonar.branch.name="${CI_COMMIT_BRANCH}" \ /d:sonar.qualitygate.wait=true \ /d:sonar.projectBaseDir="${CI_PROJECT_DIR}" \ /d:sonar.exclusions="**/bin/**,**/obj/**,**/Properties/**" fi - dotnet build --configuration Release - dotnet sonarscanner end /d:sonar.token="${SONAR_TOKEN}" allow_failure: false cache: paths: - ${SONAR_USER_HOME} - $HOME/.dotnet/tools
sonarqube-check: image: mcr.microsoft.com/dotnet/core/sdk:latest variables: SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar" # Defines the location of the analysis task cache GIT_DEPTH: "0" # Tells git to fetch all the branches of the project, required by the analysis task cache: key: "${CI_JOB_NAME}" paths: - .sonar/cache script: - "apt-get update" - "apt-get install --yes openjdk-11-jre" - "dotnet tool install --global dotnet-sonarscanner" - "export PATH=\"$PATH:$HOME/.dotnet/tools\"" - "dotnet sonarscanner begin /k:\"root_testforsonar_AZpytHmBvMocvQWN9yIR\" /d:sonar.login=\"$SONAR_TOKEN\" /d:\"sonar.host.url=$SONAR_HOST_URL\" " - "dotnet build" - "dotnet sonarscanner end /d:sonar.login=\"$SONAR_TOKEN\"" allow_failure: true only: - main
以上都可以,经供参考
只有一点注意:


上面的这个SONAR_PROJECT_KEY来自于

然后提交和并请求(哪里触发代码审查可以根据yml文件配置写的来)会扫描代码,展示代码问题了

下面是最新的sonar的安装
docker exec -it postgres psql -U sonar -c "CREATE DATABASE sonar2;" docker run -d ^ --name sonar2 ^ --network bridge ^ -p 9001:9000 ^ -e SONARQUBE_JDBC_URL=jdbc:postgresql://postgres:5432/sonar2 ^ -e SONARQUBE_JDBC_USERNAME=sonar ^ -e SONARQUBE_JDBC_PASSWORD=sonar ^ -v sonarqube2_extensions:/opt/sonarqube/extensions ^ -v sonarqube2_logs:/opt/sonarqube/logs ^ -v sonarqube2_data:/opt/sonarqube/data ^ -v sonarqube2_conf:/opt/sonarqube/conf ^ sonarqube:community
最新版本的sonar没有分支管理功能,只能查看一个分支的扫描统计,gitlab评论展示功能不变,配置好对应版本插件就行。



浙公网安备 33010602011771号