From 434251695c19ebbfe2a2240d2eddce2d56af07b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BF=AE=E9=9B=A8?= Date: Wed, 15 Jul 2026 09:08:12 +0800 Subject: [PATCH] fix(release): recover stable tag sharing beta commit --- .github/workflows/release.yml | 64 +++++++++++++++++++++++++++++------ 1 file changed, 53 insertions(+), 11 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 29e1ec5b..992a9e65 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,13 +10,24 @@ on: description: "Only publish an existing release to npm, e.g. v1.0.48" required: false type: string + recover_release_version: + description: "Recover an existing undelivered tag, e.g. v1.0.52" + required: false + type: string + recover_release_previous_tag: + description: "Previous delivered tag used for recovery changelog generation" + required: false + type: string permissions: contents: write +env: + RELEASE_VERSION: ${{ inputs.recover_release_version || github.ref_name }} + jobs: release: - if: ${{ github.event_name != 'workflow_dispatch' || inputs.repair_npm_version == '' }} + if: ${{ github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && inputs.recover_release_version != '') }} runs-on: ubuntu-latest timeout-minutes: 30 @@ -25,6 +36,35 @@ jobs: uses: actions/checkout@v4 with: fetch-depth: 0 + ref: ${{ env.RELEASE_VERSION }} + + - name: Validate undelivered recovery target + if: ${{ github.event_name == 'workflow_dispatch' }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PREVIOUS_TAG: ${{ inputs.recover_release_previous_tag }} + run: | + set -euo pipefail + case "$RELEASE_VERSION" in + v[0-9]*.[0-9]*.[0-9]*) ;; + *) echo "Recovery requires a stable vX.Y.Z tag" >&2; exit 1 ;; + esac + case "$RELEASE_VERSION" in + *-*) echo "Stable recovery cannot use a prerelease tag" >&2; exit 1 ;; + esac + test -n "$PREVIOUS_TAG" + test "$(git cat-file -t "refs/tags/$RELEASE_VERSION")" = tag + target_commit="$(git rev-parse "$RELEASE_VERSION^{commit}")" + test "$target_commit" = "$(git rev-parse HEAD)" + git fetch --force origin main --tags + test "$target_commit" = "$(git rev-parse origin/main)" + git rev-parse "$PREVIOUS_TAG^{commit}" >/dev/null + if gh release view "$RELEASE_VERSION" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then + echo "Recovery target already has a GitHub Release" >&2 + exit 1 + fi + echo "GORELEASER_CURRENT_TAG=$RELEASE_VERSION" >> "$GITHUB_ENV" + echo "GORELEASER_PREVIOUS_TAG=$PREVIOUS_TAG" >> "$GITHUB_ENV" - name: Set up Go uses: actions/setup-go@v5 @@ -92,7 +132,7 @@ jobs: - name: Post-release packaging run: ./scripts/release/post-goreleaser.sh env: - DWS_PACKAGE_VERSION: ${{ github.ref_name }} + DWS_PACKAGE_VERSION: ${{ env.RELEASE_VERSION }} DWS_REQUIRE_DEVELOPER_ID_SIGNING: ${{ github.repository_owner == 'DingTalk-Real-AI' }} - name: Remove Apple Developer ID certificate @@ -108,7 +148,7 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} DWS_PUBLISH_RELEASE: "false" - run: ./scripts/release/finalize-github-release.sh + run: GITHUB_REF_NAME="$RELEASE_VERSION" ./scripts/release/finalize-github-release.sh - name: Preserve finalized distribution files uses: actions/upload-artifact@v4 @@ -119,7 +159,7 @@ jobs: retention-days: 1 verify-darwin-signatures: - if: ${{ github.event_name != 'workflow_dispatch' || inputs.repair_npm_version == '' }} + if: ${{ github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && inputs.recover_release_version != '') }} needs: release runs-on: macos-latest timeout-minutes: 10 @@ -131,7 +171,7 @@ jobs: run: | set -euo pipefail mkdir -p dist - gh release download "$GITHUB_REF_NAME" \ + gh release download "$RELEASE_VERSION" \ --repo "$GITHUB_REPOSITORY" \ --dir dist \ --pattern 'dws-darwin-amd64.tar.gz' \ @@ -152,7 +192,7 @@ jobs: done publish-release: - if: ${{ github.event_name != 'workflow_dispatch' || inputs.repair_npm_version == '' }} + if: ${{ github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && inputs.recover_release_version != '') }} needs: - release - verify-darwin-signatures @@ -164,6 +204,8 @@ jobs: steps: - name: Check out repository uses: actions/checkout@v4 + with: + ref: ${{ env.RELEASE_VERSION }} - name: Restore finalized distribution files uses: actions/download-artifact@v4 @@ -174,14 +216,14 @@ jobs: - name: Publish verified Draft release env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: gh release edit "$GITHUB_REF_NAME" --repo "$GITHUB_REPOSITORY" --draft=false + run: gh release edit "$RELEASE_VERSION" --repo "$GITHUB_REPOSITORY" --draft=false - name: Sync release to China OSS mirror # 自动同步到国内镜像,供 install.sh 的 DWS_RELEASE_BASE 开关消费。 # 脚本自带门控:未配置 OSS_* secret 时优雅跳过,不影响海外发布。 run: ./scripts/release/sync-to-oss.sh env: - VERSION: ${{ github.ref_name }} + VERSION: ${{ env.RELEASE_VERSION }} OSS_ACCESS_KEY_ID: ${{ secrets.OSS_ACCESS_KEY_ID }} OSS_ACCESS_KEY_SECRET: ${{ secrets.OSS_ACCESS_KEY_SECRET }} OSS_ENDPOINT: ${{ secrets.OSS_ENDPOINT }} @@ -197,7 +239,7 @@ jobs: - name: Publish stable to npm # 只有官方仓库发 npm;fork(dev 预览)没有 NPM_TOKEN,跳过以免红叉。 # 必须在 Gitee mirror 前发布:Gitee 附件上传偶发长时间挂住,不能阻塞 npm/latest。 - if: ${{ github.repository_owner == 'DingTalk-Real-AI' && !contains(github.ref_name, '-') }} + if: ${{ github.repository_owner == 'DingTalk-Real-AI' && !contains(env.RELEASE_VERSION, '-') }} working-directory: dist/npm/dingtalk-workspace-cli run: npm publish --access public env: @@ -205,7 +247,7 @@ jobs: - name: Publish prerelease to npm beta # 预发布版本不能更新 npm latest,避免普通 npm 安装链路拿到 beta。 - if: ${{ github.repository_owner == 'DingTalk-Real-AI' && contains(github.ref_name, '-') }} + if: ${{ github.repository_owner == 'DingTalk-Real-AI' && contains(env.RELEASE_VERSION, '-') }} working-directory: dist/npm/dingtalk-workspace-cli run: npm publish --access public --tag beta env: @@ -220,7 +262,7 @@ jobs: timeout-minutes: 20 run: ./scripts/release/sync-to-gitee.sh env: - VERSION: ${{ github.ref_name }} + VERSION: ${{ env.RELEASE_VERSION }} GITEE_TOKEN: ${{ secrets.GITEE_TOKEN }} GITEE_USER: ${{ secrets.GITEE_USER }} GITEE_REPO: ${{ secrets.GITEE_REPO }}