- LICENSE (MIT) + README truth-pass; docs/cli.md CLI contract - CLI subcommands (src/cli_cmds/) per "TUI for users, CLI for users+AI" - Hub/detail refactor: keymap dispatch, modal split, action enum, BgMsg bus - Fix: org repos were never refreshed (owner==username match); refresh now parallel — 49 repos in ~11s, surfaced 70 previously invisible PRs - Fix: 3 date bugs in detail/git.rs (format-local, Local::now, 1y month math) - Stash indicator + [m] actions, session persistence, gh CLI token fallback - Legacy UI modules removed; plan/ docs (roadmap, audit, debate, handoff)
79 lines
3.4 KiB
Rust
79 lines
3.4 KiB
Rust
//! Fetches GitHub release metadata for the hub's General Settings update
|
|
//! tile: the latest published release, and (separately) the release that
|
|
//! matches the version currently running.
|
|
|
|
use anyhow::{Context, Result};
|
|
use serde_json::Value;
|
|
|
|
/// The GitHub repo this binary is published from. Shared with the installer
|
|
/// scripts (`install/vulp-installer.sh`/`.ps1`), which hit the same
|
|
/// `releases/latest` endpoint to fetch the newest build.
|
|
pub const VULP_REPO: &str = "dualfroz/fxg";
|
|
|
|
/// One GitHub release's metadata, trimmed to what the update tile shows.
|
|
#[derive(Debug, Clone)]
|
|
pub struct ReleaseInfo {
|
|
pub tag: String,
|
|
pub author: String,
|
|
pub published_at: String,
|
|
#[allow(dead_code)] pub body: String, // kept: release-notes preview (roadmap)
|
|
pub html_url: String,
|
|
}
|
|
|
|
async fn fetch_release(url: &str) -> Result<ReleaseInfo> {
|
|
let client = reqwest::Client::builder()
|
|
.user_agent("vulp/0.1")
|
|
.timeout(std::time::Duration::from_secs(15))
|
|
.build()?;
|
|
let resp = client.get(url).send().await?;
|
|
let status = resp.status();
|
|
let text = resp.text().await?;
|
|
if !status.is_success() {
|
|
anyhow::bail!("GitHub API {} — {}", status, text);
|
|
}
|
|
let v: Value = serde_json::from_str(&text).context("parsing release JSON")?;
|
|
Ok(ReleaseInfo {
|
|
tag: v["tag_name"].as_str().unwrap_or_default().to_string(),
|
|
author: v["author"]["login"].as_str().unwrap_or("unknown").to_string(),
|
|
published_at: v["published_at"].as_str().unwrap_or_default().to_string(),
|
|
body: v["body"].as_str().unwrap_or_default().chars().take(200).collect(),
|
|
html_url: v["html_url"].as_str().unwrap_or_default().to_string(),
|
|
})
|
|
}
|
|
|
|
/// Info about the very latest release on GitHub, regardless of what's running.
|
|
pub async fn fetch_latest() -> Result<ReleaseInfo> {
|
|
fetch_release(&format!("https://api.github.com/repos/{VULP_REPO}/releases/latest")).await
|
|
}
|
|
|
|
/// Info about the release matching the version actually running, if one was
|
|
/// tagged (`v{CARGO_PKG_VERSION}`) — lets the tile show who shipped *this*
|
|
/// build and when, not just what's newest.
|
|
pub async fn fetch_current(version: &str) -> Result<ReleaseInfo> {
|
|
fetch_release(&format!("https://api.github.com/repos/{VULP_REPO}/releases/tags/v{version}")).await
|
|
}
|
|
|
|
/// The `created_at` date (YYYY-MM-DD) of a GitHub user/org — for the General
|
|
/// Settings tile's account "since" line. Unauthenticated public endpoint.
|
|
pub async fn fetch_user_since(username: &str) -> Result<String> {
|
|
let client = reqwest::Client::builder()
|
|
.user_agent("vulp/0.1")
|
|
.timeout(std::time::Duration::from_secs(15))
|
|
.build()?;
|
|
let resp = client.get(format!("https://api.github.com/users/{username}")).send().await?;
|
|
let status = resp.status();
|
|
let text = resp.text().await?;
|
|
if !status.is_success() {
|
|
anyhow::bail!("GitHub API {} — {}", status, text);
|
|
}
|
|
let v: Value = serde_json::from_str(&text).context("parsing user JSON")?;
|
|
let created = v["created_at"].as_str().unwrap_or_default();
|
|
Ok(created.split('T').next().unwrap_or_default().to_string())
|
|
}
|
|
|
|
/// `true` when the latest published tag differs from the version running.
|
|
pub fn is_outdated(current_version: &str, latest_tag: &str) -> bool {
|
|
let latest = latest_tag.trim_start_matches('v');
|
|
!latest.is_empty() && latest != current_version
|
|
}
|