Compare commits

...

5 Commits

Author SHA1 Message Date
voson
bce01a0f2b chore(secrets-mcp): bump version to 0.1.2
Some checks failed
Secrets MCP — Build & Release / 版本 & Release (push) Successful in 3s
Secrets MCP — Build & Release / 质量检查 (fmt / clippy / test) (push) Failing after 2m21s
Secrets MCP — Build & Release / Build Linux (secrets-mcp, musl) (push) Has been skipped
Secrets MCP — Build & Release / 部署 secrets-mcp (push) Has been skipped
Secrets MCP — Build & Release / 发布草稿 Release (push) Successful in 8s
Made-with: Cursor
2026-03-20 21:56:57 +08:00
voson
8cd4dbf592 ci: 固定 Rust 1.94.0(rust-toolchain + Gitea Actions)
Made-with: Cursor
2026-03-20 21:54:13 +08:00
voson
ad3c8d1672 chore(secrets-mcp): bump version to 0.1.1
Some checks failed
Secrets MCP — Build & Release / 版本 & Release (push) Successful in 3s
Secrets MCP — Build & Release / 质量检查 (fmt / clippy / test) (push) Failing after 2m12s
Secrets MCP — Build & Release / Build Linux (secrets-mcp, musl) (push) Has been skipped
Secrets MCP — Build & Release / 部署 secrets-mcp (push) Has been skipped
Secrets MCP — Build & Release / 发布草稿 Release (push) Successful in 2s
Made-with: Cursor
2026-03-20 21:37:20 +08:00
voson
8d6b9f0368 ci: 质量检查依赖版本 job,重复 tag 时提前失败
Made-with: Cursor
2026-03-20 21:35:00 +08:00
voson
ce9e089348 chore: CI 微调、文档与 dashboard 更新、精简 Gitea Actions 安装脚本
Some checks failed
Secrets MCP — Build & Release / 版本 & Release (push) Failing after 2s
Secrets MCP — Build & Release / 质量检查 (fmt / clippy / test) (push) Failing after 2m8s
Secrets MCP — Build & Release / Build Linux (secrets-mcp, musl) (push) Has been skipped
Secrets MCP — Build & Release / 部署 secrets-mcp (push) Has been skipped
Secrets MCP — Build & Release / 发布草稿 Release (push) Has been skipped
Made-with: Cursor
2026-03-20 21:31:43 +08:00
8 changed files with 76 additions and 78 deletions

View File

@@ -3,7 +3,6 @@ name: Secrets MCP — Build & Release
on:
push:
branches: [main, feat/mcp, mcp]
paths:
- 'crates/**'
- 'Cargo.toml'
@@ -20,6 +19,7 @@ permissions:
env:
MCP_BINARY: secrets-mcp
RUST_TOOLCHAIN: 1.94.0
CARGO_INCREMENTAL: 0
CARGO_NET_RETRY: 10
CARGO_TERM_COLOR: always
@@ -139,17 +139,21 @@ jobs:
check:
name: 质量检查 (fmt / clippy / test)
needs: [version]
runs-on: debian
timeout-minutes: 15
steps:
- name: 安装 Rust
run: |
if ! command -v cargo >/dev/null 2>&1; then
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable
if ! command -v rustup >/dev/null 2>&1; then
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain "${RUST_TOOLCHAIN}"
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
fi
source "$HOME/.cargo/env" 2>/dev/null || true
rustup component add rustfmt clippy
rustup toolchain install "${RUST_TOOLCHAIN}" --profile minimal --component rustfmt --component clippy
rustup default "${RUST_TOOLCHAIN}"
rustc -V
cargo -V
- uses: actions/checkout@v4
@@ -179,12 +183,16 @@ jobs:
run: |
sudo apt-get update
sudo apt-get install -y pkg-config musl-tools binutils curl
if ! command -v cargo >/dev/null 2>&1; then
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable
if ! command -v rustup >/dev/null 2>&1; then
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain "${RUST_TOOLCHAIN}"
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
fi
source "$HOME/.cargo/env" 2>/dev/null || true
rustup target add x86_64-unknown-linux-musl
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
rustup toolchain install "${RUST_TOOLCHAIN}" --profile minimal
rustup default "${RUST_TOOLCHAIN}"
rustup target add x86_64-unknown-linux-musl --toolchain "${RUST_TOOLCHAIN}"
rustc -V
cargo -V
- uses: actions/checkout@v4
@@ -258,13 +266,17 @@ jobs:
- name: 安装 Rust
run: |
if ! command -v cargo >/dev/null 2>&1; then
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable
if ! command -v rustup >/dev/null 2>&1; then
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain "${RUST_TOOLCHAIN}"
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
fi
source "$HOME/.cargo/env" 2>/dev/null || true
sudo apt-get update -qq && sudo apt-get install -y -qq pkg-config musl-tools
rustup target add x86_64-unknown-linux-musl
rustup toolchain install "${RUST_TOOLCHAIN}" --profile minimal
rustup default "${RUST_TOOLCHAIN}"
rustup target add x86_64-unknown-linux-musl --toolchain "${RUST_TOOLCHAIN}"
rustc -V
cargo -V
- name: 缓存 Cargo
uses: actions/cache@v4

View File

@@ -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-<version>`,上传 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-<version>` 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

2
Cargo.lock generated
View File

@@ -1949,7 +1949,7 @@ dependencies = [
[[package]]
name = "secrets-mcp"
version = "0.1.0"
version = "0.1.2"
dependencies = [
"anyhow",
"askama",

View File

@@ -162,10 +162,16 @@ deploy/ # systemd、.env 示例
## CI/CDGitea 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-<version>` 与 Release 产物 → 可选 SSH 部署。
见 [`.gitea/workflows/secrets.yml`](.gitea/workflows/secrets.yml)。
- **触发**:任意分支 `push`,且变更路径包含 `crates/**``deploy/**`、根目录 `Cargo.toml` / `Cargo.lock`
- **流水线**:解析 `crates/secrets-mcp/Cargo.toml` 版本 → **若 `secrets-mcp-<version>` 的 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)(发版规则、代码规范)。

View File

@@ -1,6 +1,6 @@
[package]
name = "secrets-mcp"
version = "0.1.0"
version = "0.1.2"
edition.workspace = true
[[bin]]

View File

@@ -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 @@
<!-- ── Locked state ──────────────────────────────────────────────────── -->
<div id="locked-view">
<div class="card-title" data-i18n="lockedTitle">获取 MCP 配置</div>
<div class="card-sub" data-i18n="lockedSub">输入加密密码,派生密钥后生成完整的 MCP 配置,可直接复制到 AI 客户端。</div>
<div class="info-box">
<div class="info-title" data-i18n="aboutTitle">说明</div>
<div class="info-line" data-i18n="aboutApiKey">API Key 用于身份认证,告诉服务端“你是谁”。</div>
</div>
<!-- placeholder config -->
<div class="config-wrap">
@@ -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',

3
rust-toolchain.toml Normal file
View File

@@ -0,0 +1,3 @@
[toolchain]
channel = "1.94.0"
components = ["rustfmt", "clippy"]

View File

@@ -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