持续集成

流水线(CloudPipeline)提供可视化、可定制的持续交付流水线服务,实现缩短交付周期和提升交付质量的效果。

前提条件

基于代码库部署:对应构建的应用已经创建了代码库。由于流水线中会涉及到部署,所以对应的镜像仓库和容器云集群等资源也需要提前开通。

基于镜像部署:需要开通镜像仓库和容器云集群资源。

流水线开通

初次使用流水线产品需要经过开通。点击立即开通,跳转应用市场购买开通。

image_16365317863785

流水线管理

流水线现在支持java和npm的构建及部署。

新增流水线

image-20210826092609129

可以通过已有模版配置相应的任务(流水线),支持设置缓存、清除缓存,设置触发规则,自定义环境变量。

基本信息:选择应用、任务模版。

image-20210826100305498

流水线配置:配置流水线任务,命名流水线。

image-20210814133330899

缓存配置:选择缓存目录。

image-20210814133346146

基于JAVA要勾选Maven、Gradle,基于Npm要勾选Npm。(流水线构建失败时,可以尝试重置缓存,重新运行流水线)

企业微信截图_16311759725039

触发规则:目前支持两种触发规则

image-20210814133353505

1.代码触发 (仓库管理员):勾选“代码更新时自动执行”

复制流水线绑定的应用

企业微信截图_16311761394879

在代码托管页面搜索应用

企业微信截图_16311761629401

选中WebHooks

企业微信截图_16311761793106

当可以看见Push、TagPush、PullRequest三个事件时,“代码更新时自动执行”功能开启。

image-20211021162907261

2.定时触发

点击添加,用户根据需求自定义定时规则。

企业微信截图_16311760812630

环境变量:环境变量可以添加在任务配置中,使任务配置参数化。备注:要以${PIPLINE_ID}格式。

image-20210909174526338自定义环境变量设置以后,可以在当前流水线的多个任务配置中写入,用以设置相同的参数。可在新建流水线时,在所有任务中配置环境变量,也可以在已有的流水线配置中编辑更改环境变量。

环境变量示例

1.添加自定义环境变量

image-20210907173811075

2.在任务中添加环境变量

image-20210907174005773

3.运行后通过“执行变量”可查看添加的环境变量

image-20210907174147302

自定义脚本构建流水线任务

在任务管理处,可以新增自定义任务。

image-20210906101729609

在源码处编写groovy语法的脚本,以实现该任务的功能,其中参数化的部分可以使用环境变量(默认大写),也可以自定义参数。点击右侧的(识别代码中的参数)按钮可以获取所有的参数并在下方控件区域显示。

image-20210906101852552

同时针对这些参数,可以在下方编辑不同的控件展示和效验方法。

image-20210910103921277

“编码”与“container”对应的字段一致;

“镜像”里要包含命令里脚本运行需要的环境;

“镜像”来源于镜像仓库。

image-20210910103426724

“源码”说明

例1:

container('maven') {
try{
 result = sh returnStdout: true ,script: 'curl -X POST  -H "X-Auth-Token: ${userToken}" -H "X-Auth-Project: ${PROJECT_ID}" -H "Content-Type: application/json" -H "Authorization: $GATEWAY_TOKEN" -d  "{\\"pipRecordId\\":\\"$PIP_RECORD_ID\\",\\"stageUid\\":\\"${STAGE_UID}\\" ,\\"taskUid\\":\\"${TASK_UID}\\" ,\\"status\\":\\"IN_PROGRESS\\"}"  ${GW_URL}/paas-pipeline/project/v1/pipeline/status'
        code = new JsonSlurper().parseText(result).code
 if(code != "0"){ 
  throw new Exception("failed");
 }
        sh '''${param1}'''
 result = sh returnStdout: true ,script: 'curl -X POST  -H "X-Auth-Token: ${userToken}" -H "X-Auth-Project: ${PROJECT_ID}" -H "Content-Type: application/json" -H "Authorization: $GATEWAY_TOKEN" -d  "{\\"pipRecordId\\":\\"$PIP_RECORD_ID\\",\\"stageUid\\":\\"${STAGE_UID}\\" ,\\"taskUid\\":\\"${TASK_UID}\\" ,\\"status\\":\\"SUCCESS\\"}"  ${GW_URL}/paas-pipeline/project/v1/pipeline/status'
        code = new JsonSlurper().parseText(result).code
 if(code != "0"){ 
  throw new Exception("failed");
 }
}catch(ex){
 echo "errMsg:"+ex
 result = sh returnStdout: true ,script: 'curl -X POST  -H "X-Auth-Token: ${userToken}" -H "X-Auth-Project: ${PROJECT_ID}" -H "Content-Type: application/json" -H "Authorization: $GATEWAY_TOKEN" -d  "{\\"pipRecordId\\":\\"$PIP_RECORD_ID\\",\\"stageUid\\":\\"${STAGE_UID}\\" ,\\"taskUid\\":\\"${TASK_UID}\\" ,\\"status\\":\\"FAILED\\"}"  ${GW_URL}/paas-pipeline/project/v1/pipeline/status'
 code = new JsonSlurper().parseText(result).code
 if(code != "0"){ 
  throw new Exception("failed");
 }
 throw ex
}
}

