chore(format): Format code

Signed-off-by: Till Wegmueller <toasterson@gmail.com>
This commit is contained in:
Till Wegmueller 2026-01-25 23:16:36 +01:00
parent c0a7f7e3f2
commit d3841462cf
No known key found for this signature in database
4 changed files with 124 additions and 103 deletions

View file

@ -133,7 +133,10 @@ async fn main() -> Result<()> {
let base_url = resolve_logs_base_url(logs_base_url)?;
cmd_logs(&base_url, &job_id, category.as_deref()).await?;
}
Commands::Tui { logs_base_url, repo } => {
Commands::Tui {
logs_base_url,
repo,
} => {
let base_url = resolve_logs_base_url(logs_base_url)?;
let repo = resolve_repo_url(repo);
run_tui(&base_url, repo).await?;
@ -170,11 +173,7 @@ fn detect_git_remote() -> Option<String> {
return None;
}
let s = String::from_utf8_lossy(&output.stdout).trim().to_string();
if s.is_empty() {
None
} else {
Some(s)
}
if s.is_empty() { None } else { Some(s) }
}
fn config_path() -> Result<PathBuf> {
@ -185,7 +184,9 @@ fn config_path() -> Result<PathBuf> {
} else if let Ok(home) = std::env::var("USERPROFILE") {
PathBuf::from(home).join(".config")
} else {
return Err(miette::miette!("Unable to determine home directory for config storage"));
return Err(miette::miette!(
"Unable to determine home directory for config storage"
));
};
Ok(base.join("solstice").join("ciadm.conf"))
}
@ -212,7 +213,11 @@ fn load_logs_base_url() -> Result<Option<String>> {
let Some(node) = doc.get("logs_base_url") else {
return Ok(None);
};
let Some(value) = node.entries().first().and_then(|entry| entry.value().as_string()) else {
let Some(value) = node
.entries()
.first()
.and_then(|entry| entry.value().as_string())
else {
return Ok(None);
};
if value.trim().is_empty() {
@ -222,8 +227,7 @@ fn load_logs_base_url() -> Result<Option<String>> {
}
async fn cmd_jobs(base_url: &str, repo: Option<&str>) -> Result<()> {
let client = LogsClient::new(base_url)
.map_err(|err| miette::Report::msg(err.to_string()))?;
let client = LogsClient::new(base_url).map_err(|err| miette::Report::msg(err.to_string()))?;
let groups = client
.list_jobs()
.await
@ -254,8 +258,7 @@ async fn cmd_jobs(base_url: &str, repo: Option<&str>) -> Result<()> {
}
async fn cmd_logs(base_url: &str, job_id: &str, category: Option<&str>) -> Result<()> {
let client = LogsClient::new(base_url)
.map_err(|err| miette::Report::msg(err.to_string()))?;
let client = LogsClient::new(base_url).map_err(|err| miette::Report::msg(err.to_string()))?;
let request_id = uuid::Uuid::parse_str(job_id).into_diagnostic()?;
let text = if let Some(cat) = category {
client
@ -324,7 +327,9 @@ fn setup_terminal() -> Result<Terminal<ratatui::backend::CrosstermBackend<Stdout
Terminal::new(backend).into_diagnostic()
}
fn restore_terminal(mut terminal: Terminal<ratatui::backend::CrosstermBackend<Stdout>>) -> Result<()> {
fn restore_terminal(
mut terminal: Terminal<ratatui::backend::CrosstermBackend<Stdout>>,
) -> Result<()> {
terminal::disable_raw_mode().into_diagnostic()?;
execute!(terminal.backend_mut(), LeaveAlternateScreen).into_diagnostic()?;
terminal.show_cursor().into_diagnostic()?;
@ -333,10 +338,7 @@ fn restore_terminal(mut terminal: Terminal<ratatui::backend::CrosstermBackend<St
fn filter_groups_by_repo(groups: Vec<JobGroup>, repo: Option<&str>) -> Vec<JobGroup> {
if let Some(repo) = repo {
groups
.into_iter()
.filter(|g| g.repo_url == repo)
.collect()
groups.into_iter().filter(|g| g.repo_url == repo).collect()
} else {
groups
}
@ -434,20 +436,14 @@ impl TuiApp {
.map_err(|err| miette::Report::msg(err.to_string()))?;
let mut repos_map: BTreeMap<String, Vec<JobEntry>> = BTreeMap::new();
for group in groups {
let entries = group
.jobs
.into_iter()
.map(|job| JobEntry {
let entries = group.jobs.into_iter().map(|job| JobEntry {
request_id: job.request_id,
commit_sha: group.commit_sha.clone(),
state: job.state,
runs_on: job.runs_on,
updated_at: job.updated_at,
});
repos_map
.entry(group.repo_url)
.or_default()
.extend(entries);
repos_map.entry(group.repo_url).or_default().extend(entries);
}
let mut repos: Vec<String> = repos_map.keys().cloned().collect();
repos.sort();
@ -488,20 +484,13 @@ impl TuiApp {
};
match self.client.list_log_categories(job.request_id).await {
Ok(categories) => {
self.logs_categories = categories
.into_iter()
.map(|c| c.category)
.collect();
self.logs_categories = categories.into_iter().map(|c| c.category).collect();
if self.logs_categories.is_empty() {
self.logs_text = "No logs available.".to_string();
self.logs_category = None;
self.selected_category = 0;
} else {
if let Some(idx) = self
.logs_categories
.iter()
.position(|c| c == "default")
{
if let Some(idx) = self.logs_categories.iter().position(|c| c == "default") {
self.selected_category = idx;
} else if self.selected_category >= self.logs_categories.len() {
self.selected_category = 0;
@ -624,7 +613,11 @@ impl TuiApp {
let size = frame.area();
let layout = Layout::default()
.direction(Direction::Vertical)
.constraints([Constraint::Length(3), Constraint::Min(5), Constraint::Length(2)])
.constraints([
Constraint::Length(3),
Constraint::Min(5),
Constraint::Length(2),
])
.split(size);
self.draw_header(frame, layout[0]);
self.draw_body(frame, layout[1]);
@ -796,9 +789,7 @@ fn parse_sgr_params(bytes: &[u8]) -> Vec<u16> {
return Vec::new();
}
let s = String::from_utf8_lossy(bytes);
s.split(';')
.filter_map(|p| p.parse::<u16>().ok())
.collect()
s.split(';').filter_map(|p| p.parse::<u16>().ok()).collect()
}
fn apply_sgr(style: &mut Style, params: &[u16]) {

View file

@ -59,7 +59,11 @@ struct Opts {
hookdeck_signing_secret: Option<String>,
/// GitHub API base (e.g., https://api.github.com)
#[arg(long, env = "GITHUB_API_BASE", default_value = "https://api.github.com")]
#[arg(
long,
env = "GITHUB_API_BASE",
default_value = "https://api.github.com"
)]
github_api_base: String,
/// GitHub App ID
@ -186,7 +190,9 @@ async fn main() -> Result<()> {
.hookdeck_signing_secret
.or_else(|| std::env::var("HOOKDECK_SECRET").ok());
if webhook_secret.is_none() && hookdeck_signing_secret.is_none() {
warn!("GITHUB_WEBHOOK_SECRET and HOOKDECK_SIGNING_SECRET are not set — accepting webhooks without signature validation (dev mode)");
warn!(
"GITHUB_WEBHOOK_SECRET and HOOKDECK_SIGNING_SECRET are not set — accepting webhooks without signature validation (dev mode)"
);
}
let app_key_pem = match (&opts.app_key_pem, &opts.app_key_path) {
@ -296,7 +302,9 @@ async fn get_installation_token(state: &AppState, installation_id: u64) -> Resul
return Ok(None);
}
let v: serde_json::Value = resp.json().await.into_diagnostic()?;
Ok(v.get("token").and_then(|t| t.as_str()).map(|s| s.to_string()))
Ok(v.get("token")
.and_then(|t| t.as_str())
.map(|s| s.to_string()))
}
async fn get_installation_id_for_repo(
@ -487,15 +495,13 @@ async fn handle_webhook(
Ok(extract) => handle_pull_request(state, extract.payload).await,
Err(err) => map_webhook_error(err),
},
"ping" => match webhook::verify_signatures(
&headers,
body.as_ref(),
&checks,
SignaturePolicy::Any,
) {
"ping" => {
match webhook::verify_signatures(&headers, body.as_ref(), &checks, SignaturePolicy::Any)
{
Ok(_) => StatusCode::OK,
Err(err) => map_webhook_error(WebhookError::Signature(err)),
},
}
}
_ => StatusCode::NO_CONTENT,
}
}
@ -1290,16 +1296,19 @@ async fn handle_job_result(state: &AppState, jobres: &common::messages::JobResul
}
}
let (owner, repo) = match (
jobres.repo_owner.as_ref(),
jobres.repo_name.as_ref(),
) {
let (owner, repo) = match (jobres.repo_owner.as_ref(), jobres.repo_name.as_ref()) {
(Some(o), Some(r)) => (Some(o.clone()), Some(r.clone())),
_ => parse_owner_repo(&jobres.repo_url).map(|(o, r)| (Some(o), Some(r))).unwrap_or((None, None)),
_ => parse_owner_repo(&jobres.repo_url)
.map(|(o, r)| (Some(o), Some(r)))
.unwrap_or((None, None)),
};
let Some(owner) = owner else { return Ok(()); };
let Some(repo) = repo else { return Ok(()); };
let Some(owner) = owner else {
return Ok(());
};
let Some(repo) = repo else {
return Ok(());
};
let installation_id = match get_installation_id_for_repo(state, &owner, &repo).await? {
Some(id) => id,
@ -1310,14 +1319,25 @@ async fn handle_job_result(state: &AppState, jobres: &common::messages::JobResul
};
let conclusion = if jobres.success { "success" } else { "failure" };
let summary = jobres
.summary
.clone()
.unwrap_or_else(|| if jobres.success { "Job succeeded" } else { "Job failed" }.to_string());
let summary = jobres.summary.clone().unwrap_or_else(|| {
if jobres.success {
"Job succeeded"
} else {
"Job failed"
}
.to_string()
});
let external_id = jobres.request_id.to_string();
if let Some(check_run_id) =
find_check_run_id(state, &token, &owner, &repo, &jobres.commit_sha, &external_id).await?
if let Some(check_run_id) = find_check_run_id(
state,
&token,
&owner,
&repo,
&jobres.commit_sha,
&external_id,
)
.await?
{
let _ = update_check_run(
state,

View file

@ -96,7 +96,10 @@ impl LogsClient {
}
pub async fn list_jobs(&self) -> Result<Vec<JobGroup>> {
let url = self.base_url.join("jobs").map_err(LogsClientError::InvalidBaseUrl)?;
let url = self
.base_url
.join("jobs")
.map_err(LogsClientError::InvalidBaseUrl)?;
self.get_json(url).await
}
@ -105,11 +108,7 @@ impl LogsClient {
self.get_json(url).await
}
pub async fn get_logs_by_category(
&self,
request_id: Uuid,
category: &str,
) -> Result<String> {
pub async fn get_logs_by_category(&self, request_id: Uuid, category: &str) -> Result<String> {
let url = self.job_logs_url(request_id, Some(category))?;
self.get_text(url).await
}
@ -129,8 +128,8 @@ impl LogsClient {
}
async fn get_json<T: DeserializeOwned>(&self, url: Url) -> Result<T> {
let resp = self
.client
let resp =
self.client
.get(url.clone())
.send()
.await
@ -158,8 +157,8 @@ impl LogsClient {
}
async fn get_text(&self, url: Url) -> Result<String> {
let resp = self
.client
let resp =
self.client
.get(url.clone())
.send()
.await
@ -186,9 +185,9 @@ impl LogsClient {
fn job_logs_url(&self, request_id: Uuid, category: Option<&str>) -> Result<Url> {
let mut url = self.base_url.clone();
{
let mut segments = url
.path_segments_mut()
.map_err(|_| LogsClientError::InvalidBaseUrl(url::ParseError::RelativeUrlWithoutBase))?;
let mut segments = url.path_segments_mut().map_err(|_| {
LogsClientError::InvalidBaseUrl(url::ParseError::RelativeUrlWithoutBase)
})?;
segments.clear();
segments.extend(&["jobs", &request_id.to_string(), "logs"]);
if let Some(cat) = category {

View file

@ -1,10 +1,10 @@
use std::net::IpAddr;
use base64::Engine;
use hmac::{Hmac, Mac};
use http::HeaderMap;
use miette::Diagnostic;
use serde::de::DeserializeOwned;
use sha2::Sha256;
use miette::Diagnostic;
use std::net::IpAddr;
use thiserror::Error;
type HmacSha256 = Hmac<Sha256>;
@ -102,13 +102,17 @@ pub enum SignatureError {
#[error("missing signature headers for {0:?}")]
#[diagnostic(
code("webhook.signature.missing"),
help("Ensure the webhook sender or proxy includes the expected signature header(s) for one of the enabled signature sources.")
help(
"Ensure the webhook sender or proxy includes the expected signature header(s) for one of the enabled signature sources."
)
)]
Missing(Vec<SignatureSource>),
#[error("invalid signature for {0:?}")]
#[diagnostic(
code("webhook.signature.invalid"),
help("Check that the signing secret matches the sender/proxy configuration and that the request body is unmodified.")
help(
"Check that the signing secret matches the sender/proxy configuration and that the request body is unmodified."
)
)]
Invalid(Vec<SignatureSource>),
}
@ -124,7 +128,9 @@ enum SignatureCheckError {
#[error("signature verification failed")]
#[diagnostic(
code("webhook.signature.verify_failed"),
help("Confirm the signing secret and ensure the request body is not modified by intermediaries.")
help(
"Confirm the signing secret and ensure the request body is not modified by intermediaries."
)
)]
Invalid,
}
@ -214,7 +220,10 @@ impl WebhookInfo {
delivery: header_string(headers, "X-GitHub-Delivery"),
hook_id: header_u64(headers, "X-GitHub-Hook-Id"),
installation_target_id: header_u64(headers, "X-GitHub-Hook-Installation-Target-Id"),
installation_target_type: header_string(headers, "X-GitHub-Hook-Installation-Target-Type"),
installation_target_type: header_string(
headers,
"X-GitHub-Hook-Installation-Target-Type",
),
user_agent: header_string(headers, "User-Agent"),
};
@ -255,7 +264,9 @@ pub enum WebhookError {
#[error("signature verification failed")]
#[diagnostic(
code("webhook.signature.failed"),
help("Provide a valid signature header or disable verification only in trusted development environments.")
help(
"Provide a valid signature header or disable verification only in trusted development environments."
)
)]
Signature(#[from] SignatureError),
#[error("failed to parse json payload")]