Skip to content

Sync Release to Gitee #323

Sync Release to Gitee

Sync Release to Gitee #323

Workflow file for this run

name: Sync Release to Gitee
on:
workflow_dispatch:
jobs:
sync-release-to-gitee:
runs-on: ubuntu-latest
timeout-minutes: 180
env:
GITEE_TOKEN: ${{ secrets.GITEE_TOKEN }}
GH_TOKEN: ${{ github.token }}
steps:
- uses: actions/checkout@v4
- name: Install jq and curl
run: |
sudo apt-get update -y
sudo apt-get install -y jq curl
- name: Sync to Gitee via bash
env:
GH_OWNER: xOS
GH_REPO: ServerStatus
GITEE_OWNER: Ten
GITEE_REPO: ServerStatus
CURL_RETRY: '5'
CURL_RETRY_DELAY: '3'
run: |
set -euo pipefail
GH_API="https://api.github.com/repos/${GH_OWNER}/${GH_REPO}"
GITEE_API="https://gitee.com/api/v5/repos/${GITEE_OWNER}/${GITEE_REPO}"
# 获取最新 release 信息
echo "Fetching latest GitHub release..."
rel_json=$(curl -sS -H "Authorization: Bearer ${GH_TOKEN}" -H "Accept: application/vnd.github+json" "${GH_API}/releases/latest")
tag=$(echo "$rel_json" | jq -r .tag_name)
body=$(echo "$rel_json" | jq -r .body)
if [ -z "$tag" ] || [ "$tag" = "null" ]; then
echo "No release found on GitHub" >&2
exit 1
fi
echo "Latest tag: $tag"
# 下载资产
asset_count=$(echo "$rel_json" | jq '.assets | length')
if [ "$asset_count" -eq 0 ]; then
echo "No assets to sync." >&2
exit 1
fi
echo "Downloading $asset_count assets..."
echo "$rel_json" | jq -r '.assets[] | "\(.name) \(.browser_download_url)"' | while read -r name url; do
echo "Downloading $name"
curl -L --fail --retry ${CURL_RETRY} --retry-delay ${CURL_RETRY_DELAY} -H "Authorization: Bearer ${GH_TOKEN}" -o "$name" "$url"
done
# 创建或复用 Gitee release
echo "Creating or reusing Gitee release..."
create_resp=$(curl -sS -X POST "${GITEE_API}/releases" \
-F access_token="${GITEE_TOKEN}" \
-F tag_name="$tag" \
-F name="$tag" \
-F body="$body" \
-F target_commitish="master" \
-w "\n%{http_code}")
http_code=$(echo "$create_resp" | tail -n1)
create_body=$(echo "$create_resp" | sed '$d')
if [ "$http_code" = "201" ]; then
release_id=$(echo "$create_body" | jq -r .id)
else
echo "Create release failed ($http_code), try list to reuse..."
list_json=$(curl -sS "${GITEE_API}/releases?access_token=${GITEE_TOKEN}&page=1&per_page=100")
release_id=$(echo "$list_json" | jq -r ".[] | select(.tag_name==\"$tag\") | .id" | head -n1)
if [ -z "$release_id" ]; then
echo "No Gitee release id available for tag $tag" >&2
echo "Create response: $create_body" >&2
exit 1
fi
fi
echo "Gitee release id: $release_id"
# 列出已有资产,避免重复
detail_json=$(curl -sS "${GITEE_API}/releases/${release_id}?access_token=${GITEE_TOKEN}")
existing=$(echo "$detail_json" | jq -r '.assets[]?.name' | tr '\n' ' ')
echo "Existing assets: $existing"
# 生成上传列表(以下载得到的资产为准),并按大小排序(先小后大)
echo "$rel_json" | jq -r '.assets[] | .name' > asset_names.txt
: > upload_list.txt
while read -r n; do
[ -f "$n" ] || continue
sz=$(stat -c %s "$n" 2>/dev/null || stat -f %z "$n")
printf "%s %s\n" "$sz" "$n" >> upload_list.txt
done < asset_names.txt
mapfile -t files < <(sort -n upload_list.txt | awk '{print $2}')
attach_api="${GITEE_API}/releases/${release_id}/attach_files"
# 上传辅助函数:尝试多种参数形式
upload_one() {
local filepath="$1"
local attempt ok http_code body tmp
ok=0
tmp=$(mktemp)
# 依据前一轮日志,Gitee 需要字段名为 file;优先用 form token + file,其次 URL token + file
for attempt in 1 2; do
case "$attempt" in
1)
echo " - try1: form token + file=@\"$filepath\""
http_code=$(curl --http1.1 -4 -sS -X POST \
--retry ${CURL_RETRY} --retry-delay ${CURL_RETRY_DELAY} --retry-all-errors \
--no-keepalive --tcp-nodelay --expect100-timeout 0 \
--connect-timeout 10 --max-time 3600 \
-F access_token="${GITEE_TOKEN}" \
-F file=@"$filepath" \
-o "$tmp" -w "%{http_code}" \
"$attach_api")
;;
2)
echo " - try2: url token + file=@\"$filepath\""
http_code=$(curl --http1.1 -4 -sS -X POST \
--retry ${CURL_RETRY} --retry-delay ${CURL_RETRY_DELAY} --retry-all-errors \
--no-keepalive --tcp-nodelay --expect100-timeout 0 \
--connect-timeout 10 --max-time 3600 \
-F file=@"$filepath" \
-o "$tmp" -w "%{http_code}" \
"$attach_api?access_token=${GITEE_TOKEN}")
;;
esac
body=$(head -c 256 "$tmp" || true)
echo " http=$http_code body=${body}"
if [ "$http_code" = "201" ]; then
ok=1; break
fi
# 容错:若服务端提示已存在,视为成功
if echo "$body" | grep -Eqi '已存在|already exists|exist'; then
ok=1; break
fi
done
rm -f "$tmp"
[ "$ok" = "1" ]
}
# 并发上传(最多 3 个同时进行)
MAX_PAR=3
tmpdir=$(mktemp -d)
pids=()
names=()
i=0
for f in "${files[@]}"; do
name="$f"
if echo " $existing " | grep -q " $name "; then
echo "Skip $name (exists)"
continue
fi
echo "Uploading $name ..."
(
if upload_one "$name"; then
echo ok >"$tmpdir/${name}.status"
echo " -> uploaded"
else
echo fail >"$tmpdir/${name}.status"
echo "Upload failed for $name after all attempts" >&2
fi
) &
pids+=("$!")
names+=("$name")
i=$((i+1))
if [ "$((i % MAX_PAR))" -eq 0 ]; then
wait -n || true
fi
done
# 等待剩余任务
wait || true
# 汇总结果
fails=$(ls "$tmpdir" | grep -c \.status$ || true)
if ls "$tmpdir"/*.status >/dev/null 2>&1; then
if grep -q '^fail$' "$tmpdir"/*.status; then
echo "One or more uploads failed." >&2
exit 1
fi
fi
rm -rf "$tmpdir"