73 lines
2.6 KiB
Rust
73 lines
2.6 KiB
Rust
//! Shared helpers for the CI Actions run verbs (`ci-log`, `ci-rerun`,
|
|
//! `ci-runs`).
|
|
|
|
use anyhow::Result;
|
|
use forgejo_api::structs::{ActionRun, ListActionRunsQuery};
|
|
|
|
use crate::client::Client;
|
|
|
|
/// The per-repo run NUMBER from a run object's `html_url` (`…/runs/<n>`
|
|
/// tail) — the number the UI shows, `pr-status` surfaces, and every
|
|
/// `--run <n>` flag takes.
|
|
///
|
|
/// ⚠️ NOT [`ActionRun::id`]: Forgejo's `GET
|
|
/// /repos/{owner}/{repo}/actions/runs/{run_id}` endpoint takes that
|
|
/// internal, cross-repo id, not this number — confirmed empirically
|
|
/// (a run with `id: 3284` had display number `3092`). Don't be tempted to
|
|
/// pass a `--run` value there.
|
|
pub(crate) fn run_number_of(run: &ActionRun) -> Option<u64> {
|
|
run.html_url
|
|
.as_ref()
|
|
.and_then(|u| u.as_str().rsplit('/').next())
|
|
.and_then(|s| s.parse::<u64>().ok())
|
|
}
|
|
|
|
/// Look up a single run by its display number via `ListActionRunsQuery`'s
|
|
/// `run_number` filter — one request, not a page scan. Confirmed
|
|
/// empirically that the filter matches on the same number
|
|
/// [`run_number_of`] reads back out (both trace to `index_in_repo`
|
|
/// server-side).
|
|
///
|
|
/// `Ok(None)` means the number doesn't exist in `repo` (a fresh dispatch
|
|
/// still queued, a typo, or a purged/deleted run); `Err` is a genuine
|
|
/// transport failure.
|
|
pub(crate) fn find_run_by_number(client: &Client, run_number: u64) -> Result<Option<ActionRun>> {
|
|
let (owner, name) = client.owner_repo()?;
|
|
let body = client
|
|
.api()
|
|
.list_action_runs(
|
|
owner,
|
|
name,
|
|
ListActionRunsQuery {
|
|
run_number: Some(i64::try_from(run_number).unwrap_or(i64::MAX)),
|
|
..Default::default()
|
|
},
|
|
)
|
|
.send()?;
|
|
Ok(body.workflow_runs.unwrap_or_default().into_iter().next())
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::run_number_of;
|
|
use serde_json::json;
|
|
|
|
fn run_from(mut v: serde_json::Value) -> forgejo_api::structs::ActionRun {
|
|
let obj = v.as_object_mut().unwrap();
|
|
for key in ["created", "started", "stopped", "updated", "html_url"] {
|
|
obj.entry(key).or_insert(serde_json::Value::Null);
|
|
}
|
|
serde_json::from_value(v).unwrap()
|
|
}
|
|
|
|
#[test]
|
|
fn parses_run_number_from_html_url() {
|
|
let run = run_from(json!({ "html_url": "http://forge/h/h/actions/runs/750" }));
|
|
assert_eq!(run_number_of(&run), Some(750));
|
|
assert_eq!(
|
|
run_number_of(&run_from(json!({ "html_url": "http://forge/o/r/x" }))),
|
|
None
|
|
);
|
|
assert_eq!(run_number_of(&run_from(json!({}))), None);
|
|
}
|
|
}
|