CODING.NET DevOps 小玩持续集成 实现代码提交自动构建并发布到服务器

博文目录


云原生,DevOps,CI/CD 等概念在当下非常火,我自己也想试试,碰巧知道 CODING.NET 免费提供了这个能力,所以来尝试一把,好在最终有所成果,对托管在 CODING.NET 上的项目,实现了提交代码自动构建并发布到我自己的阿里云服务器的效果,果然非常舒适

CreatedAt: 20210609

创建项目

创建一个 全功能 DevOps 项目,项目标识为 coding.devops.test. 如果是已有项目,可以在 项目设置 - 功能开关 中打开 持续集成 这个开关

创建代码仓库

在该项目下,创建一个名为 code 的 GIT 仓库,仓库地址为 git@e.coding.net:mrathena/coding.devops.test/code.git

完成工程代码并提交推送到仓库

我创建了一个最简单的 Maven SpringBoot 工程,只有一个 Controller,其他配置如下

application.properties

server.port=8888
server.servlet.context-path=/

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>
    <groupId>com.mrathena</groupId>
    <artifactId>coding.devops.test</artifactId>
    <version>1.0.0</version>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.5.0</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
    <build>
    	<!-- 为了方便 CODING.NET 构建计划 pipeline 脚本的编写,特意定义打包后不加版本号 -->
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.5.0</version>
                <!-- 因为我们没有继承 spring-boot-starter-parent,所以需要执行 repackage,才能生成可执行 jar -->
                <!-- https://docs.spring.io/spring-boot/docs/2.3.0.RELEASE/maven-plugin/reference/html/#repackage -->
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
    <distributionManagement>
        <repository>
            <!--在本地执行 mvn deploy 时可以将工程 jar 包推送到 CODING.NET 的制品库中(估计是个 Maven 私服). 必须与 settings.xml 中配置的 id 一致-->
            <id>mrathena-coding.devops.test-maven</id>
            <name>maven</name>
            <url>https://mrathena-maven.pkg.coding.net/repository/coding.devops.test/maven/</url>
        </repository>
    </distributionManagement>
</project>

创建构建计划

持续集成

在该项目下,选择 持续集成 - 构建计划 - 创建构建计划 - 自定义构建过程 - 按需填写 代码仓库 和 配置来源(我这里选 CODING 代码源 和刚刚创建的 名为 code 的代码仓库,构建计划名为 coding.devops.test),构建计划配置好后可以保存成为模板,方便后续项目配置

设置流程配置

自定义的构建流程,其流程配置默认是这个样子,切换到文本编辑器,将下面的 pipeline 脚本复制进去,保存

pipeline {
  agent any
  stages {
    stage('检出') {
      steps {
        checkout([
          $class: 'GitSCM',
          branches: [[name: GIT_BUILD_REF]],
          userRemoteConfigs: [[
            url: GIT_REPO_URL,
            credentialsId: CREDENTIALS_ID
          ]]
        ])
      }
    }
    stage('编译') {
      steps {
        sh 'mvn clean package -Dmaven.test.skip=true'
      }
    }
    stage('测试') {
      steps {
        sh 'mvn test'
      }
    }
    stage('部署') {
      steps {
        script {
          def remote = [:]
          remote.name = "mrathena"
          remote.host = "116.62.xxx.xx"
          remote.port = 22
          remote.user = "root"
          remote.allowAnyHosts = true

		  // 留着防丢失
          withCredentials([ usernamePassword(credentialsId:'09f2156e-3706-493c-9f2c-xxxxxxxxxxxx',usernameVariable:'USERNAME',passwordVariable:'PASSWORD')]) {
            echo "${USERNAME}"
            echo "${PASSWORD}"
          }

          withCredentials([sshUserPrivateKey(credentialsId: "1619ca47-988e-4647-a143-xxxxxxxxxxxx",keyFileVariable: "id_rsa")]) {
            remote.identityFile = id_rsa
            echo '终止进程'
            // 一开始想到的是下面的命令1,但是如果程序没有在运行,则命令1会报错,会阻断构建计划,后来找到了命令2,在linux不会报错,但是该构建计划里报错,最终还是用了命令1,但是加了一个 try-catch,这样即使没有运行程序,也不会阻断构建计划了
            // 命令1: [[[[sshCommand remote: remote,command: "ps -ef | grep coding.devops.test.jar | grep -v grep | awk '{print \$2}' | xargs kill -9"]]]],$ 要用 \$ 替换,不然该构建计划不认
            // 命令2: [[[[sshCommand remote: remote,command: "n=`ps -ef | grep coding.devops.test.jar | grep -v grep | awk '{print \$2}'`; [[ $n ]] && kill -9 $n"]]]],一行写下所有逻辑(包括判断),参考 https://www.cnblogs.com/shiyiwen/p/8509417.html
            try {
              sshCommand remote: remote, command: "ps -ef | grep coding.devops.test.jar | grep -v grep | awk '{print \$2}' | xargs kill -9"
            } catch (t) {
              echo 'coding.devops.test.jar 没有运行'
            }
            echo '删除程序'
            sshCommand remote: remote, command: 'rm -rf /service/coding.devops.test.jar'
            echo '传输程序'
            // 多模块工程的话,这里可能会多加一层模块的目录,如 ./mrathena-web/target/mrathena.jar,可以点击部署节点,从日志里面找一下 jar 包的路径
            sshPut remote: remote, from: './target/coding.devops.test.jar', into: '/service'
            echo "修改权限"
            sshCommand remote: remote, command: 'chmod 777 /service/coding.devops.test.jar'
            // nohup ./program >/dev/null 2>&1 &
            // sshCommand remote: remote,command: 'nohup java -jar coding.devops.test.jar >/dev/null 2>&1 &'
            // sshCommand remote: remote,command: 'nohup java -jar coding.devops.test.jar 2>&1 &'
            echo '启动程序'
            sshCommand remote: remote, command: 'nohup java -jar /service/coding.devops.test.jar >> /service/coding.devops.test.log 2>&1 &'
            echo '部署成功'
          }
        }
      }
    }
  }
}

