From 1ed5de237453b4eeda9bdefeaa04a123a62890bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BF=AE=E9=9B=A8?= Date: Sat, 18 Jul 2026 11:08:01 +0800 Subject: [PATCH] fix(release): restore tag-push publication after recovery refactor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The guarded-recovery refactor added dispatch-contract/authorize-recovery jobs that are skipped on ordinary tag pushes. The downstream release/verify/publish jobs gated only on `needs.X.result == 'success'`, so GitHub added an implicit success() that treats the skipped ancestors as a chain failure and silently skipped the entire publish chain — a pushed annotated tag validated the contract but delivered nothing. Add an explicit `!cancelled()` status check to the release, verify-darwin-signatures, publish-release, publish-channels, and mirror-gitee-release gates. This disables the implicit success() while keeping the existing result==success conditions, restoring direct tag-push delivery. Protected recovery remains the failure break-glass; its ancestors succeed, so its behavior is unchanged. --- .github/workflows/release.yml | 10 +++++----- CHANGELOG.md | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index da743689..fe99c2bc 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -622,7 +622,7 @@ jobs: release: name: Build signed release artifacts - if: ${{ needs.release-contract.result == 'success' }} + if: ${{ !cancelled() && needs.release-contract.result == 'success' }} needs: [release-contract] runs-on: ubuntu-latest timeout-minutes: 60 @@ -788,7 +788,7 @@ jobs: verify-darwin-signatures: name: Verify Apple Developer ID signatures - if: ${{ needs.release.result == 'success' }} + if: ${{ !cancelled() && needs.release.result == 'success' }} needs: [release-contract, release] runs-on: macos-latest timeout-minutes: 10 @@ -816,7 +816,7 @@ jobs: publish-release: name: Publish immutable GitHub Release - if: ${{ needs.release-contract.result == 'success' && needs.release.result == 'success' && needs.verify-darwin-signatures.result == 'success' }} + if: ${{ !cancelled() && needs.release-contract.result == 'success' && needs.release.result == 'success' && needs.verify-darwin-signatures.result == 'success' }} needs: [release-contract, release, verify-darwin-signatures] runs-on: ubuntu-latest timeout-minutes: 30 @@ -1055,7 +1055,7 @@ jobs: publish-channels: name: Publish npm and mirrors - if: ${{ needs.release-contract.result == 'success' && needs.publish-release.result == 'success' }} + if: ${{ !cancelled() && needs.release-contract.result == 'success' && needs.publish-release.result == 'success' }} needs: [release-contract, publish-release] runs-on: ubuntu-latest timeout-minutes: 30 @@ -1286,7 +1286,7 @@ jobs: mirror-gitee-release: name: Mirror immutable release to Gitee - if: ${{ vars.ENABLE_GITEE_UPLOAD_FALLBACK == 'true' && needs.release-contract.result == 'success' && needs.release.result == 'success' && needs.publish-channels.result == 'success' }} + if: ${{ vars.ENABLE_GITEE_UPLOAD_FALLBACK == 'true' && !cancelled() && needs.release-contract.result == 'success' && needs.release.result == 'success' && needs.publish-channels.result == 'success' }} needs: [release-contract, release, publish-channels] runs-on: ubuntu-latest timeout-minutes: 120 diff --git a/CHANGELOG.md b/CHANGELOG.md index 14c2843b..a7755d8e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ The format is inspired by [Keep a Changelog](https://keepachangelog.com/) and th ### Fixed - **Release preflight reliability** — source-mode installer tests now use isolated temporary checkouts and HOME directories instead of overwriting and deleting the real repository `dws` binary, release preflight explicitly rebuilds before policy checks, and the full-suite runner gives the growing script package a non-flaky five-minute per-suite budget. +- **Tag-push publication after the recovery refactor** — the guarded-recovery jobs are skipped on ordinary tag pushes, and the downstream build/sign/publish jobs relied on an implicit `success()` that treats those skipped ancestors as a chain failure, so pushing an annotated release tag validated the contract but silently skipped every publish job. The `release`, `verify-darwin-signatures`, `publish-release`, `publish-channels`, and `mirror-gitee-release` gates now use an explicit `!cancelled()` status check alongside their existing `result == 'success'` conditions, restoring direct tag-push delivery while keeping protected recovery as the failure break-glass. ## [1.0.53-beta.4] - 2026-07-17