ci(sidecar): automated build + release workflow (Gitea Actions) #2
@@ -142,7 +142,10 @@ fn persist_token(path: &str, token: &str) -> anyhow::Result<()> {
|
||||
let text = fs::read_to_string(path)?;
|
||||
let line = format!("auth_token = \"{token}\"");
|
||||
|
||||
if text.lines().any(|l| l.trim_start().starts_with("auth_token")) {
|
||||
if text
|
||||
.lines()
|
||||
.any(|l| l.trim_start().starts_with("auth_token"))
|
||||
{
|
||||
let out: String = text
|
||||
.lines()
|
||||
.map(|l| {
|
||||
|
||||
@@ -96,7 +96,11 @@ async fn main() -> anyhow::Result<()> {
|
||||
|
||||
// Persist, then broadcast. `pong` and `ws.hello` are ephemeral chatter, not history.
|
||||
if ev.kind != "pong" {
|
||||
let t = ev.value.get("t").and_then(|v| v.as_i64()).unwrap_or_else(now_ms);
|
||||
let t = ev
|
||||
.value
|
||||
.get("t")
|
||||
.and_then(|v| v.as_i64())
|
||||
.unwrap_or_else(now_ms);
|
||||
let text = ev.value.to_string();
|
||||
if let Err(e) = event_store.insert_event(t, &ev.kind, &text).await {
|
||||
tracing::warn!(error = %e, "failed to persist event");
|
||||
|
||||
@@ -56,10 +56,7 @@ impl Rpc {
|
||||
) -> Result<Value, RpcError> {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
|
||||
self.pending
|
||||
.lock()
|
||||
.await
|
||||
.insert(corr_val.to_string(), tx);
|
||||
self.pending.lock().await.insert(corr_val.to_string(), tx);
|
||||
|
||||
if !shard.send(command.to_string()).await {
|
||||
self.pending.lock().await.remove(corr_val);
|
||||
|
||||
@@ -21,8 +21,8 @@ pub struct Store {
|
||||
impl Store {
|
||||
/// Opens (creating if absent) the SQLite database and ensures the schema exists.
|
||||
pub async fn open(path: &str) -> anyhow::Result<Self> {
|
||||
let opts = SqliteConnectOptions::from_str(&format!("sqlite://{path}"))?
|
||||
.create_if_missing(true);
|
||||
let opts =
|
||||
SqliteConnectOptions::from_str(&format!("sqlite://{path}"))?.create_if_missing(true);
|
||||
|
||||
let pool = SqlitePoolOptions::new()
|
||||
.max_connections(4)
|
||||
@@ -78,7 +78,12 @@ impl Store {
|
||||
self.recent(Some("economy.supply"), limit).await
|
||||
}
|
||||
|
||||
pub async fn record_link(&self, account: &str, website_user_id: &str, t: i64) -> anyhow::Result<()> {
|
||||
pub async fn record_link(
|
||||
&self,
|
||||
account: &str,
|
||||
website_user_id: &str,
|
||||
t: i64,
|
||||
) -> anyhow::Result<()> {
|
||||
sqlx::query(
|
||||
"INSERT INTO links (account, website_user_id, linked_t) VALUES (?, ?, ?)
|
||||
ON CONFLICT(account) DO UPDATE SET website_user_id = excluded.website_user_id, linked_t = excluded.linked_t",
|
||||
|
||||
@@ -123,7 +123,8 @@ fn iso_ms(ms: i64) -> Option<String> {
|
||||
if ms <= 0 {
|
||||
return None;
|
||||
}
|
||||
chrono::DateTime::from_timestamp_millis(ms).map(|dt| dt.format("%Y-%m-%dT%H:%M:%SZ").to_string())
|
||||
chrono::DateTime::from_timestamp_millis(ms)
|
||||
.map(|dt| dt.format("%Y-%m-%dT%H:%M:%SZ").to_string())
|
||||
}
|
||||
|
||||
// ---- gate: protocol check + auth ----
|
||||
@@ -174,8 +175,15 @@ async fn gate(State(st): State<AppState>, req: Request, next: Next) -> Response
|
||||
|
||||
fn extract_token(req: &Request) -> Option<String> {
|
||||
// Authorization: Bearer <token>
|
||||
if let Some(v) = req.headers().get("authorization").and_then(|h| h.to_str().ok()) {
|
||||
if let Some(rest) = v.strip_prefix("Bearer ").or_else(|| v.strip_prefix("bearer ")) {
|
||||
if let Some(v) = req
|
||||
.headers()
|
||||
.get("authorization")
|
||||
.and_then(|h| h.to_str().ok())
|
||||
{
|
||||
if let Some(rest) = v
|
||||
.strip_prefix("Bearer ")
|
||||
.or_else(|| v.strip_prefix("bearer "))
|
||||
{
|
||||
return Some(rest.trim().to_string());
|
||||
}
|
||||
}
|
||||
@@ -349,7 +357,10 @@ async fn page_respond(
|
||||
Path(id): Path<String>,
|
||||
Json(body): Json<Value>,
|
||||
) -> impl IntoResponse {
|
||||
let message = body.get("message").and_then(|m| m.as_str()).unwrap_or_default();
|
||||
let message = body
|
||||
.get("message")
|
||||
.and_then(|m| m.as_str())
|
||||
.unwrap_or_default();
|
||||
if message.trim().is_empty() {
|
||||
return (
|
||||
StatusCode::BAD_REQUEST,
|
||||
@@ -439,7 +450,10 @@ async fn vendors(State(st): State<AppState>, Path(account): Path<String>) -> imp
|
||||
|
||||
/// Body: {"code":"AB12CD","websiteUserId":"9931"}. Correlated on `code`.
|
||||
async fn link_confirm(State(st): State<AppState>, Json(body): Json<Value>) -> impl IntoResponse {
|
||||
let code = body.get("code").and_then(|c| c.as_str()).unwrap_or_default();
|
||||
let code = body
|
||||
.get("code")
|
||||
.and_then(|c| c.as_str())
|
||||
.unwrap_or_default();
|
||||
let web_id = body
|
||||
.get("websiteUserId")
|
||||
.and_then(|w| w.as_str())
|
||||
@@ -501,10 +515,7 @@ async fn towncrier_add(State(st): State<AppState>, Json(body): Json<Value>) -> i
|
||||
respond(st.rpc.call(&st.shard, cmd, &id).await)
|
||||
}
|
||||
|
||||
async fn towncrier_remove(
|
||||
State(st): State<AppState>,
|
||||
Path(id): Path<String>,
|
||||
) -> impl IntoResponse {
|
||||
async fn towncrier_remove(State(st): State<AppState>, Path(id): Path<String>) -> impl IntoResponse {
|
||||
let cmd = json!({"kind":"towncrier.remove","id":id});
|
||||
respond(st.rpc.call(&st.shard, cmd, &id).await)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user