From c6d10d40f5aadaa1898f65b8d77ca524336cb1f9 Mon Sep 17 00:00:00 2001 From: Daniel Norman Date: Tue, 2 Jun 2026 10:38:34 +0200 Subject: [PATCH] feat: add --latest flag to get the latest job run --- src/bin/rad-job.rs | 47 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/src/bin/rad-job.rs b/src/bin/rad-job.rs index 542c827..bbe44c2 100644 --- a/src/bin/rad-job.rs +++ b/src/bin/rad-job.rs @@ -273,15 +273,23 @@ where } fn show_job( - command::Show { pretty, rev }: command::Show, + command::Show { + pretty, + latest, + rev, + }: command::Show, jobs: &Jobs, ) -> Result<(), error::Show> where A: Access, { - // Resolve shorthand revisions (e.g. `bf23a86`) to a full commit OID. - let oid = revparse(jobs.as_ref(), &rev)?; - let (id, job) = find_by_commit(oid, jobs)?; + let (id, job) = if latest { + latest_job(jobs)? + } else { + let rev = rev.expect("rev is required unless --latest"); + let oid = revparse(jobs.as_ref(), &rev)?; + find_by_commit(oid, jobs)? + }; let show = radicle_job::display::Job::new(id, &job); if pretty { println!("{}", show.pretty()); @@ -305,6 +313,21 @@ where .map_err(|err| error::Find::FindCommit { oid, err }) } +/// Find the job with the most recent run activity, across all nodes. +fn latest_job(jobs: &Jobs) -> Result<(JobId, Job), error::Latest> +where + A: Access, +{ + jobs.all() + .map_err(error::Latest::All)? + .filter_map(Result::ok) + .map(|(id, job)| (JobId::from(id), job)) + // Jobs with no runs have no timestamp (`None`), so any job with run + // activity sorts ahead of them. + .max_by_key(|(_, job)| job.latest().map(|(_, _, run)| *run.timestamp()).max()) + .ok_or(error::Latest::NoJobs) +} + /// Resolve a Git revision, such as a shorthand OID, to a full commit OID. fn revparse(repo: &Repository, rev: &str) -> Result { repo.backend @@ -385,8 +408,12 @@ mod command { /// Format output in a more human oriented way than JSON. #[clap(long)] pub pretty: bool, + /// Show the most recently active job instead of one for a revision. + #[clap(long, conflicts_with = "rev")] + pub latest: bool, /// Git revision for the commit, such as a full or shorthand OID. - pub rev: String, + #[clap(required_unless_present = "latest")] + pub rev: Option, } /// Record a new run for an existing job COB. @@ -439,10 +466,20 @@ mod error { Revparse(#[from] Revparse), #[error(transparent)] Find(#[from] Find), + #[error(transparent)] + Latest(#[from] Latest), #[error("failed to show job, could not serialize to JSON")] Json(#[source] serde_json::Error), } + #[derive(Debug, Error)] + pub enum Latest { + #[error("failed to list jobs")] + All(#[source] cob::store::Error), + #[error("no jobs found in this repository")] + NoJobs, + } + #[derive(Debug, Error)] #[error("failed to resolve Git revision {rev}")] pub struct Revparse {