linuxea:jenkins流水线集成juit/sonarqube/覆盖率扫描配置一(7)

marksugar
2022-07-05 / 0 评论 / 1,788 阅读 / 正在检测是否收录...

到了当前阶段流水线阶段,我们需要配置mvn去打包,sonarqube,以及容器的镜像构建,这些东西都会被安排到流水线上,直到docker镜像构建完成,此阶段,我将一个docker镜像构建完成视作为一个制品的完成。这些流程被放置在一起,因此称作持续集成。当然,这在这里只是一个非常简单的模型。

阅读此篇,你将了解如下列表中简单的实现方式:

  • jenkins和gitlab触发(上一章实现)
  • jenkins凭据使用(上一章实现)
  • juit配置(本章实现)
  • sonarqube简单扫描(本章实现)
  • sonarqube简单分支扫描(本章实现)
  • sonarqube覆盖率(本章实现)
  • sonarqube与gitlab关联
  • 配置docker中构建docker
  • mvn打包
  • 打包基于java的skywalking agent(上一章实现)
  • 基于gitlab来管理kustomize的k8s配置清单
  • kubectl部署
  • kubeclt deployment的状态跟踪
  • 钉钉消息的构建状态推送

开始

  • 下载一个java程序包

另外,为了演示这个效果,我们需要一个合适的jar包来测试,而不是在前面提供的那个hello-world的包。于是在https://start.spring.io/页面默认选择,选择java 8,而后点击CENERATE下载demo包,解压这个包将代码推送到gitlab

image-20220703163258442.png

而后选择ADD

image-20220703163321846.png

最后点击GENERATE,下载一个java-demo的包

image-20220703163704027.png

错误修改

如果构建失败,mvn使用aliyun的直接构建即可

<mirrors>
    ....
    <mirror>
        <id>nexus-aliyun</id>
        <mirrorOf>*</mirrorOf>
        <name>Nexus aliyun</name>
        <url>http://maven.aliyun.com/nexus/content/groups/public</url>
    </mirror>
</mirrors>

而后,我们创建一个新分支来存放

cd /tmp 
git clone git@172.16.100.47:java/java-demo.git
cd java-demo
git checkout -b web
mkdir linuxea

而后将java-demo.zip解压复制进去

