转载

持续集成之 Spring Boot 实战篇

本文作者: CODING 用户 - 何健

这次实战篇,我们借助 「CODING 持续集成」 ,实现一个简单的 Spring Boot 项目从编码到最后部署的完整过程。本教程还有 B 站视频版 ,帮助读者更好地学习理解。

思路

在线上环境构建、测试、部署

这种情况,通常会将 jenkins 安装在服务器上,确保构建测试等操作环境和线上环境一致。

此时通常会在 jenkins 中配置好需要持续集成的仓库,以及具体流程。

这种方式非常简单粗暴,也非常有效,但是缺点也很明显。可能 jenkins 会成为线上环境的旁站漏洞,这是非常不安全的。

那么,我们就需要更高级的方式,可以线上环境之外的构建测试,最终部署到线上环境。「CODING 持续集成」正是提供这类持续集成模式的平台。

不在实际部署服务器上构建、测试

为了避免占用线上服务器的资源,也为了避免安全问题,我们可以使用单独的 jenkins (或者其它此类软件)完成构建、测试、分发,实际部署通过单独的 webhook 实现。这样就可以避免在线上环境安装 Jenkins,还可以避免更复杂的系统安全维护。

这样做的优点:不会影响在线服务; 缺点:部署地机器最好是可以公网访问的,否则会无法完成后续分发步骤。

终极解决方案:使用 SaaS 化的 Jenkins

Software as a Service,软件即服务。「CODING 持续集成」集成了 SaaS 化的 Jenkins 等主流企业开发流程工具,实现了 DevOps 流程全自动化。开箱即用,直接用它就好!

捋一下思路

我们这次实战针对后一种思路

  1. 检出代码

  2. 构建

  3. 测试

  4. 分发

  5. 触发部署

实战

实际体验,还是很不错的。

视频地址: CODING 持续集成 - Spring Boot 项目

持续集成之 Spring Boot 实战篇

第一步:初始化一个持续集成

  1. 首先,我们需要进入准备持续集成的项目。

    这里我用start.spring.io 初始化一个 demo 示例项目,并推送到仓库。 为了方便大家,亲自体验,我准备了一个现成的仓库,可以直接 git clone 下来再 git push 到自己账户下使用。仓库地址:demoForCI

    持续集成之 Spring Boot 实战篇
  2. 解压 demo 项目,进入 demo 目录,初始化仓库。

cd g:/demo/
      git init
      git set remote giturl
      git add ./
      git commit -m 'init repo'
      git push -u origin master
复制代码

别忘了 git config user.name yournamegit config user.email youremail

  1. 开始体验 仓库准备好后,就可以开始体验「CODING 持续集成」。

    持续集成之 Spring Boot 实战篇

    第一次的使用,需要先创建一个 Jenkinsfile,很多小伙伴会说,第一次用,不知道是啥。

    没关系,「CODING 持续集成」已经给我们准备好了模板,非常容易理解,可以认为是特定格式语法写一套 task 流程。

    点击一下 “简易模板”,更具实际情况修改一下就可以。

    持续集成之 Spring Boot 实战篇

第二步:编写 Jenkinsfile

为了方便理解,我们从简易模板开始,分别修改对应阶段的任务。

  1. 配置构建环境,「CODING 持续集成」目前支持 java-8、python-3.5、ruby-2.3、go-1.11 等等。 在 Jenkinsfile 的 pipeline 里添加:
agent {
      // 此处设定构建环境,目前可选有
      // default, java-8, python-3.5, ruby-2.3, go-1.11 等
      // 详情请阅 https://dev.tencent.com/help/knowledge-base/how-to-use-ci#agents
      label "java-8"
    }
复制代码
  1. 检出 这里不得不说,「CODING 持续集成」这里做的还是很方便的,提供了适用于好几种不同场景的模板。默认简易模板是带有检出部分的,我们可以根据实际情况进行修改。默认情况下,env.GIT_BUILD_REF 的值就是 master 主分支,实际上我们可以定制为其它专门用于构建发的分支。

    这里,大家可以自己修改具体要检出的分支。

stage("检出") {
      steps {
          sh 'ci-init'
          checkout(
            [$class: 'GitSCM', branches: [[name: env.GIT_BUILD_REF]], 
            userRemoteConfigs: [[url: env.GIT_REPO_URL]]]
          )
      }
    }
复制代码
  1. 构建
stage("构建") {
      steps {
        echo "构建中..."
        sh 'java -version'
        sh 'mvn package'
        echo "构建完成."
        archiveArtifacts artifacts: '**/target/*.jar', fingerprint: true // 收集构建产物
      }
    }
复制代码

这里需要注意,Spring Boot 的 pom 中需要添加一个插件。 修改后:

<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>
        <version>2.6</version>
        <configuration>
        <skipTests>true</skipTests>
        </configuration>
      </plugin>
复制代码
  1. 测试 这里我偷个懒,只做了单元测试, 没有提取测试报告,大家可以根据实际项目定制这个流程。
stage("测试") {
      steps {
          echo "单元测试中..."
          sh 'mvn test'
          echo "单元测试完成."
          //junit 'target/surefire-reports/*.xml' // 收集单元测试报告的调用过程
      }
    }
