This commit is contained in:
cc
2026-04-17 22:07:40 +08:00
parent a36da9d565
commit a1ab0834b7
4 changed files with 273 additions and 98 deletions

212
.github/scripts/release-utils.sh vendored Normal file
View File

@@ -0,0 +1,212 @@
#!/usr/bin/env bash
set -euo pipefail
retry_cmd() {
local attempts="$1"
local delay_seconds="$2"
shift 2
local i
local exit_code
for ((i = 1; i <= attempts; i++)); do
if "$@"; then
return 0
fi
exit_code=$?
if [ "$i" -lt "$attempts" ]; then
echo "Command failed (attempt $i/$attempts, exit=$exit_code): $*" >&2
echo "Retrying in ${delay_seconds}s..." >&2
sleep "$delay_seconds"
fi
done
echo "Command failed after $attempts attempts: $*" >&2
return "$exit_code"
}
capture_cmd_with_retry() {
local result_var="$1"
local attempts="$2"
local delay_seconds="$3"
shift 3
local i
local output=""
local exit_code=1
for ((i = 1; i <= attempts; i++)); do
if output="$("$@" 2>/dev/null)"; then
printf -v "$result_var" "%s" "$output"
return 0
fi
exit_code=$?
if [ "$i" -lt "$attempts" ]; then
echo "Capture command failed (attempt $i/$attempts, exit=$exit_code): $*" >&2
echo "Retrying in ${delay_seconds}s..." >&2
sleep "$delay_seconds"
fi
done
echo "Capture command failed after $attempts attempts: $*" >&2
return "$exit_code"
}
wait_for_release_id() {
local repo="$1"
local tag="$2"
local attempts="${3:-12}"
local delay_seconds="${4:-2}"
local i
local release_id
for ((i = 1; i <= attempts; i++)); do
release_id="$(gh api "repos/$repo/releases/tags/$tag" --jq '.id' 2>/dev/null || true)"
if [[ "$release_id" =~ ^[0-9]+$ ]]; then
echo "$release_id"
return 0
fi
if [ "$i" -lt "$attempts" ]; then
echo "Release id for tag '$tag' is not ready yet (attempt $i/$attempts), retrying in ${delay_seconds}s..." >&2
sleep "$delay_seconds"
fi
done
echo "Unable to fetch release id for tag '$tag' after $attempts attempts." >&2
gh api "repos/$repo/releases/tags/$tag" --jq '{draft: .draft, prerelease: .prerelease, url: .html_url}' 2>/dev/null || true
return 1
}
settle_release_state() {
local repo="$1"
local release_id="$2"
local tag="$3"
local attempts="${4:-12}"
local delay_seconds="${5:-2}"
local endpoint="repos/$repo/releases/tags/$tag"
local i
local draft_state
local prerelease_state
for ((i = 1; i <= attempts; i++)); do
gh api --method PATCH "repos/$repo/releases/$release_id" -F draft=false -F prerelease=true >/dev/null 2>&1 || true
draft_state="$(gh api "$endpoint" --jq '.draft' 2>/dev/null || echo true)"
prerelease_state="$(gh api "$endpoint" --jq '.prerelease' 2>/dev/null || echo false)"
if [ "$draft_state" = "false" ] && [ "$prerelease_state" = "true" ]; then
return 0
fi
if [ "$i" -lt "$attempts" ]; then
echo "Release '$tag' state not settled yet (attempt $i/$attempts), retrying in ${delay_seconds}s..." >&2
sleep "$delay_seconds"
fi
done
echo "Failed to settle release state for tag '$tag'." >&2
gh api "$endpoint" --jq '{draft: .draft, prerelease: .prerelease, url: .html_url}' 2>/dev/null || true
return 1
}
wait_for_release_absent() {
local repo="$1"
local tag="$2"
local attempts="${3:-12}"
local delay_seconds="${4:-2}"
local i
for ((i = 1; i <= attempts; i++)); do
if gh release view "$tag" --repo "$repo" >/dev/null 2>&1; then
if [ "$i" -lt "$attempts" ]; then
echo "Release '$tag' still exists (attempt $i/$attempts), waiting ${delay_seconds}s..." >&2
sleep "$delay_seconds"
fi
continue
fi
return 0
done
echo "Release '$tag' still exists after waiting." >&2
gh release view "$tag" --repo "$repo" --json url,isDraft,isPrerelease 2>/dev/null || true
return 1
}
wait_for_git_tag_absent() {
local repo="$1"
local tag="$2"
local attempts="${3:-12}"
local delay_seconds="${4:-2}"
local i
for ((i = 1; i <= attempts; i++)); do
if gh api "repos/$repo/git/ref/tags/$tag" >/dev/null 2>&1; then
if [ "$i" -lt "$attempts" ]; then
echo "Git tag '$tag' still exists (attempt $i/$attempts), waiting ${delay_seconds}s..." >&2
sleep "$delay_seconds"
fi
continue
fi
return 0
done
echo "Git tag '$tag' still exists after waiting." >&2
gh api "repos/$repo/git/ref/tags/$tag" --jq '{ref: .ref, object: .object.sha}' 2>/dev/null || true
return 1
}
recreate_fixed_prerelease() {
local repo="$1"
local tag="$2"
local target_branch="$3"
local release_title="$4"
local release_notes="$5"
if gh release view "$tag" --repo "$repo" >/dev/null 2>&1; then
retry_cmd 5 3 gh release delete "$tag" --repo "$repo" --yes --cleanup-tag
fi
wait_for_release_absent "$repo" "$tag" 12 2
if gh api "repos/$repo/git/ref/tags/$tag" >/dev/null 2>&1; then
retry_cmd 5 2 gh api --method DELETE "repos/$repo/git/refs/tags/$tag"
fi
wait_for_git_tag_absent "$repo" "$tag" 12 2
local created="false"
local i
for ((i = 1; i <= 6; i++)); do
if gh release create "$tag" --repo "$repo" --title "$release_title" --notes "$release_notes" --prerelease --target "$target_branch"; then
created="true"
break
fi
if gh release view "$tag" --repo "$repo" >/dev/null 2>&1; then
echo "Release '$tag' appears to exist after create failure; continue to settle state." >&2
created="true"
break
fi
if [ "$i" -lt 6 ]; then
echo "Create release '$tag' failed (attempt $i/6), retrying in 3s..." >&2
sleep 3
fi
done
if [ "$created" != "true" ]; then
echo "Failed to create release '$tag'." >&2
return 1
fi
local release_id
release_id="$(wait_for_release_id "$repo" "$tag" 12 2)"
settle_release_state "$repo" "$release_id" "$tag" 12 2
}
upload_release_assets_with_retry() {
local repo="$1"
local tag="$2"
shift 2
if [ "$#" -eq 0 ]; then
echo "No release assets provided for upload." >&2
return 1
fi
wait_for_release_id "$repo" "$tag" 12 2 >/dev/null
retry_cmd 5 3 gh release upload "$tag" "$@" --repo "$repo" --clobber
}

