如何在Jenkins中处理语义化版本控制(构建号重置场景)
我之前从TeamCity迁移到Jenkins时,也遇到过一模一样的语义化版本管理和构建文件夹冲突问题,结合你的Jenkins 2.89.4版本和Vue前端、Python后端的场景,给你一套落地可行的方案:
核心思路:解耦Jenkins BUILD_NUMBER与语义化版本号
Jenkins默认用BUILD_NUMBER命名构建文件夹的机制是硬伤,重置后必然会覆盖旧工件。所以我们要把语义化版本号作为独立的标识,完全和BUILD_NUMBER解耦,工件存储、版本递增都围绕语义化版本号来做。
步骤1:用脚本/插件管理语义化版本的自动递增
方案A:无插件纯脚本实现(推荐,兼容性好)
在代码仓库根目录维护一个version.txt文件,用来存储当前的语义化版本(比如1.3.1_develop.1),每次构建前用Shell/Python脚本读取并递增版本号,构建后更新文件并提交回仓库:
Shell脚本示例(适配分支策略)
#!/bin/bash # 读取当前版本 CURRENT_VERSION=$(cat version.txt) # 拆分版本各部分(以1.3.1_develop.1为例) # 主版本:1,次版本:3,补丁版本:1,分支后缀:develop,构建序号:1 MAIN_VER=$(echo "$CURRENT_VERSION" | cut -d. -f1) MINOR_VER=$(echo "$CURRENT_VERSION" | cut -d. -f2) PATCH_VER=$(echo "$CURRENT_VERSION" | cut -d. -f3 | cut -d_ -f1) BRANCH_TAG=$(echo "$CURRENT_VERSION" | cut -d_ -f2 | cut -d. -f1) BUILD_NUM=$(echo "$CURRENT_VERSION" | cut -d. -f4) # 递增构建序号 NEW_BUILD_NUM=$((BUILD_NUM + 1)) NEW_VERSION="${MAIN_VER}.${MINOR_VER}.${PATCH_VER}_${BRANCH_TAG}.${NEW_BUILD_NUM}" # 主分支(main/master)使用正式版本号(无分支后缀) if [ "$BRANCH_NAME" = "main" ]; then NEW_VERSION="${MAIN_VER}.${MINOR_VER}.${PATCH_VER}" fi # 更新版本文件 echo "$NEW_VERSION" > version.txt # 提交版本变更到仓库(需确保Jenkins有代码仓库的读写权限) git add version.txt git commit -m "Auto bump version to $NEW_VERSION" git push origin "$BRANCH_NAME"
方案B:使用Jenkins插件
如果偏好插件,可以试试Semantic Versioning Plugin(注意确认与Jenkins 2.89.4的兼容性),它能帮你解析、递增语义化版本号,不过灵活性不如自定义脚本。
步骤2:修改工件存储路径,避免文件夹冲突
不要依赖Jenkins默认的$JENKINS_HOME/jobs/$JOB_NAME/builds/$BUILD_NUMBER路径,而是在构建后步骤中,将工件复制到以语义化版本号命名的独立文件夹:
Vue前端构建后示例
# 创建语义化版本对应的工件目录 SEMANTIC_VERSION=$(cat version.txt) ARTIFACT_PATH="$JENKINS_HOME/artifacts/$JOB_NAME/$SEMANTIC_VERSION" mkdir -p "$ARTIFACT_PATH" # 复制Vue打包后的dist文件夹到目标路径 cp -r ./dist/* "$ARTIFACT_PATH/"
Python后端构建后示例
假设你用setup.py打包成wheel包:
SEMANTIC_VERSION=$(cat version.txt) ARTIFACT_PATH="$JENKINS_HOME/artifacts/$JOB_NAME/$SEMANTIC_VERSION" mkdir -p "$ARTIFACT_PATH" # 复制打包好的wheel包到目标路径 cp ./dist/*.whl "$ARTIFACT_PATH/"
步骤3:将语义化版本注入项目构建过程
让你的Vue和Python项目在构建时带上当前的语义化版本号:
Vue项目版本注入
- 方式1:在
vue.config.js中读取版本号,注入到应用中:const fs = require('fs'); const version = fs.readFileSync('./version.txt', 'utf8').trim(); module.exports = { configureWebpack: { plugins: [ new webpack.DefinePlugin({ 'process.env.VERSION': JSON.stringify(version) }) ] } } - 方式2:构建前用sed替换
public/index.html中的版本占位符:sed -i "s/{{APP_VERSION}}/$SEMANTIC_VERSION/g" public/index.html
Python后端版本注入
修改__init__.py中的版本号,再打包:
sed -i "s/__version__ = .*/__version__ = '$SEMANTIC_VERSION'/g" my_project/__init__.py
步骤4:版本重置与升级
当需要升级主/次/补丁版本时,直接手动修改version.txt的内容即可:
- 比如从
1.3.1_develop.5升级到1.3.2_develop.0,下次构建脚本会自动递增为1.3.2_develop.1 - 主分支发布时,将
version.txt改为1.3.2,构建后直接生成正式版本工件
这样一来,不管你怎么重置Jenkins的BUILD_NUMBER,都不会影响语义化版本的管理和工件存储,完全复刻TeamCity的语义化版本机制。
内容的提问来源于stack exchange,提问作者Carlos Cupeiro