复制代码
  1. 分发 jar 包到目标服务器 这里比较无奈,我没有单独针对这次演示写部署 jar 包和上传 jar 包的 webhookApi,但是构建好的 jar 包需要要放置到待部署的服务器。

    于是有了这个过程,借助 scp私钥 来上传构建好的jar包。

    这里千万记着提前部署好密钥。并且将密钥放到仓库一份,用于分发jar包。

stage("分发jar包") {
      steps {
        echo "分发中..."
        echo "chmod 600 pkey"
        sh 'chmod 600 authorized_keys.pem'
        echo "upload"
        sh 'scp -i authorized_keys.pem ./target/*.jar root@yourip:/root/'
        echo "准备部署"
      }
    }
复制代码
  1. 部署

    前面有提到,这里部署仍然需要触发一个钩子,否则只能手动部署了。 这里我写了一个最简单的,实际上我们可以写细致一点,判断一下接口返回的结果再根据结果输出部署情况。

stage("部署") {
      steps {
        sh 'curl http://youapi'
        echo "部署完毕"
      }
    }
复制代码

第三步:保存 Jenkinsfile 并运行

修改好 Jenkinsfile 和 pom.xml。

我们要保存 Jenkinsfile,编辑框可以直接编辑内容,编辑好可以直接提交到仓库下的 ./Jenkinsfile

持续集成之 Spring Boot 实战篇

接下来, 平台会自动读取 Jenkinsfile 并开始走持续集成的流程:

持续集成之 Spring Boot 实战篇

持续集成的流程是可以看到的:

持续集成之 Spring Boot 实战篇

每个阶段都对应 Jenkinsfile 一个 stage, 我们可以点击查看对应阶段的构建结果。

第四步:排查持续集成的报错

如果某个过程出错,「CODING 持续集成」的流程会停止,并提示失败。此时我们可以进入具体节点查看具体失败原因。

持续集成之 Spring Boot 实战篇

比如现在是提示“分发 jar 包失败”,那么我们可以点击对应节点展开看看日志,排查具体分发失败的原因。

持续集成之 Spring Boot 实战篇

现在可以清晰地看到,报错原因是我没有填写正确的主机 ip。

文中涉及的文件及代码

Jenkinsfile

pipeline {
    agent {
        // 此处设定构建环境,目前可选有
        // default, java-8, python-3.5, ruby-2.3, go-1.11 等
        // 详情请阅 https://dev.tencent.com/help/knowledge-base/how-to-use-ci#agents
        label "java-8"
    }
    stages  {
        // 检出仓库
        stage("检出") {
            steps {
                // 这里sh调用ci-init 初始化
                sh 'ci-init'
                // 这里检出仓库,默认检出分支为环境变量中的GIT_BUILD_REF
                checkout(
                  [$class: 'GitSCM', branches: [[name: env.GIT_BUILD_REF]], 
                  userRemoteConfigs: [[url: env.GIT_REPO_URL]]]
                )
            }
        }
        // 构建jar包
        stage("构建") {
            steps {
                echo "构建中..."
                // 输出java版本
                sh 'java -version'
                // 调用maven 构建jar包
                sh 'mvn package'
                echo "构建完成."
                //收集构建产物,这一步成功,我们就可以在平台上看到构建产物
                archiveArtifacts artifacts: '**/target/*.jar', fingerprint: true // 收集构建产物
            }
        }
        // 测试
        stage("测试") {
            steps {
                echo "单元测试中..."
                // 做单元测试
                sh 'mvn test'
                echo "单元测试完成."
            }
        }
        // 分发jar包,这里只是简单的通过scp分发jar包到目标机器指定目录
        stage("分发jar包") {
            steps {
                echo "分发中..."
                echo "chmod 600 pkey"
                sh 'chmod 600 authorized_keys.pem'
                echo "upload"
              	sh 'scp -i authorized_keys.pem ./target/*.jar root@youip:/root/'
                echo "准备部署"
            }
        }
        // 部署jar包
        stage("部署") {
            // 这里需要触发一个部署的webhook,可以是一个很简单的重启java进程的操作
            steps {
                // 用curl 来触发hook
                sh 'curl http://baidu.com'
                echo "请登录服务器手动部署"
            }
        }
    }
}
复制代码

pom.xml

文中所用 Spring Boot 示例项目的 pom.xml

实际上,大家可以直接去start.spring.io 参考照这份 pom 来创建一个 demo。

<?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 http://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.1.2.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>tech.hejian</groupId>
	<artifactId>codingj8</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>codingj8</name>
	<description>coding 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.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<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>
				<version>2.6</version>
				<configuration>
				<skipTests>true</skipTests>
				</configuration>
			</plugin>
		</plugins>


	</build>

</project>
复制代码

总结

CODING是一个面向开发者的云端开发平台,提供 Git/SVN 代码托管、任务管理、在线 WebIDE、Cloud Studio、开发协作、文件管理、Wiki 管理、提供个人服务及企业服务,其中「CODING 持续集成」集成了 SaaS 化的 Jenkins 等主流企业开发流程工具,实现了 DevOps 流程全自动化,为企业提供软件研发全流程管理工具,打通了从团队构建、产品策划、开发测试到部署上线的全过程。

原文  https://juejin.im/post/5c862c85f265da2da67c65d0
正文到此结束
Loading...