View File

@@ -55,28 +55,8 @@ jobs:
shell: bash
run: |
set -euo pipefail
if gh release view "$FIXED_DEV_TAG" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then
gh release delete "$FIXED_DEV_TAG" --repo "$GITHUB_REPOSITORY" --yes --cleanup-tag
fi
gh release create "$FIXED_DEV_TAG" --repo "$GITHUB_REPOSITORY" --title "Daily Dev Build" --notes "开发版发布页" --prerelease --target "$TARGET_BRANCH"
RELEASE_REST_ID="$(gh api "repos/$GITHUB_REPOSITORY/releases/tags/$FIXED_DEV_TAG" --jq '.id')"
RELEASE_ENDPOINT="repos/$GITHUB_REPOSITORY/releases/tags/$FIXED_DEV_TAG"
settled="false"
for i in 1 2 3 4 5; do
gh api --method PATCH "repos/$GITHUB_REPOSITORY/releases/$RELEASE_REST_ID" -F draft=false -F prerelease=true >/dev/null 2>&1 || true
DRAFT_STATE="$(gh api "$RELEASE_ENDPOINT" --jq '.draft' 2>/dev/null || echo true)"
PRERELEASE_STATE="$(gh api "$RELEASE_ENDPOINT" --jq '.prerelease' 2>/dev/null || echo false)"
if [ "$DRAFT_STATE" = "false" ] && [ "$PRERELEASE_STATE" = "true" ]; then
settled="true"
break
fi
sleep 2
done
if [ "$settled" != "true" ]; then
echo "Failed to settle release state after create:"
gh api "$RELEASE_ENDPOINT" --jq '{draft: .draft, prerelease: .prerelease, url: .html_url}'
exit 1
fi
source .github/scripts/release-utils.sh
recreate_fixed_prerelease "$GITHUB_REPOSITORY" "$FIXED_DEV_TAG" "$TARGET_BRANCH" "Daily Dev Build" "开发版发布页"
dev-mac-arm64:
needs: prepare
@@ -134,6 +114,8 @@ jobs:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
shell: bash
run: |
set -euo pipefail
source .github/scripts/release-utils.sh
assets=()
while IFS= read -r file; do
assets+=("$file")
@@ -142,7 +124,7 @@ jobs:
echo "No release files found in ./release"
exit 1
fi
gh release upload "$FIXED_DEV_TAG" "${assets[@]}" --repo "$GITHUB_REPOSITORY" --clobber
upload_release_assets_with_retry "$GITHUB_REPOSITORY" "$FIXED_DEV_TAG" "${assets[@]}"
dev-linux:
needs: prepare
@@ -181,6 +163,8 @@ jobs:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
shell: bash
run: |
set -euo pipefail
source .github/scripts/release-utils.sh
assets=()
while IFS= read -r file; do
assets+=("$file")
@@ -189,7 +173,7 @@ jobs:
echo "No release files found in ./release"
exit 1
fi
gh release upload "$FIXED_DEV_TAG" "${assets[@]}" --repo "$GITHUB_REPOSITORY" --clobber
upload_release_assets_with_retry "$GITHUB_REPOSITORY" "$FIXED_DEV_TAG" "${assets[@]}"
dev-win-x64:
needs: prepare
@@ -228,6 +212,8 @@ jobs:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
shell: bash
run: |
set -euo pipefail
source .github/scripts/release-utils.sh
assets=()
while IFS= read -r file; do
assets+=("$file")
@@ -236,7 +222,7 @@ jobs:
echo "No release files found in ./release"
exit 1
fi
gh release upload "$FIXED_DEV_TAG" "${assets[@]}" --repo "$GITHUB_REPOSITORY" --clobber
upload_release_assets_with_retry "$GITHUB_REPOSITORY" "$FIXED_DEV_TAG" "${assets[@]}"
dev-win-arm64:
needs: prepare
@@ -275,6 +261,8 @@ jobs:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
shell: bash
run: |
set -euo pipefail
source .github/scripts/release-utils.sh
assets=()
while IFS= read -r file; do
assets+=("$file")
@@ -283,7 +271,7 @@ jobs:
echo "No release files found in ./release"
exit 1
fi
gh release upload "$FIXED_DEV_TAG" "${assets[@]}" --repo "$GITHUB_REPOSITORY" --clobber
upload_release_assets_with_retry "$GITHUB_REPOSITORY" "$FIXED_DEV_TAG" "${assets[@]}"
update-dev-release-notes:
needs:
@@ -382,22 +370,7 @@ jobs:
}
update_release_notes
RELEASE_REST_ID="$(gh api "repos/$REPO/releases/tags/$TAG" --jq '.id')"
RELEASE_ENDPOINT="repos/$REPO/releases/tags/$TAG"
settled="false"
for i in 1 2 3 4 5; do
gh api --method PATCH "repos/$REPO/releases/$RELEASE_REST_ID" -F draft=false -F prerelease=true >/dev/null 2>&1 || true
DRAFT_STATE="$(gh api "$RELEASE_ENDPOINT" --jq '.draft' 2>/dev/null || echo true)"
PRERELEASE_STATE="$(gh api "$RELEASE_ENDPOINT" --jq '.prerelease' 2>/dev/null || echo false)"
if [ "$DRAFT_STATE" = "false" ] && [ "$PRERELEASE_STATE" = "true" ]; then
settled="true"
break
fi
sleep 2
done
if [ "$settled" != "true" ]; then
echo "Failed to settle release state after notes update:"
gh api "$RELEASE_ENDPOINT" --jq '{draft: .draft, prerelease: .prerelease, url: .html_url}'
exit 1
fi
source .github/scripts/release-utils.sh
RELEASE_REST_ID="$(wait_for_release_id "$REPO" "$TAG" 12 2)"
settle_release_state "$REPO" "$RELEASE_REST_ID" "$TAG" 12 2
gh api "repos/$REPO/releases/tags/$TAG" --jq '{isDraft: .draft, isPrerelease: .prerelease, url: .html_url}'

