717f239f1b
CI/CD Pipeline / Validate Code Quality And Tests (push) Failing after 0s
CI/CD Pipeline / Frontend Lint (push) Failing after 0s
CI/CD Pipeline / Production Browser E2E (push) Failing after 1656h0m9s
CI/CD Pipeline / Staging API Integration Tests (push) Failing after 1656h0m11s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 1656h0m11s
CI/CD Pipeline / Build & Push Staging (Watchtower auto-deploy) (push) Failing after 1656h0m13s
CI/CD Pipeline / Deploy Production (push) Failing after 1656h31m41s
CI/CD Pipeline / Build Production Runtime Images (push) Failing after 1656h31m43s
98 lines
3.1 KiB
Bash
98 lines
3.1 KiB
Bash
#!/bin/sh
|
||
# CI Checkout script - 从 Gitea API 下载源码 tar 包并解压
|
||
# 用法: ci_checkout.sh [repo_api_base] [ref] [target_dir] [token]
|
||
# repo_api_base: 仓库 API 基础 URL,如 https://git.xiaoxiajianji.com/api/v1/repos/xiaoxia/xiaoxia-saas
|
||
# ref: commit SHA 或分支名
|
||
# target_dir: 目标目录(默认当前目录)
|
||
# token: API token
|
||
# 所有参数均可省略,将从 Gitea Actions 环境变量中读取
|
||
|
||
set -eu
|
||
|
||
# ── 参数解析 ──────────────────────────────────────────────────
|
||
REPO_API_BASE="${1:-}"
|
||
REF="${2:-}"
|
||
TARGET_DIR="${3:-.}"
|
||
TOKEN="${4:-}"
|
||
|
||
# 从环境变量补全默认值(兼容 Gitea Actions)
|
||
if [ -z "$REPO_API_BASE" ]; then
|
||
REPO_API_BASE="${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}"
|
||
fi
|
||
if [ -z "$REF" ]; then
|
||
REF="${GITHUB_SHA}"
|
||
fi
|
||
if [ -z "$TOKEN" ]; then
|
||
TOKEN="${GITHUB_TOKEN:-}"
|
||
fi
|
||
|
||
if [ -z "$REPO_API_BASE" ] || [ -z "$REF" ]; then
|
||
echo "ERROR: repo API base and ref are required" >&2
|
||
echo "Usage: $0 [repo_api_base] [ref] [target_dir] [token]" >&2
|
||
exit 1
|
||
fi
|
||
|
||
# ── 下载并解压 ────────────────────────────────────────────────
|
||
ARCHIVE_URL="${REPO_API_BASE}/archive/${REF}.tar.gz"
|
||
|
||
echo "Checkout: ${ARCHIVE_URL}"
|
||
echo "Target dir: ${TARGET_DIR}"
|
||
|
||
mkdir -p "${TARGET_DIR}"
|
||
|
||
# 通过环境变量传递给 Python
|
||
_CHECKOUT_URL="${ARCHIVE_URL}" \
|
||
_CHECKOUT_TOKEN="${TOKEN}" \
|
||
_CHECKOUT_TARGET_DIR="${TARGET_DIR}" \
|
||
python3 - <<'PY'
|
||
import io, os, tarfile, time, urllib.request, urllib.error
|
||
|
||
url = os.environ['_CHECKOUT_URL']
|
||
token = os.environ.get('_CHECKOUT_TOKEN', '')
|
||
target_dir = os.environ['_CHECKOUT_TARGET_DIR']
|
||
|
||
headers = {}
|
||
if token:
|
||
headers["Authorization"] = f"token {token}"
|
||
|
||
request = urllib.request.Request(url, headers=headers)
|
||
|
||
last_err = None
|
||
for attempt in range(5):
|
||
try:
|
||
with urllib.request.urlopen(request, timeout=120) as response:
|
||
archive = response.read()
|
||
break
|
||
except urllib.error.HTTPError as e:
|
||
last_err = e
|
||
if e.code >= 500 and attempt < 4:
|
||
wait = 2 ** attempt
|
||
print(f"Checkout HTTP {e.code}, retrying in {wait}s (attempt {attempt+1}/5)...")
|
||
time.sleep(wait)
|
||
continue
|
||
raise
|
||
except Exception as e:
|
||
last_err = e
|
||
if attempt < 4:
|
||
wait = 2 ** attempt
|
||
print(f"Checkout error: {e}, retrying in {wait}s (attempt {attempt+1}/5)...")
|
||
time.sleep(wait)
|
||
continue
|
||
raise
|
||
else:
|
||
raise last_err
|
||
|
||
with tarfile.open(fileobj=io.BytesIO(archive), mode='r:gz') as tar:
|
||
root_prefix = tar.getmembers()[0].name.split('/', 1)[0] + '/'
|
||
for member in tar.getmembers():
|
||
name = member.name
|
||
if name == root_prefix[:-1]:
|
||
continue
|
||
if name.startswith(root_prefix):
|
||
member.name = name[len(root_prefix):]
|
||
if member.name:
|
||
tar.extract(member, target_dir)
|
||
|
||
print("Checkout complete.")
|
||
PY
|