Sync Release to Gitee #323
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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" |