fix(workflows): refine release and notarization processes for macOS and Linux

- Updated the notarization workflow to correctly reference the "Release macOS" workflow.
- Enhanced version and run ID resolution logic to ensure accurate detection from the latest release or inputs.
- Improved asset verification process on R2 with a retry mechanism to handle potential delays in asset availability.
- Removed the deprecated unified release workflow, streamlining the release process for macOS and Linux.
- Adjusted CDN update prerequisites to reflect the new workflow structure.
This commit is contained in:
Max 2026-04-19 18:48:06 +08:00
parent 0ffd04c428
commit aabd875bdf
5 changed files with 210 additions and 198 deletions

View file

@ -2,7 +2,7 @@ name: Notarize macOS
on:
workflow_run:
workflows: ["Release"]
workflows: ["Release macOS"]
types: [completed]
workflow_dispatch:
inputs:
@ -18,7 +18,7 @@ permissions:
actions: write
concurrency:
group: notarize-${{ github.run_id }}
group: notarize-${{ github.event.workflow_run.head_branch || github.run_id }}
cancel-in-progress: true
jobs:
@ -29,7 +29,8 @@ jobs:
runs-on: ubuntu-latest
if: >
github.event_name == 'workflow_dispatch' ||
github.event.workflow_run.conclusion == 'success'
(github.event.workflow_run.conclusion == 'success' &&
startsWith(github.event.workflow_run.head_branch, 'v'))
outputs:
version: ${{ steps.resolve.outputs.version }}
run_id: ${{ steps.resolve.outputs.run_id }}
@ -42,24 +43,19 @@ jobs:
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
VERSION="${{ github.event.inputs.version }}"
RUN_ID="${{ github.event.inputs.run_id }}"
fi
# Auto-detect version from latest GitHub Release
if [ -z "$VERSION" ]; then
TAG=$(gh release view --repo "$GITHUB_REPOSITORY" --json tagName -q '.tagName')
if [ -z "$VERSION" ]; then
TAG=$(gh release view --repo "$GITHUB_REPOSITORY" --json tagName -q '.tagName')
VERSION="${TAG#v}"
fi
if [ -z "$RUN_ID" ]; then
RUN_ID=$(gh run list --repo "$GITHUB_REPOSITORY" \
--workflow="Release macOS" --branch="v${VERSION}" --limit=1 \
--json databaseId,conclusion --jq '.[] | select(.conclusion=="success") | .databaseId')
fi
else
TAG="${{ github.event.workflow_run.head_branch }}"
VERSION="${TAG#v}"
fi
if [ -z "$VERSION" ]; then
echo "::error::Could not determine version from latest release"
exit 1
fi
# Auto-detect macOS build run_id
if [ -z "$RUN_ID" ]; then
RUN_ID=$(gh run list --repo "$GITHUB_REPOSITORY" \
--workflow="Release macOS" --branch="v${VERSION}" --limit=1 \
--json databaseId,conclusion --jq '.[] | select(.conclusion=="success") | .databaseId')
RUN_ID="${{ github.event.workflow_run.id }}"
fi
if [ -z "$VERSION" ] || [ -z "$RUN_ID" ]; then
@ -146,7 +142,7 @@ jobs:
echo "Yao ${{ matrix.arch }} notarization accepted."
# ===================================================================
# After both architectures finish: verify R2 assets + trigger CDN
# After both architectures finish: wait for Linux R2, then trigger CDN
# ===================================================================
finalize:
needs: [resolve, notarize]
@ -168,7 +164,7 @@ jobs:
aws configure set default.region us-east-1
aws configure set default.s3.signature_version s3v4
- name: Verify all platform assets on R2
- name: Wait for all platform assets on R2
run: |
VERSION="${{ needs.resolve.outputs.version }}"
PREFIX="yao/${VERSION}"
@ -180,25 +176,29 @@ jobs:
"linux-arm64"
)
MISSING=0
for P in "${PLATFORMS[@]}"; do
KEY="${PREFIX}/yao-${VERSION}-${P}"
if ! aws s3 ls "s3://${R2_BUCKET}/${KEY}" --endpoint-url "$R2_ENDPOINTS" >/dev/null 2>&1; then
echo "::warning::Missing asset: ${KEY}"
MISSING=$((MISSING+1))
fi
if ! aws s3 ls "s3://${R2_BUCKET}/${KEY}.sha256" --endpoint-url "$R2_ENDPOINTS" >/dev/null 2>&1; then
echo "::warning::Missing sha256: ${KEY}.sha256"
MISSING=$((MISSING+1))
for ATTEMPT in $(seq 1 30); do
MISSING=0
for P in "${PLATFORMS[@]}"; do
KEY="${PREFIX}/yao-${VERSION}-${P}"
if ! aws s3 ls "s3://${R2_BUCKET}/${KEY}" --endpoint-url "$R2_ENDPOINTS" >/dev/null 2>&1; then
MISSING=$((MISSING+1))
fi
if ! aws s3 ls "s3://${R2_BUCKET}/${KEY}.sha256" --endpoint-url "$R2_ENDPOINTS" >/dev/null 2>&1; then
MISSING=$((MISSING+1))
fi
done
if [ "$MISSING" -eq 0 ]; then
echo "All 4 platform assets verified on R2."
exit 0
fi
echo "Attempt $ATTEMPT: $MISSING asset(s) still missing, waiting 30s..."
sleep 30
done
if [ "$MISSING" -gt 0 ]; then
echo "::error::$MISSING required asset(s) missing on R2."
echo "Ensure release.yml has completed successfully before running notarize."
exit 1
fi
echo "All 4 platform assets verified on R2."
echo "::error::Timed out waiting for all platform assets on R2."
exit 1
- name: Trigger CDN latest.json update
env:

