如何在Jenkins构建后生成含变更内容及对应路径的增量更新包
需求可行性结论
该需求完全可以实现,核心逻辑是对比两次构建之间的产物差异,筛选出变更文件后按部署目录结构打包,全程不需要修改FTP传输的强制要求,仅调整Jenkins流水线逻辑即可落地。
核心实现思路
- Jenkins侧保留上一次成功构建的产物哈希清单(包含文件路径、MD5/SHA1校验值),也可以直接保留上一次的完整产物目录用于对比
- 本次构建完成后,遍历本次所有构建产物,和上一次的哈希清单逐文件对比,筛选出新增、修改、删除的文件列表
- 按照目标服务器的部署目录结构,把新增/修改的文件按对应路径打包成增量更新包,同时生成变更记录文件(标注需要替换的文件路径、需要删除的废弃文件路径)
- 下载增量包后,先根据变更记录删除服务器上的废弃文件,再通过FTP把增量包里的文件按路径上传覆盖即可,无需全量替换。
可用的Jenkins插件及工具
- Files Changed Plugin:可以直接提取两次构建之间版本控制系统(Git/SVN)的变更文件列表,如果你的构建产物目录结构和代码仓库结构一一对应,直接用这个插件输出的变更列表筛选产物即可,不需要额外做哈希对比,执行效率最高。
- Pipeline Utility Steps Plugin:提供了
hashFiles、readJSON、writeJSON、zip等流水线内置方法,可以非常方便的生成产物文件哈希清单、对比差异、打包增量更新包,不需要额外安装外部工具。 - FTP Plugin:如果后续想把增量包的上传步骤也集成到Jenkins中,这个插件支持基于文件列表的定向FTP上传,不需要传输全量文件,完全符合不得更换FTP传输的限制要求。
- Groovy Script Plugin:如果有自定义的差异筛选逻辑(比如需要忽略临时文件、本地配置文件的变更),可以直接在流水线中写Groovy脚本实现自定义规则的差异对比。
简易流水线示例代码片段
pipeline { agent any stages { stage('常规构建') { steps { // 替换为你的原有构建逻辑,产物最终输出到dist目录 sh 'npm run build' } } stage('生成增量更新包') { steps { script { def lastHashList = [:] // 读取上一次成功构建的哈希清单,首次构建直接生成全量包 if (currentBuild.previousSuccessfulBuild) { lastHashList = readJSON file: "${currentBuild.previousSuccessfulBuild.artifactManager.root}/hash-list.json" } // 生成当前构建的产物哈希清单 def currentHashList = [:] def distFiles = findFiles glob: 'dist/**/*' distFiles.each { file -> if (!file.directory) { currentHashList[file.path] = sha1(file: file.path) } } // 筛选出所有变更文件 def changedFiles = currentHashList.entrySet().findAll { entry -> lastHashList[entry.key] != entry.value }.collect { it.key } // 按原有目录结构打包变更文件 zip zipFile: 'incremental-update.zip', archive: true, dir: 'dist', glob: changedFiles.join(',') // 保存本次哈希清单供下一次构建对比使用 writeJSON file: 'hash-list.json', json: currentHashList archiveArtifacts artifacts: 'hash-list.json', fingerprint: true } } } } }
注意事项
- 首次构建时会生成全量更新包,从第二次成功构建开始就会自动生成增量包
- 如果构建过程会对产物文件做随机字符串注入(比如前端资源的哈希后缀),需要提前适配这类文件的命名规则,避免误判为变更文件
- 建议每次增量更新前备份服务器上的对应文件,避免更新出错无法回滚
内容的提问来源于stack exchange,提问作者Akshay Jain
相关产品推荐
相关产品推荐