例2:

container('node') {
try{
 result = sh returnStdout: true ,script: 'curl -X POST  -H "X-Auth-Token: ${userToken}" -H "X-Auth-Project: ${PROJECT_ID}" -H "Content-Type: application/json" -H "Authorization: $GATEWAY_TOKEN" -d  "{\\"pipRecordId\\":\\"$PIP_RECORD_ID\\",\\"stageUid\\":\\"${STAGE_UID}\\" ,\\"taskUid\\":\\"${TASK_UID}\\" ,\\"status\\":\\"IN_PROGRESS\\"}"  ${GW_URL}/paas-pipeline/project/v1/pipeline/status'
       code = new JsonSlurper().parseText(result).code
 if(code != "0"){ 
  throw new Exception("failed");
 }
        sh '''cp /home/jenkins/agent/caches/${TENANT_CODE}/${PROJECT_CODE}/${DEPLOYMENT_CODE}/.npm/.npmrc /root
 echo "node_modules/" > .npmignore
 ${param1}'''
 result = sh returnStdout: true ,script: 'curl -X POST  -H "X-Auth-Token: ${userToken}" -H "X-Auth-Project: ${PROJECT_ID}" -H "Content-Type: application/json" -H "Authorization: $GATEWAY_TOKEN" -d  "{\\"pipRecordId\\":\\"$PIP_RECORD_ID\\",\\"stageUid\\":\\"${STAGE_UID}\\" ,\\"taskUid\\":\\"${TASK_UID}\\" ,\\"status\\":\\"SUCCESS\\"}"  ${GW_URL}/paas-pipeline/project/v1/pipeline/status'
        code = new JsonSlurper().parseText(result).code
 if(code != "0"){ 
  throw new Exception("failed");
 }
}catch(ex){
 echo "errMsg:"+ex
 result = sh returnStdout: true ,script: 'curl -X POST  -H "X-Auth-Token: ${userToken}" -H "X-Auth-Project: ${PROJECT_ID}" -H "Content-Type: application/json" -H "Authorization: $GATEWAY_TOKEN" -d  "{\\"pipRecordId\\":\\"$PIP_RECORD_ID\\",\\"stageUid\\":\\"${STAGE_UID}\\" ,\\"taskUid\\":\\"${TASK_UID}\\" ,\\"status\\":\\"FAILED\\"}"  ${GW_URL}/paas-pipeline/project/v1/pipeline/status'
 code = new JsonSlurper().parseText(result).code
 if(code != "0"){ 
  throw new Exception("failed");
 }
 throw ex
}
}

groovy脚本内容说明

  1. 如上,sh''' ''' 中的内容为用户自定义编写内容(如例2中的sh '''cp /home/jenkins/agent/caches/${TENANT_CODE}/${PROJECT_CODE}/${DEPLOYMENT_CODE}/.npm/.npmrc /root echo "node_modules/" > .npmignore ${param1}''')

  2. container('node') { try{ result = sh returnStdout: true ,script: 'curl -X POST -H "X-Auth-Token: ${userToken}" -H "X-Auth-Project: ${PROJECT_ID}" -H "Content-Type: application/json" -H "Authorization: $GATEWAY_TOKEN" -d "{\"pipRecordId\":\"$PIP_RECORD_ID\",\"stageUid\":\"${STAGE_UID}\" ,\"taskUid\":\"${TASK_UID}\" ,\"status\":\"IN_PROGRESS\"}" ${GW_URL}/paas-pipeline/project/v1/pipeline/status'

       code = new JsonSlurper().parseText(result).code
    

    if(code != "0"){ throw new Exception("failed"); }

    以上为脚本开始状态的回调,需写在自定义命令前(不需要修改,可直接复制)

  3. result = sh returnStdout: true ,script: 'curl -X POST -H "X-Auth-Token: ${userToken}" -H "X-Auth-Project: ${PROJECT_ID}" -H "Content-Type: application/json" -H "Authorization: $GATEWAY_TOKEN" -d "{\"pipRecordId\":\"$PIP_RECORD_ID\",\"stageUid\":\"${STAGE_UID}\" ,\"taskUid\":\"${TASK_UID}\" ,\"status\":\"SUCCESS\"}" ${GW_URL}/paas-pipeline/project/v1/pipeline/status'

    code = new JsonSlurper().parseText(result).code
    

    if(code != "0"){ throw new Exception("failed"); } }catch(ex){ echo "errMsg:"+ex result = sh returnStdout: true ,script: 'curl -X POST -H "X-Auth-Token: ${userToken}" -H "X-Auth-Project: ${PROJECT_ID}" -H "Content-Type: application/json" -H "Authorization: $GATEWAY_TOKEN" -d "{\"pipRecordId\":\"$PIP_RECORD_ID\",\"stageUid\":\"${STAGE_UID}\" ,\"taskUid\":\"${TASK_UID}\" ,\"status\":\"FAILED\"}" ${GW_URL}/paas-pipeline/project/v1/pipeline/status' code = new JsonSlurper().parseText(result).code if(code != "0"){ throw new Exception("failed"); } throw ex } }