View File

@@ -81,28 +81,8 @@ jobs:
shell: bash
run: |
set -euo pipefail
if gh release view "$FIXED_PREVIEW_TAG" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then
gh release delete "$FIXED_PREVIEW_TAG" --repo "$GITHUB_REPOSITORY" --yes --cleanup-tag
fi
gh release create "$FIXED_PREVIEW_TAG" --repo "$GITHUB_REPOSITORY" --title "Preview Nightly Build" --notes "预览版发布页" --prerelease --target "$TARGET_BRANCH"
RELEASE_REST_ID="$(gh api "repos/$GITHUB_REPOSITORY/releases/tags/$FIXED_PREVIEW_TAG" --jq '.id')"
RELEASE_ENDPOINT="repos/$GITHUB_REPOSITORY/releases/tags/$FIXED_PREVIEW_TAG"
settled="false"
for i in 1 2 3 4 5; do
gh api --method PATCH "repos/$GITHUB_REPOSITORY/releases/$RELEASE_REST_ID" -F draft=false -F prerelease=true >/dev/null 2>&1 || true
DRAFT_STATE="$(gh api "$RELEASE_ENDPOINT" --jq '.draft' 2>/dev/null || echo true)"
PRERELEASE_STATE="$(gh api "$RELEASE_ENDPOINT" --jq '.prerelease' 2>/dev/null || echo false)"
if [ "$DRAFT_STATE" = "false" ] && [ "$PRERELEASE_STATE" = "true" ]; then
settled="true"
break
fi
sleep 2
done
if [ "$settled" != "true" ]; then
echo "Failed to settle release state after create:"
gh api "$RELEASE_ENDPOINT" --jq '{draft: .draft, prerelease: .prerelease, url: .html_url}'
exit 1
fi
source .github/scripts/release-utils.sh
recreate_fixed_prerelease "$GITHUB_REPOSITORY" "$FIXED_PREVIEW_TAG" "$TARGET_BRANCH" "Preview Nightly Build" "预览版发布页"
preview-mac-arm64:
needs: prepare
@@ -163,6 +143,8 @@ jobs:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
shell: bash
run: |
set -euo pipefail
source .github/scripts/release-utils.sh
assets=()
while IFS= read -r file; do
assets+=("$file")
@@ -171,7 +153,7 @@ jobs:
echo "No release files found in ./release"
exit 1
fi
gh release upload "$FIXED_PREVIEW_TAG" "${assets[@]}" --repo "$GITHUB_REPOSITORY" --clobber
upload_release_assets_with_retry "$GITHUB_REPOSITORY" "$FIXED_PREVIEW_TAG" "${assets[@]}"
preview-linux:
needs: prepare
@@ -214,6 +196,8 @@ jobs:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
shell: bash
run: |
set -euo pipefail
source .github/scripts/release-utils.sh
assets=()
while IFS= read -r file; do
assets+=("$file")
@@ -222,7 +206,7 @@ jobs:
echo "No release files found in ./release"
exit 1
fi
gh release upload "$FIXED_PREVIEW_TAG" "${assets[@]}" --repo "$GITHUB_REPOSITORY" --clobber
upload_release_assets_with_retry "$GITHUB_REPOSITORY" "$FIXED_PREVIEW_TAG" "${assets[@]}"
preview-win-x64:
needs: prepare
@@ -265,6 +249,8 @@ jobs:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
shell: bash
run: |
set -euo pipefail
source .github/scripts/release-utils.sh
assets=()
while IFS= read -r file; do
assets+=("$file")
@@ -273,7 +259,7 @@ jobs:
echo "No release files found in ./release"
exit 1
fi
gh release upload "$FIXED_PREVIEW_TAG" "${assets[@]}" --repo "$GITHUB_REPOSITORY" --clobber
upload_release_assets_with_retry "$GITHUB_REPOSITORY" "$FIXED_PREVIEW_TAG" "${assets[@]}"
preview-win-arm64:
needs: prepare
@@ -316,6 +302,8 @@ jobs:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
shell: bash
run: |
set -euo pipefail
source .github/scripts/release-utils.sh
assets=()
while IFS= read -r file; do
assets+=("$file")
@@ -324,7 +312,7 @@ jobs:
echo "No release files found in ./release"
exit 1
fi
gh release upload "$FIXED_PREVIEW_TAG" "${assets[@]}" --repo "$GITHUB_REPOSITORY" --clobber
upload_release_assets_with_retry "$GITHUB_REPOSITORY" "$FIXED_PREVIEW_TAG" "${assets[@]}"
update-preview-release-notes:
needs:
@@ -425,22 +413,7 @@ jobs:
}
update_release_notes
RELEASE_REST_ID="$(gh api "repos/$REPO/releases/tags/$TAG" --jq '.id')"
RELEASE_ENDPOINT="repos/$REPO/releases/tags/$TAG"
settled="false"
for i in 1 2 3 4 5; do
gh api --method PATCH "repos/$REPO/releases/$RELEASE_REST_ID" -F draft=false -F prerelease=true >/dev/null 2>&1 || true
DRAFT_STATE="$(gh api "$RELEASE_ENDPOINT" --jq '.draft' 2>/dev/null || echo true)"
PRERELEASE_STATE="$(gh api "$RELEASE_ENDPOINT" --jq '.prerelease' 2>/dev/null || echo false)"
if [ "$DRAFT_STATE" = "false" ] && [ "$PRERELEASE_STATE" = "true" ]; then
settled="true"
break
fi
sleep 2
done
if [ "$settled" != "true" ]; then
echo "Failed to settle release state after notes update:"
gh api "$RELEASE_ENDPOINT" --jq '{draft: .draft, prerelease: .prerelease, url: .html_url}'
exit 1
fi
source .github/scripts/release-utils.sh
RELEASE_REST_ID="$(wait_for_release_id "$REPO" "$TAG" 12 2)"
settle_release_state "$REPO" "$RELEASE_REST_ID" "$TAG" 12 2
gh api "repos/$REPO/releases/tags/$TAG" --jq '{isDraft: .draft, isPrerelease: .prerelease, url: .html_url}'

