use std::fmt::{Display, Formatter};
use chrono::{DateTime, Utc};
use serde::{Deserialize, Deserializer, Serialize};
use url::Url;
use crate::resource::{App, CheckSuite, Field, GitSha, MinimalCheckSuite, NodeId, PullRequest};
use crate::{id, name};
pub use self::conclusion::CheckRunConclusion;
pub use self::output::{CheckRunOutput, CheckRunOutputSummary, CheckRunOutputTitle};
pub use self::status::CheckRunStatus;
mod conclusion;
mod output;
mod status;
id!(
CheckRunId
);
name!(
CheckRunName
);
#[derive(Clone, Eq, PartialEq, Debug, Deserialize, Serialize)]
pub struct CheckRun {
id: CheckRunId,
node_id: NodeId,
name: CheckRunName,
head_sha: GitSha,
external_id: String,
url: Url,
html_url: Url,
details_url: Url,
status: CheckRunStatus,
conclusion: Option<CheckRunConclusion>,
started_at: DateTime<Utc>,
completed_at: Option<DateTime<Utc>>,
check_suite: Field<MinimalCheckSuite, CheckSuite>,
app: App,
pull_requests: Vec<PullRequest>,
#[serde(deserialize_with = "deserialize_output")]
output: Option<CheckRunOutput>,
}
impl CheckRun {
#[cfg_attr(feature = "tracing", tracing::instrument)]
pub fn id(&self) -> CheckRunId {
self.id
}
#[cfg_attr(feature = "tracing", tracing::instrument)]
pub fn node_id(&self) -> &NodeId {
&self.node_id
}
#[cfg_attr(feature = "tracing", tracing::instrument)]
pub fn name(&self) -> &CheckRunName {
&self.name
}
#[cfg_attr(feature = "tracing", tracing::instrument)]
pub fn head_sha(&self) -> &GitSha {
&self.head_sha
}
#[cfg_attr(feature = "tracing", tracing::instrument)]
pub fn external_id(&self) -> &str {
&self.external_id
}
#[cfg_attr(feature = "tracing", tracing::instrument)]
pub fn url(&self) -> &Url {
&self.url
}
#[cfg_attr(feature = "tracing", tracing::instrument)]
pub fn html_url(&self) -> &Url {
&self.html_url
}
#[cfg_attr(feature = "tracing", tracing::instrument)]
pub fn details_url(&self) -> &Url {
&self.details_url
}
#[cfg_attr(feature = "tracing", tracing::instrument)]
pub fn status(&self) -> CheckRunStatus {
self.status
}
#[cfg_attr(feature = "tracing", tracing::instrument)]
pub fn conclusion(&self) -> Option<CheckRunConclusion> {
self.conclusion
}
#[cfg_attr(feature = "tracing", tracing::instrument)]
pub fn started_at(&self) -> &DateTime<Utc> {
&self.started_at
}
#[cfg_attr(feature = "tracing", tracing::instrument)]
pub fn completed_at(&self) -> &Option<DateTime<Utc>> {
&self.completed_at
}
#[cfg_attr(feature = "tracing", tracing::instrument)]
pub fn output(&self) -> &Option<CheckRunOutput> {
&self.output
}
#[cfg_attr(feature = "tracing", tracing::instrument)]
pub fn check_suite(&self) -> &Field<MinimalCheckSuite, CheckSuite> {
&self.check_suite
}
#[cfg_attr(feature = "tracing", tracing::instrument)]
pub fn app(&self) -> &App {
&self.app
}
#[cfg_attr(feature = "tracing", tracing::instrument)]
pub fn pull_requests(&self) -> &Vec<PullRequest> {
&self.pull_requests
}
}
impl Display for CheckRun {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.name)
}
}
fn deserialize_output<'de, D>(deserializer: D) -> Result<Option<CheckRunOutput>, D::Error>
where
D: Deserializer<'de>,
{
let json = serde_json::Value::deserialize(deserializer)?;
let title_field = match json.get("title") {
Some(title) => title,
None => return Ok(None),
};
if title_field.is_null() {
return Ok(None);
}
let output = serde_json::from_value(json).expect("failed to deserialize check run output");
Ok(Some(output))
}
#[cfg(test)]
mod tests {
use super::CheckRun;
#[test]
fn trait_deserialize() {
let check_run: CheckRun = serde_json::from_str(include_str!(
"../../../tests/fixtures/resource/check_run.json"
))
.unwrap();
assert_eq!(&None, check_run.output());
}
#[test]
fn trait_send() {
fn assert_send<T: Send>() {}
assert_send::<CheckRun>();
}
#[test]
fn trait_sync() {
fn assert_sync<T: Sync>() {}
assert_sync::<CheckRun>();
}
}