feat: 开源准备与 upgrade URL 构建时配置
- upgrade: SECRETS_UPGRADE_URL 改为构建时优先(option_env!),CI 自动注入 - upgrade: 支持运行时回退(.env/export),添加 dotenvy 加载 .env - 泛化示例:IP/实例 ID/域名/密钥名改为示例值(10.0.0.1、example.com 等) - tasks.json: 文件 secret 测试改用 test-fixtures/example-key.pem - 文档更新:AGENTS.md、README.md Made-with: Cursor
This commit is contained in:
@@ -542,7 +542,7 @@ mod tests {
|
||||
kind: "service".to_string(),
|
||||
name: "gitea.main".to_string(),
|
||||
tags: vec!["prod".to_string()],
|
||||
metadata: json!({"url": "https://gitea.refining.dev", "enabled": true}),
|
||||
metadata: json!({"url": "https://code.example.com", "enabled": true}),
|
||||
version: 1,
|
||||
created_at: Utc::now(),
|
||||
updated_at: Utc::now(),
|
||||
@@ -579,7 +579,7 @@ mod tests {
|
||||
|
||||
assert_eq!(
|
||||
map.get("GITEA_MAIN_URL").map(String::as_str),
|
||||
Some("https://gitea.refining.dev")
|
||||
Some("https://code.example.com")
|
||||
);
|
||||
assert_eq!(
|
||||
map.get("GITEA_MAIN_ENABLED").map(String::as_str),
|
||||
|
||||
@@ -5,10 +5,26 @@ use sha2::{Digest, Sha256};
|
||||
use std::io::{Cursor, Read, Write};
|
||||
use std::time::Duration;
|
||||
|
||||
const GITEA_API: &str = "https://gitea.refining.dev/api/v1/repos/refining/secrets/releases/latest";
|
||||
|
||||
const CURRENT_VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
|
||||
/// Build-time config via `option_env!("SECRETS_UPGRADE_URL")`. Set during `cargo build`, e.g.:
|
||||
/// SECRETS_UPGRADE_URL=https://... cargo build --release
|
||||
const BUILD_UPGRADE_URL: Option<&'static str> = option_env!("SECRETS_UPGRADE_URL");
|
||||
|
||||
fn upgrade_api_url() -> Result<String> {
|
||||
if let Some(url) = BUILD_UPGRADE_URL.filter(|s| !s.trim().is_empty()) {
|
||||
return Ok(url.to_string());
|
||||
}
|
||||
let url = std::env::var("SECRETS_UPGRADE_URL").context(
|
||||
"SECRETS_UPGRADE_URL is not set at build or runtime. Set it when building: \
|
||||
SECRETS_UPGRADE_URL=https://... cargo build, or export before running secrets upgrade.",
|
||||
)?;
|
||||
if url.trim().is_empty() {
|
||||
anyhow::bail!("SECRETS_UPGRADE_URL is empty.");
|
||||
}
|
||||
Ok(url)
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct Release {
|
||||
tag_name: String,
|
||||
@@ -186,13 +202,14 @@ pub async fn run(check_only: bool) -> Result<()> {
|
||||
.build()
|
||||
.context("failed to build HTTP client")?;
|
||||
|
||||
let api_url = upgrade_api_url()?;
|
||||
let release: Release = client
|
||||
.get(GITEA_API)
|
||||
.get(&api_url)
|
||||
.send()
|
||||
.await
|
||||
.context("failed to fetch release info from Gitea")?
|
||||
.context("failed to fetch release info")?
|
||||
.error_for_status()
|
||||
.context("Gitea API returned an error")?
|
||||
.context("release API returned an error")?
|
||||
.json()
|
||||
.await
|
||||
.context("failed to parse release JSON")?;
|
||||
|
||||
22
src/main.rs
22
src/main.rs
@@ -7,6 +7,11 @@ mod models;
|
||||
mod output;
|
||||
|
||||
use anyhow::Result;
|
||||
|
||||
/// Load .env from current or parent directories (best-effort, no error if missing).
|
||||
fn load_dotenv() {
|
||||
let _ = dotenvy::dotenv();
|
||||
}
|
||||
use clap::{Parser, Subcommand};
|
||||
use tracing_subscriber::EnvFilter;
|
||||
|
||||
@@ -76,25 +81,25 @@ EXAMPLES:
|
||||
# Add a server
|
||||
secrets add -n refining --kind server --name my-server \\
|
||||
--tag aliyun --tag shanghai \\
|
||||
-m ip=47.117.131.22 -m desc=\"Aliyun Shanghai ECS\" \\
|
||||
-m ip=10.0.0.1 -m desc=\"Example ECS\" \\
|
||||
-s username=root -s ssh_key=@./keys/server.pem
|
||||
|
||||
# Add a service credential
|
||||
secrets add -n refining --kind service --name gitea \\
|
||||
--tag gitea \\
|
||||
-m url=https://gitea.refining.dev -m default_org=refining \\
|
||||
-m url=https://code.example.com -m default_org=myorg \\
|
||||
-s token=<token>
|
||||
|
||||
# Add typed JSON metadata
|
||||
secrets add -n refining --kind service --name gitea \\
|
||||
-m port:=3000 \\
|
||||
-m enabled:=true \\
|
||||
-m domains:='[\"gitea.refining.dev\",\"git.refining.dev\"]' \\
|
||||
-m domains:='[\"code.example.com\",\"git.example.com\"]' \\
|
||||
-m tls:='{\"enabled\":true,\"redirect_http\":true}'
|
||||
|
||||
# Add with token read from a file
|
||||
secrets add -n ricnsmart --kind service --name mqtt \\
|
||||
-m host=mqtt.ricnsmart.com -m port=1883 \\
|
||||
-m host=mqtt.example.com -m port=1883 \\
|
||||
-s password=@./mqtt_password.txt
|
||||
|
||||
# Add typed JSON secrets
|
||||
@@ -114,7 +119,7 @@ EXAMPLES:
|
||||
/// Kind of record: server, service, key, ...
|
||||
#[arg(long)]
|
||||
kind: String,
|
||||
/// Human-readable unique name, e.g. gitea, i-uf63f2uookgs5uxmrdyc
|
||||
/// Human-readable unique name, e.g. gitea, i-example0abcd1234efgh
|
||||
#[arg(long)]
|
||||
name: String,
|
||||
/// Tag for categorization (repeatable), e.g. --tag aliyun --tag hongkong
|
||||
@@ -177,7 +182,7 @@ EXAMPLES:
|
||||
/// Filter by kind, e.g. server, service
|
||||
#[arg(long)]
|
||||
kind: Option<String>,
|
||||
/// Exact name filter, e.g. gitea, i-uf63f2uookgs5uxmrdyc
|
||||
/// Exact name filter, e.g. gitea, i-example0abcd1234efgh
|
||||
#[arg(long)]
|
||||
name: Option<String>,
|
||||
/// Filter by tag, e.g. --tag aliyun (repeatable for AND intersection)
|
||||
@@ -423,8 +428,8 @@ EXAMPLES:
|
||||
|
||||
/// Check for a newer version and update the binary in-place.
|
||||
///
|
||||
/// Downloads the latest release from Gitea and replaces the current binary.
|
||||
/// No database connection or master key required.
|
||||
/// Downloads the latest release and replaces the current binary. No database connection or master key required.
|
||||
/// Release URL defaults to the upstream server; override via SECRETS_UPGRADE_URL for self-hosted or fork.
|
||||
#[command(after_help = "EXAMPLES:
|
||||
# Check for updates only (no download)
|
||||
secrets upgrade --check
|
||||
@@ -530,6 +535,7 @@ enum ConfigAction {
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<()> {
|
||||
load_dotenv();
|
||||
let cli = Cli::parse();
|
||||
|
||||
let filter = if cli.verbose {
|
||||
|
||||
Reference in New Issue
Block a user