wip: pull request view & md rendering
This commit is contained in:
@@ -1,17 +1,22 @@
|
||||
use std::ops::Deref;
|
||||
|
||||
use graphql_client::{GraphQLQuery, Response};
|
||||
use reqwest::Method;
|
||||
use graphql_client::GraphQLQuery;
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::{
|
||||
api::{
|
||||
self,
|
||||
issues::pull_request_query::{PullRequestQuerySearchEdgesNode, PullRequestState},
|
||||
issues::{
|
||||
pull_request_pagination_query::PullRequestPaginationQuerySearchEdgesNode,
|
||||
pull_request_query::PullRequestQueryNode,
|
||||
},
|
||||
},
|
||||
query,
|
||||
};
|
||||
|
||||
type DateTime = String;
|
||||
type URI = String;
|
||||
|
||||
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, Deserialize)]
|
||||
#[serde(transparent)]
|
||||
#[repr(transparent)]
|
||||
@@ -25,6 +30,24 @@ impl Deref for Id {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for Id {
|
||||
fn from(value: &str) -> Self {
|
||||
Self(value.to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for Id {
|
||||
fn from(value: String) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Id> for String {
|
||||
fn from(value: Id) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub(crate) struct PullRequestPaginatedResponse {
|
||||
pub(crate) items: Vec<PullRequest>,
|
||||
@@ -34,18 +57,155 @@ pub(crate) struct PullRequestPaginatedResponse {
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub(crate) struct PullRequest {
|
||||
pub(crate) id: Id,
|
||||
pub(crate) title: String,
|
||||
pub(crate) state: IssueState,
|
||||
pub(crate) state: PullRequestState,
|
||||
pub(crate) is_draft: bool,
|
||||
pub(crate) repo_slug: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize)]
|
||||
pub(crate) enum IssueState {
|
||||
Open,
|
||||
Closed,
|
||||
Merged,
|
||||
Unknown,
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub(crate) struct DetailedPullRequest {
|
||||
pub(crate) title: String,
|
||||
pub(crate) state: PullRequestState,
|
||||
pub(crate) is_draft: bool,
|
||||
pub(crate) body: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub(crate) struct PullRequestTimeline {
|
||||
pub(crate) items: Vec<PullRequestTimelineItem>,
|
||||
pub(crate) end_cursor: Option<String>,
|
||||
pub(crate) has_next_page: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub(crate) enum PullRequestTimelineItem {
|
||||
Assigned {
|
||||
created_at: String,
|
||||
actor: Option<TimelineActor>,
|
||||
assignee: Option<TimelineActor>,
|
||||
},
|
||||
Unassigned {
|
||||
created_at: String,
|
||||
actor: Option<TimelineActor>,
|
||||
assignee: Option<TimelineActor>,
|
||||
},
|
||||
Comment {
|
||||
created_at: String,
|
||||
author: Option<TimelineActor>,
|
||||
body: String,
|
||||
},
|
||||
Commit {
|
||||
committed_at: String,
|
||||
abbreviated_oid: String,
|
||||
message_headline: String,
|
||||
},
|
||||
Review {
|
||||
created_at: String,
|
||||
author: Option<TimelineActor>,
|
||||
state: String,
|
||||
body: String,
|
||||
},
|
||||
ReviewRequested {
|
||||
created_at: String,
|
||||
actor: Option<TimelineActor>,
|
||||
reviewer: Option<TimelineActor>,
|
||||
},
|
||||
ReviewRequestRemoved {
|
||||
created_at: String,
|
||||
actor: Option<TimelineActor>,
|
||||
reviewer: Option<TimelineActor>,
|
||||
},
|
||||
ReviewDismissed {
|
||||
created_at: String,
|
||||
actor: Option<TimelineActor>,
|
||||
},
|
||||
Merged {
|
||||
created_at: String,
|
||||
actor: Option<TimelineActor>,
|
||||
},
|
||||
Closed {
|
||||
created_at: String,
|
||||
actor: Option<TimelineActor>,
|
||||
},
|
||||
Reopened {
|
||||
created_at: String,
|
||||
actor: Option<TimelineActor>,
|
||||
},
|
||||
ConvertToDraft {
|
||||
created_at: String,
|
||||
actor: Option<TimelineActor>,
|
||||
},
|
||||
ReadyForReview {
|
||||
created_at: String,
|
||||
actor: Option<TimelineActor>,
|
||||
},
|
||||
HeadRefForcePushed {
|
||||
created_at: String,
|
||||
actor: Option<TimelineActor>,
|
||||
before_commit_oid: Option<String>,
|
||||
after_commit_oid: Option<String>,
|
||||
},
|
||||
BaseRefChanged {
|
||||
created_at: String,
|
||||
actor: Option<TimelineActor>,
|
||||
},
|
||||
Labeled {
|
||||
created_at: String,
|
||||
actor: Option<TimelineActor>,
|
||||
label: String,
|
||||
},
|
||||
Unlabeled {
|
||||
created_at: String,
|
||||
actor: Option<TimelineActor>,
|
||||
label: String,
|
||||
},
|
||||
Milestoned {
|
||||
created_at: String,
|
||||
actor: Option<TimelineActor>,
|
||||
milestone_title: String,
|
||||
},
|
||||
Demilestoned {
|
||||
created_at: String,
|
||||
actor: Option<TimelineActor>,
|
||||
milestone_title: String,
|
||||
},
|
||||
Referenced {
|
||||
created_at: String,
|
||||
actor: Option<TimelineActor>,
|
||||
},
|
||||
CrossReferenced {
|
||||
created_at: String,
|
||||
actor: Option<TimelineActor>,
|
||||
},
|
||||
AutoMergeEnabled {
|
||||
created_at: String,
|
||||
actor: Option<TimelineActor>,
|
||||
},
|
||||
AutoMergeDisabled {
|
||||
created_at: String,
|
||||
actor: Option<TimelineActor>,
|
||||
reason: String,
|
||||
},
|
||||
AddedToMergeQueue {
|
||||
created_at: String,
|
||||
actor: Option<TimelineActor>,
|
||||
},
|
||||
RemovedFromMergeQueue {
|
||||
created_at: String,
|
||||
actor: Option<TimelineActor>,
|
||||
},
|
||||
Other {
|
||||
typename: String,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub(crate) struct TimelineActor {
|
||||
pub(crate) kind: String,
|
||||
pub(crate) name: String,
|
||||
pub(crate) avatar_url: Option<String>,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Id {
|
||||
@@ -54,24 +214,50 @@ impl std::fmt::Display for Id {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PullRequestState> for IssueState {
|
||||
fn from(state: PullRequestState) -> Self {
|
||||
match state {
|
||||
PullRequestState::OPEN => Self::Open,
|
||||
PullRequestState::CLOSED => Self::Closed,
|
||||
PullRequestState::MERGED => Self::Merged,
|
||||
_ => Self::Unknown,
|
||||
}
|
||||
}
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Deserialize)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
pub(crate) enum PullRequestState {
|
||||
Open,
|
||||
Closed,
|
||||
Merged,
|
||||
}
|
||||
|
||||
#[derive(graphql_client::GraphQLQuery)]
|
||||
#[graphql(
|
||||
schema_path = "src/api/graphql/schema.json",
|
||||
query_path = "src/api/graphql/list_pull_requests.graphql"
|
||||
extern_enums("PullRequestState")
|
||||
)]
|
||||
struct PullRequestPaginationQuery;
|
||||
|
||||
#[derive(graphql_client::GraphQLQuery)]
|
||||
#[graphql(
|
||||
schema_path = "src/api/graphql/schema.json",
|
||||
query_path = "src/api/graphql/fetch_pull_request.graphql"
|
||||
extern_enums("PullRequestState")
|
||||
)]
|
||||
struct PullRequestQuery;
|
||||
|
||||
#[derive(graphql_client::GraphQLQuery)]
|
||||
#[graphql(
|
||||
schema_path = "src/api/graphql/schema.json",
|
||||
query_path = "src/api/graphql/fetch_pull_request_timeline.graphql"
|
||||
)]
|
||||
struct PullRequestTimelineQuery;
|
||||
|
||||
pub(super) type PullRequestTimelineResponse = pull_request_timeline_query::ResponseData;
|
||||
#[cfg(test)]
|
||||
pub(super) type PullRequestTimelineResponseNode = PullRequestTimelineQueryNode;
|
||||
#[cfg(test)]
|
||||
pub(super) type PullRequestTimelineNode =
|
||||
pull_request_timeline_query::PullRequestTimelineQueryNodeOnPullRequestTimelineItemsNodes;
|
||||
|
||||
use self::pull_request_timeline_query::{
|
||||
PullRequestReviewState, PullRequestTimelineQueryNode,
|
||||
PullRequestTimelineQueryNodeOnPullRequestTimelineItemsNodes, actorFields, actorFieldsOn,
|
||||
assigneeFields, requestedReviewerFields,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct ListPullRequests {
|
||||
pub filter: Option<&'static str>,
|
||||
@@ -103,20 +289,15 @@ impl query::QueryFn for ListPullRequests {
|
||||
None => "is:pr archived:false sort:updated-desc".into(),
|
||||
};
|
||||
|
||||
let gql = PullRequestQuery::build_query(pull_request_query::Variables {
|
||||
query: query_string,
|
||||
});
|
||||
let gql =
|
||||
PullRequestPaginationQuery::build_query(pull_request_pagination_query::Variables {
|
||||
query: query_string,
|
||||
});
|
||||
|
||||
let res = c
|
||||
.github_request(Method::POST, "/graphql")?
|
||||
.json(&gql)
|
||||
.send()
|
||||
.await?;
|
||||
let res = c.github_graphql_request(&gql)?.send().await?;
|
||||
|
||||
let data = api::parse_graphql_response::<pull_request_query::ResponseData>(res)
|
||||
.await?
|
||||
.data
|
||||
.unwrap();
|
||||
let (_, data) =
|
||||
api::parse_graphql_response::<pull_request_pagination_query::ResponseData>(res).await?;
|
||||
|
||||
Ok(PullRequestPaginatedResponse {
|
||||
items: data
|
||||
@@ -127,10 +308,11 @@ impl query::QueryFn for ListPullRequests {
|
||||
.flatten()
|
||||
.filter_map(|edge| {
|
||||
edge.node.and_then(|n| match n {
|
||||
PullRequestQuerySearchEdgesNode::PullRequest(p) => {
|
||||
PullRequestPaginationQuerySearchEdgesNode::PullRequest(p) => {
|
||||
Some(PullRequest {
|
||||
id: p.id.into(),
|
||||
title: p.title,
|
||||
state: p.state.into(),
|
||||
state: p.state,
|
||||
is_draft: p.is_draft,
|
||||
repo_slug: format!(
|
||||
"{}/{}",
|
||||
@@ -149,3 +331,399 @@ impl query::QueryFn for ListPullRequests {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct FetchPullRequest {
|
||||
pub(crate) id: Id,
|
||||
}
|
||||
|
||||
impl query::QueryFn for FetchPullRequest {
|
||||
type Data = DetailedPullRequest;
|
||||
type Error = api::Error;
|
||||
type Context = api::QueryContext;
|
||||
|
||||
fn key(&self) -> query::Key {
|
||||
format!("issues/{}", self.id).into()
|
||||
}
|
||||
|
||||
async fn run(&self, c: &Self::Context) -> Result<Self::Data, Self::Error> {
|
||||
#[cfg(debug_assertions)]
|
||||
if c.should_use_fixtures {
|
||||
return super::mock::fetch_pull_request(&self.id);
|
||||
}
|
||||
|
||||
let gql = PullRequestQuery::build_query(pull_request_query::Variables {
|
||||
id: self.id.clone().into(),
|
||||
});
|
||||
|
||||
let res = c.github_graphql_request(&gql)?.send().await?;
|
||||
let (_, data) =
|
||||
api::parse_graphql_response::<pull_request_query::ResponseData>(res).await?;
|
||||
|
||||
data.node
|
||||
.ok_or(api::Error::MalformedResponse(
|
||||
"missing 'node' field on PullRequestQuery response".into(),
|
||||
))
|
||||
.and_then(|n| match n {
|
||||
PullRequestQueryNode::PullRequest(p) => Ok(DetailedPullRequest {
|
||||
title: p.title,
|
||||
state: p.state,
|
||||
is_draft: p.is_draft,
|
||||
body: p.body,
|
||||
}),
|
||||
_ => Err(api::Error::MalformedResponse(
|
||||
"unexpected node type on PullRequestQuery".into(),
|
||||
)),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct FetchPullRequestTimeline {
|
||||
pub(crate) id: Id,
|
||||
pub(crate) first: i64,
|
||||
pub(crate) after: Option<String>,
|
||||
}
|
||||
|
||||
impl FetchPullRequestTimeline {
|
||||
pub(crate) fn new(id: Id, first: i64, after: Option<String>) -> Self {
|
||||
Self { id, first, after }
|
||||
}
|
||||
}
|
||||
|
||||
impl query::QueryFn for FetchPullRequestTimeline {
|
||||
type Data = PullRequestTimeline;
|
||||
type Error = api::Error;
|
||||
type Context = api::QueryContext;
|
||||
|
||||
fn key(&self) -> query::Key {
|
||||
format!(
|
||||
"issues/{}/timeline?first={}&after={}",
|
||||
self.id,
|
||||
self.first,
|
||||
self.after.as_deref().unwrap_or_default()
|
||||
)
|
||||
.into()
|
||||
}
|
||||
|
||||
async fn run(&self, c: &Self::Context) -> Result<Self::Data, Self::Error> {
|
||||
fn normalize_actor(actor: actorFields) -> TimelineActor {
|
||||
let actorFields {
|
||||
login,
|
||||
avatar_url,
|
||||
on,
|
||||
} = actor;
|
||||
|
||||
TimelineActor {
|
||||
kind: match on {
|
||||
actorFieldsOn::Bot => "Bot",
|
||||
actorFieldsOn::EnterpriseUserAccount => "EnterpriseUserAccount",
|
||||
actorFieldsOn::Mannequin => "Mannequin",
|
||||
actorFieldsOn::Organization => "Organization",
|
||||
actorFieldsOn::User => "User",
|
||||
}
|
||||
.into(),
|
||||
name: login,
|
||||
avatar_url: Some(avatar_url),
|
||||
}
|
||||
}
|
||||
|
||||
fn normalize_assignee(actor: assigneeFields) -> TimelineActor {
|
||||
match actor {
|
||||
assigneeFields::Bot(actor) => TimelineActor {
|
||||
kind: "Bot".into(),
|
||||
name: actor.login,
|
||||
avatar_url: Some(actor.avatar_url),
|
||||
},
|
||||
assigneeFields::Mannequin(actor) => TimelineActor {
|
||||
kind: "Mannequin".into(),
|
||||
name: actor.login,
|
||||
avatar_url: Some(actor.avatar_url),
|
||||
},
|
||||
assigneeFields::Organization(actor) => TimelineActor {
|
||||
kind: "Organization".into(),
|
||||
name: actor.login,
|
||||
avatar_url: Some(actor.avatar_url),
|
||||
},
|
||||
assigneeFields::User(actor) => TimelineActor {
|
||||
kind: "User".into(),
|
||||
name: actor.login,
|
||||
avatar_url: Some(actor.avatar_url),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn normalize_requested_reviewer(actor: requestedReviewerFields) -> TimelineActor {
|
||||
match actor {
|
||||
requestedReviewerFields::Bot(actor) => TimelineActor {
|
||||
kind: "Bot".into(),
|
||||
name: actor.login,
|
||||
avatar_url: Some(actor.avatar_url),
|
||||
},
|
||||
requestedReviewerFields::Mannequin(actor) => TimelineActor {
|
||||
kind: "Mannequin".into(),
|
||||
name: actor.login,
|
||||
avatar_url: Some(actor.avatar_url),
|
||||
},
|
||||
requestedReviewerFields::Team(actor) => TimelineActor {
|
||||
kind: "Team".into(),
|
||||
name: actor.name,
|
||||
avatar_url: None,
|
||||
},
|
||||
requestedReviewerFields::User(actor) => TimelineActor {
|
||||
kind: "User".into(),
|
||||
name: actor.login,
|
||||
avatar_url: Some(actor.avatar_url),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn normalize_review_state(state: PullRequestReviewState) -> String {
|
||||
match state {
|
||||
PullRequestReviewState::PENDING => "PENDING",
|
||||
PullRequestReviewState::COMMENTED => "COMMENTED",
|
||||
PullRequestReviewState::APPROVED => "APPROVED",
|
||||
PullRequestReviewState::CHANGES_REQUESTED => "CHANGES_REQUESTED",
|
||||
PullRequestReviewState::DISMISSED => "DISMISSED",
|
||||
_ => "OTHER",
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
||||
fn normalize_item(
|
||||
value: PullRequestTimelineQueryNodeOnPullRequestTimelineItemsNodes,
|
||||
) -> PullRequestTimelineItem {
|
||||
match value {
|
||||
PullRequestTimelineQueryNodeOnPullRequestTimelineItemsNodes::AssignedEvent(
|
||||
event,
|
||||
) => PullRequestTimelineItem::Assigned {
|
||||
created_at: event.created_at,
|
||||
actor: event.actor.map(normalize_actor),
|
||||
assignee: event.assignee.map(normalize_assignee),
|
||||
},
|
||||
PullRequestTimelineQueryNodeOnPullRequestTimelineItemsNodes::UnassignedEvent(
|
||||
event,
|
||||
) => PullRequestTimelineItem::Unassigned {
|
||||
created_at: event.created_at,
|
||||
actor: event.actor.map(normalize_actor),
|
||||
assignee: event.assignee.map(normalize_assignee),
|
||||
},
|
||||
PullRequestTimelineQueryNodeOnPullRequestTimelineItemsNodes::IssueComment(
|
||||
event,
|
||||
) => PullRequestTimelineItem::Comment {
|
||||
created_at: event.created_at,
|
||||
author: event.author.map(normalize_actor),
|
||||
body: event.body,
|
||||
},
|
||||
PullRequestTimelineQueryNodeOnPullRequestTimelineItemsNodes::PullRequestCommit(
|
||||
event,
|
||||
) => PullRequestTimelineItem::Commit {
|
||||
committed_at: event.commit.committed_date,
|
||||
abbreviated_oid: event.commit.abbreviated_oid,
|
||||
message_headline: event.commit.message_headline,
|
||||
},
|
||||
PullRequestTimelineQueryNodeOnPullRequestTimelineItemsNodes::PullRequestReview(
|
||||
event,
|
||||
) => PullRequestTimelineItem::Review {
|
||||
created_at: event.created_at,
|
||||
author: event.author.map(normalize_actor),
|
||||
state: normalize_review_state(event.state),
|
||||
body: event.body,
|
||||
},
|
||||
PullRequestTimelineQueryNodeOnPullRequestTimelineItemsNodes::ReviewRequestedEvent(
|
||||
event,
|
||||
) => PullRequestTimelineItem::ReviewRequested {
|
||||
created_at: event.created_at,
|
||||
actor: event.actor.map(normalize_actor),
|
||||
reviewer: event.requested_reviewer.map(normalize_requested_reviewer),
|
||||
},
|
||||
PullRequestTimelineQueryNodeOnPullRequestTimelineItemsNodes::ReviewRequestRemovedEvent(
|
||||
event,
|
||||
) => PullRequestTimelineItem::ReviewRequestRemoved {
|
||||
created_at: event.created_at,
|
||||
actor: event.actor.map(normalize_actor),
|
||||
reviewer: event.requested_reviewer.map(normalize_requested_reviewer),
|
||||
},
|
||||
PullRequestTimelineQueryNodeOnPullRequestTimelineItemsNodes::ReviewDismissedEvent(
|
||||
event,
|
||||
) => PullRequestTimelineItem::ReviewDismissed {
|
||||
created_at: event.created_at,
|
||||
actor: event.actor.map(normalize_actor),
|
||||
},
|
||||
PullRequestTimelineQueryNodeOnPullRequestTimelineItemsNodes::MergedEvent(
|
||||
event,
|
||||
) => PullRequestTimelineItem::Merged {
|
||||
created_at: event.created_at,
|
||||
actor: event.actor.map(normalize_actor),
|
||||
},
|
||||
PullRequestTimelineQueryNodeOnPullRequestTimelineItemsNodes::ClosedEvent(
|
||||
event,
|
||||
) => PullRequestTimelineItem::Closed {
|
||||
created_at: event.created_at,
|
||||
actor: event.actor.map(normalize_actor),
|
||||
},
|
||||
PullRequestTimelineQueryNodeOnPullRequestTimelineItemsNodes::ReopenedEvent(
|
||||
event,
|
||||
) => PullRequestTimelineItem::Reopened {
|
||||
created_at: event.created_at,
|
||||
actor: event.actor.map(normalize_actor),
|
||||
},
|
||||
PullRequestTimelineQueryNodeOnPullRequestTimelineItemsNodes::ConvertToDraftEvent(
|
||||
event,
|
||||
) => PullRequestTimelineItem::ConvertToDraft {
|
||||
created_at: event.created_at,
|
||||
actor: event.actor.map(normalize_actor),
|
||||
},
|
||||
PullRequestTimelineQueryNodeOnPullRequestTimelineItemsNodes::ReadyForReviewEvent(
|
||||
event,
|
||||
) => PullRequestTimelineItem::ReadyForReview {
|
||||
created_at: event.created_at,
|
||||
actor: event.actor.map(normalize_actor),
|
||||
},
|
||||
PullRequestTimelineQueryNodeOnPullRequestTimelineItemsNodes::HeadRefForcePushedEvent(
|
||||
event,
|
||||
) => PullRequestTimelineItem::HeadRefForcePushed {
|
||||
created_at: event.created_at,
|
||||
actor: event.actor.map(normalize_actor),
|
||||
before_commit_oid: event.before_commit.map(|commit| commit.abbreviated_oid),
|
||||
after_commit_oid: event.after_commit.map(|commit| commit.abbreviated_oid),
|
||||
},
|
||||
PullRequestTimelineQueryNodeOnPullRequestTimelineItemsNodes::BaseRefChangedEvent(
|
||||
event,
|
||||
) => PullRequestTimelineItem::BaseRefChanged {
|
||||
created_at: event.created_at,
|
||||
actor: event.actor.map(normalize_actor),
|
||||
},
|
||||
PullRequestTimelineQueryNodeOnPullRequestTimelineItemsNodes::LabeledEvent(
|
||||
event,
|
||||
) => PullRequestTimelineItem::Labeled {
|
||||
created_at: event.created_at,
|
||||
actor: event.actor.map(normalize_actor),
|
||||
label: event.label.name,
|
||||
},
|
||||
PullRequestTimelineQueryNodeOnPullRequestTimelineItemsNodes::UnlabeledEvent(
|
||||
event,
|
||||
) => PullRequestTimelineItem::Unlabeled {
|
||||
created_at: event.created_at,
|
||||
actor: event.actor.map(normalize_actor),
|
||||
label: event.label.name,
|
||||
},
|
||||
PullRequestTimelineQueryNodeOnPullRequestTimelineItemsNodes::MilestonedEvent(
|
||||
event,
|
||||
) => PullRequestTimelineItem::Milestoned {
|
||||
created_at: event.created_at,
|
||||
actor: event.actor.map(normalize_actor),
|
||||
milestone_title: event.milestone_title,
|
||||
},
|
||||
PullRequestTimelineQueryNodeOnPullRequestTimelineItemsNodes::DemilestonedEvent(
|
||||
event,
|
||||
) => PullRequestTimelineItem::Demilestoned {
|
||||
created_at: event.created_at,
|
||||
actor: event.actor.map(normalize_actor),
|
||||
milestone_title: event.milestone_title,
|
||||
},
|
||||
PullRequestTimelineQueryNodeOnPullRequestTimelineItemsNodes::ReferencedEvent(
|
||||
event,
|
||||
) => PullRequestTimelineItem::Referenced {
|
||||
created_at: event.created_at,
|
||||
actor: event.actor.map(normalize_actor),
|
||||
},
|
||||
PullRequestTimelineQueryNodeOnPullRequestTimelineItemsNodes::CrossReferencedEvent(
|
||||
event,
|
||||
) => PullRequestTimelineItem::CrossReferenced {
|
||||
created_at: event.created_at,
|
||||
actor: event.actor.map(normalize_actor),
|
||||
},
|
||||
PullRequestTimelineQueryNodeOnPullRequestTimelineItemsNodes::AutoMergeEnabledEvent(
|
||||
event,
|
||||
) => PullRequestTimelineItem::AutoMergeEnabled {
|
||||
created_at: event.created_at,
|
||||
actor: event.actor.map(normalize_actor),
|
||||
},
|
||||
PullRequestTimelineQueryNodeOnPullRequestTimelineItemsNodes::AutoMergeDisabledEvent(
|
||||
event,
|
||||
) => PullRequestTimelineItem::AutoMergeDisabled {
|
||||
created_at: event.created_at,
|
||||
actor: event.actor.map(normalize_actor),
|
||||
reason: event.reason.unwrap_or_default(),
|
||||
},
|
||||
PullRequestTimelineQueryNodeOnPullRequestTimelineItemsNodes::AddedToMergeQueueEvent(
|
||||
event,
|
||||
) => PullRequestTimelineItem::AddedToMergeQueue {
|
||||
created_at: event.created_at,
|
||||
actor: event.actor.map(normalize_actor),
|
||||
},
|
||||
PullRequestTimelineQueryNodeOnPullRequestTimelineItemsNodes::RemovedFromMergeQueueEvent(
|
||||
event,
|
||||
) => PullRequestTimelineItem::RemovedFromMergeQueue {
|
||||
created_at: event.created_at,
|
||||
actor: event.actor.map(normalize_actor),
|
||||
},
|
||||
_ => PullRequestTimelineItem::Other {
|
||||
typename: "Other".into(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
let data = if c.should_use_fixtures {
|
||||
super::mock::fetch_pull_request_timeline(&self.id, self.after.as_deref())?
|
||||
} else {
|
||||
let gql =
|
||||
PullRequestTimelineQuery::build_query(pull_request_timeline_query::Variables {
|
||||
id: self.id.clone().into(),
|
||||
first: self.first,
|
||||
after: self.after.clone(),
|
||||
});
|
||||
|
||||
let res = c.github_graphql_request(&gql)?.send().await?;
|
||||
|
||||
api::parse_graphql_response::<PullRequestTimelineResponse>(res)
|
||||
.await?
|
||||
.1
|
||||
};
|
||||
|
||||
#[cfg(not(debug_assertions))]
|
||||
let data = {
|
||||
let gql =
|
||||
PullRequestTimelineQuery::build_query(pull_request_timeline_query::Variables {
|
||||
id: self.id.clone().into(),
|
||||
first: self.first,
|
||||
after: self.after.clone(),
|
||||
});
|
||||
|
||||
let res = c.github_graphql_request(&gql)?.send().await?;
|
||||
|
||||
api::parse_graphql_response::<PullRequestTimelineResponse>(res)
|
||||
.await?
|
||||
.1
|
||||
};
|
||||
|
||||
let pull_request = data
|
||||
.node
|
||||
.ok_or(api::Error::MalformedResponse(
|
||||
"missing 'node' field on PullRequestTimelineQuery response".into(),
|
||||
))
|
||||
.and_then(|node| match node {
|
||||
PullRequestTimelineQueryNode::PullRequest(pull_request) => Ok(pull_request),
|
||||
_ => Err(api::Error::MalformedResponse(
|
||||
"unexpected node type on PullRequestTimelineQuery".into(),
|
||||
)),
|
||||
})?;
|
||||
|
||||
let timeline = pull_request.timeline_items;
|
||||
let items = timeline
|
||||
.nodes
|
||||
.unwrap_or_default()
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.map(normalize_item)
|
||||
.collect();
|
||||
|
||||
Ok(PullRequestTimeline {
|
||||
items,
|
||||
end_cursor: timeline.page_info.end_cursor,
|
||||
has_next_page: timeline.page_info.has_next_page,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user