​ 以上为结束状态的回调及异常处理,写在自定义命令后(不需要修改,可直接复制)

串行与并行

流水线支持配置串行任务与并行任务。

image-20210826091744463

image-20210906153855528

运行流水线

image-20210302191246967

流水线详情

左侧为执行历史,点击可以查看执行历史的配置。

点击详细日志,可以查看运行日志,点击每个阶段的右上角可以查看每个阶段的日志。执行历史编号是递增的,每执行一次生成一个记录;

点击执行变量可以查看流水线运行时有哪些变量赋值;

点击每个阶段的任务,可以查看历史任务的配置详情;

image-20210814134038530

重新执行

重新执行有两类,一类是整条流水线重新执行,另一类是点击阶段的右上角,是从当前阶段开始重新执行。

image-20210826100404241

任务配置

当前支持的任务:

  • 获取源码
  • JAVA构建
  • node.js构建
  • Maven单元测试
  • JAVA制品上传
  • npm制品上传
  • 镜像构建
  • 容器部署
  • 条件执行
  • 代码扫描

用户可根据自己的需求配置对应的任务。

获取源码

用户可针对该应用,选择对应的仓库和分支。

仓库:选择发布单元仓库地址。

分之:选择对应的分支。

image-20210825103710186

JAVA构建

任务名称:输入任务名称。

jdk版本:选择jdk版本(目前只支持 java1.8 版本)。

构建命令:默认命令如图,用户可根据自身需求修改命令。

企业微信截图_16298594218073

node.js构建

任务名称:输入任务名称。

构建:默认命令如图,用户可根据自身需求修改命令。

node-version:选择node-version版本(目前只支持12.22.1版本)。

企业微信截图_16297957903106

Maven单元测试

任务名称:输入任务名称。

是否执行:勾选任务是否执行。

企业微信截图_16297954424879

前提条件:

pom配置jacoco:

unittest-01

本地跑单元测试命令,本地代码存放目录不要带有中文 mvn clean install -Dmaven.test.failure.ignore=true 在本地 target/site 目录中生成测试测试报告,打开index.html文件可以查看详情 请确保可以正确生成测试报告,并且观察日志,跑本地单元测试时没有启动应用,否则自行调整至成功!!! 目录结构大致如下:

unittest-02

python单元测试

当前暂时无法支持python语言的单元测试

python语言本地生成代码覆盖率报告的操作如下:

引用pytest和coverage模块 pip install pytest coverage 运行单元测试并生成报告的命令pytest tests/ --cov={项目指定目录} --cov-report=html --cov-report=term-missing 在本地根目录中会生成对应的报告目录如下: unittest-03 报告内容为: unittest-04

JAVA制品上传

任务名称:输入任务名称。

jdk版本:选择jdk版本

构建:默认命令如图,用户可根据自身需求修改命令。

企业微信截图_16297957319401

npm制品上传

任务名称:输入任务名称。

node版本:选择node版本。

上传:默认命令如图,用户可根据自身需求修改命令。

企业微信截图_16297953162630

镜像构建

任务名称:输入任务名称。

镜像名称:镜像地址,默认如图中所示,用户可自定义进行编辑。

镜像标签:对应镜像地址的版本标签,默认如图中所示,用户可自定义进行编辑。

Dockerfile路径:Dockerfile路径为Dockerfile文件相对于代码库根目录所在路径,如META/config/Dockerfile或Dockerfile,默认为“.”当前路径,用户可自定义进行编辑。

Dockerfile命令执行上下文路径:Docker build命令执行上下文路径。填写相对于代码根目录的路径,如target,默认为“.”当前路径,用户可自定义进行编辑。

是否使用缓存:缓存使用开关,关闭则在构建镜像时不使用缓存。

企业微信截图_16297958405768

容器部署

任务名称:自定义任务名称。

部署资源组:选择资源组,即指定部署的目标集群命名空间位置。用户在天枢控制台提前配置。

部署名称:部署后,显示的发布单元名称,默认为应用的CODE,用户可自定义进行编辑。

