Jenkins代碼檢查


一.靜態代碼分析

靜態代碼分析是指在不允許程序的前提下,對源代碼進行分析或檢查,范圍包括代碼風格、可能出現的空指針、代碼塊大小、重復的代碼等。

沒有通過編譯,靜態代碼分析就沒有意義。所以在整個pipeline中,靜態代碼分析通常被安排在編譯階段之后。非編譯型語言就另當別論了。

寫代碼時大括號該不該換行?對於這樣的問題很容易引起爭議,如果公司對代碼定標准,那符合與否不可能找一個人總盯着,開發組着雖然管理代碼合並,也不可能逐行去看檢查是否符合標准。

代碼檢查規范的方案是使用構建工具或者代碼分析器進行代碼檢查,不通過,pipeline就中止。

二.規范檢查

PMD進行檢查

PMD(https://pmd.github.io)是一款可擴展的靜態代碼分析器,它不僅可以對代碼風格進行檢查,還可以檢查設計、對線程、性能等方面的問題。
Maven的PMD插件,是我們能在Maven上使用PMD

1.在Maven項目的pom.xml中加入PMD插件

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-pmd-plugin</artifactId>
    <version>3.8</version>
    <configuration>
        <rulesets>
            <ruleset>rulesets/java/ali-comment.xml</ruleset>
            <ruleset>rulesets/java/ali-concurrent.xml</ruleset>
            <ruleset>rulesets/java/ali-exception.xml</ruleset>
            <ruleset>rulesets/java/ali-flowcontrol.xml</ruleset>
            <ruleset>rulesets/java/ali-naming.xml</ruleset>
            <ruleset>rulesets/java/ali-oop.xml</ruleset>
            <ruleset>rulesets/java/ali-orm.xml</ruleset>
            <ruleset>rulesets/java/ali-other.xml</ruleset>
            <ruleset>rulesets/java/ali-set.xml</ruleset>
        </rulesets>
        <printFailingErrors>true</printFailingErrors>
    </configuration>
    <executions>
        <execution>
            <goals>
                <goal>check</goal>
            </goals>
        </execution>
    </executions>
    <dependencies>
        <dependency>
            <groupId>com.alibaba.p3c</groupId>
            <artifactId>p3c-pmd</artifactId>
            <version>1.3.5</version>
        </dependency>
    </dependencies>
</plugin>

maven-pmd-plugin插件並不會自動使用p3c-pmd,需要在引入dependencies部分手動加入p3c-pmd依賴,然后在rulesets屬性中引入p3c的規則。

2.安裝Jenkins PMD插件,作用是將PMD報告呈現在任務詳情頁中。

3.在Jenkkinsfile中加入pmd步驟

pipeline {
    agent any

    tools {
        maven 'mvn-3.5.4'
    }

    stages {
        stage('pmd') {
            steps {
                sh "mvn pmd:pmd"
            }
        }
    }

    post {
        always {
            pmd(canRunOnFailed: true, pattern: '**/target/pmd.xml')
        }
    }
}

執行完成后,可以在任務詳情頁看到PMD報告的鏈接
file

單機鏈接進入報告頁面,可以看到更詳細的信息
file

分析器區別

目前每種語言基本都有自己的靜態代碼分析器,比如JAVA語言,除了PMD外,還有Check-style、FindBugs等。但是沒有一款能“大統一”,實現對所有語言和場景的支持。

另外,同一種語言下的不同分析器,他們在功能上既有區別,又有重疊,讀者需要根據自己團隊的情況進行選擇。但是不論選擇哪款分析器,所有進行靜態代碼分析的地方都必須統一分析規則。比如我們決定使用阿里巴巴的開發規范,那Maven插件、IDE插件以及SonarQube都必須使用;否則,分析結果可能會不一致,進而影響分析結果的可信度。

三.持續代碼質量檢測

SonarQube是一個代碼質量管理工 具,能對20多種編程語言源碼進行代碼味道( Code Smells)、Bug、 安全漏洞方面的靜態分析。SonarQube有4個版本:開源版、開發者版、企業版、數據中心版( Data Center Edition)。

詳細的區別,可前往官方網站進行了解,本篇使用的是開源版6.7.5LTS,假設讀者已經安裝此版本。

Maven與SonarQube集成

為方便起見,我們就不自己寫例子了而是直接使用JUnit 4源碼來做示例。將JUnit 4從GitHub克隆下來后,在pom.xml中加入SonarQube插件依賴。

<build>
    <plugins>
        <plugin>
            <groupId>org . codehaus . mojo</ groupId>
            <artifactId>sonar-maven-plugin</artifactId>
            <version>3.4.1.1168< /version>
        </plugin>
    </plugins>
</build>

執行命令:
mvn clean org.sonarsource.scanner.maven:sonar-maven-plugin:3.4.1.1168:sonar -Dsonar.host.url=http://127.0.0.1:9000

sonar.host.url參數用於指定SonarQube服務的地址。這時,就可以在SonarQube的"Projects" 中看到JUnit 4的分析結果,可以看到JUnit 4有11個Bug。
file

SonarQube服務默認允許任何人執行源碼分析,因此在生產環境中使用會有安全隱患,以下幾步可以提高其安全性:
1.設置SonarQube禁此非登錄用戶使用
file

2.為用戶生成Token,Jenkins只能通過Token與SonarQube集成。登陸SonarQube,進入個人設置頁面中的Security tab頁
file

3.在執行mvn命令時加入相應的sonar.login參數
mvn clean package org.sonarsource.scanner.maven:sonar-maven- plugin:3.4.1.1168:sonar -Dsonar.host.url=http://192.168.1.8:9000 -Dsonar.login=e2f92b48d047be825fe3c2c06dec818788855a3e

Jenkins與SonarQube集成

將Maven與SonarQube集成,這時SonarQube對於Jenkins來說還是透明的,Jenkins並不知道代碼質量如何。將集成Jenkins與SonarQube ,以實現當代碼質量不合格時, Jenkins pipeline失敗。

具體步驟如下:
1.Jenkins安裝SonarQube Scanner插件

2.Jenkins配置SonarQube Scanner插件
file

3.SonarQube設置Webhooks,不同代碼規模的源碼,分析過程的耗時是不一樣的。所以當分析完成時,由SonarQube主動通知Jenkins。設置方法就是進入SonarQube的Adminstration -》Configuration -》 Webhooks頁 ,加入http://jenkins地址/sonarqube-webhook 這個接口地址由SonarQube插件提供
file

4.在Jenkinsfile中加入SonarQube的stage

pipeline {
    angent any
    tools {
        maven ' mvn- -3.5.4
    }

    stages {
        stage( 'Code Analysis') {
            steps {
                withSonarQubeEnv(' sonarqube') {
                    sh """
                    mvn clean package org.sonarsource.scanner.maven:sonar-maven-plugin:3.4.1.1168:sonar \
                    -Dsonar.host.url=${SONAR_ HOST_ URL} \
                    -Dsonar.login=${ SONAR_ AUTH_ TOKEN}
                    """
                }
            }
        }

        stage("Quality Gate" ) {
            steps {
                timeout(time: 1, unit: 'HOURS') {
                    waitForQualityGate abortPipeline: true
                }
            }
        }
    }
}

withSonarQubeEnv是一個環境變量包裝器,讀取的是我們所配置的變量。在它的閉包內,我們可以使用以下變量。

  • SONAR_HOST_URL : SonarQube服務的地址
  • SONAR_AUTH_TOKEN : SonarQube認證所需要的Token

waitForQualityGate步驟告訴Jenkins等待SonarQube返回的分析結果。當它的abortPipeline參數為true時,代表當質量不合格,將pipeline的狀態設置為UNSTABLE。

我們同時使用了timeout包裝器來設置waitForQualityGate步驟的超時時間,避免當網絡出問題時, Jenkins任務-直處於等待狀態。

5.設置Quality Gates(質量閾值)。 在SonarQube的"Quality Gates"下,我們可以看到系統自帶的質量閾值,如圖所示。可以看出它是針對新代碼的。所以,在初次及沒有新代碼加入的情況下,執行代碼分析是不會報出構建失敗的。
file

代碼掃描

使用Maven插件實現代碼掃描的,也就是利用構建工具本身提供的插件來實現。在構建I具本身不支持的情況下,我們使用SonarQube本身提供的掃描工具(Scanner )進行代碼掃描。

具體步驟如下:
1.在安裝SonarQube Scanner插件后,設置掃描工具自動下載並安裝(推薦)
file

也可以取消自動安裝, 改成手動安裝后指定目錄
file

注意,這里的Name值與圖中所設置的值是兩碼事,此處設置的是SonarScanner工具本身的名稱與路徑

2.在代碼項目根目錄下放入sonar-project.properties文件,sonar-scanner會讀取其配置,內容如下:

# must be unique in a given SonarQube instance
sonar.projectKey=my:project

# this is the name and version displayed in the SonarQube UI. Was mandatory prior to SonarQube 6.1.
sonar.projectName=My project
sonar.projectVersion=1.0

# This property is optional if sonar . modules is set.
sonar.sources=.

# Encoding of the source code. Default is default system encoding
#sonar.sourceEncoding=UTF-8

3.pipeline部分代碼如下:

script{
    def sonarHome = tool name: 'sonarqube3.2.0', type: 'hudson.plugins.sonar.SonarRunnerInstallation'
    withSonarQubeEnv('sonar') {
        sh "${sonarHome}/bin/sonar-scanner -Dsonar.host.url=${SONAR_HOST_URL} -Dsonar.login=${SONAR_AUTH_TOKEN}"
    }
}

SonarQube集成p3c

必須在所有做代碼規范檢查的地方使用同一套規范,而SonarQube默認使 用的是它自帶的規范( SonarQube稱為規則),所以也需要設置SonarQube使用p3c的規范。

有好心的朋友開源了SonarQube的p3cPMD插件,我們可以拿來直接使用。

具體步驟如下:
1.從GitHub下載p3c PMD插件,編譯打包

2.將上一步打包好的JAR包放到SonarQube所在服務器的<SonarQube的home目錄>/extensions/plugins目錄下

3.SonarQube:創建p3c profile,單擊SonarQube頂部的"Quality Profiles",然后單擊面右上角的"Create"按鈕,輸入新profile名稱,選擇Java語言。
file

4.SonarQube在profile列表中找到剛剛創建的p3c profile,單擊其最右邊的下三角按鈕,選擇"Set as Default"
file

5.創建成功
file

6.SonarQube為p3c profile激活p3c規則,新創建的profile是沒有激活任何規則的,需要手動激活。單擊下三角按鈕,選擇“Activate More Rules”
file

7.跳轉到激活頁面,激活所有的p3c規則,這樣當SonarQube分析Java代碼時,就會使用p3c規則了。
file

將分析報告推送到GitLab

如果希望對每一次代碼的commit都進行分析,並將分析結果與該commit關聯起來,那么SonarQube的GitLab插件就是一個不錯的選擇。SonarQube Gitlab插件的功能就是將SonarQube的分析結果推送到GitLab。

1.在SonarQube上安裝GitLab插件(https:/github.com/gabrie-allaigre/sonar-gitlab-plugin)如果因為網絡原因安裝失敗,則可進行手動安裝。
file

2.配置SonarQube GitLab插件
file

配置好SonarQube GitLab插件后,需要為sonar-scanner添加幾個參數,以告訴SonarQube將分析結果關聯到GitLab的相應commit上。

script{
    def sonarHome = tool name: 'sonarqube3.2.0', type: 'hudson.plugins.sonar.SonarRunnerInstallation'
    def GIT_COMMIT_ID = sh(
        script: "git rev-parse --short=10 HEAD",
        returnStdout: true
    )
    sh "${sonarHome}/bin/sonar-scanner -Dsonar.host.url=${SONAR_HOST_URL} -Dsonar.analysis.mode=preview -Dsonar.gitlab.ref_name=master -Dsonar.gitlab.project_ id=jenkins-book/sonarqube -Dsonar.projectName=jenkins-book -Dsonar.gitlab.commit_sha=${GIT_COMMIT_ID} -Dsonar.login=${SONAR_AUTH_TOKEN}"
}

首先通過sh步驟獲取代碼的commit ID,然后在執行掃描時加入如下參數。
-Dsonar.analysis.mode :分析報告模式,值為preview,代表將結果推送到GitLab。此參數雖然官方標注SonarQube 6.6后被廢棄,但是筆者使用6.7版本依然需要加上它。
-Dsonar.gitlab.ref_name :分支名稱
-Dsonar.gitlab.project_id : GitLab對應的項目路徑
-Dsonar.projectName :對應SonarQube上的項目名稱
-Dsonar.gitlab.commit_sha :代碼的commit ID

當SonarQube分析完成后,我們就可以在GitLab的相應commit頁面上的代碼行內或commit評論區看到分析結果了
file

分析結果是顯示在行內還是評論區,由SonarQube GitLab插件的配置決定。

Allure測試報告

是不是覺得JUnit輸出的測試報告不美觀。不只是JUnit ,很多其他編程語言的測試框架的測試報告也差不多。Allure測試報告是一個框架,能將各種測試報告更美觀地呈現出來。

接下來,我們將Allure、Maven、Jenkins集成。 Allure與其他編程語言及構建工具的集成與此類似。

具體步驟如下:
1.安裝Allure Jenkins插件,進入Jenkins的Manage Jenkins ——》Global Tool Configuration-》Allure Commandline頁,配置Allure自動下載並安裝的版本
file

2.在pom.xml文件中加入依賴

<dependency>
    <groupId>io.qameta.allure</groupId>
    <artifactId>allure-junit4</artifactId>
    <version>2.0-BETA13</version>
</dependency>

3.在pom.xml文件中加入Allure插件

<p1ugin>
    <groupId>org.apache.maven.plugins</ groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.19.1</version>
    <configuration>
        <argLine>
            - javaagent:" ${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar"
        </argLine>
        <properties>
            <property>
                <name>listener</name>
                <value>io.qameta.allure.junit4.AllureJunit4</value>
            </property>
        </properties>
        <systemProperties>
            <property>
                <name>allure.results.directory</name>
                <value>${project.build.directory}/allure- results</value>
            </property>
            <property>
                <name>allure.link.issue.pattern</name>
                <value>https://example.org/issue/{}</value>
            </property>
        </systemProperties>
    </configuration>
    <dependencies>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>${aspectj.version}</version>
        </dependency>
    </dependencies>
</plugin>
<plugin>
    <groupId>io.qameta.allure</groupId>
    <artifactId>allure-maven</artifactId>
    <version>2.8</version>
</plugin>

4.在jenkinsfile中的post階段加入allure步驟

script {
    allure([
        includeProperties: false,
        jdk:
        properties:[],
        reportBuildPolicy:' ALWAYS',
        results: [[path: 'target/allure-results']]
    ])
}

構建完成后,可以看到在構建歷史記錄中出現了Allure的logo,單擊就可以進入優美的測試報告頁面了
file


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM