楔子

上篇文章解决了提交/合并请求自动触发的需求,但所有前端模块都在同一个代码仓库里,如何获取变更文件路径确定要发布哪个模块呢?本文将带你解决这个问题。

思路

分别解决 3 个问题:

  1. 获取变更的文件列表
  2. 根据文件列表判断所属模块
  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].itemsfor (int j = 0; j < entries.length; j++) {def entry = entries[j]changedFiles.addAll(entry.getAffectedPaths());}}println '输出修改文件列表:' + changedFilesreturn 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/testdef modulePath = filePath.substring(0, index)println 'add module path: ' + modulePathmodulePaths.add(modulePath)}}println '输出待发布模块列表:' + modulePathsreturn modulePaths;
}

写个构建发布 Shell 脚本

publish-web-module.sh

#!/bin/bash
#此脚本用于构建发布前端模块,@author: Hellxz
#$1:发布版本/$2:模块目录
set -euecho "------------开始发布$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=devrelativeTarget="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].itemsfor (int j = 0; j < entries.length; j++) {def entry = entries[j]changedFiles.addAll(entry.getAffectedPaths());}}println '输出修改文件列表:' + changedFilesreturn 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/testdef modulePath = filePath.substring(0, index)println 'add module path: ' + modulePathmodulePaths.add(modulePath)}}println '输出待发布模块列表:' + modulePathsreturn modulePaths;
}

仅供抛砖引玉,抽取出来的方法本人将它们放到共享库中,写脚本就更清晰简短了。

还有什么问题

  • 首次构建会识别不到提交记录,可能会漏发一次
  • 切到未构建过的分支,也会漏发一次
  • 限于文章篇幅,未添加手动传参指定模块发布的功能

对于多分支首次检出漏发的问题,这是因为没有上一个可供参考的相同分支提交ID作参考,本身不是技术问题,预先将所有前端发版分支提交点内容,只要构建触发了,后续就不会再漏发了。

最后

希望对您能有所启发,如果您有更优雅的实现方式 或者 文中有错误,希望您能不吝赐教评论指出,感谢。

本文同步发布于博客园(东北小狐狸 https://www.cnblogs.com/hellxz/)与CSDN(东北小狐狸-Hellxz https://blog.csdn.net/u012586326)禁止转载。

Jenkins教程(八)实现 GitLab 触发 Jenkins 自动按模块发布前端相关推荐

  1. [3] Jenkins 系列:如何获取触发Jenkins Job的用户信息?

    Jenkins提供两种方式的Script,一种是基于声明式的,一种是基于脚本式的. Jenkins申明式的格式 Jenkins脚本式的格式 Jenkins 官方推荐使用申明式的方式定义Jenkins的 ...

  2. Jenkins教程(一)安装Jenkins

    前言 写了好久Jenkins的脚本了,写得虽然不是太好,但是可以基本满足需要,最近比较忙,这个月也没怎么更新博客,开始更新Jenkins这个系列的文章,打算从安装Jenkins -> 流水线工程 ...

  3. Gitlab自动触发Jenkins构建打包

    一.目的 在部门的测试环境中,开发人员一旦向gitlab仓库提交成功代码,gitlab就会自动触发jenkins构建项目.当然在构建后还可以添加项目部署或者自动化测试的脚本.这里只针对测试环境. 二. ...

  4. GitLab 自动触发 Jenkins 构建

    GitLab 是当前应用非常广泛的 Git Hosting 工具,Jenkins 是非常牛逼的持续集成工具.尽管 GitLab 有内建的 GitLab CI,但它远没有 Jenkins 那么强大好用. ...

  5. P8-07-23 在 GitLab 提交代码后自动触发 Jenkins 构建;使用禅道进行项目管理

    DevOps 运维开发一体化 持续集成 CI GitLab 用户分组 添加用户 用户权限 访客 开发者 Dev/master主分支 测试 主管 拥有者 里程碑:项目管理与质量管理 禅道(免费开源版本) ...

  6. gitlab hook触发jenkins自动构建

    意义,gitlab推送或合并代码后触发jenkin自动构建发布代码或者执行命令推送规则 1.安装gitlab和hook插件 有时需要重启jenkins服务,可能兼容性问题,安装完之后构建中看不到hoo ...

  7. Gitlab自动触发Jenkins构建项目

    Gitlab自动触发Jenkins构建项目 一.前提 Gitlab已安装配置好. Jenkins已安装Gitlab plugin. 二.配置jenkins中Job 1.勾选触发器下的gitlab触发器 ...

  8. Gitlab通过Webhook自动触发Jenkins构建任务并在更新完毕后发送钉钉消息通知

    Gitlab通过Webhook自动触发Jenkins构建任务并在更新完毕后发送钉钉消息通知 文章目录 Gitlab通过Webhook自动触发Jenkins构建任务并在更新完毕后发送钉钉消息通知 1.实 ...

  9. 码云Webhook触发Jenkins自动构建 - Jenkins演练(一)

    今天自己看着插件文档摸索了一下,实现了git push后Webhook自动触发Jenkins进行代码构建,可通用gitlab.github等平台,中文关于这方面自动部署的文档比较少,所以把我的学习过程 ...

  10. 通过URL自动触发Jenkins构建任务

    方法一: 进入jenkins安全设置,开启安全域及授权策略 2.在用户设置处生成api token,复制生成的token 3.选择测试项目-配置-构建触发器,选择触发远程构建,将token粘贴在身份验 ...

最新文章

  1. linux命令tar
  2. coreldraw 导入面料_Coreldraw文件导入Photoshop方法
  3. 第十章 使用机器学习的建议-机器学习老师板书-斯坦福吴恩达教授
  4. bigpipe merge对F5做批量配置
  5. 双向链表VS单向链表
  6. 第五章(1)Libgdx应用框架之生命周期
  7. 对一个可进行带括号 加减乘除运算类的分析
  8. redis学习笔记之虚拟内存
  9. 请阐述调用Activity有哪几种方法,并写出相关的Java代码
  10. k近邻算法matlab实现_k近邻算法
  11. java cp命令:命令行指定需要加载的类classpath
  12. Ognl表达式(根据Apache-Ognl文档直译)
  13. Ubuntu中的截图工具
  14. Ubuntu没有屏幕亮度调节怎么调整屏幕亮度?
  15. HDU-4826 Labyrinth
  16. 知识图谱中三元组抽取
  17. 设置时区serverTimezone
  18. 用电脑“自动生成”的图书
  19. 1.0django入门01
  20. 基本算术运算优先级(高到低)

热门文章

  1. 《Excel VBA实战技巧精粹》终于登场了
  2. 蓝桥杯——练习系统登录
  3. 博士德霸道软件_霸道+远程版7.0
  4. 高性能mysql 3 pdf下载_《高性能MySQL_第3版》PDF版本下载
  5. Java面试宝典大集锦
  6. mysql下载安装安装包_mysql下载安装包及安装步骤
  7. python制作简单文本编辑器
  8. 【实用软件工程】知识点
  9. 《概率论与数理统计》(浙大第四版)第三章总结笔记(纯手写)
  10. JavaSocket编程的一个简单例子