#!/usr/bin/env bash
set -u
ARG_FILE="$1"
API="$2"
TAG="$3"
BASE="$4"
SUMMARY="${GITHUB_STEP_SUMMARY:-}"
note() { [ -n "${SUMMARY}" ] && echo "$1" >> "${SUMMARY}"; }
FILE="${ARG_FILE}"
if [ ! -e "${FILE}" ]; then
FOUND=$(find "${GITHUB_WORKSPACE:-.}" -name "${BASE}" -type f 2>/dev/null | head -1)
if [ -n "${FOUND}" ]; then
FILE="${FOUND}"
echo "==> 按文件名定位到附件: ${FILE}"
else
echo "::error::未找到附件文件:${ARG_FILE}(find 也未命中 ${BASE})"
note "## GitCode 上传失败:找不到附件 ${BASE}"
exit 1
fi
fi
SIZE=$(stat -c %s "${FILE}")
note "### 上传 ${BASE}"
note "- 文件: \`${FILE}\`"
note "- 大小: $((SIZE/1024/1024)) MB(${SIZE} 字节)"
export TAG BASE
LIST_RESP=$(curl -s --max-time 60 "${API}/releases?access_token=${GITCODE_TOKEN}&per_page=100")
HAS_EXIST=$(echo "${LIST_RESP}" | python -c "
import json, sys, os
data = json.load(sys.stdin)
tag = os.environ.get('TAG', '')
base = os.environ.get('BASE', '')
for r in data:
if r.get('tag_name') == tag:
assets = r.get('assets', []) or r.get('attachments', [])
names = [a.get('name', '') for a in assets]
sys.exit(0 if base in names else 1)
sys.exit(1)
" 2>/dev/null)
if [ $? -eq 0 ]; then
echo "==> 已存在附件 ${BASE},跳过"
note "- 结果: 附件已存在,跳过(幂等)"
exit 0
fi
echo "==> 获取上传地址: ${BASE}"
UPLOAD_INFO=$(curl -s --max-time 60 "${API}/releases/${TAG}/upload_url?access_token=${GITCODE_TOKEN}&file_name=${BASE}")
UPLOAD_URL=$(echo "${UPLOAD_INFO}" | python -c "import json,sys; print(json.load(sys.stdin).get('url',''))")
if [ -z "${UPLOAD_URL}" ]; then
echo "::error::获取上传地址失败: ${UPLOAD_INFO:0:500}"
note "- 结果: ❌ 获取上传地址失败"
note "- 响应: \`\`\`${UPLOAD_INFO:0:500}\`\`\`"
exit 1
fi
echo " 上传 URL: ${UPLOAD_URL:0:80}..."
timeout=$(( SIZE / 5120 + 600 ))
[ "${timeout}" -lt 900 ] && timeout=900
[ "${timeout}" -gt 21600 ] && timeout=21600
echo "==> 上传 ${BASE} ($(du -h "${FILE}" | cut -f1)) -> GitCode(timeout=${timeout}s)"
export UPLOAD_INFO FILE timeout
UPLOAD_RESP=$(python << 'PYEOF'
import json, sys, urllib.request, os
upload_info = json.loads(os.environ['UPLOAD_INFO'])
upload_url = upload_info['url']
headers = upload_info.get('headers', {})
file_path = os.environ['FILE']
timeout = int(os.environ['timeout'])
with open(file_path, 'rb') as f:
data = f.read()
req = urllib.request.Request(upload_url, data=data, method='PUT')
for k, v in headers.items():
req.add_header(k, v)
try:
with urllib.request.urlopen(req, timeout=timeout) as resp:
print(f'http={resp.status}')
except urllib.error.HTTPError as e:
body = e.read().decode('utf-8', errors='replace')[:500]
print(f'http={e.code} error={body}')
sys.exit(1)
except Exception as e:
print(f'error={e}')
sys.exit(1)
PYEOF
)
CURL_EXIT=$?
echo " Python 上传结果: ${UPLOAD_RESP}"
note "- 上传结果: ${UPLOAD_RESP}"
if [ "${CURL_EXIT}" -ne 0 ]; then
echo "::error::GitCode 上传 ${BASE} 失败: ${UPLOAD_RESP:0:500}"
note "- 结果: ❌ 上传失败"
note ""
note "补救:1) 本页 Re-run failed jobs;2) 手动从 GitHub Release 下载后到 GitCode Release 页添加附件。"
exit 1
fi
echo " ${BASE} 上传成功"
note "- 结果: ✅ 上传成功"