阶段说明 测试

不需要则删除即可

阶段说明 部署

核心内容就在这里了,原理很简单,就是将编译好的可执行 jar 传到指定远程服务器,然后执行一系列命令将该 jar 跑起来即可,因为我在相关方面知识和经验比较薄弱,花了不少时间才成功

定义远程服务器信息

要连接其他服务器,需要先定义远程服务器信息,该信息在后续远程操作服务器都有使用到,猜测是用于连接和鉴权,注意,该配置目前还不完整,需要在鉴权后补充鉴权信息

def remote = [:]
remote.name = "mrathena"
remote.host = "116.62.xxx.xx"
remote.port = 22
remote.user = "root"
remote.allowAnyHosts = true

远程服务器鉴权

项目级功能设置 凭据管理
持续集成 调取已录入的凭据

这里让 CODING.NET 通过 SSH 的方式连接远程服务器,官方文档讲的不清不楚的,差评

创建 SSH 密钥

在远程服务器上执行 ssh-keygen -m PEM -t rsa -b 4096 -C "your.email@example.com" 可在 ~/.ssh 目录下生成公私钥文件,私钥口令可以不用输入,直接回车跳过,id_rsa 是私钥,id_rsa.pub 是公钥,需要把公钥内容复制到 authorized_keys 中 cp id_rsa.pub authorized_keys (a通过ssh远程链接b,在a端生成公私钥对,把公钥内容复制到b端的authorized_keys文件中,a端通过私钥即可访问b了)

ssh-keygen -m PEM -t rsa -b 4096 -C "your.email@example.com"
cat ~/.ssh/id_rsa
-----BEGIN RSA PRIVATE KEY-----
JvKE3WXugDp2YuswF4MAJq/o+R9kRKZzNfeM9A6NWjwjnIYP4yUVwqa/20MYmVpT
......
录入凭据

在该项目下,选择项目设置 - 开发者选项 - 凭据管理 - 录入凭据,凭据类型是 SSH 私钥,将 id_rsa 私钥的内容拷贝到指定位置,按需填写私钥口令,勾选 授权所有持续集成构建计划,创建

在 凭据管理 页面可以复制 凭据 ID,用于在 持续集成 的 构建脚本 中使用

在 持续集成 的 构建脚本 中做 SSH 鉴权
// 根据凭据做SSH鉴权,并把鉴权信息保存到 id_rsa 这个变量中,然后赋值到 remote 远程服务器信息的 identifyFile 属性中
withCredentials([sshUserPrivateKey(credentialsId: "这里填写刚刚创建的SSH私钥凭据的凭据ID",keyFileVariable: "id_rsa")]) {
  // 补充鉴权信息,不然的话,sshCommand 和 sshPut 等都无法正确鉴权
  remote.identityFile = id_rsa
  // ...
}

还有一种 用户名/密码 的鉴权方式,没有仔细研究,大概如下

