如何在GitHub Actions中自动递增pubspec.yaml的版本号?
问题背景
我对传统Linux命令及grep工具不熟悉,已经在GitHub Actions中搭建了流水线,期望在应用发布大版本时完成两个操作:
- 创建GitHub标签
- 递增pubspec.yaml中的版本号与构建号(例如:
1.2.3+22→1.2.4+23;2.14.9+99→2.14.10+100)
目前创建标签的命令已经正常运行,但版本号递增的现有实现还有优化空间,现有命令如下:
- name: "Retrieve version" id: version run: | echo "OLD_VERSION=$(cat ${GITHUB_WORKSPACE}/pubspec.yaml | grep 'version:' | head -1 | cut -f2- -d: | sed -e 's/^[ ]*//')" >> $GITHUB_OUTPUT echo "NEW_VERSION=$(awk '{ match($0,/([0-9]+)\+([0-9]+)/,a); a[1]=a[1]+1; a[2]=a[2]+1; sub(/[0-9]+\+[0-9]+/,a[1]"+"a[2])}1' ${GITHUB_WORKSPACE}/pubspec.yaml | grep 'version:' | head -1 | cut -f2- -d: | sed -e 's/^[ ]*//')" >> $GITHUB_OUTPUT - name: "Increment version" run: | sed -i 's/${{ steps.version.outputs.OLD_VERSION }}/${{ steps.version.outputs.NEW_VERSION }}/g' ${GITHUB_WORKSPACE}/pubspec.yaml echo ${{ steps.version.outputs.OLD_VERSION }} echo ${{ steps.version.outputs.NEW_VERSION }}
优化建议与替代方案
方案1:简化Shell命令逻辑,减少冗余操作
现有命令多次读取pubspec.yaml文件并嵌套多层管道,可读性和效率都可以优化。拆分版本号提取与递增逻辑,更清晰易维护:
- name: "Retrieve & increment version" id: version run: | # 直接提取第一行version字段的值,避免多余操作 OLD_VERSION=$(grep '^version:' ${GITHUB_WORKSPACE}/pubspec.yaml | sed 's/version: //') # 拆分语义版本(比如1.2.3)和构建号(比如22) SEMVER=$(echo "$OLD_VERSION" | cut -d'+' -f1) BUILD_NUM=$(echo "$OLD_VERSION" | cut -d'+' -f2) # 递增语义版本的最后一位 NEW_SEMVER=$(echo "$SEMVER" | awk -F. '{print $1"."$2"."($3+1)}') # 递增构建号 NEW_BUILD_NUM=$((BUILD_NUM + 1)) NEW_VERSION="$NEW_SEMVER+$NEW_BUILD_NUM" echo "OLD_VERSION=$OLD_VERSION" >> $GITHUB_OUTPUT echo "NEW_VERSION=$NEW_VERSION" >> $GITHUB_OUTPUT - name: "Update pubspec.yaml" run: | # 只替换以version:开头的行,避免全局替换误改其他内容 sed -i "s/^version: ${{ steps.version.outputs.OLD_VERSION }}/version: ${{ steps.version.outputs.NEW_VERSION }}/" ${GITHUB_WORKSPACE}/pubspec.yaml
优势:
- 仅读取一次pubspec.yaml文件,减少IO操作
- 逻辑拆分后更易理解和修改
- 用
^version:限定替换范围,避免误改文件中其他出现旧版本号的内容
方案2:用Dart官方工具pub version(最可靠)
如果是Flutter/Dart项目,直接用官方的pub version命令递增版本号,完全规避手动解析版本号的边缘问题(比如版本号进位、格式异常等):
- name: "Increment version with pub" id: version run: | cd ${GITHUB_WORKSPACE} # 保存旧版本号 OLD_VERSION=$(grep '^version:' pubspec.yaml | sed 's/version: //') # 递增补丁版本号(对应x.y.z → x.y.z+1),--no-git-tag-version避免自动创建本地标签 pub version patch --no-git-tag-version # 获取新版本号 NEW_VERSION=$(grep '^version:' pubspec.yaml | sed 's/version: //') echo "OLD_VERSION=$OLD_VERSION" >> $GITHUB_OUTPUT echo "NEW_VERSION=$NEW_VERSION" >> $GITHUB_OUTPUT - name: "Create GitHub tag" uses: actions/github-script@v6 with: script: | github.rest.git.createRef({ owner: context.repo.owner, repo: context.repo.repo, ref: `refs/tags/${{ steps.version.outputs.NEW_VERSION }}`, sha: context.sha })
优势:
- 官方工具,完美兼容pubspec.yaml的版本格式规范
- 自动处理版本号进位场景(比如
2.14.9→2.14.10) - 无需手动编写复杂正则或拆分逻辑,出错概率极低
方案3:用社区GitHub Action替代Shell命令
如果不想写Shell命令,可以用社区维护的Action完成版本号递增,配置化操作更省心:
- name: "Increment version" id: version uses: poad/flutter-version-action@v1 with: path: ${{ GITHUB_WORKSPACE }}/pubspec.yaml version: patch build-number: auto-increment - name: "Create GitHub tag" uses: actions/github-script@v6 with: script: | github.rest.git.createRef({ owner: context.repo.owner, repo: context.repo.repo, ref: `refs/tags/${{ steps.version.outputs.version }}`, sha: context.sha })
优势:
- 完全无需编写Shell命令,通过参数配置完成操作
- 自动处理版本号与构建号的递增逻辑
- 内置格式验证,避免版本号格式错误
内容的提问来源于stack exchange,提问作者Thomas
相关产品推荐
相关产品推荐

