use serde::{Deserialize, Serialize};
use crate::api::model::{Capped, QueueState, RepoId};
use crate::api::{ApiError, GitHub};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct QueueEntry {
pub position: u64,
pub state: QueueState,
pub enqueued_at: String,
pub by: Option<String>,
pub eta: Option<u64>,
pub solo: bool,
pub jump: bool,
pub number: Option<u64>,
pub title: String,
pub author: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct MergeQueue {
pub exists: bool,
pub method: Option<String>,
pub entries: Capped<QueueEntry>,
}
impl GitHub {
pub async fn merge_queue(&self, repo: &RepoId, branch: &str) -> Result<MergeQueue, ApiError> {
let vars = crate::api::client::repo_vars!(repo, "branch": branch);
let what = format!("a merge queue for {repo}'s {branch}");
let repository: wire::Repository = self
.graphql_json(crate::api::raw::MERGE_QUEUE, vars, what, "/repository")
.await?;
let Some(q) = repository.merge_queue else {
return Ok(MergeQueue {
exists: false,
method: None,
entries: Capped::default(),
});
};
let entries = q.entries.into_capped(|e| {
let pr = e.pull_request;
Some(QueueEntry {
position: u64::try_from(e.position).unwrap_or(0),
state: e.state,
enqueued_at: e.enqueued_at,
by: e.enqueuer.map(|a| a.login),
eta: e
.estimated_time_to_merge
.and_then(|s| u64::try_from(s).ok()),
solo: e.solo,
jump: e.jump,
number: pr.as_ref().and_then(|p| u64::try_from(p.number).ok()),
title: pr.as_ref().map(|p| p.title.clone()).unwrap_or_default(),
author: pr.and_then(|p| p.author).map(|a| a.login),
})
});
Ok(MergeQueue {
exists: true,
method: q.configuration.and_then(|c| c.merge_method),
entries,
})
}
}
mod wire {
use serde::Deserialize;
use crate::api::browse::UserLogin as Login;
use crate::api::browse::wire::Counted;
use crate::api::model::QueueState;
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Repository {
pub merge_queue: Option<Queue>,
}
#[derive(Deserialize)]
pub struct Queue {
pub configuration: Option<Configuration>,
pub entries: Counted<Entry>,
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Configuration {
pub merge_method: Option<String>,
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Entry {
pub position: i64,
pub state: QueueState,
pub enqueued_at: String,
pub enqueuer: Option<Login>,
pub estimated_time_to_merge: Option<i64>,
pub solo: bool,
pub jump: bool,
pub pull_request: Option<Pr>,
}
#[derive(Deserialize)]
pub struct Pr {
pub number: i64,
pub title: String,
pub author: Option<Login>,
}
}