// 做鉴权,把用户名和密码保存到 USERNAME 和 PASSWORD 这两个变量中,同样需要赋值到 remote 中,具体字段需要百度
withCredentials([ usernamePassword(credentialsId:'这里填写刚刚创建的SSH私钥凭据的凭据ID',passwordVariable:'PASSWORD')]) {
  echo "${USERNAME}"
  echo "${PASSWORD}"
}
操作远程服务器
echo '终止进程'
// 一开始想到的是下面的命令1,也不会阻断构建计划了
// 命令1: [[[[sshCommand remote: remote,不然该构建计划不认
// 命令2: [[[[sshCommand remote: remote,参考 https://www.cnblogs.com/shiyiwen/p/8509417.html
try {
  sshCommand remote: remote, command: "ps -ef | grep coding.devops.test.jar | grep -v grep | awk '{print \$2}' | xargs kill -9"
} catch (t) {
  echo 'coding.devops.test.jar 没有运行'
}
echo '删除程序'
sshCommand remote: remote, command: 'rm -rf /service/coding.devops.test.jar'
echo '传输程序'
sshPut remote: remote, into: '/service'
echo "修改权限"
sshCommand remote: remote, command: 'chmod 777 /service/coding.devops.test.jar'
// nohup ./program >/dev/null 2>&1 &
// sshCommand remote: remote,command: 'nohup java -jar coding.devops.test.jar >/dev/null 2>&1 &'
// sshCommand remote: remote,command: 'nohup java -jar coding.devops.test.jar 2>&1 &'
echo '启动程序'
sshCommand remote: remote, command: 'nohup java -jar /service/coding.devops.test.jar >> /service/coding.devops.test.log 2>&1 &'
echo '部署成功'

部署完成后需要自行验证是否成功,可以自行完善相关功能,成品和构建大概是这个样子


设置触发规则

按需自行配置

设置变量与缓存

Maven 工程照下图配置即可

使用限制

DODING.NET 提供的免费能力在并行数(代码扫描和构建计划都算)和构建时长是有限制的


CODING.NET 同样也提供了接入自己机器来作为构建节点的能力,可以在构建节点池中配置,这样就没有限制了. 我目前在使用免费能力

持续集成 构建节点介绍

原文地址:https://blog.csdn.net/mrathena

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


