Files
linkmaster-node/all-upload-release.sh
2025-12-07 18:09:49 +08:00

950 lines
29 KiB
Bash
Executable File
Raw Permalink 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.
#!/bin/bash
# 发布上传脚本
# 支持多种上传方式GitHub Releases、Gitea Releases、SCP、FTP、本地复制
set -e
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
# 项目信息
PROJECT_NAME="agent"
BUILD_DIR="bin"
RELEASE_DIR="release"
TEMP_DIR=$(mktemp -d)
# Gitea Token (硬编码)
GITEA_TOKEN="3becb08eee31b422481ce1b8986de1cd645b468e"
# 版本配置文件路径
VERSION_FILE="version.json"
# 从版本配置文件读取版本信息
read_version_config() {
local version_file="${VERSION_FILE}"
if [ ! -f "$version_file" ]; then
return 1
fi
# 检查是否有 jq 命令
if command -v jq &> /dev/null; then
local version=$(jq -r '.version' "$version_file" 2>/dev/null)
local tag=$(jq -r '.tag' "$version_file" 2>/dev/null)
if [ -n "$version" ] && [ "$version" != "null" ]; then
echo "$version|$tag"
return 0
fi
else
# 如果没有 jq使用 grep 和 sed 解析 JSON
local version=$(grep -o '"version"[[:space:]]*:[[:space:]]*"[^"]*"' "$version_file" 2>/dev/null | sed 's/.*"version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/')
local tag=$(grep -o '"tag"[[:space:]]*:[[:space:]]*"[^"]*"' "$version_file" 2>/dev/null | sed 's/.*"tag"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/')
if [ -n "$version" ]; then
echo "$version|$tag"
return 0
fi
fi
return 1
}
# 初始化版本号(从配置文件读取,如果失败则使用时间戳)
VERSION_CONFIG=$(read_version_config)
if [ $? -eq 0 ] && [ -n "$VERSION_CONFIG" ]; then
IFS='|' read -r config_version config_tag <<< "$VERSION_CONFIG"
VERSION="${VERSION:-$config_version}"
DEFAULT_TAG="${config_tag}"
else
VERSION="${VERSION:-$(date +%Y%m%d-%H%M%S)}"
DEFAULT_TAG=""
fi
# 支持的平台列表
PLATFORMS=(
"linux/amd64"
"linux/arm64"
"darwin/amd64"
"darwin/arm64"
"windows/amd64"
"windows/arm64"
)
# 清理函数
cleanup() {
if [ -d "$TEMP_DIR" ]; then
rm -rf "$TEMP_DIR"
fi
}
trap cleanup EXIT
# 显示使用说明
usage() {
echo -e "${BLUE}使用方法:${NC}"
echo " $0 [选项]"
echo ""
echo -e "${BLUE}选项:${NC}"
echo " -h, --help 显示帮助信息"
echo " -m, --method METHOD 上传方式: github|gitea|scp|ftp|local (默认: gitea)"
echo " -v, --version VERSION 版本号 (默认: 时间戳)"
echo " -p, --platform PLATFORM 只上传指定平台 (例如: linux/amd64)"
echo " -t, --tag TAG Git标签 (GitHub/Gitea Releases需要)"
echo " -r, --repo REPO 仓库 (格式: owner/repo默认从.git/config读取)"
echo " -b, --base-url URL Gitea基础URL (默认从.git/config读取)"
echo " -T, --token TOKEN 访问令牌 (已硬编码,此选项已废弃)"
echo " -d, --dest DEST 目标路径 (SCP/FTP/local需要)"
echo " -H, --host HOST 主机地址 (SCP/FTP需要)"
echo " -u, --user USER 用户名 (SCP/FTP需要)"
echo " -P, --port PORT 端口号 (SCP/FTP需要默认: SCP=22, FTP=21)"
echo " -k, --key KEY 私钥路径 (SCP需要)"
echo " --pack-only 只打包不上传"
echo " --no-pack 不上传压缩包,直接上传二进制文件"
echo " --notes NOTES 发布说明 (GitHub/Gitea Releases)"
echo " --notes-file FILE 从文件读取发布说明"
echo ""
echo -e "${BLUE}上传方式说明:${NC}"
echo ""
echo -e "${CYAN}Gitea Releases (自动从.git/config和version.json读取):${NC}"
echo " $0 -m gitea"
echo " $0 -m gitea -t v1.0.0 -v 1.0.0"
echo ""
echo -e "${CYAN}GitHub Releases:${NC}"
echo " $0 -m github -r owner/repo -t v1.0.0 -v 1.0.0"
echo ""
echo -e "${CYAN}SCP上传:${NC}"
echo " $0 -m scp -H example.com -u user -d /path/to/release"
echo " $0 -m scp -H example.com -u user -d /path/to/release -k ~/.ssh/id_rsa"
echo ""
echo -e "${CYAN}FTP上传:${NC}"
echo " $0 -m ftp -H ftp.example.com -u user -d /path/to/release"
echo ""
echo -e "${CYAN}本地复制:${NC}"
echo " $0 -m local -d /path/to/release"
echo ""
echo -e "${CYAN}只打包:${NC}"
echo " $0 --pack-only -v 1.0.0"
}
# 从 .git/config 读取 Git 信息
read_git_info() {
local git_config=".git/config"
if [ ! -f "$git_config" ]; then
return 1
fi
# 读取 origin URL
local url=$(git config --get remote.origin.url 2>/dev/null || echo "")
if [ -z "$url" ]; then
return 1
fi
# 解析 URL
# 支持格式:
# - https://user:pass@host/owner/repo.git
# - https://host/owner/repo.git
# - git@host:owner/repo.git
# - ssh://user@host/owner/repo.git
local base_url=""
local owner=""
local repo_name=""
local token=""
# 提取 token (如果有)
if [[ "$url" =~ https://([^:]+):([^@]+)@(.+) ]]; then
token="${BASH_REMATCH[2]}"
url="https://${BASH_REMATCH[1]}@${BASH_REMATCH[3]}"
fi
# 提取 base_url, owner, repo
if [[ "$url" =~ https://([^/]+)/([^/]+)/([^/]+)\.git ]]; then
base_url="https://${BASH_REMATCH[1]}"
owner="${BASH_REMATCH[2]}"
repo_name="${BASH_REMATCH[3]}"
elif [[ "$url" =~ git@([^:]+):([^/]+)/([^/]+)\.git ]]; then
base_url="https://${BASH_REMATCH[1]}"
owner="${BASH_REMATCH[2]}"
repo_name="${BASH_REMATCH[3]}"
elif [[ "$url" =~ ssh://[^@]+@([^/]+)/([^/]+)/([^/]+)\.git ]]; then
base_url="https://${BASH_REMATCH[1]}"
owner="${BASH_REMATCH[2]}"
repo_name="${BASH_REMATCH[3]}"
fi
if [ -n "$base_url" ] && [ -n "$owner" ] && [ -n "$repo_name" ]; then
echo "$base_url|$owner|$repo_name|$token"
return 0
fi
return 1
}
# 检查必要的工具
check_dependencies() {
local method=$1
local missing_tools=()
case $method in
github)
if ! command -v gh &> /dev/null; then
missing_tools+=("gh (GitHub CLI)")
fi
;;
gitea)
if ! command -v curl &> /dev/null; then
missing_tools+=("curl")
fi
if ! command -v jq &> /dev/null; then
echo -e "${YELLOW}警告: jq 未安装,某些功能可能受限${NC}"
fi
;;
scp)
if ! command -v scp &> /dev/null; then
missing_tools+=("scp")
fi
;;
ftp)
if ! command -v curl &> /dev/null && ! command -v ftp &> /dev/null; then
missing_tools+=("curl 或 ftp")
fi
;;
esac
if [ ${#missing_tools[@]} -gt 0 ]; then
echo -e "${RED}错误: 缺少必要的工具:${NC}"
for tool in "${missing_tools[@]}"; do
echo " - $tool"
done
exit 1
fi
}
# 检查构建文件是否存在
check_build_files() {
if [ ! -d "$BUILD_DIR" ] || [ -z "$(ls -A $BUILD_DIR 2>/dev/null)" ]; then
echo -e "${RED}错误: 构建目录为空或不存在${NC}"
echo "请先运行 ./all-build.sh 编译项目"
exit 1
fi
local found=0
for platform in "${PLATFORMS[@]}"; do
local os=$(echo $platform | cut -d'/' -f1)
local arch=$(echo $platform | cut -d'/' -f2)
local file="${BUILD_DIR}/${PROJECT_NAME}-${os}-${arch}"
if [ "$os" = "windows" ]; then
file="${file}.exe"
fi
if [ -f "$file" ]; then
found=1
break
fi
done
if [ $found -eq 0 ]; then
echo -e "${RED}错误: 未找到任何构建文件${NC}"
echo "请先运行 ./all-build.sh 编译项目"
exit 1
fi
}
# 打包文件
pack_files() {
local platform=$1
local os=$(echo $platform | cut -d'/' -f1)
local arch=$(echo $platform | cut -d'/' -f2)
local binary="${BUILD_DIR}/${PROJECT_NAME}-${os}-${arch}"
if [ "$os" = "windows" ]; then
binary="${binary}.exe"
fi
if [ ! -f "$binary" ]; then
echo -e "${YELLOW}[跳过]${NC} ${platform} - 文件不存在"
return 1
fi
local pack_name="${PROJECT_NAME}-${os}-${arch}-${VERSION}"
local pack_file
if [ "$os" = "windows" ]; then
pack_file="${TEMP_DIR}/${pack_name}.zip"
echo -e "${BLUE}[打包]${NC} ${platform} -> ${pack_name}.zip"
(cd "$BUILD_DIR" && zip -q "${pack_file}" "$(basename $binary)")
else
pack_file="${TEMP_DIR}/${pack_name}.tar.gz"
echo -e "${BLUE}[打包]${NC} ${platform} -> ${pack_name}.tar.gz"
tar -czf "$pack_file" -C "$BUILD_DIR" "$(basename $binary)"
fi
echo "$pack_file"
return 0
}
# 创建发布说明
create_release_notes() {
local notes_file="${TEMP_DIR}/release_notes.md"
cat > "$notes_file" <<EOF
# ${PROJECT_NAME} ${VERSION}
## 版本信息
- **版本号**: ${VERSION}
- **发布日期**: $(date '+%Y-%m-%d %H:%M:%S')
- **Git提交**: $(git rev-parse --short HEAD 2>/dev/null || echo "N/A")
- **Git分支**: $(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "N/A")
## 支持的平台
EOF
for platform in "${PLATFORMS[@]}"; do
local os=$(echo $platform | cut -d'/' -f1)
local arch=$(echo $platform | cut -d'/' -f2)
local binary="${BUILD_DIR}/${PROJECT_NAME}-${os}-${arch}"
if [ "$os" = "windows" ]; then
binary="${binary}.exe"
fi
if [ -f "$binary" ]; then
local size=$(ls -lh "$binary" | awk '{print $5}')
echo "- ${os}/${arch} (${size})" >> "$notes_file"
fi
done
echo "" >> "$notes_file"
echo "## 安装说明" >> "$notes_file"
echo "" >> "$notes_file"
echo "### Linux/macOS" >> "$notes_file"
echo "\`\`\`bash" >> "$notes_file"
echo "tar -xzf ${PROJECT_NAME}-linux-amd64-${VERSION}.tar.gz" >> "$notes_file"
echo "chmod +x ${PROJECT_NAME}-linux-amd64" >> "$notes_file"
echo "./${PROJECT_NAME}-linux-amd64" >> "$notes_file"
echo "\`\`\`" >> "$notes_file"
echo "" >> "$notes_file"
echo "### Windows" >> "$notes_file"
echo "\`\`\`powershell" >> "$notes_file"
echo "Expand-Archive ${PROJECT_NAME}-windows-amd64-${VERSION}.zip" >> "$notes_file"
echo ".\\${PROJECT_NAME}-windows-amd64.exe" >> "$notes_file"
echo "\`\`\`" >> "$notes_file"
echo "$notes_file"
}
# GitHub Releases 上传
upload_github() {
local repo=$1
local tag=$2
local notes_file=$3
if [ -z "$repo" ]; then
echo -e "${RED}错误: GitHub仓库未指定使用 -r owner/repo${NC}"
exit 1
fi
if [ -z "$tag" ]; then
echo -e "${RED}错误: Git标签未指定使用 -t TAG${NC}"
exit 1
fi
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}上传到 GitHub Releases${NC}"
echo -e "${GREEN}========================================${NC}"
echo -e "仓库: ${BLUE}${repo}${NC}"
echo -e "标签: ${BLUE}${tag}${NC}"
echo -e "版本: ${BLUE}${VERSION}${NC}"
echo ""
# 检查是否已存在release
if gh release view "$tag" --repo "$repo" &>/dev/null; then
echo -e "${YELLOW}警告: Release ${tag} 已存在${NC}"
read -p "是否删除并重新创建? (y/N): " confirm
if [[ "$confirm" =~ ^[Yy]$ ]]; then
gh release delete "$tag" --repo "$repo" --yes
else
echo "取消上传"
exit 0
fi
fi
# 创建release
echo -e "${BLUE}[创建Release]${NC} ${tag}"
if [ -f "$notes_file" ]; then
gh release create "$tag" \
--repo "$repo" \
--title "${PROJECT_NAME} ${VERSION}" \
--notes-file "$notes_file" \
--draft=false \
--prerelease=false
else
gh release create "$tag" \
--repo "$repo" \
--title "${PROJECT_NAME} ${VERSION}" \
--notes "Release ${VERSION}" \
--draft=false \
--prerelease=false
fi
# 上传文件
local upload_count=0
shopt -s nullglob
for file in "${TEMP_DIR}"/*.tar.gz "${TEMP_DIR}"/*.zip; do
if [ -f "$file" ]; then
echo -e "${BLUE}[上传]${NC} $(basename $file)"
gh release upload "$tag" "$file" --repo "$repo" --clobber
((upload_count++))
fi
done
shopt -u nullglob
if [ $upload_count -eq 0 ] && [ "$NO_PACK" != "true" ]; then
echo -e "${YELLOW}警告: 没有找到要上传的文件${NC}"
else
echo -e "${GREEN}[完成]${NC} 已上传 ${upload_count} 个文件"
echo -e "${CYAN}Release链接:${NC} https://github.com/${repo}/releases/tag/${tag}"
fi
}
# Gitea Releases 上传
upload_gitea() {
local base_url=$1
local owner=$2
local repo=$3
local tag=$4
local token=$5
local notes_file=$6
if [ -z "$base_url" ] || [ -z "$owner" ] || [ -z "$repo" ]; then
echo -e "${RED}错误: Gitea仓库信息不完整${NC}"
exit 1
fi
if [ -z "$tag" ]; then
echo -e "${RED}错误: Git标签未指定使用 -t TAG${NC}"
exit 1
fi
# Token 已硬编码,确保使用硬编码的 token
if [ -z "$token" ]; then
token="${GITEA_TOKEN}"
fi
if [ -z "$token" ]; then
echo -e "${RED}错误: 访问令牌未配置${NC}"
exit 1
fi
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}上传到 Gitea Releases${NC}"
echo -e "${GREEN}========================================${NC}"
echo -e "基础URL: ${BLUE}${base_url}${NC}"
echo -e "仓库: ${BLUE}${owner}/${repo}${NC}"
echo -e "标签: ${BLUE}${tag}${NC}"
echo -e "版本: ${BLUE}${VERSION}${NC}"
echo ""
local api_base="${base_url}/api/v1"
local repo_api="${api_base}/repos/${owner}/${repo}"
# 读取发布说明
local notes="Release ${VERSION}"
if [ -f "$notes_file" ]; then
notes=$(cat "$notes_file")
fi
# 转义 JSON 字符串(不使用 jq
local notes_escaped=$(echo "$notes" | sed 's/\\/\\\\/g' | sed 's/"/\\"/g' | sed ':a;N;$!ba;s/\n/\\n/g')
# 检查是否已存在release
local existing_release=$(curl -s -X GET \
"${repo_api}/releases/tags/${tag}" \
-H "Authorization: token ${token}" \
-H "Content-Type: application/json" 2>/dev/null)
if echo "$existing_release" | grep -q '"id"'; then
echo -e "${YELLOW}警告: Release ${tag} 已存在${NC}"
read -p "是否删除并重新创建? (y/N): " confirm
if [[ "$confirm" =~ ^[Yy]$ ]]; then
local release_id=$(echo "$existing_release" | grep -o '"id":[0-9]*' | head -1 | cut -d':' -f2)
if [ -n "$release_id" ]; then
curl -s -X DELETE \
"${repo_api}/releases/${release_id}" \
-H "Authorization: token ${token}" > /dev/null
echo -e "${BLUE}[删除]${NC} 已删除现有 Release"
fi
else
echo "取消上传"
exit 0
fi
fi
# 创建release
echo -e "${BLUE}[创建Release]${NC} ${tag}"
local release_data=$(cat <<EOF
{
"tag_name": "${tag}",
"target_commitish": "main",
"name": "${PROJECT_NAME} ${VERSION}",
"body": "${notes_escaped}",
"draft": false,
"prerelease": false
}
EOF
)
local create_response=$(curl -s -X POST \
"${repo_api}/releases" \
-H "Authorization: token ${token}" \
-H "Content-Type: application/json" \
-d "$release_data")
if echo "$create_response" | grep -q '"id"'; then
local release_id=$(echo "$create_response" | grep -o '"id":[0-9]*' | head -1 | cut -d':' -f2)
echo -e "${GREEN}[成功]${NC} Release 已创建 (ID: ${release_id})"
else
echo -e "${RED}[失败]${NC} 创建 Release 失败"
echo "$create_response" | head -20
exit 1
fi
# 上传文件
local upload_count=0
shopt -s nullglob
for file in "${TEMP_DIR}"/*.tar.gz "${TEMP_DIR}"/*.zip; do
if [ -f "$file" ]; then
echo -e "${BLUE}[上传]${NC} $(basename $file)"
local upload_response=$(curl -s -X POST \
"${repo_api}/releases/${release_id}/assets?name=$(basename $file)" \
-H "Authorization: token ${token}" \
-H "Content-Type: application/octet-stream" \
--data-binary "@${file}")
if echo "$upload_response" | grep -q '"id"'; then
echo -e " ${GREEN}${NC} 上传成功"
((upload_count++))
else
echo -e " ${RED}${NC} 上传失败"
echo "$upload_response" | head -5
fi
fi
done
shopt -u nullglob
if [ $upload_count -eq 0 ] && [ "$NO_PACK" != "true" ]; then
echo -e "${YELLOW}警告: 没有找到要上传的文件${NC}"
else
echo -e "${GREEN}[完成]${NC} 已上传 ${upload_count} 个文件"
echo -e "${CYAN}Release链接:${NC} ${base_url}/${owner}/${repo}/releases/tag/${tag}"
fi
}
# SCP上传
upload_scp() {
local host=$1
local user=$2
local dest=$3
local port=${4:-22}
local key=$5
if [ -z "$host" ] || [ -z "$user" ] || [ -z "$dest" ]; then
echo -e "${RED}错误: SCP需要指定主机(-H)、用户(-u)和目标路径(-d)${NC}"
exit 1
fi
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}上传到 SCP${NC}"
echo -e "${GREEN}========================================${NC}"
echo -e "主机: ${BLUE}${user}@${host}:${port}${NC}"
echo -e "目标: ${BLUE}${dest}${NC}"
echo ""
local scp_opts="-P $port"
if [ -n "$key" ]; then
scp_opts="$scp_opts -i $key"
fi
# 创建远程目录
local ssh_cmd="ssh"
if [ -n "$key" ]; then
ssh_cmd="$ssh_cmd -i $key"
fi
ssh -p "$port" $([ -n "$key" ] && echo "-i $key") "$user@$host" "mkdir -p $dest" || true
# 上传文件
local upload_count=0
if [ "$NO_PACK" = "true" ]; then
# 直接上传二进制文件
for platform in "${SELECTED_PLATFORMS[@]}"; do
local os=$(echo $platform | cut -d'/' -f1)
local arch=$(echo $platform | cut -d'/' -f2)
local binary="${BUILD_DIR}/${PROJECT_NAME}-${os}-${arch}"
if [ "$os" = "windows" ]; then
binary="${binary}.exe"
fi
if [ -f "$binary" ]; then
echo -e "${BLUE}[上传]${NC} $(basename $binary)"
scp $scp_opts "$binary" "$user@$host:$dest/"
((upload_count++))
fi
done
else
# 上传压缩包
shopt -s nullglob
for file in "${TEMP_DIR}"/*.tar.gz "${TEMP_DIR}"/*.zip; do
if [ -f "$file" ]; then
echo -e "${BLUE}[上传]${NC} $(basename $file)"
scp $scp_opts "$file" "$user@$host:$dest/"
((upload_count++))
fi
done
shopt -u nullglob
fi
echo -e "${GREEN}[完成]${NC} 已上传 ${upload_count} 个文件"
}
# FTP上传
upload_ftp() {
local host=$1
local user=$2
local dest=$3
local port=${4:-21}
if [ -z "$host" ] || [ -z "$user" ] || [ -z "$dest" ]; then
echo -e "${RED}错误: FTP需要指定主机(-H)、用户(-u)和目标路径(-d)${NC}"
exit 1
fi
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}上传到 FTP${NC}"
echo -e "${GREEN}========================================${NC}"
echo -e "主机: ${BLUE}${host}:${port}${NC}"
echo -e "用户: ${BLUE}${user}${NC}"
echo -e "目标: ${BLUE}${dest}${NC}"
echo ""
read -sp "请输入FTP密码: " ftp_pass
echo ""
local upload_count=0
if [ "$NO_PACK" = "true" ]; then
# 直接上传二进制文件
for platform in "${SELECTED_PLATFORMS[@]}"; do
local os=$(echo $platform | cut -d'/' -f1)
local arch=$(echo $platform | cut -d'/' -f2)
local binary="${BUILD_DIR}/${PROJECT_NAME}-${os}-${arch}"
if [ "$os" = "windows" ]; then
binary="${binary}.exe"
fi
if [ -f "$binary" ]; then
echo -e "${BLUE}[上传]${NC} $(basename $binary)"
curl -T "$binary" \
"ftp://${host}:${port}${dest}/$(basename $binary)" \
--user "${user}:${ftp_pass}" \
--ftp-create-dirs
((upload_count++))
fi
done
else
# 上传压缩包
shopt -s nullglob
for file in "${TEMP_DIR}"/*.tar.gz "${TEMP_DIR}"/*.zip; do
if [ -f "$file" ]; then
echo -e "${BLUE}[上传]${NC} $(basename $file)"
curl -T "$file" \
"ftp://${host}:${port}${dest}/$(basename $file)" \
--user "${user}:${ftp_pass}" \
--ftp-create-dirs
((upload_count++))
fi
done
shopt -u nullglob
fi
echo -e "${GREEN}[完成]${NC} 已上传 ${upload_count} 个文件"
}
# 本地复制
upload_local() {
local dest=$1
if [ -z "$dest" ]; then
echo -e "${RED}错误: 本地复制需要指定目标路径(-d)${NC}"
exit 1
fi
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}复制到本地目录${NC}"
echo -e "${GREEN}========================================${NC}"
echo -e "目标: ${BLUE}${dest}${NC}"
echo ""
mkdir -p "$dest"
local copy_count=0
if [ "$NO_PACK" = "true" ]; then
# 直接复制二进制文件
for platform in "${SELECTED_PLATFORMS[@]}"; do
local os=$(echo $platform | cut -d'/' -f1)
local arch=$(echo $platform | cut -d'/' -f2)
local binary="${BUILD_DIR}/${PROJECT_NAME}-${os}-${arch}"
if [ "$os" = "windows" ]; then
binary="${binary}.exe"
fi
if [ -f "$binary" ]; then
echo -e "${BLUE}[复制]${NC} $(basename $binary)"
cp "$binary" "$dest/"
((copy_count++))
fi
done
else
# 复制压缩包
shopt -s nullglob
for file in "${TEMP_DIR}"/*.tar.gz "${TEMP_DIR}"/*.zip; do
if [ -f "$file" ]; then
echo -e "${BLUE}[复制]${NC} $(basename $file)"
cp "$file" "$dest/"
((copy_count++))
fi
done
shopt -u nullglob
fi
echo -e "${GREEN}[完成]${NC} 已复制 ${copy_count} 个文件"
}
# 主函数
main() {
local method="gitea"
local selected_platforms=()
local tag="${DEFAULT_TAG}"
local repo=""
local base_url=""
local token="${GITEA_TOKEN}" # 使用硬编码的 token
local dest=""
local host=""
local user=""
local port=""
local key=""
local pack_only=false
local notes=""
local notes_file=""
# 解析参数
while [[ $# -gt 0 ]]; do
case $1 in
-h|--help)
usage
exit 0
;;
-m|--method)
method="$2"
shift 2
;;
-v|--version)
VERSION="$2"
shift 2
;;
-p|--platform)
selected_platforms+=("$2")
shift 2
;;
-t|--tag)
tag="$2"
shift 2
;;
-r|--repo)
repo="$2"
shift 2
;;
-b|--base-url)
base_url="$2"
shift 2
;;
-T|--token)
echo -e "${YELLOW}警告: Token 已硬编码,-T 参数将被忽略${NC}"
shift 2
;;
-d|--dest)
dest="$2"
shift 2
;;
-H|--host)
host="$2"
shift 2
;;
-u|--user)
user="$2"
shift 2
;;
-P|--port)
port="$2"
shift 2
;;
-k|--key)
key="$2"
shift 2
;;
--pack-only)
pack_only=true
shift
;;
--no-pack)
NO_PACK=true
shift
;;
--notes)
notes="$2"
shift 2
;;
--notes-file)
notes_file="$2"
shift 2
;;
*)
echo -e "${RED}未知参数: $1${NC}"
usage
exit 1
;;
esac
done
# 确定要处理的平台
if [ ${#selected_platforms[@]} -eq 0 ]; then
SELECTED_PLATFORMS=("${PLATFORMS[@]}")
else
SELECTED_PLATFORMS=("${selected_platforms[@]}")
fi
# 检查构建文件
check_build_files
# 检查依赖
if [ "$pack_only" != "true" ]; then
check_dependencies "$method"
fi
# 打包文件
if [ "$NO_PACK" != "true" ]; then
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}开始打包${NC}"
echo -e "${GREEN}========================================${NC}"
echo -e "版本: ${BLUE}${VERSION}${NC}"
echo -e "平台数量: ${BLUE}${#SELECTED_PLATFORMS[@]}${NC}"
echo ""
for platform in "${SELECTED_PLATFORMS[@]}"; do
pack_files "$platform" > /dev/null
done
echo ""
echo -e "${GREEN}打包完成${NC}"
echo -e "${BLUE}打包文件:${NC}"
shopt -s nullglob
ls -lh "${TEMP_DIR}"/*.tar.gz "${TEMP_DIR}"/*.zip 2>/dev/null | awk '{print " " $9 " (" $5 ")"}'
shopt -u nullglob
echo ""
fi
# 如果只是打包则复制到release目录
if [ "$pack_only" = "true" ]; then
mkdir -p "$RELEASE_DIR"
shopt -s nullglob
cp "${TEMP_DIR}"/*.tar.gz "${TEMP_DIR}"/*.zip "$RELEASE_DIR/" 2>/dev/null || true
shopt -u nullglob
echo -e "${GREEN}文件已复制到 ${RELEASE_DIR} 目录${NC}"
exit 0
fi
# 创建发布说明
local release_notes=""
if [ -n "$notes_file" ] && [ -f "$notes_file" ]; then
release_notes="$notes_file"
elif [ -n "$notes" ]; then
echo "$notes" > "${TEMP_DIR}/release_notes.md"
release_notes="${TEMP_DIR}/release_notes.md"
elif [ "$method" = "github" ] || [ "$method" = "gitea" ]; then
release_notes=$(create_release_notes)
fi
# 根据方法上传
case $method in
gitea)
# 从 .git/config 读取信息(如果未指定)
local git_info=""
if [ -z "$base_url" ] || [ -z "$repo" ]; then
git_info=$(read_git_info)
if [ $? -eq 0 ] && [ -n "$git_info" ]; then
IFS='|' read -r git_base_url git_owner git_repo_name git_token <<< "$git_info"
if [ -z "$base_url" ]; then
base_url="$git_base_url"
fi
if [ -z "$repo" ]; then
repo="${git_owner}/${git_repo_name}"
fi
# Token 已硬编码,不从 git config 读取
# if [ -z "$token" ] && [ -n "$git_token" ]; then
# token="$git_token"
# fi
echo -e "${CYAN}[信息]${NC} 从 .git/config 读取仓库信息: ${repo}"
fi
fi
if [ -z "$base_url" ] || [ -z "$repo" ]; then
echo -e "${RED}错误: Gitea仓库信息不完整${NC}"
echo "请指定 -b BASE_URL 和 -r owner/repo或确保 .git/config 中有正确的远程仓库配置"
exit 1
fi
IFS='/' read -r owner repo_name <<< "$repo"
if [ -z "$owner" ] || [ -z "$repo_name" ]; then
echo -e "${RED}错误: 仓库格式不正确,应为 owner/repo${NC}"
exit 1
fi
upload_gitea "$base_url" "$owner" "$repo_name" "$tag" "$token" "$release_notes"
;;
github)
upload_github "$repo" "$tag" "$release_notes"
;;
scp)
upload_scp "$host" "$user" "$dest" "$port" "$key"
;;
ftp)
upload_ftp "$host" "$user" "$dest" "$port"
;;
local)
upload_local "$dest"
;;
*)
echo -e "${RED}错误: 不支持的上传方式: ${method}${NC}"
echo "支持的方式: gitea, github, scp, ftp, local"
exit 1
;;
esac
echo ""
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}发布完成${NC}"
echo -e "${GREEN}========================================${NC}"
}
# 运行主函数
main "$@"