unzip java-demo.zip
cp java-demo/* /tmp/java-demo/linuxea/

上传到git仓库

git add .
git commit -m "first commit"
git push -u origin web

另外还需要将Dockerfile放入

4.1 配置凭据

你可以使用密钥或者账号密码来进行配置,如果是账号密码需要配置一个Credentials后来进行引用。因此,需要安装Credentials插件

install plugins "Credentials"

Manage Jenkins -> Manage Credentials -> 选择全局,而后添加凭据

image-20220618192715514.png

而后复制创建完成的id,将会在拉取代码时候用到,如下

        //阶段1 获取代码
          stage("CheckOut"){
            steps {
                script {
                    println("下载代码 --> 分支: ${env.branch}")
                    checkout(   [$class: 'GitSCM', 
                        branches: [[name: "${branch}"]], 
                        extensions: [], 
                        userRemoteConfigs: [[
                            credentialsId: 'gitlab-mark', 
                            url: "${BASEURL}"]]])
                    }
            }
        }

总的如下

try {
    if ( "${onerun}" == "gitlabs"){
        println("Trigger Branch: ${info_ref}")
        RefName="${info_ref.split("/")[-1]}"
        //自定义显示名称
        currentBuild.displayName = "#${info_event_name}-${RefName}-${info_checkout_sha}"
        //自定义描述
        currentBuild.description = "Trigger by user ${info_user_username} 自动触发 \n branch: ${RefName} \n commit message: ${info_commits_0_message}"
        BUILD_TRIGGER_BY="${info_user_username}"
        BASEURL="${info_project_git_http_url}"
    } 
}catch(e){
    BUILD_TRIGGER_BY="${currentBuild.getBuildCauses()[0].userId}"
    currentBuild.description = "Trigger by user ${BUILD_TRIGGER_BY} 非自动触发 \n branch: ${branch} \ngit: ${BASEURL}"
}
pipeline{
    //指定运行此流水线的节点
    agent any
    
    //管道运行选项
    options {
        skipDefaultCheckout true
        skipStagesAfterUnstable()
        buildDiscarder(logRotator(numToKeepStr: '2'))
    }
    //流水线的阶段
    stages{
        //阶段1 获取代码
          stage("CheckOut"){
            steps {
                script {
                    println("下载代码 --> 分支: ${env.branch}")
                    checkout(   [$class: 'GitSCM', 
                        branches: [[name: "${branch}"]], 
                        extensions: [], 
                        userRemoteConfigs: [[
                            credentialsId: 'gitlab-root', 
                            url: "${BASEURL}"]]])
                    }
            }
        }                                
    }
}

但是这里面涉及到两个变量,分别是:

  • $branch: 分支

    这里我们修改为: web

  • $BASEURL: git地址

    这个就是这个项目地地址

这两个参数化构建过程中需要在选项参数中进行添加

4.2 配置mvn源地址

如果没有配置mvn的,参考如下

.m2下的settings.xml文件不好用了,或者反正就不好用了,我们直接配置绝对路径

找到mirrors字段,字段内全部删除,复制下面的粘贴进去即可

<mirrors>
    <mirror>
      <id>alimaven</id>
      <name>aliyun maven</name>
      <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
      <mirrorOf>central</mirrorOf>        
    </mirror>
</mirrors>

像这样,而后存放在一个位置

<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
  <pluginGroups>
  </pluginGroups>

  <proxies>
  </proxies>
  <servers>
    <server>
     <id>maven-releases</id>
     <username>admin</username>
     <password>admin</password>
    </server>
    <server>
     <id>maven-snapshots</id>
     <username>admin</username>
     <password>admin</password>
    </server>
  </servers>

  <mirrors>
<!--    <mirror>
        <id>nexus</id>
        <mirrorOf>local</mirrorOf>
        <name>nexus</name>
        <url>http://172.16.15.136:8081/repository/maven-public/</url>
    </mirror>-->
    <mirror>
      <id>alimaven</id>
      <name>aliyun maven</name>
          <url>http://172.16.15.136:8081/repository/maven2-group/</url>
      <mirrorOf>central</mirrorOf>
    </mirror>
  </mirrors>
  <profiles>
  </profiles>
</settings>

4.3 juit测试

pom文件增加依赖

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>    

我们的目录结构中,首先是一个Linuxea的目录,于是我们每次都需要cd进去

        stage("unit Test"){
            steps{
                script{
                sh """
                      cd linuxea && mvn test -s /var/jenkins_home/.m2/settings.xml       
                """
                }
            }
            post {
                success {
                    script {
                    junit 'linuxea/target/surefire-reports/*.xml'
                    }
                }
            }        
        }

正常情况下会在surefire-reports下创建一个xml文件,jenkins读取此文件

[root@linuxea-48 /data/jenkins-latest/jenkins_home/workspace/linuxea-2022/linuxea/target]# ll
total 0
drwxr-xr-x 3 root root  47 Jul  3 18:31 classes
drwxr-xr-x 3 root root  25 Jul  3 01:30 generated-sources
drwxr-xr-x 3 root root  30 Jul  3 01:45 generated-test-sources
drwxr-xr-x 3 root root  35 Jul  3 01:40 maven-status
drwxr-xr-x 2 root root 257 Jul  3 18:32 surefire-reports
drwxr-xr-x 3 root root  17 Jul  3 18:31 test-classes

如果代码里没有单元测试,这里是没有报告产生的,并且有可能因为版本问题会报错

现在我们将web合并到master,开始构建。最终如下

image-20220703184717080.png

4.4 sonarqube

简单使用,安装插件即可,SonarQube Scanner,或者下载SonarQube Scanner安装挂载到容器内

1.首先我们配置token信息和Jenkins互联

image-20220701221111925.png

复制token

01c2f60766bd896fe82a378bb105e1a73d9161c3

2.回到jenkins添加凭据

image-20220701222728244.png

  • 插件配置

如果此时用的插件就可以这么配置,在Manage Jenkins->Configure System

image-20220618220820677.png

流水线阶段如下

   stage('SonarQube analysis') {
         // sonarqube installation name
        steps{
         withSonarQubeEnv( installationName: 'sonarqube-servers') { 
              sh """
              cd demo && mvn clean verify sonar:sonar -s /var/jenkins_home/.m2/settings.xml
              """ 
         }
        }
   }
  • 不使用插件(现在就是)

不用插件就需要下载sonar-scanner-cli包使用,如下

wget https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-4.6.2.2472-linux.zip
unzi sonar-scanner-cli-4.6.2.2472-linux.zip -d /usr/local/
ln -s /usr/local/sonar-scanner-4.6.2.2472-linux/bin/sonar-scanner /usr/local/sbin/
sed -i 's/use_embedded_jre=true/use_embedded_jre=false/g' /usr/local/sonar-scanner-4.6.2.2472-linux/bin/sonar-scanner

这个包最终是被挂载到容器的/usr/local/package/下

如果不用插件,用命令组合变量,因此需要生成一下命令的格式

在流水线语法中-选中"withCredentials; Build credentials to variables",而后绑定到"sonarqube-token"变量中

image-20220701223218406.png

将生成的流水线脚本复制,并进行修改

        stage("coed sonar"){
            steps{
               script {
                 withCredentials([string(credentialsId: 'sonarqube-token', variable: 'SONAR_TOKEN')]) {           
                    sh """
                        cd linuxea && \
                        /usr/local/package/sonar-scanner-4.6.2.2472-linux/bin/sonar-scanner \
                        -Dsonar.host.url=http://172.16.100.47:9000 \
                        -Dsonar.projectKey=${JOB_NAME}_${branch} \
                        -Dsonar.projectName=${JOB_NAME}_${branch} \
                        -Dsonar.projectVersion=${BUILD_NUMBER} \
                        -Dsonar.login=${SONAR_TOKEN} \
                        -Dsonar.ws.timeout=30 \
                        -Dsonar.projectDescription="my first project!" \
                        -Dsonar.links.homepage=${env.BASEURL} \
                        -Dsonar.links.ci=${BUILD_URL} \
                        -Dsonar.sources=src \
                        -Dsonar.sourceEncoding=UTF-8 \
                        -Dsonar.java.binaries=target/classes \
                        -Dsonar.java.test.binaries=target/test-classes \
                        -Dsonar.java.surefire.report=target/surefire-reports
                    """
                   }
               }
            }
        }

此阶段运行后如下

image-20220703185103588.png

现在在sonarqube生成的就是master分支的

image-20220703185130422.png

4.5 代码覆盖率

在8.9.2的版本里面jacoco默认是有的,因此我们不需要额外插件

image-20220702002542611.png

但是仍然需要配置pom.xml中的dependency,如下

      <dependency>
        <groupId>org.jacoco</groupId>
        <artifactId>jacoco-maven-plugin</artifactId>
        <version>0.8.3</version>
        <scope>test</scope>
      </dependency>

还有一个plugins

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
            </plugin>

            <plugin>
                <groupId>org.jacoco</groupId>
                <artifactId>jacoco-maven-plugin</artifactId>
                <version>0.8.2</version>
                <configuration>
                    <destFile>target/jacoco.exec</destFile>
                    <detaFile>target/jacoco.exec</detaFile>
                </configuration>
                <executions>
                    <execution>
                        <id>jacoco-initialize</id>
                        <goals>
                            <goal>prepare-agent</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>jacoco-site</id>
                        <phase>test</phase>
                        <goals>
                            <goal>report</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

修改完成的pom.xml如下

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.1</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.linuxea</groupId>
    <artifactId>java-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>java-demo</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.jacoco</groupId>
            <artifactId>jacoco-maven-plugin</artifactId>
            <version>0.8.3</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>            
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.jacoco</groupId>
                <artifactId>jacoco-maven-plugin</artifactId>
                <version>0.8.2</version>
                <configuration>
                    <destFile>target/jacoco.exec</destFile>
                    <detaFile>target/jacoco.exec</detaFile>
                </configuration>
                <executions>
                    <execution>
                        <id>jacoco-initialize</id>
                        <goals>
                            <goal>prepare-agent</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>jacoco-site</id>
                        <phase>test</phase>
                        <goals>
                            <goal>report</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>                        
        </plugins>
    </build>
</project>

而后在构建的命令中添加如下

-Dsonar.core.codeCoveragePlugin=jacoco \
-Dsonar.jacoco.reportPaths=target/jacoco.exec

添加到流水线

        stage("coed sonar"){
            steps{
               script {
                 withCredentials([string(credentialsId: 'sonarqube-token', variable: 'SONAR_TOKEN')]) {           
                    sh """
                        cd linuxea && \
                        /usr/local/package/sonar-scanner-4.6.2.2472-linux/bin/sonar-scanner \
                        -Dsonar.host.url=http://172.16.100.47:9000 \
                        -Dsonar.projectKey=${JOB_NAME}_${branch} \
                        -Dsonar.projectName=${JOB_NAME}_${branch} \
                        -Dsonar.projectVersion=${BUILD_NUMBER} \
                        -Dsonar.login=${SONAR_TOKEN} \
                        -Dsonar.ws.timeout=30 \
                        -Dsonar.projectDescription="my first project!" \
                        -Dsonar.links.homepage=${env.BASEURL} \
                        -Dsonar.links.ci=${BUILD_URL} \
                        -Dsonar.sources=src \
                        -Dsonar.sourceEncoding=UTF-8 \
                        -Dsonar.java.binaries=target/classes \
                        -Dsonar.java.test.binaries=target/test-classes \
                        -Dsonar.java.surefire.report=target/surefire-reports \
                        -Dsonar.core.codeCoveragePlugin=jacoco \
                        -Dsonar.jacoco.reportPaths=target/jacoco.exec             
                    """
                   }
               }
            }
        }

构建后sonarqube的覆盖率将会出现值

  • 如果没有配置测试用例,这里是0

image-20220703185435009.png

0

评论

博主关闭了所有页面的评论