mirror of
https://github.com/esengine/DeepSeek-Reasonix.git
synced 2026-11-07 10:45:59 -10:00
Problem: The stable orchestrator reported success after approval even though the CLI, npm, and Desktop publication jobs were skipped through a transitive skipped dependency. The existing recovery dispatch also could not use a workflow fix without moving the already-published tags. Root cause: Each reusable publisher joined an orchestrated guard with a deliberately skipped standalone gate. The cache guard used an explicit status condition, but its descendants did not, so GitHub propagated the skipped ancestor through the dependency chain. Recovery also checked out and executed control scripts from the old release candidate. Fix: Add explicit success conditions to every affected publication stage, keep recovery authorization and verification on protected main-v2 while building the immutable historical tag SHA, and reject non-ancestor or mismatched tag sets. Add a stable postflight that verifies required CLI/Desktop release assets and the exact npm latest version so a no-op release cannot stay green. Verification: - bash scripts/release-workflows.test.sh - go run github.com/rhysd/actionlint/cmd/[email protected] -ignore 'label "windows-11-arm" is unknown' on all release workflows - bash -n on all changed release scripts - verify-stable-release-artifacts.sh against public v1.17.14 artifacts - ./scripts/cache-guard.sh - go test ./... - git diff --check
176 lines
6.0 KiB
YAML
176 lines
6.0 KiB
YAML
name: Release stable
|
|
run-name: Release stable ${{ inputs.tag || github.ref_name }}
|
|
|
|
# Stable publication has exactly one GitHub environment gate. Push the CLI,
|
|
# npm, and desktop tags atomically; the vX.Y.Z tag starts this workflow,
|
|
# preflight verifies that all three tags point to the current main-v2 commit,
|
|
# and one GitHub approval releases every channel. A manual recovery runs the
|
|
# fixed control plane from protected main-v2 while preserving an older tagged
|
|
# candidate on main-v2 history. SignPath intentionally keeps its separate
|
|
# manual confirmations. Prerelease and canary workflows remain independently
|
|
# callable.
|
|
on:
|
|
push:
|
|
tags:
|
|
- 'v*'
|
|
- '!v*-*'
|
|
workflow_dispatch:
|
|
inputs:
|
|
tag:
|
|
description: "Existing stable CLI tag to recover (for example v1.18.0)"
|
|
required: true
|
|
type: string
|
|
|
|
concurrency:
|
|
group: stable-release-${{ inputs.tag || github.ref_name }}
|
|
cancel-in-progress: false
|
|
|
|
# Reusable release workflows can only reduce caller permissions, so the
|
|
# orchestrator grants the union needed by CLI/Desktop publication.
|
|
permissions:
|
|
actions: write
|
|
contents: write
|
|
|
|
jobs:
|
|
preflight:
|
|
name: validate stable release set
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
contents: read
|
|
outputs:
|
|
version: ${{ steps.release.outputs.version }}
|
|
cli_tag: ${{ steps.release.outputs.cli_tag }}
|
|
npm_tag: ${{ steps.release.outputs.npm_tag }}
|
|
desktop_tag: ${{ steps.release.outputs.desktop_tag }}
|
|
sha: ${{ steps.release.outputs.sha }}
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
with:
|
|
fetch-depth: 0
|
|
# A recovery dispatch uses the fixed workflow/scripts from protected
|
|
# main-v2. Publishers still check out the immutable approved tag SHA.
|
|
ref: ${{ github.sha }}
|
|
- uses: actions/setup-go@v6
|
|
with:
|
|
go-version-file: go.mod
|
|
cache: true
|
|
- uses: actions/setup-node@v6
|
|
with:
|
|
node-version: "22"
|
|
- name: Resolve stable release
|
|
id: release
|
|
env:
|
|
RELEASE_TAG: ${{ inputs.tag || github.ref_name }}
|
|
ALLOW_STABLE_RECOVERY: ${{ github.event_name == 'workflow_dispatch' }}
|
|
run: bash scripts/resolve-stable-release.sh
|
|
- name: Validate reviewed release notes
|
|
run: node scripts/release-notes.mjs render --version "${{ steps.release.outputs.cli_tag }}" --output /tmp/release-notes.md
|
|
- name: Cache hit guard
|
|
run: ./scripts/cache-guard.sh
|
|
|
|
authorize:
|
|
name: approve stable release
|
|
needs: preflight
|
|
runs-on: ubuntu-latest
|
|
environment: release
|
|
permissions:
|
|
contents: read
|
|
outputs:
|
|
version: ${{ steps.approved.outputs.version }}
|
|
cli_tag: ${{ steps.approved.outputs.cli_tag }}
|
|
npm_tag: ${{ steps.approved.outputs.npm_tag }}
|
|
desktop_tag: ${{ steps.approved.outputs.desktop_tag }}
|
|
sha: ${{ steps.approved.outputs.sha }}
|
|
steps:
|
|
- name: Record approved release
|
|
id: approved
|
|
env:
|
|
VERSION: ${{ needs.preflight.outputs.version }}
|
|
CLI_TAG: ${{ needs.preflight.outputs.cli_tag }}
|
|
NPM_TAG: ${{ needs.preflight.outputs.npm_tag }}
|
|
DESKTOP_TAG: ${{ needs.preflight.outputs.desktop_tag }}
|
|
RELEASE_SHA: ${{ needs.preflight.outputs.sha }}
|
|
run: |
|
|
{
|
|
echo "version=$VERSION"
|
|
echo "cli_tag=$CLI_TAG"
|
|
echo "npm_tag=$NPM_TAG"
|
|
echo "desktop_tag=$DESKTOP_TAG"
|
|
echo "sha=$RELEASE_SHA"
|
|
} >> "$GITHUB_OUTPUT"
|
|
echo "Approved stable release $VERSION at $RELEASE_SHA"
|
|
|
|
cli:
|
|
name: publish CLI and Homebrew
|
|
needs: authorize
|
|
uses: ./.github/workflows/release.yml
|
|
with:
|
|
tag: ${{ needs.authorize.outputs.cli_tag }}
|
|
approved_cli_tag: ${{ needs.authorize.outputs.cli_tag }}
|
|
approved_sha: ${{ needs.authorize.outputs.sha }}
|
|
orchestrated: true
|
|
secrets: inherit
|
|
|
|
npm:
|
|
name: publish npm
|
|
needs: authorize
|
|
uses: ./.github/workflows/release-npm.yml
|
|
with:
|
|
channel: stable
|
|
base_version: ${{ needs.authorize.outputs.version }}
|
|
tag: ${{ needs.authorize.outputs.npm_tag }}
|
|
approved_cli_tag: ${{ needs.authorize.outputs.cli_tag }}
|
|
approved_sha: ${{ needs.authorize.outputs.sha }}
|
|
orchestrated: true
|
|
secrets: inherit
|
|
|
|
desktop:
|
|
name: publish desktop
|
|
needs: authorize
|
|
uses: ./.github/workflows/release-desktop.yml
|
|
with:
|
|
channel: stable
|
|
tag: ${{ needs.authorize.outputs.desktop_tag }}
|
|
approved_cli_tag: ${{ needs.authorize.outputs.cli_tag }}
|
|
approved_sha: ${{ needs.authorize.outputs.sha }}
|
|
orchestrated: true
|
|
secrets: inherit
|
|
|
|
postflight:
|
|
name: verify stable release artifacts
|
|
needs: [authorize, cli, npm, desktop]
|
|
if: ${{ always() && !cancelled() }}
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
contents: read
|
|
steps:
|
|
- name: Require every publisher to succeed
|
|
env:
|
|
CLI_RESULT: ${{ needs.cli.result }}
|
|
NPM_RESULT: ${{ needs.npm.result }}
|
|
DESKTOP_RESULT: ${{ needs.desktop.result }}
|
|
run: |
|
|
set -euo pipefail
|
|
for result in "$CLI_RESULT" "$NPM_RESULT" "$DESKTOP_RESULT"; do
|
|
if [ "$result" != "success" ]; then
|
|
echo "::error::stable publisher result is $result, expected success"
|
|
exit 1
|
|
fi
|
|
done
|
|
- uses: actions/checkout@v7
|
|
with:
|
|
# Postflight belongs to the trusted control plane, not the old build
|
|
# candidate, which may predate this verifier.
|
|
ref: ${{ github.sha }}
|
|
- uses: actions/setup-node@v6
|
|
with:
|
|
node-version: "22"
|
|
- name: Verify public artifacts and npm latest
|
|
env:
|
|
GH_TOKEN: ${{ github.token }}
|
|
RELEASE_REPOSITORY: ${{ github.repository }}
|
|
RELEASE_VERSION: ${{ needs.authorize.outputs.version }}
|
|
CLI_TAG: ${{ needs.authorize.outputs.cli_tag }}
|
|
DESKTOP_TAG: ${{ needs.authorize.outputs.desktop_tag }}
|
|
run: bash scripts/verify-stable-release-artifacts.sh
|