前言
首次接触代码分析,源于公司对迭代规范流程的的试点。在迭代中,如何保证输出的代码是高质量的,或者说是没有明显缺陷的,这种高质如何量化,这就是接下来要介绍的: 静态代码分析。
代码分析的意义
降低风险
迭代中代码扫描分析,成为上线发版不可或缺的一环,代码分析能检测出代码中明显存在的问题,降低风险,比如:强制类型转换、内存泄漏、空指针……
提高代码质量
代码的质量水平,是直接影响系统稳定程度的原因之一,Code Review分为工具、人工两种,通过Code Review,可以量化代码质量,是否达到发版的质量标准,这里重点讲工具Code Review。
扫描环境搭建
1. 环境
- 版本控制工具:Git
- 源码语言版本:Swift 5、OC
- 开发工具:Xcode 11.3
- JDK:Jdk-1.8.0_221 JDK1.8地址
- 持续集成工具:Jenkins
- 质量管理工具:SonarQube(7.8 )
2. SonarQube的工具链
- 源码工程(Project):Swift、OC
- MySQL数据库(SonarQube Database):版本5.7.28-macos10.14-x86_643,存放配置信息和分析结果信息
- 服务器(SonarQube Server):iMac ,发布应用,在线浏览、配置分析;
- 客户端(SonarQube Scanner):版本4.2.0.1873,执行源代码分析。
注:Sonarqube-7.8 社区版 7.9版本以下支持MySQL(>=5.6<8)
3. 运行SonarQube
- 解压sonarqube-7.8.zip
- 修改sonarqube-7.8中conf文件夹下的sonar.properties
sonar.jdbc.url=jdbc:mysql://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&useConfigs=maxPerformance&useSSL=false
# mysql中创建的sonarQube用户
sonar.jdbc.username=root
# 创建用户对应的密码
sonar.jdbc.password=12345678
# 设置编码格式为UTF-8
sonar.sorceEncoding=UTF-8
# sonar登陆用户名
sonar.login=admin
# sonar登陆密码
sonar.password=admin
sonar安装成功
image.png- 开启SonarQube访问外部访问,修改sonarqube-7.8中conf文件夹下的sonar.properties文件,注释掉sonar.web.context=
-
开启apache httpd随机启动,提供外部访问
sudo launchctl load -w /System/Library/LaunchDaemons/org.apache.httpd.plist -
配置sonar开机自启,在sonarqube-7.8/bin/macosx-universal-64目录下新增 run sonar.sh文件,添加以下脚本
cd /usr/local/sonarqube-7.8/bin/macosx-universal-64
sh sonar.sh start
-
将run sonar.sh文件添加到iMac登录项中
image.png
自此SonarQube服务开机自启动、外部访问配置完毕
image.png
4. 安装插件
- sonar-swift-0.4.6
- xcpretty-0.3.0 (see instructions below)
-
SwiftLint-3.31.1 (HomeBrew installed and
brew install swiftlint
). Version 0.3.0 or above. -
Tailor-0.12.0_1 (HomeBrew installed and
brew install tailor
). Version 0.11.1 or above. -
slather-2.4.7 (
gem install slather
). Version 2.1.0 or above (2.4 since Xcode 8.3). -
lizard (PIP installed and
sudo pip install lizard
) - OCLint-0.13.1 installed. Version 0.11.0 recommended (0.13.0 since Xcode 9).
- Faux Pas command line tools installed (optional)
5. 插件配置
-
从已下载的sonar-swift-0.4.6中,拷贝backelite-sonar-swift-plugin-0.4.6.jar文件到sonarqube-7.8/extensions/plugins里
-
下载run-sonar-swift.sh文夹拷贝到swift项目的根目录下(与projext.xcodeproj 同级)
-
下载sonar-project.properties文件拷贝到swift项目的根目录下(与projext.xcodeproj 同级)
- 编辑sonar-project.properties文件,根据swift项目修改其中的参数
#
# Swift SonarQube Plugin - Enables analysis of Swift and Objective-C projects into SonarQube.
# Copyright © 2015 Backelite (${email})
#
##########################
# Required configuration #
##########################
# 项目key, 与sonar中项目key一致
sonar.projectKey=xxx
# 项目 name
sonar.projectName=xxx
# 版本号
sonar.projectVersion=2.3.0
# Encoding of the source code
sonar.sourceEncoding=UTF-8
# 语言 ObjC / Swift
sonar.language=swift
# swift 源文件路径
sonar.sources=Project/Clasess
# 过滤文件、目录
sonar.test.inclusions=**/*Test*/**
sonar.test.inclusions=*.swift
sonar.exclusions=Project/Clasess/Vendors/**/*
# 项目描述
sonar.projectDescription=xazm ios with the SonarScanner
# 测试目录的路径
sonar.tests=ProjectTests,ProjectUITests
# 模拟器配置
sonar.swift.simulator=platform=iOS Simulator,name=iPhone X,OS=latest
# scheme Configuration Debug/Release
sonar.swift.appConfiguration=Debug
# Xcode 工程文件配置 xcodeproj、xcworkspace
sonar.swift.project=Project.xcodeproj
sonar.swift.workspace=Project.xcworkspace
# Xcode Scheme
sonar.swift.appScheme=Project
# App 名称
sonar.swift.appName=Project
##########################
# Optional configuration #
##########################
# SCM
sonar.scm.enabled=true
# sonar.scm.url=scm:git:http://xxx
# JUnit report generated
sonar.junit.reportsPath=sonar-reports/
# Lizard report generated
sonar.swift.lizard.report=sonar-reports/lizard-report.xml
# Coverage report generated
sonar.swift.coverage.reportPattern=sonar-reports/coverage-swift*.xml
# OCLint report generated
sonar.objectivec.oclint.report=sonar-reports/*oclint.txt
# Swiftlint report generated
sonar.swift.swiftlint.report=sonar-reports/*swiftlint.txt
# Paths to exclude from coverage report (surefire, 3rd party libraries etc.)
# sonar.swift.excludedPathsFromCoverage=pattern1,pattern2
sonar.swift.excludedPathsFromCoverage=.*Tests.*
# Tailor report generated
sonar.swift.tailor.config=--no-color --max-line-length=100 --max-file-length=500 --max-name-length=40 --max-name-length=40 --min-name-length=4
sonar.swift.tailor.report=sonar-reports/*tailor.txt
# login info
sonar.host.url=http://localhost:9000
sonar.login=admin
sonar.password=xxx
# database info
sonar.jdbc.username=root
sonar.jdbc.password=xxx
sonar.jdbc.url=jdbc:mysql://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&useConfigs=maxPerformance&useSSL=false
- 配置插件规则,在扫描文件下添加.swiftlint.yml文件,根据自身代码的情况,选择性的忽略部分规则,或者修改swift插件规则。
use_nested_configs: true
# 执行 linting 时忽略的路径。 优先级比 `included` 更高。
excluded:
- Pods
# 执行时排除掉的规则
disabled_rules:
- force_cast # 强制转换
- force_try # try语句判断
- line_length # 单行代码长度
#代码复杂度
cyclomatic_complexity:
warning: 19
error: 20
# 文件长度
file_length:
warning: 999
error: 1000
# 实体类长度
type_body_length:
warning: 999
error: 1000
# 函数体长度
function_body_length:
warning: 99
error: 100
# 命名规则可以设置最小长度和最大程度的警告/错误。此外它们也可以设置排除在外的名字
type_name:
min_length: 4 # 只是警告
max_length: # 警告和错误
warning: 40
error: 50
# excluded: iPhone # 排除某个名字
#variable_name:
# min_length: # 只有最小长度
# error: 4 # 只有错误
# excluded: # 排除某些名字
# - id
# - URL
# - GlobalAPIKey
reporter: "xcode" # 报告类型 (xcode, json, csv, checkstyle)
更多规则,可参考
注:.swiftlint.yml 文件必须放在扫描的具体路径下,放在工程根目录下无效。
6. 配置变量配置
open ~/.bash_profile
# jdk
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_221.jdk/ Contents/Home
export CLASSPATH=.:${JAVA_HOME}/lib/dt.jar:${JAVA_HOME}/lib/ tools.jar
export PATH=${JAVA_HOME}/bin:$PATH
# gradle
GRADLE_HOME=/usr/local/Cellar/gradle/4.1
export GRADLE_HOME
export PATH=$PATH:$GRADLE_HOME/bin
# mysql
export PATH=${PATH}:/usr/local/mysql/bin
export PATH=$PATH:/usr/local/mysql/support-files
# sonarqube
export SONAR_HOME=/usr/local/sonarqube-7.8 export PATH=$SONAR_HOME/bin:$PATH
# sonar-scanner
export SONAR_SCANNER_HOME=/usr/local/sonar-scanner-4.2.0.1873-macosx export PATH=$PATH:$SONAR_SCANNER_HOME/bin
# python
export PYTHON=/Library/Frameworks/Python.framework/Versions/3.8 PATH=$PYTHON/bin:$PATH
alias python="/Library/Frameworks/Python.framework/Versions/3.8/bin/ python3.8"
#export PYTHON=/System/Library/Frameworks/Python.framework/Versions/ 2.7
#PATH=$PYTHON/bin:$PATH
#alias python="/System/Library/Frameworks/Python.framework/Versions/ 2.7/bin/python2.7"
# oclint
OCLINT_HOME=/usr/local/Cellar/oclint/0.13.1
export PATH=$OCLINT_HOME/bin:$PATH
# swiftlint
export SWIFTLINT=/usr/local/Cellar/swiftlint/3.31.1
PATH=$SWIFTLINT/bin:$PATH
# xcpretty
export XCPRETTY=/usr/local/xcpretty
PATH=$XCPRETTY/bin:$PATH
# tailor
export TAILOR=/usr/local/Cellar/tailor/0.12.0_1
PATH=$TAILOR/bin:$PATH
# lizard
export LIZARD=/Library/Frameworks/Python.framework/Versions/3.8
PATH=$LIZARD/bin:$PATH
# slather
export LIZARD=/Library/Ruby/Gems/2.6.0/gems/slather-2.4.7
PATH=$LIZARD/bin:$PATH
# xcodebuild
export XCODEBUILD=/usr/bin/xcodebuild
export PATH=$XCODEBUILD:$PATH
# local
export USRLOCAL=/usr/local
PATH=$USRLOCAL/bin:$PATH
source ~/.bashrc
保存环境配置
source ~/.bash_profile
7. 源码工程配置
Tagrget配置:Tests、UITests必不可少
image.png8. Jenkins构建扫描
创建Jenkins扫描任务
image.png配置源码
image.png关于SonrQube 分析iOS项目的详细配置,可参考SonarQube Integration with iOS
配置Jenkins扫描脚本
source /Users/xxxx/.bash_profile
export LC_ALL="en_US.UTF-8"
cd $WORKSPACE
./run-sonar-swift.sh -v
扫描成功结果图
image.png扫描日志
image.pngSonarQube分析结果
image.png image.png到这里,SonarQube代码扫描结束,接下来就是根据分析结果,做针对性的整改代码。我们目前的策略把定义为阻断、严重、主要问题清零,次要、提示这两类问题先不处理,后期有时间再处理。中间针对一些不合理的维度,比如:循环复杂度到达10定义为严重问题,文件、类代码行数限制200行,超过定义主要问题,单行代码长度限制120字符等等,做了插件规则的调整:忽略/修改阈值。总之一句话:具体问题具体分析,根据自家代码实际情况做评估,如果代码整改需要大刀阔斧,那跟重构无异了,厉害关系需要权衡清楚。另外SonarQube问题的整改,尽量放在项目中去做,迭代周期太短,开发、测试很难把控到位。如果一定要放在迭代中来做,那一定要排好整改计划,按节奏推进。
网友评论