fastjson2 是 fastjson 项目的重要升级,目标是为下一个十年提供一个高性能的 JSON 库,同一套 API 支持JSON/JSONB 两种协议,JSONPath 是一等公民,支持全量解析和部分解析,支持 Java 服务端、客户端Android、大数据场景。 fastjson 2 代码
博文目录文章目录问题描述解决方案问题描述阿里云ECS, 系统切换为 Aliyun Linux 2.1903 LTS 64位 后, SSH可以连接, SFTP无法连接, 端口 22 已添加到阿里云ECS网络安全组表现为 Xshell 可以连接, Xftp 使用 SFTP 协议无法连接, 一片空白, 很长时间也不报错提示, 鼠标挪动的时候显示为圆圈(等待响应)解决方案将 /etc/ssh/sshd_config 中的Subsystem sftp /usr/libexec/opens
博文目录文章目录创建项目创建代码仓库完成工程代码并提交推送到仓库application.propertiespom.xml创建构建计划设置流程配置阶段说明 测试阶段说明 部署定义远程服务器信息远程服务器鉴权创建 SSH 密钥录入凭据在 持续集成 的 构建脚本 中做 SSH 鉴权操作远程服务器设置触发规则设置变量与缓存CODING 持续集成 帮助文档当下 DevOps, CI/CD 等概念非常火, 我自己也想试试, 碰巧知道 CODING.NET 免费提供了这个能力, 所以来尝试一把, 好在最终有
下载CentOS官网CentOS下载CentOS-7-x86_64-DVD-2003.isoCentOS-7-x86_64-DVD-2003.iso安装
博文目录文章目录服务端客户端测试效果服务端配置到 nginx 反向代理FRP Releases使用frp进行内网穿透FRP 示例FRP 实例 通过自定义域名访问内网的 Web 服务FRP 参考 服务端配置FRP Linux Server ReleaseFRP Windows Client Release服务端在 linux 上执行 arch, 结果如果是 [X86_64] 即可选择 [linux amd64] 版本的 Release 包wget https://github.co
博文目录文章目录环境下载安装配置使用环境阿里云ECS(Aliyun Linux 2.1903 LTS 64位)下载https://www.oracle.com/java/technologies/oracle-java-archive-downloads.htmlJava SE 8 (8u202 and earlier) 可以用于商业Java SE 8 (8u211 and later) 不可以用于商业安装tar -zxvf jdk-8u202-linux-x64.tar.gz 得到
博文目录文章目录环境下载安装配置使用环境阿里云ECS(Aliyun Linux 2.1903 LTS 64位)下载https://maven.apache.org/download.cgi安装tar -zxvf apache-maven-3.6.3-bin.tar.gz 得到解压包配置在 /root/.bashrc 文件内添加如下内容export MAVEN_HOME=/mrathena/application/maven-3.6.3export PATH=$JAVA_HOME/
博文目录文章目录嵩山版(2020.08.03)阿里开发手册官网嵩山版(2020.08.03)手册的详细版叫做 码出高效
博文目录文章目录EncodingFontMavenGradleOtherPluginsEncodingsetting 搜索 encodFile | Settings | Editor | File Encodings, 3个 UTF-8File | Settings | Tools | SSH Terminal, 1个 UTF-8Fontsetting 搜索 fontFile | Settings | Editor | FontMavensetting 搜索 mavenFile |
博文目录文章目录环境下载安装配置使用参考环境阿里云ECS(Aliyun Linux 2.1903 LTS 64位)下载http://nginx.org/en/download.htmlhttp://nginx.org/download/nginx-1.18.0.tar.gz选择稳定版(Stable version)下载即可, 分 linux 和 windows 两种, linux 版下载的是源码, 需要自行编译安装tar -zxvf nginx-1.18.0.tar.gz 得到解压包
博文目录文章目录单密钥方式多密钥方式默认生成的 rsa密钥位置在 ~/.ssh, 如 C:Usersmrathena.ssh. 各代码托管平台是可以使用同一个SSH密钥的, 这样最方便, 但是为了更安全也可以配置在不同的平台使用不同的密钥单密钥方式cmd 执行命令 ssh-keygen -t rsa -b 4096 -C "generic", -t type rsa, -b 位数 4096位, 如果不用 -C 指定邮箱, 则会生成一个默认的注释, 该注释无关紧要, 不影响验证选项全部默认(
博文目录文章目录环境下载安装配置使用参考环境阿里云ECS(Aliyun Linux 2.1903 LTS 64位)下载https://github.com/git/git/releaseshttps://codeload.github.com/git/git/tar.gz/v2.28.0, 下载之后可以重命名为 git-2.28.0.tar.gz安装tar -zxvf apache-maven-3.6.3-bin.tar.gz 得到解压包make prefix=/mrathena/a
博文目录文章目录环境下载安装简单配置汉化皮肤JDKMaven简单使用环境阿里云ECS(Aliyun Linux 2.1903 LTS 64位)下载Jenkins 官网, 支持选择中文https://www.jenkins.io/选择 LTS 长期支持版的最新版下载, 这里是 2.235.3 LTS, Generic Java package (.war) 是 java war 包, 可以通过 java -jar jenkins.war 直接运行官网下载 wget http://mir
原因分析 是因为使用了pycharm的版本的问题。并不是flask框架本身的问题(不管你是如何设置的flask配置,通过加载config也好,还是通过run的时候传入形参也好,均不影响) 可以很明显的
背景 兜兜转转以为做测试不用接触这么多编程,结果不仅要接触 py,还要接触 java,还有 elixir,更有 Lua,啊 我绝望了 太久没玩 Java,连导入项目都不会了...特此记录一下侮辱性的时
1. 安装制作工具 mkisofs 2. Linux 操作系统镜像 iso 打包 3. 校验并写入 md5 值
最近在学习 MySQL 的 bin-log 时候考虑到数据备份的问题,突然想到如果能将数据通过 Linux 命令行方式备份到百度网盘,那是一件多么牛逼的事情。百度网盘有免费的 2TB 存储空间,而且有
作为一名开发者,熟悉使用 git 代码管理工具是一项必备的基本技能。git 相较 SVN 而言,其优点不言而喻。git 的功能非常强大,其包括的操作命令也非常的多,但是从实用性而言,很多命令可能我们一
kickstart 能实现 linux 系统的自动化安装,需要设置 ks.cfg 文件,而这个 ks.cfg 文件的生成最好使用 system-config-kickstart 工具生成,比较准确,也
介绍 GitBook是一个基于Node.js的命令行工具,可使用 Github/Git和Markdown来制作精美的电子书,GitBook 并非关 Git的教程。 导出格式有PDF、HTML等,需要添