#!/usr/bin/env bash # # 为 refining/secrets 仓库配置 Gitea Actions 所需的 Secrets 和 Variables # 参考: .gitea/workflows/secrets.yml # # 所需配置: # - secrets.RELEASE_TOKEN (必选) Release 上传用,值为 Gitea PAT # - vars.WEBHOOK_URL (可选) 飞书通知 # - vars.DEPLOY_HOST (可选) 部署目标 SSH 主机(IP 或域名) # - vars.DEPLOY_USER (可选) SSH 用户名 # - secrets.DEPLOY_SSH_KEY (可选) SSH 私钥 PEM 全文(原始字符,含 BEGIN/END 行);通过 DEPLOY_SSH_KEY_FILE 写入 API # # 注意: # - Gitea 不允许 secret/variable 名以 GITEA_ 或 GITHUB_ 开头,故使用 RELEASE_TOKEN # - Gitea Actions 的 secrets(API 的 data 字段,及网页里粘贴的值)必须是未经 base64 的原始值。 # 若事先 base64 再写入,工作流里拿到的仍是「一串 base64 文本」,SSH/OpenSSH 无法识别,部署会失败。 # DEPLOY_SSH_KEY 须与 .pem 文件内容一致:本脚本用 jq --rawfile 按原文上传。 # - Variables 的 value 字段同样为原始字符串,不要 base64。 # # 用法: # 1. 从 ~/.config/gitea/config.env 读取 GITEA_URL, GITEA_TOKEN, GITEA_WEBHOOK_URL # 2. 或通过环境变量覆盖: GITEA_TOKEN(作为 RELEASE_TOKEN 的值), WEBHOOK_URL, # DEPLOY_HOST, DEPLOY_USER, DEPLOY_SSH_KEY_FILE(部署到 ECS) # 3. 或使用 secrets CLI 获取: 需 DATABASE_URL,从 refining/service gitea 读取 # set -e OWNER="refining" REPO="secrets" # 解析参数 USE_SECRETS_CLI=false while [[ $# -gt 0 ]]; do case $1 in --from-secrets) USE_SECRETS_CLI=true; shift ;; -h|--help) echo "用法: $0 [--from-secrets]" echo "" echo " --from-secrets 从 secrets CLI (refining/service gitea) 获取 token 和 webhook_url" echo " 否则从 ~/.config/gitea/config.env 读取" echo "" echo "环境变量覆盖:" echo " GITEA_URL Gitea 实例地址" echo " GITEA_TOKEN 用于 Release 上传的 PAT (创建 RELEASE_TOKEN secret)" echo " WEBHOOK_URL 飞书 Webhook URL (创建 variable,可选)" exit 0 ;; *) shift ;; esac done # 加载配置 load_config() { local config="$HOME/.config/gitea/config.env" if [[ -f "$config" ]]; then # shellcheck source=/dev/null source "$config" fi } # 从 secrets CLI 获取 gitea 凭据 fetch_from_secrets() { if ! command -v secrets &>/dev/null; then echo "❌ secrets CLI 未找到,请先构建: cargo build --release" >&2 return 1 fi # 输出 JSON 格式便于解析;需要 --show-secrets # secrets 当前无 JSON 输出,用简单解析 local out out=$(secrets search -n refining --kind service -q gitea --show-secrets 2>/dev/null || true) if [[ -z "$out" ]]; then echo "❌ 未找到 refining/service gitea 记录" >&2 return 1 fi # 简化:从 metadata 和 secrets 中提取,实际格式需根据 search 输出调整 # 此处仅作占位,实际解析较复杂;建议用户优先用 config.env echo "⚠️ --from-secrets 暂不支持自动解析,请使用 config.env 或环境变量" >&2 return 1 } load_config # 优先使用环境变量 if [[ -n "$GITEA_TOKEN" && -z "$GITEA_URL" ]]; then echo "❌ 请设置 GITEA_URL (或确保 config.env 中有)" >&2 exit 1 fi if [[ -z "$GITEA_URL" ]]; then echo "❌ GITEA_URL 未配置" echo " 请创建 ~/.config/gitea/config.env 或设置环境变量" >&2 exit 1 fi # 去掉 URL 尾部斜杠 GITEA_URL="${GITEA_URL%/}" # 确保使用 /api/v1 基础路径(若用户只写了根 URL) [[ "$GITEA_URL" != *"/api/v1"* ]] || true API_BASE="${GITEA_URL}/api/v1" # 获取 GITEA_TOKEN(作为 workflow 中 secrets.RELEASE_TOKEN 的值) if [[ -z "$GITEA_TOKEN" ]]; then if $USE_SECRETS_CLI; then fetch_from_secrets || exit 1 fi echo "❌ GITEA_TOKEN 未配置" echo " 在 ~/.config/gitea/config.env 中设置,或 export GITEA_TOKEN=xxx" >&2 echo " Token 需具备 repo 写权限(创建 Release、上传附件)" >&2 exit 1 fi echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "配置 Gitea Actions: $OWNER/$REPO" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "" # 1. 创建 Secret: RELEASE_TOKEN(data = PAT 原文,勿 base64) echo "1. 创建 Secret: RELEASE_TOKEN" secret_payload=$(jq -n --arg t "$GITEA_TOKEN" '{data: $t}') resp=$(curl -s -w "\n%{http_code}" -X PUT \ -H "Authorization: token $GITEA_TOKEN" \ -H "Content-Type: application/json" \ -d "$secret_payload" \ "${API_BASE}/repos/${OWNER}/${REPO}/actions/secrets/RELEASE_TOKEN") http_code=$(echo "$resp" | tail -n1) body=$(echo "$resp" | sed '$d') if [[ "$http_code" == "200" || "$http_code" == "201" || "$http_code" == "204" ]]; then echo " ✓ RELEASE_TOKEN 已创建/更新" else echo " ❌ 失败 (HTTP $http_code)" >&2 echo "$body" | jq -r '.message // .' 2>/dev/null || echo "$body" >&2 exit 1 fi # 2. 创建/更新 Variable: WEBHOOK_URL(可选,value 为原始 URL 字符串,勿 base64) WEBHOOK_VALUE="${WEBHOOK_URL:-$GITEA_WEBHOOK_URL}" if [[ -n "$WEBHOOK_VALUE" ]]; then echo "" echo "2. 创建/更新 Variable: WEBHOOK_URL" var_payload=$(jq -n --arg v "$WEBHOOK_VALUE" '{value: $v}') resp=$(curl -s -w "\n%{http_code}" -X POST \ -H "Authorization: token $GITEA_TOKEN" \ -H "Content-Type: application/json" \ -d "$var_payload" \ "${API_BASE}/repos/${OWNER}/${REPO}/actions/variables/WEBHOOK_URL") http_code=$(echo "$resp" | tail -n1) body=$(echo "$resp" | sed '$d') if [[ "$http_code" == "200" || "$http_code" == "201" || "$http_code" == "204" ]]; then echo " ✓ WEBHOOK_URL 已创建/更新" elif [[ "$http_code" == "409" ]]; then # 变量已存在,用 PUT 更新 resp=$(curl -s -w "\n%{http_code}" -X PUT \ -H "Authorization: token $GITEA_TOKEN" \ -H "Content-Type: application/json" \ -d "$var_payload" \ "${API_BASE}/repos/${OWNER}/${REPO}/actions/variables/WEBHOOK_URL") http_code=$(echo "$resp" | tail -n1) if [[ "$http_code" == "200" || "$http_code" == "204" ]]; then echo " ✓ WEBHOOK_URL 已更新" else echo " ⚠ 更新失败 (HTTP $http_code)" >&2 fi else echo " ⚠ 失败 (HTTP $http_code),飞书通知将不可用" >&2 fi else echo "" echo "2. 跳过 WEBHOOK_URL(未配置 GITEA_WEBHOOK_URL 或 WEBHOOK_URL)" echo " 飞书通知将不可用;如需可后续在仓库 Settings → Variables 中添加" fi # 3. 部署用 Variable + Secret(与 .gitea/workflows/secrets.yml 中 deploy-mcp 一致) upsert_repo_variable() { local var_name="$1" var_value="$2" local var_payload http_code body resp var_payload=$(jq -n --arg v "$var_value" '{value: $v}') resp=$(curl -s -w "\n%{http_code}" -X POST \ -H "Authorization: token $GITEA_TOKEN" \ -H "Content-Type: application/json" \ -d "$var_payload" \ "${API_BASE}/repos/${OWNER}/${REPO}/actions/variables/${var_name}") http_code=$(echo "$resp" | tail -n1) if [[ "$http_code" == "200" || "$http_code" == "201" || "$http_code" == "204" ]]; then return 0 fi if [[ "$http_code" == "409" ]]; then resp=$(curl -s -w "\n%{http_code}" -X PUT \ -H "Authorization: token $GITEA_TOKEN" \ -H "Content-Type: application/json" \ -d "$var_payload" \ "${API_BASE}/repos/${OWNER}/${REPO}/actions/variables/${var_name}") http_code=$(echo "$resp" | tail -n1) [[ "$http_code" == "200" || "$http_code" == "204" ]] return fi body=$(echo "$resp" | sed '$d') echo " ❌ 变量 ${var_name} 失败 (HTTP $http_code)" >&2 echo "$body" | jq -r '.message // .' 2>/dev/null || echo "$body" >&2 return 1 } if [[ -n "$DEPLOY_HOST" && -n "$DEPLOY_USER" && -n "$DEPLOY_SSH_KEY_FILE" ]]; then echo "" echo "3. 部署目标: vars.DEPLOY_HOST / vars.DEPLOY_USER + secrets.DEPLOY_SSH_KEY" if [[ ! -f "$DEPLOY_SSH_KEY_FILE" ]]; then echo " ❌ DEPLOY_SSH_KEY_FILE 不是文件: $DEPLOY_SSH_KEY_FILE" >&2 exit 1 fi upsert_repo_variable DEPLOY_HOST "$DEPLOY_HOST" || exit 1 echo " ✓ DEPLOY_HOST" upsert_repo_variable DEPLOY_USER "$DEPLOY_USER" || exit 1 echo " ✓ DEPLOY_USER" # PEM 原文写入 secret.data;勿对文件先做 base64,否则 runner 侧 ssh 无法解析密钥 secret_payload=$(jq -n --rawfile k "$DEPLOY_SSH_KEY_FILE" '{data: $k}') resp=$(curl -s -w "\n%{http_code}" -X PUT \ -H "Authorization: token $GITEA_TOKEN" \ -H "Content-Type: application/json" \ -d "$secret_payload" \ "${API_BASE}/repos/${OWNER}/${REPO}/actions/secrets/DEPLOY_SSH_KEY") http_code=$(echo "$resp" | tail -n1) body=$(echo "$resp" | sed '$d') if [[ "$http_code" == "200" || "$http_code" == "201" || "$http_code" == "204" ]]; then echo " ✓ DEPLOY_SSH_KEY" else echo " ❌ DEPLOY_SSH_KEY 失败 (HTTP $http_code)" >&2 echo "$body" | jq -r '.message // .' 2>/dev/null || echo "$body" >&2 exit 1 fi else echo "" echo "3. 跳过部署配置(需同时设置 DEPLOY_HOST、DEPLOY_USER、DEPLOY_SSH_KEY_FILE)" fi echo "" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "✓ 配置完成" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "" echo "Workflow 将使用:" echo " - secrets.RELEASE_TOKEN 创建 Release 并上传二进制" echo " - vars.WEBHOOK_URL 发送飞书通知(如已配置)" echo " - vars.DEPLOY_* / secrets.DEPLOY_SSH_KEY deploy-mcp(如已配置)" echo "" echo "推送代码触发构建:" echo " git push origin main" echo ""