镜像名称:部署所指定的镜像地址,默认为流水线镜像构建的地址,用户可自定义进行编辑。

部署规模:选择POD的资源限制,默认每个PODlimit为1CPU, 2G内存,用户可根据实际情况自定义进行选择。

部署副本:为POD的实例副本数,用户可根据实际情况进行填写。

环境变量:对发布单元进行标签和环境变量的设置,用户可根据需求进行填写。

企业微信截图_16297960113785

虚拟机部署

image-20210910110533581

image-20210910110549272

部署资源组:资源组来源于项目。

先为虚拟机创建资源组,然后才能在虚拟机部署任务里找到虚拟机资源组(包含一台或多台虚拟机)。

image-20210910111042958

脚本:来源于“脚本管理”, 只有管理员可以新建脚本。

image-20210910111406271

部署参数:脚本的参数。

制品:支持上传功能(脚本文件)。

路径:脚本文件会被推送到资源组里包含的所有虚拟机的该路径上。

鼠标停留(虚拟机部署任务,悬停在哪个ip上展示哪个地址的内容)或日志(“详细日志”)里可以看到脚本输出内容。

image-20210910111601819

条件执行

执行条件:支持用户用groovy语法进行条件编辑。常规用法:"$RUN_USER_CODE" == "caoyf001" 判断当前流水线的执行人是否为caoyf001、"$MANUAL_INVASION" == "通过" 判断人工卡点结果为通过 设置条件通过后,才会执行下面的任务列表。

image-20210907180904298

嵌套流水线

任务名称:填写任务名称。

目标流水线:选择需要启动的流水线。(嵌套的流水线需和原流水线在同一项目)

支持在流水线中,嵌入其他的流水线,实现过程中进行流水线嵌套。

企业微信截图_16297963428086

人工卡点

任务名称:填写任务名称。

审核人:输入审核人员。

卡点选择项:编辑卡点选择项。

支持再流水线配置中设置人工卡点,在流水线运行到该阶段时,会暂停,对应的审核人审批通过后,才能继续运行。

企业微信截图_1629796399543

流水线待审批时会给审核人发送短信、邮件。

待审批界面

image-20210910102040219

短信、邮件通知

image-20210910101940094

image-20210910101958125代码扫描

在流水线中插入“代码扫描”任务

image-20210909174656706

设置“质量门禁”,当扫描结果为failed时,流水线不会执行“代码扫描”后的任务。

image-20210909174738982

获取内源中心代码

若你在内源中心拥有一个代码仓库,想在流水线去拉取内源中心代码,可以使用如下任务卡片:

image-20220627144959739

若租户下拉框内容为空,请联系内源中心的仓库管理员协助你加入租户

image-20220627145059739

自定义任务

可基于镜像部署流水线(需要开通镜像仓库和容器云集群资源)

1.在镜像中心上传本地镜像

企业微信截图_16311753964958

2.复制镜像地址

企业微信截图_16311754193453

企业微信截图_16311754701830

企业微信截图_16311755221799

3.在流水线中配置“部署”任务(不需要获取源码),将镜像地址粘贴至“镜像名称”。点击确定即可通过镜像构建流水线任务。

企业微信截图_16311756212275

模板管理

系统准备了标准的java和node.js流水线模板,如果需要自定义模板,可以在此新建编辑。备注:后续会补充go基础模版

image-20210814135554563

任务管理

任务管理中支持用户自定义任务内容,然后用于流水线的配置中(在新建流水线中可选择配置好的任务模版)。

image-20210814135635530

任务运行的环境,用户可以自定义镜像,可以将打包好的镜像填在此处支持任务运行的环境。

image-20210909101019052

流程对接

配置第三方对接系统的基础信息。

对接系统

接入新系统

image_16360974364958

系统地址:发起流程时调用的API地址。

API认证:发起流程时调用的API认证方式,REST类型:GET,POST等信息的描述。

image_16360974733453

对接系统详情

右侧编辑按钮,可对对接系统进行编辑、删除(管理员)操作。

image_16360975061830

image-20211105155608366

流程表单

新建表单

image_16360975922630

image_16360975675039

表单详情

右侧编辑按钮,可对表单进行编辑、删除(管理员有权限)的操作。

image_16360976284879

脚本管理

脚本用于构建虚拟机部署任务。

新建脚本

image_16360976799401

输入脚本名称,选择执行角色、脚本类型,输入脚本内容、可直接上传本地文件作为脚本内容,输入脚本描述。

image_16360976963106

脚本详情

右侧编辑按钮可对脚本进行编辑、删除(管理员有权限进行删除)的操作。

image_16360977165768

image_16360977433785

流水线对接

该功能还未有系统进行对接,敬请期待。

results matching ""

    No results matching ""