Files
website/.gitea/workflows/mirror-to-gitee.yml
T
2026-11-04 11:29:29 +08:00

125 lines
6.3 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
name: mirror-to-gitee
# 把本仓(开源项目门户站)镜像到 Gitee 企业仓 <GITEE_OWNER>/<同名仓库>。
# 触发:main 分支推送、v* tag 推送、手动;另有每日兜底重试。
on:
push:
branches:
- main
tags:
- 'v*'
schedule:
# Gitea Actions 的 cron 用 UTC:18:30 UTC = 次日 02:30 北京时间
- cron: '30 18 * * *'
workflow_dispatch:
concurrency:
group: mirror-${{ github.ref }}
cancel-in-progress: true
jobs:
mirror:
runs-on: host
steps:
- name: 同步到 Gitee
env:
SRC_TOKEN: ${{ secrets.SRC_GIT_TOKEN }}
DST_TOKEN: ${{ secrets.GITEE_TOKEN }}
DST_OWNER: ${{ secrets.GITEE_OWNER }}
DST_USER: ${{ secrets.GITEE_USER }}
run: |
set -u
# 仓库名取当前仓。取不到就直接失败,不要回退到别的仓名
# (回退会把本仓的内容推进另一个仓,是危险的默认值)。
REPO_NAME="${GITHUB_REPOSITORY#*/}"
if [ -z "${REPO_NAME:-}" ] || [ "$REPO_NAME" = "${GITHUB_REPOSITORY:-}" ]; then
echo "❌ 取不到仓库名(GITHUB_REPOSITORY=${GITHUB_REPOSITORY:-<空>}),中止"
exit 1
fi
SRC="git.5iot.com/iotlcm-public/${REPO_NAME}.git"
DST="gitee.com/${DST_OWNER}/${REPO_NAME}.git"
echo "源:$SRC"
echo "目标:$DST"
# Gitee 不支持 push 建仓,目标仓不存在时先按企业 API 创建(已存在会报 400,忽略)
if ! git ls-remote "https://${DST_USER}:${DST_TOKEN}@${DST}" >/dev/null 2>&1; then
echo "目标仓不存在,尝试创建 ${DST_OWNER}/${REPO_NAME}"
curl -sS -X POST \
"https://gitee.com/api/v5/enterprises/${DST_OWNER}/repos?access_token=${DST_TOKEN}" \
-H 'Content-Type: application/json' \
-d "{\"name\":\"${REPO_NAME}\",\"auto_init\":false,\"private\":false,\"description\":\"雪羊科技开源项目门户:iotLCM / 秀杰 DTU / XiuAdmin 等开源项目索引\"}" \
-o /tmp/repo-create.json -w '建仓 HTTP %{http_code}\n' || true
head -c 300 /tmp/repo-create.json 2>/dev/null; echo
else
echo "目标仓已存在"
fi
WORK=$(mktemp -d)
trap 'rm -rf "$WORK"' EXIT
git clone --mirror "https://jenkins:${SRC_TOKEN}@git.5iot.com/iotlcm-public/${REPO_NAME}.git" "$WORK/repo.git"
cd "$WORK/repo.git"
echo "本地 ref:$(git for-each-ref --format='%(refname:short)' | tr '\n' ' ')"
# Gitee 在推送密集时会返回 429 Pending queue overflowed / 408 Authorization server timeout,
# 属服务端限流,退避重试即可。
attempt=0
while [ "$attempt" -lt 5 ]; do
attempt=$((attempt + 1))
echo "----- 推送尝试 $attempt/5"
if git push --mirror "https://${DST_USER}:${DST_TOKEN}@${DST}" 2>&1; then
echo "✅ 已同步到 Gitee"
# 推送后校验:远端 main 与 tag 集合必须与本地一致
# (避免“绿了但其实没推上去” —— Gitee 限流时容易发生)
#
# 每条赋值都带 `|| true`:命令替换里任何一段返回非零(新建仓没有 tag 时
# `grep -v` 会返回 1)在 set -e 下会直接中断脚本,
# 导致「推送其实成功了,但 job 报红」这种假失败。
LOCAL_MAIN=$(git rev-parse refs/heads/main 2>/dev/null || true)
REMOTE_MAIN=$(git ls-remote "https://${DST_USER}:${DST_TOKEN}@${DST}" refs/heads/main 2>/dev/null | awk '{print $1}' || true)
LOCAL_TAGS=$(git for-each-ref --format='%(refname:short)' refs/tags 2>/dev/null | sort | tr '\n' ' ' || true)
REMOTE_TAGS=$(git ls-remote --tags "https://${DST_USER}:${DST_TOKEN}@${DST}" 2>/dev/null \
| awk '{print $2}' | sed 's#refs/tags/##' | { grep -v '\^{}$' || true; } | sort | tr '\n' ' ' || true)
echo "本地 main: ${LOCAL_MAIN:-<无>}"
echo "远端 main: ${REMOTE_MAIN:-<无>}"
echo "本地 tag: ${LOCAL_TAGS:-<无>}"
echo "远端 tag: ${REMOTE_TAGS:-<无>}"
if [ -n "$LOCAL_MAIN" ] && [ -n "$REMOTE_MAIN" ] && [ "$LOCAL_MAIN" != "$REMOTE_MAIN" ]; then
echo "❌ 校验失败:远端 main 与本地不一致"
exit 1
fi
if [ "${LOCAL_TAGS% }" != "${REMOTE_TAGS% }" ]; then
echo "❌ 校验失败:远端 tag 与本地不一致"
exit 1
fi
echo "✅ 校验通过:Gitee 端 main 与 tag 均已对齐"
# 目标仓可见性:企业仓建仓 API 忽略 public/private 字段,
# 新建的仓一律是私有的;改可见性需要企业仓管理员权限,
# 本令牌(普通成员令牌)会被拒(401「修改仓库公开属性失败,您没有此项权限」)。
# 因此这里只做「尽力而为 + 明确提示」,失败不算 job 失败。
echo "----- 尝试把目标仓可见性校正为公开"
HTTP=$(curl -sS -m 25 -X PATCH \
"https://gitee.com/api/v5/repos/${DST_OWNER}/${REPO_NAME}?access_token=${DST_TOKEN}" \
-H 'Content-Type: application/json' \
-d "{\"name\":\"${REPO_NAME}\",\"private\":false,\"internal\":false,\"description\":\"雪羊科技开源项目门户:iotLCM / 秀杰 DTU / XiuAdmin 等开源项目索引\"}" \
-o /tmp/repo-patch.json -w '%{http_code}' || echo 000)
echo "改可见性 HTTP ${HTTP}"
head -c 300 /tmp/repo-patch.json 2>/dev/null; echo
case "$HTTP" in
2*) echo "✅ 目标仓已为公开" ;;
*) echo "ℹ️ 目标仓当前为私有。需要用企业仓管理员账号在 Gitee 后台把 ${DST_OWNER}/${REPO_NAME} 改为「公开」;代码已同步,不影响镜像内容。" ;;
esac
exit 0
fi
wait_s=$((attempt * 30))
echo "推送失败,${wait_s}s 后重试"
sleep "$wait_s"
done
echo "❌ 连续 5 次推送失败,请检查 Gitee 状态或令牌"
exit 1