git分支名转docker标签需用环境变量:github actions用${{ github.ref_name }}或${{ github.head_ref }}并处理非法字符,jenkins用env.branch_name并正则替换;禁止直接用latest,应按tag/branch优先级逻辑判断,避免镜像覆盖。

Git分支名怎么变成Docker标签?别硬编码,用环境变量就行
GitHub Actions 和 Jenkins 都能直接拿到当前分支名,不需要写脚本去 git rev-parse --abbrev-ref HEAD。关键是要知道平台暴露了哪个变量、什么时候可用、会不会被覆盖。
- GitHub Actions 中用
${{ github.head_ref }}(PR 场景)或${{ github.ref_name }}(push 场景),注意github.ref是完整 ref 路径,比如refs/heads/main,得切掉前缀 - Jenkins Pipeline 里默认有
env.BRANCH_NAME,但仅在 SCM 拉取后才生效 —— 如果你在agent none下提前用,会是空值 - GitLab CI 用
$CI_COMMIT_REF_SLUG,它自动把分支名转成小写+连字符格式(feature/login-page→feature-login-page),比手动处理更安全
分支名含斜杠或大写字母,Docker标签会报错吗?会,而且很早
Docker 标签不支持 /、大写字母、下划线,遇到就直接 invalid reference format。不是构建失败,是 docker tag 或 docker push 命令执行前就拒绝。
使用 `gh` CLI 与 GitHub 交互。通过`gh issue`、`gh pr`、`gh run` 和 `gh api` 管理 issue、PR、CI 运行以及高级查询。
- GitHub Actions 推荐用
${{ github.head_ref | replace('/', '-') | downcase }}(Liquid 语法),但注意:这个只在if条件或with参数里生效,不能直接塞进run的 shell 命令里 - Jenkins 推荐在
script块里用 Groovy 处理:env.BRANCH_NAME.replaceAll('[^a-z0-9.-]', '-').replaceAll('-+', '-') - 别用
latest冲掉分支标签 —— 比如main分支打latest同时再打main,会导致镜像摘要被覆盖,历史不可追溯
main 分支该不该打 latest?生产环境真不用
打 latest 不是技术问题,是部署风险问题。Kubernetes、Argo CD 这类工具默认拉 latest 时不会校验摘要,一旦镜像被覆盖,滚动更新可能悄无声息地把旧版本替换成新版本,连日志都难查。
- 如果非要
latest,只在测试环境用,并确保镜像仓库开启 immutable tags(比如 Harbor 的“不可变标签”策略) - GitHub Actions 的
Publish-Docker-Github-Action默认给main打latest,得显式关掉:tags: ${{ (github.ref == 'refs/heads/main') && 'main' || github.head_ref }} - Jenkins 流水线里建议加判断:
if (env.BRANCH_NAME == 'main') { sh 'docker tag myapp:${TAG} myapp:stable' },用stable替代latest
Git tag 和分支名冲突怎么办?优先级要定死
同一提交既打了 tag 又在分支上,到底用哪个当标签?没人帮你决定,必须自己写逻辑。否则今天推的是 v1.2.0,明天别人切到 main 上又推了个 main,镜像仓库里就出现两个不同内容却同名的 myapp:main。
- GitHub Actions 推荐按这个顺序判断:
github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') → 用 tag;否则用 branch - Jenkins 里常用
sh(script: 'git describe --tags --exact-match 2>/dev/null', returnStdout: true).trim()判断是否精确匹配 tag,有结果就用它,没结果再 fallback 到BRANCH_NAME - 注意
git describe在浅克隆(shallow clone)下可能失败,Jenkins 要设checkout([$class: 'GitSCM', ... , extensions: [[$class: 'CloneOption', depth: 0]]])