View File

@@ -58,15 +58,21 @@ jobs:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
shell: bash
run: |
set -euo pipefail
source .github/scripts/release-utils.sh
TAG=${GITHUB_REF_NAME}
REPO=${{ github.repository }}
MINIMUM_VERSION="4.1.7"
wait_for_release_id "$REPO" "$TAG" 12 2 >/dev/null
for YML_FILE in latest-mac.yml latest-arm64-mac.yml; do
gh release download "$TAG" --repo "$REPO" --pattern "$YML_FILE" --output "/tmp/$YML_FILE" 2>/dev/null || continue
if ! retry_cmd 5 3 gh release download "$TAG" --repo "$REPO" --pattern "$YML_FILE" --output "/tmp/$YML_FILE"; then
echo "Skip $YML_FILE because download failed after retries."
continue
fi
if ! grep -q 'minimumVersion' "/tmp/$YML_FILE"; then
echo "minimumVersion: $MINIMUM_VERSION" >> "/tmp/$YML_FILE"
fi
gh release upload "$TAG" --repo "$REPO" "/tmp/$YML_FILE" --clobber
retry_cmd 5 3 gh release upload "$TAG" --repo "$REPO" "/tmp/$YML_FILE" --clobber
done
release-linux:
@@ -115,13 +121,16 @@ jobs:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
shell: bash
run: |
set -euo pipefail
source .github/scripts/release-utils.sh
TAG=${GITHUB_REF_NAME}
REPO=${{ github.repository }}
MINIMUM_VERSION="4.1.7"
gh release download "$TAG" --repo "$REPO" --pattern "latest-linux.yml" --output "/tmp/latest-linux.yml" 2>/dev/null || true
wait_for_release_id "$REPO" "$TAG" 12 2 >/dev/null
retry_cmd 5 3 gh release download "$TAG" --repo "$REPO" --pattern "latest-linux.yml" --output "/tmp/latest-linux.yml" || true
if [ -f /tmp/latest-linux.yml ] && ! grep -q 'minimumVersion' /tmp/latest-linux.yml; then
echo "minimumVersion: $MINIMUM_VERSION" >> /tmp/latest-linux.yml
gh release upload "$TAG" --repo "$REPO" /tmp/latest-linux.yml --clobber
retry_cmd 5 3 gh release upload "$TAG" --repo "$REPO" /tmp/latest-linux.yml --clobber
fi
release:
@@ -165,13 +174,16 @@ jobs:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
shell: bash
run: |
set -euo pipefail
source .github/scripts/release-utils.sh
TAG=${GITHUB_REF_NAME}
REPO=${{ github.repository }}
MINIMUM_VERSION="4.1.7"
gh release download "$TAG" --repo "$REPO" --pattern "latest.yml" --output "/tmp/latest.yml" 2>/dev/null || true
wait_for_release_id "$REPO" "$TAG" 12 2 >/dev/null
retry_cmd 5 3 gh release download "$TAG" --repo "$REPO" --pattern "latest.yml" --output "/tmp/latest.yml" || true
if [ -f /tmp/latest.yml ] && ! grep -q 'minimumVersion' /tmp/latest.yml; then
echo "minimumVersion: $MINIMUM_VERSION" >> /tmp/latest.yml
gh release upload "$TAG" --repo "$REPO" /tmp/latest.yml --clobber
retry_cmd 5 3 gh release upload "$TAG" --repo "$REPO" /tmp/latest.yml --clobber
fi
release-windows-arm64:
@@ -215,13 +227,16 @@ jobs:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
shell: bash
run: |
set -euo pipefail
source .github/scripts/release-utils.sh
TAG=${GITHUB_REF_NAME}
REPO=${{ github.repository }}
MINIMUM_VERSION="4.1.7"
gh release download "$TAG" --repo "$REPO" --pattern "latest-arm64.yml" --output "/tmp/latest-arm64.yml" 2>/dev/null || true
wait_for_release_id "$REPO" "$TAG" 12 2 >/dev/null
retry_cmd 5 3 gh release download "$TAG" --repo "$REPO" --pattern "latest-arm64.yml" --output "/tmp/latest-arm64.yml" || true
if [ -f /tmp/latest-arm64.yml ] && ! grep -q 'minimumVersion' /tmp/latest-arm64.yml; then
echo "minimumVersion: $MINIMUM_VERSION" >> /tmp/latest-arm64.yml
gh release upload "$TAG" --repo "$REPO" /tmp/latest-arm64.yml --clobber
retry_cmd 5 3 gh release upload "$TAG" --repo "$REPO" /tmp/latest-arm64.yml --clobber
fi
update-release-notes:
@@ -239,12 +254,14 @@ jobs:
shell: bash
run: |
set -euo pipefail
source .github/scripts/release-utils.sh
TAG="$GITHUB_REF_NAME"
REPO="$GITHUB_REPOSITORY"
RELEASE_PAGE="https://github.com/$REPO/releases/tag/$TAG"
wait_for_release_id "$REPO" "$TAG" 12 2 >/dev/null
ASSETS_JSON="$(gh release view "$TAG" --repo "$REPO" --json assets)"
capture_cmd_with_retry ASSETS_JSON 8 3 gh release view "$TAG" --repo "$REPO" --json assets
pick_asset() {
local pattern="$1"
@@ -295,7 +312,7 @@ jobs:
> 如果某个平台链接暂时未生成,可进入[完整发布页]($RELEASE_PAGE)查看全部资源
EOF
gh release edit "$TAG" --repo "$REPO" --notes-file release_notes.md
retry_cmd 5 3 gh release edit "$TAG" --repo "$REPO" --notes-file release_notes.md
deploy-aur:
runs-on: ubuntu-latest