hive-forge: add ci-runs listing verb, fix ci-log's ambiguous no-log message
This commit is contained in:
parent
55eaebc9cf
commit
56c0602c2f
6 changed files with 204 additions and 59 deletions
78
hive-forge/src/verbs/ci_runs.rs
Normal file
78
hive-forge/src/verbs/ci_runs.rs
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
//! `ci-runs [--workflow <file>] [--branch <name>] [--limit N] [--page N]` —
|
||||
//! list a repo's CI Actions runs, newest first.
|
||||
//!
|
||||
//! A `ci-rerun` dispatch creates a `workflow_dispatch` run that publishes
|
||||
//! no commit status, so there was previously no way from the CLI to see
|
||||
//! what it actually created — or to discover a real run number to hand
|
||||
//! `ci-log`/`artifact-get` at all, short of guessing near a known one.
|
||||
//! This lists runs directly; `--workflow`/`--branch` filter server-side
|
||||
//! via `ListActionRunsQuery`, not a client-side scan.
|
||||
|
||||
use anyhow::Result;
|
||||
use clap::Args as ClapArgs;
|
||||
use forgejo_api::structs::{ActionRun, ListActionRunsQuery};
|
||||
|
||||
use super::ci_common::run_number_of;
|
||||
use crate::client::Client;
|
||||
use crate::verbs::print_json;
|
||||
|
||||
#[derive(ClapArgs)]
|
||||
pub struct Args {
|
||||
/// Only runs of this workflow file (e.g. `ci.yml`).
|
||||
#[arg(long)]
|
||||
workflow: Option<String>,
|
||||
/// Only runs on this branch or ref (e.g. `main`, `damocles/foo`).
|
||||
#[arg(long)]
|
||||
branch: Option<String>,
|
||||
/// How many runs to print (default 20).
|
||||
#[arg(long, default_value_t = 20, value_parser = clap::value_parser!(u64).range(1..))]
|
||||
limit: u64,
|
||||
/// Page number (1-based, default 1). Combine with `--limit` to page
|
||||
/// through further back than the default window.
|
||||
#[arg(long, default_value_t = 1, value_parser = clap::value_parser!(u64).range(1..))]
|
||||
page: u64,
|
||||
}
|
||||
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns an error if the list request fails (network, or a non-2xx).
|
||||
pub fn run(client: &Client, args: Args) -> Result<()> {
|
||||
let (owner, name) = client.owner_repo()?;
|
||||
let query = ListActionRunsQuery {
|
||||
workflow_id: args.workflow.clone(),
|
||||
r#ref: args.branch.clone(),
|
||||
..Default::default()
|
||||
};
|
||||
let body = client
|
||||
.api()
|
||||
.list_action_runs(owner, name, query)
|
||||
.page(u32::try_from(args.page).unwrap_or(u32::MAX))
|
||||
.page_size(u32::try_from(args.limit).unwrap_or(u32::MAX))
|
||||
.send()?;
|
||||
let runs = body.workflow_runs.unwrap_or_default();
|
||||
|
||||
if client.json_mode() {
|
||||
return print_json(&serde_json::to_value(&runs)?);
|
||||
}
|
||||
|
||||
if runs.is_empty() {
|
||||
println!("no matching runs in {}", client.repo());
|
||||
return Ok(());
|
||||
}
|
||||
for run in &runs {
|
||||
print_row(run);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// One human-readable line per run: number, status, workflow file, ref,
|
||||
/// title. Widths are cosmetic alignment, not a fixed schema — a longer
|
||||
/// value just pushes the next column over rather than truncating.
|
||||
fn print_row(run: &ActionRun) {
|
||||
let number = run_number_of(run).map_or_else(|| "?".to_owned(), |n| format!("#{n}"));
|
||||
let status = run.status.as_deref().unwrap_or("unknown");
|
||||
let workflow = run.workflow_id.as_deref().unwrap_or("?");
|
||||
let run_ref = run.prettyref.as_deref().unwrap_or("?");
|
||||
let title = run.title.as_deref().unwrap_or("");
|
||||
println!("{number:<7} {status:<10} {workflow:<20} {run_ref:<28} {title}");
|
||||
}
|
||||
Loading…
Reference in a new issue