diff --git a/.gitea/workflows/secrets.yml b/.gitea/workflows/secrets.yml index 8599b9a..c57df49 100644 --- a/.gitea/workflows/secrets.yml +++ b/.gitea/workflows/secrets.yml @@ -3,7 +3,6 @@ name: Secrets MCP — Build & Release on: push: - branches: [main, feat/mcp, mcp] paths: - 'crates/**' - 'Cargo.toml' diff --git a/AGENTS.md b/AGENTS.md index 7899d0c..6687844 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -148,11 +148,13 @@ git tag -l 'secrets-mcp-*' ## CI/CD -- **触发**:`main` / `feat/mcp`(以仓库 workflow 为准);路径含 `crates/**`、`deploy/**`、`Cargo.toml`、`Cargo.lock`。 -- **构建**:`x86_64-unknown-linux-musl` → `secrets-mcp`。 -- **Release**:tag `secrets-mcp-`,上传 tar.gz + `.sha256`。 -- **部署**:可选在仓库 Actions 中配置 `vars.DEPLOY_HOST`、`vars.DEPLOY_USER` 与 `secrets.DEPLOY_SSH_KEY`(勿写进 workflow);可用 `scripts/setup-gitea-actions.sh` 调 Gitea API 写入。Actions **secrets 须为原始值**(如 PEM 全文、PAT 明文),**不要**先 base64 再写入,否则工作流内无法识别(例如 SSH 私钥无效)。**勿**在 CI 中保存 `GOOGLE_CLIENT_SECRET`、DB 密码。 -- **通知**:`vars.WEBHOOK_URL`(可选)。 +- **触发**:任意分支 `push`,且路径含 `crates/**`、`deploy/**`、根目录 `Cargo.toml`、`Cargo.lock`(见 `.gitea/workflows/secrets.yml`)。 +- **版本与 tag**:从 `crates/secrets-mcp/Cargo.toml` 读版本;若远程已存在同名 `secrets-mcp-` tag,**工作流失败**(须先 bump 版本并 `cargo build` 同步 `Cargo.lock`);否则由 CI 创建并推送该 tag。 +- **质量与构建**:`fmt` / `clippy --locked` / `test --locked` → `x86_64-unknown-linux-musl` 发布构建 `secrets-mcp`。 +- **Release(可选)**:`secrets.RELEASE_TOKEN`(Gitea PAT)用于创建草稿 Release、上传 `tar.gz` + `.sha256`、构建成功后发布;未配置则跳过 API Release,仅 tag + 构建。 +- **部署(可选)**:仅 `main`、`feat/mcp`、`mcp` 分支在构建成功时跑 `deploy-mcp`;需 `vars.DEPLOY_HOST`、`vars.DEPLOY_USER`、`secrets.DEPLOY_SSH_KEY`。勿把 OAuth/DB 等写进 workflow,用 `deploy/.env.example` 在目标机配置。 +- **Secrets 写法**:Actions **secrets 须为原始值**(PEM、PAT 明文),**勿** base64;否则 SSH/Release 会失败。**勿**在 CI 中保存 `GOOGLE_CLIENT_SECRET`、DB 密码。 +- **通知**:`vars.WEBHOOK_URL`(可选,飞书)。 ## 环境变量(secrets-mcp) diff --git a/README.md b/README.md index cede465..39bc95a 100644 --- a/README.md +++ b/README.md @@ -162,10 +162,16 @@ deploy/ # systemd、.env 示例 ## CI/CD(Gitea Actions) -见 [`.gitea/workflows/secrets.yml`](.gitea/workflows/secrets.yml)。变更 `crates/**`、`deploy/**`、根目录 `Cargo.toml`/`Cargo.lock` 并推送到配置的分支时:fmt / clippy / test → 构建 `x86_64-unknown-linux-musl` → tag `secrets-mcp-` 与 Release 产物 → 可选 SSH 部署。 +见 [`.gitea/workflows/secrets.yml`](.gitea/workflows/secrets.yml)。 + +- **触发**:任意分支 `push`,且变更路径包含 `crates/**`、`deploy/**`、根目录 `Cargo.toml` / `Cargo.lock`。 +- **流水线**:解析 `crates/secrets-mcp/Cargo.toml` 版本 → **若 `secrets-mcp-` 的 tag 已存在则整次运行失败**(避免重复发版)→ 否则自动打 tag → `cargo fmt` / `clippy --locked` / `test --locked` → 交叉编译 `x86_64-unknown-linux-musl` 的 `secrets-mcp`。 +- **Release(可选)**:配置仓库 Secret `RELEASE_TOKEN`(Gitea PAT,明文勿 base64)时,会通过 API 创建**草稿** Release、在 Linux 构建成功后上传 `tar.gz` 与 `.sha256`,再自动将草稿**正式发布**;未配置则跳过创建 Release 与产物上传,仅保留 tag 与构建结果。 +- **部署(可选)**:仅在 `main`、`feat/mcp` 或 `mcp` 分支且构建成功时,若已配置 `vars.DEPLOY_HOST`、`vars.DEPLOY_USER` 与 `secrets.DEPLOY_SSH_KEY`,则 `deploy-mcp` 通过 SCP/SSH 更新目标机二进制并 `systemctl restart secrets-mcp`。 +- **通知(可选)**:`vars.WEBHOOK_URL` 为飞书 Webhook 时,构建/部署/发布节点会推送简要状态。 ```bash -./scripts/setup-gitea-actions.sh # 配置 Gitea 变量与 Secrets +./scripts/setup-gitea-actions.sh # 通过 Gitea API 写入 RELEASE_TOKEN、WEBHOOK_URL、部署相关变量等 ``` 详见 [AGENTS.md](AGENTS.md)(发版规则、代码规范)。 diff --git a/crates/secrets-mcp/templates/dashboard.html b/crates/secrets-mcp/templates/dashboard.html index 3f279f9..04be739 100644 --- a/crates/secrets-mcp/templates/dashboard.html +++ b/crates/secrets-mcp/templates/dashboard.html @@ -37,12 +37,7 @@ padding: 48px 24px 24px; min-height: calc(100vh - 52px); } .card { background: var(--surface); border: 1px solid var(--border); border-radius: 12px; padding: 32px; width: 100%; max-width: 980px; } - .card-title { font-size: 18px; font-weight: 600; margin-bottom: 6px; } - .card-sub { font-size: 13px; color: var(--text-muted); line-height: 1.6; margin-bottom: 24px; } - .info-box { background: var(--surface2); border: 1px solid var(--border); border-radius: 8px; - padding: 12px 14px; margin-bottom: 18px; } - .info-title { font-size: 12px; font-weight: 600; color: var(--text); margin-bottom: 8px; } - .info-line { font-size: 12px; color: var(--text-muted); line-height: 1.6; } + .card-title { font-size: 18px; font-weight: 600; margin-bottom: 24px; } /* Form */ .field { margin-bottom: 12px; } .field label { display: block; font-size: 12px; color: var(--text-muted); margin-bottom: 5px; } @@ -167,11 +162,6 @@
获取 MCP 配置
-
输入加密密码,派生密钥后生成完整的 MCP 配置,可直接复制到 AI 客户端。
-
-
说明
-
API Key 用于身份认证,告诉服务端“你是谁”。
-
@@ -313,9 +303,6 @@ const T = { 'zh-CN': { signOut: '退出', lockedTitle: '获取 MCP 配置', - lockedSub: '输入加密密码,派生密钥后生成 MCP 配置;请按你所用客户端在解锁后选择对应卡片。', - aboutTitle: '说明', - aboutApiKey: 'API Key 用于身份认证;X-Encryption-Key 用于加解密密文。二者请仅保存在本机配置中。', labelPassphrase: '加密密码', labelConfirm: '确认密码', labelNew: '新密码', @@ -350,9 +337,6 @@ const T = { 'zh-TW': { signOut: '登出', lockedTitle: '取得 MCP 設定', - lockedSub: '輸入加密密碼,派生金鑰後生成 MCP 設定;請依你所用用戶端在解鎖後選擇對應卡片。', - aboutTitle: '說明', - aboutApiKey: 'API Key 用於身份驗證;X-Encryption-Key 用於加解密密文。二者請僅保存在本機設定中。', labelPassphrase: '加密密碼', labelConfirm: '確認密碼', labelNew: '新密碼', @@ -387,9 +371,6 @@ const T = { 'en': { signOut: 'Sign out', lockedTitle: 'Get MCP Config', - lockedSub: 'Enter your encryption password to derive your key and generate MCP config. After unlock, pick the card that matches your client.', - aboutTitle: 'About', - aboutApiKey: 'The API key authenticates you; X-Encryption-Key encrypts secret payloads. Keep both only in local client config.', labelPassphrase: 'Encryption password', labelConfirm: 'Confirm password', labelNew: 'New password', diff --git a/scripts/setup-gitea-actions.sh b/scripts/setup-gitea-actions.sh index ccfdc25..256fb5c 100755 --- a/scripts/setup-gitea-actions.sh +++ b/scripts/setup-gitea-actions.sh @@ -4,7 +4,7 @@ # 参考: .gitea/workflows/secrets.yml # # 所需配置: -# - secrets.RELEASE_TOKEN (必选) Release 上传用,值为 Gitea PAT +# - secrets.RELEASE_TOKEN (可选,推荐) Gitea PAT;未配置则工作流跳过 Release 创建与产物上传 # - vars.WEBHOOK_URL (可选) 飞书通知 # - vars.DEPLOY_HOST (可选) 部署目标 SSH 主机(IP 或域名) # - vars.DEPLOY_USER (可选) SSH 用户名 @@ -21,7 +21,7 @@ # 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 读取 +# 3. 凭据勿用 base64;部署私钥路径见 DEPLOY_SSH_KEY_FILE # set -e @@ -30,26 +30,41 @@ OWNER="refining" REPO="secrets" # 解析参数 -USE_SECRETS_CLI=false while [[ $# -gt 0 ]]; do case $1 in - --from-secrets) USE_SECRETS_CLI=true; shift ;; + --from-secrets) + echo "❌ --from-secrets 尚未实现,请使用 ~/.config/gitea/config.env 或环境变量" >&2 + exit 1 + ;; -h|--help) - echo "用法: $0 [--from-secrets]" + echo "用法: $0" echo "" - echo " --from-secrets 从 secrets CLI (refining/service gitea) 获取 token 和 webhook_url" - echo " 否则从 ~/.config/gitea/config.env 读取" + 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,可选)" + echo "环境变量:" + echo " GITEA_URL Gitea 实例根地址(可误带尾部 /api/v1,脚本会规范化后拼接)" + echo " GITEA_TOKEN 用于 Release 的 PAT → secrets.RELEASE_TOKEN" + echo " WEBHOOK_URL 或 GITEA_WEBHOOK_URL → vars.WEBHOOK_URL(可选)" + echo " DEPLOY_HOST 部署 SSH 主机(可选,须与下面两项同时设置)" + echo " DEPLOY_USER 部署 SSH 用户" + echo " DEPLOY_SSH_KEY_FILE 本地 PEM 路径 → secrets.DEPLOY_SSH_KEY(原文上传,勿 base64)" exit 0 ;; - *) shift ;; + *) + echo "❌ 未知参数: $1" >&2 + echo " 使用 $0 --help 查看用法" >&2 + exit 1 + ;; esac done +for cmd in curl jq; do + if ! command -v "$cmd" &>/dev/null; then + echo "❌ 未找到命令: $cmd(本脚本依赖 curl 与 jq)" >&2 + exit 1 + fi +done + # 加载配置 load_config() { local config="$HOME/.config/gitea/config.env" @@ -59,26 +74,6 @@ load_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 # 优先使用环境变量 @@ -93,18 +88,17 @@ if [[ -z "$GITEA_URL" ]]; then exit 1 fi -# 去掉 URL 尾部斜杠 +# 规范为实例根 URL:去尾部斜杠,并去掉重复的 .../api/v1 后缀(避免拼成 .../api/v1/api/v1) GITEA_URL="${GITEA_URL%/}" -# 确保使用 /api/v1 基础路径(若用户只写了根 URL) -[[ "$GITEA_URL" != *"/api/v1"* ]] || true +while [[ "$GITEA_URL" == */api/v1 ]]; do + GITEA_URL="${GITEA_URL%/api/v1}" + GITEA_URL="${GITEA_URL%/}" +done 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