You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于python-semantic-release与Woodpecker CI实现RC构建并保持最终版本的聚合式变更日志?

解决python-semantic-release + Woodpecker CI的RC发布与聚合变更日志问题

我完全懂你现在的纠结——既要用规范的RC版本做测试部署,又要保证正式发布时变更日志是整整齐齐聚合在一起的,确实很容易在semantic-release的提交"消耗"逻辑上踩坑。结合你的技术栈(python-semantic-release、Woodpecker CI、Docker化FastAPI)和需求,我给你拆解一套可行的落地方案:

核心思路:把「RC版本计算」和「正式版本发布」拆解开

semantic-release所谓的"消耗"提交,本质是因为它会把计算后的版本写入CHANGELOG、打标签并推送到仓库。所以我们要做的是:

  • 预发布分支(dev/release/*)只负责生成RC版本的工件(比如Docker镜像),绝不修改CHANGELOG、绝不打正式标签
  • 正式发布只在main分支运行,基于完整的提交历史计算版本,生成聚合式的CHANGELOG

1. 推荐的分支结构

我建议用「dev -> release/x.y -> main」的三层分支模式:

  • main:纯正式发布分支,只接受从release/*分支的普通合并(禁止直接提交、禁止squash merge)
  • dev:日常开发分支,所有功能分支通过squash merge合并到这里,保证dev分支的提交都是规范的conventional commits
  • release/x.y:预发布准备分支,当dev上的功能足够发布一个新版本(比如v2.1.0)时,从dev创建该分支,专门用于生成RC版本和最终发布准备

2. Woodpecker CI配置示例

我把不同分支的CI流程拆成三个配置文件,清晰又好维护:

(1)dev分支:CI验证+临时RC镜像

dev分支只做测试和临时镜像,用提交短SHA做标记足够清晰:

# .woodpecker/dev.yml
when:
  branch: dev
steps:
  - name: run-tests
    image: python:3.11
    commands:
      - pip install -r requirements.txt
      - pytest --cov=your_app
  - name: build-temp-rc-image
    image: woodpeckerci/plugin-docker-buildx
    settings:
      repo: your-docker-registry/your-fastapi-app
      tags: ${CI_COMMIT_SHA:0:7}-rc
      secrets: [docker_username, docker_password]
  - name: deploy-dev
    # 部署到开发环境的脚本,比如用docker-compose更新
    commands:
      - ./deploy-dev.sh ${CI_COMMIT_SHA:0:7}-rc

(2)release/x.y分支:生成规范RC版本+预发布部署

这里用semantic-release的--noop模式计算RC版本,只输出版本号不修改仓库:

# .woodpecker/release.yml
when:
  branch: release/*
steps:
  - name: run-tests
    image: python:3.11
    commands:
      - pip install -r requirements.txt
      - pytest --cov=your_app
  - name: calculate-rc-version
    image: python:3.11
    commands:
      - pip install python-semantic-release
      # 计算RC版本,--noop表示只输出不修改仓库
      - semantic-release version --prerelease rc --noop | grep "New version" | awk '{print $3}' > rc_version.txt
      - export SEMVER_RC=$(cat rc_version.txt)
  - name: build-rc-image
    image: woodpeckerci/plugin-docker-buildx
    settings:
      repo: your-docker-registry/your-fastapi-app
      tags: ${SEMVER_RC}
      secrets: [docker_username, docker_password]
  - name: deploy-staging
    # 部署到测试环境的脚本
    commands:
      - ./deploy-staging.sh ${SEMVER_RC}

(3)main分支:正式发布+聚合CHANGELOG

这里运行完整的semantic-release流程,生成聚合的CHANGELOG并打正式标签:

# .woodpecker/main.yml
when:
  branch: main
steps:
  - name: run-tests
    image: python:3.11
    commands:
      - pip install -r requirements.txt
      - pytest --cov=your_app
  - name: semantic-release-publish
    image: python:3.11
    commands:
      - pip install python-semantic-release
      # 完整发布流程:计算版本、更新CHANGELOG、打标签、推送到仓库
      - semantic-release publish
    secrets: [github_token] # 用于推送CHANGELOG和标签到Git仓库
  - name: build-release-image
    image: woodpeckerci/plugin-docker-buildx
    settings:
      repo: your-docker-registry/your-fastapi-app
      tags: v${SEMANTIC_RELEASE_VERSION}
      secrets: [docker_username, docker_password]
  - name: deploy-production
    # 部署到生产环境的脚本
    commands:
      - ./deploy-prod.sh v${SEMANTIC_RELEASE_VERSION}

3. python-semantic-release配置调整

在pyproject.toml里明确分支规则,让预发布分支只允许计算版本,禁止修改仓库:

[tool.semantic_release]
version_variable = "your_app/__init__.py:__version__"
commit_message_template = "chore(release): v{version}"
prerelease_token = "rc"
# 只有main分支允许完整发布流程
branches = ["main"]

# 针对release分支的特殊配置:只生成RC版本,不推送变更
[tool.semantic_release.branches.release/*]
prerelease = true
allow_deployment = false  # 禁止推送CHANGELOG和标签

4. 解答你的核心疑问

(1)如何设计分支与CI配置?

就是上面的三层分支模式:

  • dev分支持续集成,用短SHA做临时RC标记,不影响正式发布
  • release/x.y分支生成规范RC版本,方便测试团队追踪,且不修改仓库历史
  • main分支基于release分支的完整提交历史,运行semantic-release生成聚合的CHANGELOG

(2)semantic-release该在哪些分支运行?

  • main分支:必须运行完整的publish流程,负责生成CHANGELOG、打正式标签
  • release/x.y分支:只运行version --prerelease rc --noop计算版本,绝不修改仓库
  • dev分支:可以不用运行semantic-release,用短SHA做标记足够清晰,节省CI资源

(3)测试部署该用什么版本标记?

  • 开发环境:用提交短SHA(如abc123-rc),足够追溯且不会和正式RC冲突
  • 预发布/测试环境:用release分支生成的规范RC版本(如v2.1.0-rc.1),方便测试团队对应需求和bug
  • 这样既保证了可追溯性,又不会消耗提交影响正式发布的CHANGELOG

(4)是否误用了semantic-release?

完全没有!你之前的问题只是让预发布分支的semantic-release修改了仓库历史,导致提交被"消耗"。核心是要区分版本计算和**版本发布(修改仓库)**这两个步骤,预发布只做计算,正式发布才做修改。


额外小技巧

  • 当需要更新RC版本时,只要把dev分支的最新代码merge到release/x.y分支,重新运行CI就能生成下一个RC版本(比如v2.1.0-rc.2),semantic-release会自动递增RC序号
  • 合并release/x.y到main时,一定要用普通merge,不要squash,这样main分支会保留所有提交历史,semantic-release才能正确计算版本并聚合所有变更到一个版本条目里
  • 如果担心release分支的临时文件,可以在正式发布后删除release分支,保持仓库整洁

内容的提问来源于stack exchange,提问作者AK-23

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 06:40:16