fix(release): v0.22.3 — native arm64-linux + gh-CLI Publish (no race, no draft)

Two production-readiness fixes motivated by the v0.22.2 post-mortem.

1. aarch64-linux: native ARM runner instead of cross-compile

   v0.22.2 consistently failed `Install aarch64 cross-linker` (apt
   gcc-aarch64-linux-gnu) on the ubuntu-latest x86_64 runner. Was
   carried as `experimental: true` so non-blocking, but meant no
   aarch64-linux Rust tarball ever shipped.

   Fix: move to ubuntu-24.04-arm (native ARM64 runner). Rust builds
   aarch64-unknown-linux-gnu HOST-NATIVELY — no cross-linker, no
   `.cargo/config.toml` linker override. `experimental: false` now —
   native path is reliable.

2. Publish step: softprops/action-gh-release → `gh release create` CLI

   v0.22.2 softprops/action-gh-release v2.6.2 uploaded all 15 assets
   successfully but exited with `failure` due to a metadata-update
   race: asset uploaded to GitHub's blob store, then the subsequent
   PATCH to set the asset's `name` returned 404 because the Releases
   metadata API hadn't caught up yet (eventual consistency). Workflow
   failure → Release left in Draft. We had to promote it manually
   (`gh release edit --draft=false`) and re-upload one missing sha256.

   Fix: replace the action with `gh release create` + `gh release
   upload --clobber` in a bash step.
   - Idempotent: existing release gets updated in place.
   - No metadata PATCH race: CLI never patches, it creates fresh.
   - Retry loop: up to 3 tries per asset on transient network errors.
   - `--clobber` means re-runs replace cleanly.
   - GitHub CLI is pre-installed on every runner, zero new deps.

Verified post-polish on v0.22.2: 16/16 assets present, Release
Published, `kei-mcp-server-darwin-arm64` + `keisei` both execute on
this MacBook (arm64) — adapter list shows Claude Code detected at
project+user scope. SHA256 of `keisei-aarch64-apple-darwin.tar.gz`
verified OK.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Parfii-bot 2026-04-22 23:22:50 +08:00
parent 42d964b14f
commit 71cb04525b

View file

@ -16,13 +16,18 @@ jobs:
strategy:
fail-fast: false
matrix:
# v0.22.3 fix: aarch64-linux moved from ubuntu-latest + cross-linker
# install (apt gcc-aarch64-linux-gnu consistently failed in CI) to
# ubuntu-24.04-arm NATIVE ARM runner. No cross-compile, rustc builds
# the target host-native. `experimental: false` — native path is
# reliable.
include:
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
experimental: false
- os: ubuntu-latest
- os: ubuntu-24.04-arm
target: aarch64-unknown-linux-gnu
experimental: true
experimental: false
- os: macos-latest
target: x86_64-apple-darwin
experimental: false
@ -47,14 +52,8 @@ jobs:
with:
workspaces: _primitives/_rust
- name: Install aarch64 cross-linker (Linux only)
if: matrix.target == 'aarch64-unknown-linux-gnu'
run: |
sudo apt-get update
sudo apt-get install -y gcc-aarch64-linux-gnu
mkdir -p .cargo
printf '[target.aarch64-unknown-linux-gnu]\nlinker = "aarch64-linux-gnu-gcc"\n' \
> _primitives/_rust/.cargo/config.toml
# v0.22.3: cross-linker step removed — aarch64-linux now builds
# natively on ubuntu-24.04-arm. No cross-compile, no gcc-aarch64-linux-gnu.
- name: Build workspace (release)
working-directory: _primitives/_rust
@ -246,19 +245,49 @@ jobs:
echo 'KEISEI_NOTES_EOF'
} >> "$GITHUB_OUTPUT"
# v0.22.3 fix: softprops/action-gh-release v2.6.2 exited with failure
# on v0.22.2 due to a metadata-update race (asset uploaded to blob
# store but Releases metadata API returned 404 on the subsequent
# PATCH — eventual-consistency window). All 15 assets WERE uploaded,
# but the action exited 1 and left the Release in Draft state.
#
# Replaced with `gh release create` (bundled on all GitHub runners).
# CLI is idempotent: if the release already exists it updates it; if
# assets already exist `--clobber` replaces them. No metadata-PATCH
# race. Retry loop on transient upload failures.
- name: Publish GitHub Release
# HIGH priority pin: this action has `contents: write` — a compromised
# tag would let an attacker publish arbitrary releases under this repo.
uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.2
with:
name: ${{ github.ref_name }}
tag_name: ${{ github.ref_name }}
body: ${{ steps.notes.outputs.notes }}
files: |
release-assets/*.tar.gz
release-assets/*.sha256
release-assets/kei-mcp-server-*
fail_on_unmatched_files: false
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG: ${{ github.ref_name }}
NOTES: ${{ steps.notes.outputs.notes }}
shell: bash
run: |
set -euo pipefail
# Create the release if missing; `|| true` absorbs "already exists"
# on workflow re-run.
gh release view "$TAG" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1 || \
gh release create "$TAG" \
--repo "$GITHUB_REPOSITORY" \
--title "$TAG" \
--notes "$NOTES"
# Upload all assets with --clobber so re-runs replace cleanly.
# Retry each asset up to 3 times on transient network errors.
shopt -s nullglob
for f in release-assets/*.tar.gz release-assets/*.sha256 release-assets/kei-mcp-server-*; do
[ -f "$f" ] || continue
for try in 1 2 3; do
if gh release upload "$TAG" --repo "$GITHUB_REPOSITORY" --clobber "$f"; then
break
elif [ "$try" -eq 3 ]; then
echo "::error::failed to upload $f after 3 tries" >&2
exit 1
else
echo "upload of $f failed (attempt $try/3), retrying in 5s..." >&2
sleep 5
fi
done
done
echo "✓ Release $TAG published with all assets"
npm-publish:
name: Publish npm packages (optional)