Jenkins教程(八)实现 GitLab 触发 Jenkins 自动按模块发布前端
楔子
上篇文章解决了提交/合并请求自动触发的需求,但所有前端模块都在同一个代码仓库里,如何获取变更文件路径确定要发布哪个模块呢?本文将带你解决这个问题。
思路
分别解决 3 个问题:
- 获取变更的文件列表
- 根据文件列表判断所属模块
- 构建与发布脚本
过程
GitLab 事件触发 Jenkins 构建只是一个启动信号,获取变更文件列表需要知晓上一次构建时某个仓库的版本号,这里 Jenkins 的插件 git-plugin 已经帮我们实现了这部分工作。所以只需要通过 git-plugin 检出代码即可。
检出代码
checkout([
$class: 'GitSCM',
branches: [[name: "*/$branchName"]],
doGenerateSubmoduleConfigurations: false,
extensions: [
[$class: 'RelativeTargetDirectory',
relativeTargetDir: "$relativeTarget"]
],
submoduleCfg: [],
userRemoteConfigs: [
[credentialsId: "$credentialsId", url: "$gitUrl"]
]
])
请自行替换
$branchName为分支名,$relativeTarget为检出相对路径,$credentialsId为用户凭据,$gitUrl即 GIT仓库地址。
获取变更文件列表
//获取变更文件列表,返回HashSet,注意添加的影响文件路径不含仓库目录名
@NonCPS
def getChangeFilePathSet() {
def changedFiles = new HashSet<String>();
echo "开始获取变更的文件列表"
for (int i = 0; i < currentBuild.changeSets.size(); i++) {
def entries = currentBuild.changeSets[i].items
for (int j = 0; j < entries.length; j++) {
def entry = entries[j]
changedFiles.addAll(entry.getAffectedPaths());
}
}
println '输出修改文件列表:' + changedFiles
return changedFiles;
}
这个方法可以放到 pipeline 块外,直接在 script 块中引用。实现思路是访问 currentBuild.changeSets 获取所有本次构建相比上次构建的变更列表,返回的是 HashSet 是为了方便,用其他容器也是可以的。
注意:变更文件列表的各个文件是相对于它所在仓库的路径!
变更文件列表截字符串,获取模块列表并去重
//获取合并报表前端自动发布模块set集合。
//pathPrefix为模块路径前缀,如develop/@gc
@NonCPS
def getAutoPublishModuleSet(pathPrefix) {
//使用Set容器去重,保证待发布模块只有一份
def modulePaths = new HashSet<String>();
for(def filePath in getChangeFilePathSet()){
//忽略非前端模块的文件,比如 Jenkinsfile 等
if(filePath.startsWith(pathPrefix)){
//从超过模块前缀长度的下标开始,获取下一个/的位置。即分串位置
int index = filePath.indexOf('/', pathPrefix.length()+1)
//分串得到模块路径,比如 develop/@gc/test
def modulePath = filePath.substring(0, index)
println 'add module path: ' + modulePath
modulePaths.add(modulePath)
}
}
println '输出待发布模块列表:' + modulePaths
return modulePaths;
}
写个构建发布 Shell 脚本
publish-web-module.sh
#!/bin/bash
#此脚本用于构建发布前端模块,@author: Hellxz
#$1:发布版本/$2:模块目录
set -eu
echo "------------开始发布$2模块------------>"
cd $2
echo "清理dist node_modules package-lock.json ……"
rm -rf dist node_modules package-lock.json
echo "正在安装依赖 ……"
npm i
echo "开始构建 ……"
npm run build:dev
echo "开始发布 ……"
npm --no-git-tag-version version $1
npm publish
echo "<------------发布$2模块完成------------"
cd ${WORKSPACE}/web; #回到前端源码目录
exit 0;
循环调用构建发布脚本
for(def modulePath in modulePaths){
sh label: "构建发布前端模块 ${publishVersion} ${modulePath}",
script: "bash ${SHELL_PATH}/publish-web-module.sh ${publishVersion} ${modulePath}"
}
流水线示例
需将下列 Jenkinsfile 与 publish-web-module.sh 提交到同一仓库中
Jenkinsfile
pipeline{
agent any;
environment{
gitUrl="http://xxxxxxxx/xxxx/web.git"
branchName=dev
relativeTarget="web"
credentialsId=credentials('git-user')
pathPrefix="develop/@gc"
publishVersion="v1.0"
npmRepo="http://xxxxxx/nexus/repository/npm-public/"
npmToken=credentials('npm-token')
shellPath="${WORKSPACE}/jenkins" //脚本与Jenkinsfile在同级目录中
}
stages{
stage("检出代码"){
steps{
script {
cleanWs()
checkoutRepo("master", "jenkins", "${credentialsId}", "http://xxxxxxxx/xxxx/jenkins.git")
checkoutRepo("${branchName}", "${relativeTarget}", "${credentialsId}", "${gitUrl}")
}
}
}
stage("构建发布"){
steps{
script{
sh label: "设置npm仓库", script: "npm set registry ${npmRepo}"
sh label: "登录npm仓库", script: "npm config set //xxxxxx/nexus/repository/npm-public/:_authToken ${npmToken}"
def modulePaths = getAutoPublishModuleSet(env.pathPrefix)
for(def modulePath in modulePaths){
sh label: "构建发布前端模块 ${publishVersion} ${modulePath}",
script: "bash ${shellPath}/publish-web-module.sh ${publishVersion} ${modulePath}"
}
}
}
post{
always{
script{
cleanWs()
}
}
}
}
}
}
//抽取检出代码方法
@NonCPS
def checkoutRepo(branchName, relativeTarget, credentialsId, gitUrl){
checkout([
$class: 'GitSCM',
branches: [[name: "*/$branchName"]],
doGenerateSubmoduleConfigurations: false,
extensions: [
[$class: 'RelativeTargetDirectory',
relativeTargetDir: "$relativeTarget"]
],
submoduleCfg: [],
userRemoteConfigs: [
[credentialsId: "$credentialsId", url: "$gitUrl"]
]
])
}
//获取变更文件列表,返回HashSet,注意添加的影响文件路径不含仓库目录名
@NonCPS
def getChangeFilePathSet() {
def changedFiles = new HashSet<String>();
echo "开始获取变更的文件列表"
for (int i = 0; i < currentBuild.changeSets.size(); i++) {
def entries = currentBuild.changeSets[i].items
for (int j = 0; j < entries.length; j++) {
def entry = entries[j]
changedFiles.addAll(entry.getAffectedPaths());
}
}
println '输出修改文件列表:' + changedFiles
return changedFiles;
}
//获取合并报表前端自动发布模块set集合。
@NonCPS
def getAutoPublishModuleSet(pathPrefix) {
//使用Set容器去重,保证待发布模块只有一份
def modulePaths = new HashSet<String>();
for(def filePath in getChangeFilePathSet()){
//忽略非前端模块的文件,比如 Jenkinsfile 等
if(filePath.startsWith(pathPrefix)){
//从超过模块前缀长度的下标开始,获取下一个/的位置。即分串位置
int index = filePath.indexOf('/', pathPrefix.length()+1)
//分串得到模块路径,比如 develop/@gc/test
def modulePath = filePath.substring(0, index)
println 'add module path: ' + modulePath
modulePaths.add(modulePath)
}
}
println '输出待发布模块列表:' + modulePaths
return modulePaths;
}
仅供抛砖引玉,抽取出来的方法本人将它们放到共享库中,写脚本就更清晰简短了。
还有什么问题
- 首次构建会识别不到提交记录,可能会漏发一次
- 切到未构建过的分支,也会漏发一次
- 限于文章篇幅,未添加手动传参指定模块发布的功能
对于多分支首次检出漏发的问题,这是因为没有上一个可供参考的相同分支提交ID作参考,本身不是技术问题,预先将所有前端发版分支提交点内容,只要构建触发了,后续就不会再漏发了。
最后
希望对您能有所启发,如果您有更优雅的实现方式 或者 文中有错误,希望您能不吝赐教评论指出,感谢。
本文同步发布于博客园(东北小狐狸 https://www.cnblogs.com/hellxz/)与CSDN(东北小狐狸-Hellxz https://blog.csdn.net/u012586326)禁止转载。
Jenkins教程(八)实现 GitLab 触发 Jenkins 自动按模块发布前端的更多相关文章
- 持续集成之④:GitLab触发jenkins构建项目
持续集成之④:GitLab触发jenkins构建项目 一:目的为在公司的测试环境当中一旦开发向gitlab仓库提交成功代码,gitlab通知jenkins进行构建项目.代码质量测试然后部署至测试环境, ...
- Gitlab触发jenkins并获取项目post参数
jenkins -- Generic Webhook Trigger插件 此插件是git webhook的高阶应用,安装后会暴露出来一个公共API,GWT插件接收到 JSON 或 XML 的 HTTP ...
- gitlab与jenkins结合构建持续集成
Jenkins是java编写,需要安装JDK,这里采用 yum 安装,对版本有需求的,可以到 oracle 官网下载 JDK. yum install -y java-1.8.0-openjdk 一. ...
- Gitlab自动触发Jenkins构建打包
一.目的 在部门的测试环境中,开发人员一旦向gitlab仓库提交成功代码,gitlab就会自动触发jenkins构建项目.当然在构建后还可以添加项目部署或者自动化测试的脚本.这里只针对测试环境. 二. ...
- Gitlab源码库里代码提交后,如何触发jenkins自动构建?
版本库里代码提交后,如何触发jenkins自动构建?这是一个面试题,感觉自己回答的并不好,因为并没有用过这个功能,之前公司实际项目用的是svn版本管理,一般都用立刻构建,和定时任务构建(不管代码是否有 ...
- jenkins+gitlab webhooks 实现自动触发打包
说明:实现代码在gitlab上的提交后立马自动进行jenkins的job构建 安装插件: Gitlab Hook Plugin Build Authorization Token Root Plug ...
- 配置GitLab Push 自动触发Jenkins构建
配置GitLab Push 自动触发Jenkins构建 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 本篇博客是对之前的笔记:https://www.cnblogs.com/yin ...
- Jenkins + GitLab 通过 Webhook 自动触发构建爬坑记录
前言 在局域网搭建了一个Jenkins服务,用于自动构建和发布,在调通了构建程序之后,想使用内网的GitLab的Webhook功能触发代码推送事件,然后进行自动构建.后来发现在GitLab上做测试 ...
- GitLab 自动触发 Jenkins 构建
GitLab 是当前应用非常广泛的 Git Hosting 工具,Jenkins 是非常牛逼的持续集成工具.尽管 GitLab 有内建的 GitLab CI,但它远没有 Jenkins 那么强大好用. ...
随机推荐
- 重新整理 .net core 周边阅读篇————AspNetCoreRateLimit 之规则[二]
前言 本文和上文息息相关. https://www.cnblogs.com/aoximin/p/15315102.html 是紧接着上文invoke来书写的,那么现在来逐行分析invoke到底干了啥. ...
- jenkins+allure中测试包括为空,没有数据
- Shell 编程 基础用法
Shell 编程 更改shell脚本权限 chmod u+x shell.sh 标准头部写法 #! /bin/bash #! /bin/dash 变量使用 a=10 print $a 读取命令行参数 ...
- UltraSoft - DDL Killer - Alpha 项目展示
团队介绍 CookieLau fmh 王 FUJI LZH DZ Monster PM & 后端 前端 前端 前端 后端 后端 软件介绍 项目简介 项目名称:DDLKiller 项目描述:&q ...
- 转:Linux常用命令总结
学习linux也有一阵子了,现总结一些常用的linux操作命令,方便大家查找1. cd命令这个命令是最基本的也是最常用的.它用于切换当前目录,可以是绝对路径,也可以是相对路径.例:cd /root/h ...
- dubbo 配置 loadbalance 不生效?撸一把源码
背景 很久之前我给业务方写了一个 dubbo loadbalance 的扩展(为了叙述方便,这个 loadbalance 扩展就叫它 XLB 吧),这两天业务方反馈说 XLB 不生效了 我心想,不可能 ...
- Redis安装、配置和卸载
1.安装 mkdir /usr/local/redis 添加目录 wget [http://download.redis.io/releases/redis-4.0.1](http://downloa ...
- Linux&C open creat read write lseek 函数用法总结
一:五个函数的参数以及返回值. 函数 参数 返回值 open (文件名,打开方式以及读 ...
- centos redhat 安装g++
正确安装命令 : yum install gcc-c++ libstdc++-devel 安装后可以在/bin/找到
- 什么是SimpleNVR流媒体服务器软件?
SimpleNVR是一款新兴流媒体服务器应用软件,占用内存少,无插件.跨平台,应用非常广泛,操作简单易上手,同时还支持一键观看,十分便捷.另外,跟其他一般流媒体服务器不同,SimpleNVR支持开发者 ...