View file

@ -138,3 +138,76 @@ jobs:
tags: |
${{ env.IMAGE_NAME }}:${{ steps.version.outputs.version }}
${{ env.IMAGE_NAME }}:latest
# ===================================================================
# GitHub Release + R2 Upload (Linux binaries)
# ===================================================================
release:
needs: build
if: startsWith(github.ref, 'refs/tags/v')
runs-on: ubuntu-latest
steps:
- name: Get Version
id: version
run: |
if [[ "$GITHUB_REF" != refs/tags/v* ]]; then
echo "::error::This workflow requires a tag. Got: $GITHUB_REF"
exit 1
fi
VERSION="${GITHUB_REF#refs/tags/v}"
TAG="${GITHUB_REF#refs/tags/}"
echo "version=${VERSION}" >> $GITHUB_OUTPUT
echo "tag=${TAG}" >> $GITHUB_OUTPUT
- name: Download Linux Artifacts
uses: actions/download-artifact@v4
with:
name: yao-linux
path: artifacts
- name: Prepare Release Files
run: |
VERSION="${{ steps.version.outputs.version }}"
mkdir -p release
cp "artifacts/yao-${VERSION}-linux-amd64-prod" "release/yao-${VERSION}-linux-amd64"
cp "artifacts/yao-${VERSION}-linux-arm64-prod" "release/yao-${VERSION}-linux-arm64"
cp "artifacts/yao-${VERSION}-linux-amd64" "release/yao-${VERSION}-linux-amd64-dev"
cp "artifacts/yao-${VERSION}-linux-arm64" "release/yao-${VERSION}-linux-arm64-dev"
chmod +x release/yao-*
ls -lh release/
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ steps.version.outputs.tag }}
name: Yao v${{ steps.version.outputs.version }}
files: release/*
generate_release_notes: true
make_latest: false
- name: Upload Linux binaries to R2
env:
AWS_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
R2_ENDPOINTS: ${{ secrets.R2_ENDPOINTS }}
R2_BUCKET: ${{ secrets.R2_BUCKET || 'releases' }}
run: |
aws configure set default.region us-east-1
aws configure set default.s3.signature_version s3v4
VERSION="${{ steps.version.outputs.version }}"
PREFIX="yao/${VERSION}"
for PLATFORM in linux-amd64 linux-arm64; do
FILE="release/yao-${VERSION}-${PLATFORM}"
NAME="yao-${VERSION}-${PLATFORM}"
sha256sum "$FILE" | awk '{print $1}' > "/tmp/${NAME}.sha256"
aws s3 cp "$FILE" "s3://${R2_BUCKET}/${PREFIX}/${NAME}" \
--endpoint-url "$R2_ENDPOINTS" \
--content-type "application/octet-stream"
aws s3 cp "/tmp/${NAME}.sha256" "s3://${R2_BUCKET}/${PREFIX}/${NAME}.sha256" \
--endpoint-url "$R2_ENDPOINTS" \
--content-type "text/plain"
echo "Uploaded: ${NAME} + ${NAME}.sha256"
done

View file

@ -217,3 +217,100 @@ jobs:
with:
name: yao-darwin-checksums
path: /tmp/checksums/*.sha256
# ===================================================================
# GitHub Release + R2 Upload (macOS binaries)
# ===================================================================
release:
needs: build
if: startsWith(github.ref, 'refs/tags/v')
runs-on: ubuntu-latest
steps:
- name: Get Version
id: version
run: |
if [[ "$GITHUB_REF" != refs/tags/v* ]]; then
echo "::error::This workflow requires a tag. Got: $GITHUB_REF"
exit 1
fi
VERSION="${GITHUB_REF#refs/tags/v}"
TAG="${GITHUB_REF#refs/tags/}"
echo "version=${VERSION}" >> $GITHUB_OUTPUT
echo "tag=${TAG}" >> $GITHUB_OUTPUT
- name: Download macOS Artifacts
uses: actions/download-artifact@v4
with:
name: yao-darwin-arm64
path: artifacts/arm64-prod
- name: Download arm64 Dev
uses: actions/download-artifact@v4
with:
name: yao-darwin-arm64-dev
path: artifacts/arm64-dev
- name: Download amd64 Prod
uses: actions/download-artifact@v4
with:
name: yao-darwin-amd64
path: artifacts/amd64-prod
- name: Download amd64 Dev
uses: actions/download-artifact@v4
with:
name: yao-darwin-amd64-dev
path: artifacts/amd64-dev
- name: Download Checksums
uses: actions/download-artifact@v4
with:
name: yao-darwin-checksums
path: artifacts/checksums
- name: Prepare Release Files
run: |
VERSION="${{ steps.version.outputs.version }}"
mkdir -p release
cp artifacts/arm64-prod/yao "release/yao-${VERSION}-darwin-arm64"
cp artifacts/amd64-prod/yao "release/yao-${VERSION}-darwin-amd64"
cp artifacts/arm64-dev/yao "release/yao-${VERSION}-darwin-arm64-dev"
cp artifacts/amd64-dev/yao "release/yao-${VERSION}-darwin-amd64-dev"
cp artifacts/checksums/*.sha256 release/ 2>/dev/null || true
chmod +x release/yao-*
ls -lh release/
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ steps.version.outputs.tag }}
name: Yao v${{ steps.version.outputs.version }}
files: release/*
generate_release_notes: true
- name: Upload macOS binaries to R2
env:
AWS_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
R2_ENDPOINTS: ${{ secrets.R2_ENDPOINTS }}
R2_BUCKET: ${{ secrets.R2_BUCKET || 'releases' }}
run: |
aws configure set default.region us-east-1
aws configure set default.s3.signature_version s3v4
VERSION="${{ steps.version.outputs.version }}"
PREFIX="yao/${VERSION}"
for PLATFORM in darwin-arm64 darwin-amd64; do
FILE="release/yao-${VERSION}-${PLATFORM}"
NAME="yao-${VERSION}-${PLATFORM}"
sha256sum "$FILE" | awk '{print $1}' > "/tmp/${NAME}.sha256"
aws s3 cp "$FILE" "s3://${R2_BUCKET}/${PREFIX}/${NAME}" \
--endpoint-url "$R2_ENDPOINTS" \
--content-type "application/octet-stream"
aws s3 cp "/tmp/${NAME}.sha256" "s3://${R2_BUCKET}/${PREFIX}/${NAME}.sha256" \
--endpoint-url "$R2_ENDPOINTS" \
--content-type "text/plain"
echo "Uploaded: ${NAME} + ${NAME}.sha256"
done

View file

@ -1,159 +0,0 @@
name: Release
on:
workflow_run:
workflows: ["Release Linux", "Release macOS"]
types:
- completed
permissions:
contents: write
jobs:
# ===================================================================
# Wait for both workflows to succeed, then create a unified release
# ===================================================================
release:
runs-on: ubuntu-latest
if: >
github.event.workflow_run.conclusion == 'success' &&
startsWith(github.event.workflow_run.head_branch, 'v')
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Get Version
id: version
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Prefer head_branch from upstream (works for first-level workflow_run)
TAG="${{ github.event.workflow_run.head_branch }}"
if [[ "$TAG" =~ ^v ]]; then
VERSION="${TAG#v}"
else
# Fallback: get from latest GitHub Release
TAG=$(gh release view --repo "$GITHUB_REPOSITORY" --json tagName -q '.tagName')
VERSION="${TAG#v}"
fi
echo "version=${VERSION}" >> $GITHUB_OUTPUT
echo "tag=${TAG}" >> $GITHUB_OUTPUT
echo "TAG=${TAG} VERSION=${VERSION}"
- name: Wait for Both Workflows
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
TAG="${{ steps.version.outputs.tag }}"
echo "Waiting for both Release Linux and Release macOS to complete for $TAG..."
for i in $(seq 1 60); do
LINUX_STATUS=$(gh run list --workflow="Release Linux" --branch="$TAG" --limit=1 --json conclusion --jq '.[0].conclusion // "pending"')
MACOS_STATUS=$(gh run list --workflow="Release macOS" --branch="$TAG" --limit=1 --json conclusion --jq '.[0].conclusion // "pending"')
echo "Attempt $i: Linux=$LINUX_STATUS macOS=$MACOS_STATUS"
if [ "$LINUX_STATUS" = "success" ] && [ "$MACOS_STATUS" = "success" ]; then
echo "Both workflows completed successfully."
exit 0
fi
if [ "$LINUX_STATUS" = "failure" ] || [ "$MACOS_STATUS" = "failure" ]; then
echo "::error::One or both workflows failed (Linux=$LINUX_STATUS macOS=$MACOS_STATUS)"
exit 1
fi
sleep 60
done
echo "::error::Timed out waiting for workflows"
exit 1
- name: Download Linux Artifacts
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
TAG="${{ steps.version.outputs.tag }}"
LINUX_RUN_ID=$(gh run list --workflow="Release Linux" --branch="$TAG" --limit=1 --json databaseId --jq '.[0].databaseId')
mkdir -p dist/linux
gh run download "$LINUX_RUN_ID" --name yao-linux --dir dist/linux
- name: Download macOS Artifacts
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
TAG="${{ steps.version.outputs.tag }}"
MACOS_RUN_ID=$(gh run list --workflow="Release macOS" --branch="$TAG" --limit=1 --json databaseId --jq '.[0].databaseId')
mkdir -p dist/macos
gh run download "$MACOS_RUN_ID" --name yao-darwin-arm64 --dir dist/macos/arm64-prod
gh run download "$MACOS_RUN_ID" --name yao-darwin-arm64-dev --dir dist/macos/arm64-dev
gh run download "$MACOS_RUN_ID" --name yao-darwin-amd64 --dir dist/macos/amd64-prod
gh run download "$MACOS_RUN_ID" --name yao-darwin-amd64-dev --dir dist/macos/amd64-dev
gh run download "$MACOS_RUN_ID" --name yao-darwin-checksums --dir dist/macos/checksums
- name: Prepare Release Files
run: |
VERSION="${{ steps.version.outputs.version }}"
mkdir -p release
# Linux prod binaries (canonical name = prod/stripped)
cp "dist/linux/yao-${VERSION}-linux-amd64-prod" "release/yao-${VERSION}-linux-amd64"
cp "dist/linux/yao-${VERSION}-linux-arm64-prod" "release/yao-${VERSION}-linux-arm64"
# Linux dev binaries
cp "dist/linux/yao-${VERSION}-linux-amd64" "release/yao-${VERSION}-linux-amd64-dev"
cp "dist/linux/yao-${VERSION}-linux-arm64" "release/yao-${VERSION}-linux-arm64-dev"
# macOS prod binaries
cp dist/macos/arm64-prod/yao "release/yao-${VERSION}-darwin-arm64"
cp dist/macos/amd64-prod/yao "release/yao-${VERSION}-darwin-amd64"
# macOS dev binaries
cp dist/macos/arm64-dev/yao "release/yao-${VERSION}-darwin-arm64-dev"
cp dist/macos/amd64-dev/yao "release/yao-${VERSION}-darwin-amd64-dev"
# Checksums
cp dist/macos/checksums/*.sha256 release/ 2>/dev/null || true
chmod +x release/yao-* 2>/dev/null || true
echo "=== Release files ==="
ls -lh release/
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ steps.version.outputs.tag }}
name: Yao v${{ steps.version.outputs.version }}
files: release/*
generate_release_notes: true
- name: Upload all binaries to R2
env:
AWS_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
R2_ENDPOINTS: ${{ secrets.R2_ENDPOINTS }}
R2_BUCKET: ${{ secrets.R2_BUCKET || 'releases' }}
run: |
aws configure set default.region us-east-1
aws configure set default.s3.signature_version s3v4
VERSION="${{ steps.version.outputs.version }}"
PREFIX="yao/${VERSION}"
echo "Uploading release binaries to R2: ${PREFIX}"
for file in release/yao-${VERSION}-*; do
name=$(basename "$file")
case "$name" in *-dev|*-prod|*.sha256) continue ;; esac
sha256sum "$file" | awk '{print $1}' > "/tmp/${name}.sha256"
aws s3 cp "$file" "s3://${R2_BUCKET}/${PREFIX}/${name}" \
--endpoint-url "$R2_ENDPOINTS" \
--content-type "application/octet-stream"
aws s3 cp "/tmp/${name}.sha256" "s3://${R2_BUCKET}/${PREFIX}/${name}.sha256" \
--endpoint-url "$R2_ENDPOINTS" \
--content-type "text/plain"
echo "Uploaded: ${name} + ${name}.sha256"
done

View file

@ -5,7 +5,8 @@ name: Update CDN latest.json
# Normally triggered automatically by notarize-macos.yml's finalize job after
# notarization completes. Can also be triggered manually as a fallback.
#
# Prerequisites: release.yml must have uploaded all 4 platform binaries to R2.
# Prerequisites: release-linux.yml and release-macos.yml must have uploaded
# all 4 platform binaries to R2.
on:
workflow_dispatch: