fix: enforce ServerApi as the wire authority
This commit is contained in:
@@ -19,10 +19,10 @@ use crate::records::{
|
||||
ObjectiveQueryItem, ObjectiveQueryRequest, ObjectiveQueryResponse, ObjectiveResourceSummary,
|
||||
ObjectiveShowRequest, ObjectiveSummary, ProjectRecordList, QueryPage, TicketActionEligibility,
|
||||
TicketAssignmentPrincipalSummary, TicketAssignmentSummary, TicketDetail, TicketEventDetail,
|
||||
TicketEvidenceEvent, TicketEvidenceSummary, TicketListPageRequest, TicketMergeRequestSummary,
|
||||
TicketQueryItem, TicketQueryRequest, TicketQueryResponse, TicketRelationView,
|
||||
TicketEvidenceEvent, TicketEvidenceSummary, TicketListProjectionRequest,
|
||||
TicketMergeRequestSummary, TicketQueryItem, TicketQueryRequest, TicketQueryResponse,
|
||||
TicketRoleAssignmentSummary, TicketShowRequest, TicketSummary, TicketSummaryPage,
|
||||
summarize_body, truncate_body,
|
||||
summarize_body, ticket_relation_view_from_domain, truncate_body,
|
||||
};
|
||||
use crate::store::{
|
||||
ControlPlaneStore, MemoryDocumentRecord, MemoryStagingRecord, MemoryStagingResolutionRecord,
|
||||
@@ -48,7 +48,7 @@ impl<T> WorkspaceAuthority for T where T: ObjectiveAuthority + TicketAuthority +
|
||||
|
||||
pub trait TicketAuthority {
|
||||
fn list_tickets(&self, limit: usize) -> Result<ProjectRecordList<TicketSummary>>;
|
||||
fn list_ticket_page(&self, request: TicketListPageRequest) -> Result<TicketSummaryPage>;
|
||||
fn list_ticket_page(&self, request: TicketListProjectionRequest) -> Result<TicketSummaryPage>;
|
||||
fn query_tickets(&self, query: TicketQueryRequest) -> Result<TicketQueryResponse>;
|
||||
fn ticket(&self, id: &str) -> Result<TicketDetail>;
|
||||
fn show_ticket(&self, id: &str, query: TicketShowRequest) -> Result<TicketDetail>;
|
||||
@@ -86,14 +86,14 @@ pub trait MemoryAuthority {
|
||||
fn ensure_memory_document(&self) -> Result<MemoryDocument>;
|
||||
fn memory_document(&self) -> Result<MemoryDocument>;
|
||||
fn update_memory_document(&self, body_md: &str) -> Result<MemoryDocument>;
|
||||
fn list_memory_staging_records(&self, limit: usize) -> Result<Vec<MemoryStagingEntry>>;
|
||||
fn memory_staging_record(&self, candidate_id: &str) -> Result<MemoryStagingEntry>;
|
||||
fn list_memory_staging_records(&self, limit: usize) -> Result<Vec<InternalMemoryStagingEntry>>;
|
||||
fn memory_staging_record(&self, candidate_id: &str) -> Result<InternalMemoryStagingEntry>;
|
||||
fn upsert_memory_staging_record(
|
||||
&self,
|
||||
candidate_id: &str,
|
||||
raw_json: &str,
|
||||
source_path: Option<&str>,
|
||||
) -> Result<MemoryStagingEntry>;
|
||||
) -> Result<InternalMemoryStagingEntry>;
|
||||
fn close_memory_staging_record(
|
||||
&self,
|
||||
candidate_id: &str,
|
||||
@@ -114,7 +114,7 @@ pub struct MemoryDocument {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct MemoryStagingEntry {
|
||||
pub struct InternalMemoryStagingEntry {
|
||||
pub candidate_id: String,
|
||||
pub raw_json: String,
|
||||
pub source_path: Option<String>,
|
||||
@@ -966,7 +966,7 @@ impl SqliteWorkspaceAuthority {
|
||||
&ticket.meta.id,
|
||||
)?)
|
||||
.ok_or_else(|| Error::Store(format!("missing resource key for {}", ticket.meta.id)))?;
|
||||
let mut relations: TicketRelationView = ticket.relations.into();
|
||||
let mut relations = ticket_relation_view_from_domain(ticket.relations);
|
||||
for relation in &mut relations.outgoing {
|
||||
relation.target_resource_key = self.store.resource_key(
|
||||
&self.workspace_id,
|
||||
@@ -1073,7 +1073,7 @@ impl TicketAuthority for SqliteWorkspaceAuthority {
|
||||
})
|
||||
}
|
||||
|
||||
fn list_ticket_page(&self, request: TicketListPageRequest) -> Result<TicketSummaryPage> {
|
||||
fn list_ticket_page(&self, request: TicketListProjectionRequest) -> Result<TicketSummaryPage> {
|
||||
let limit = request.limit.unwrap_or(30).clamp(1, 100);
|
||||
let mut states = request.states;
|
||||
states.sort();
|
||||
@@ -1587,7 +1587,7 @@ impl MemoryAuthority for SqliteWorkspaceAuthority {
|
||||
Ok(memory_document_from_record(record))
|
||||
}
|
||||
|
||||
fn list_memory_staging_records(&self, limit: usize) -> Result<Vec<MemoryStagingEntry>> {
|
||||
fn list_memory_staging_records(&self, limit: usize) -> Result<Vec<InternalMemoryStagingEntry>> {
|
||||
self.store
|
||||
.list_memory_staging_records(&self.workspace_id, limit)
|
||||
.map(|records| {
|
||||
@@ -1598,7 +1598,7 @@ impl MemoryAuthority for SqliteWorkspaceAuthority {
|
||||
})
|
||||
}
|
||||
|
||||
fn memory_staging_record(&self, candidate_id: &str) -> Result<MemoryStagingEntry> {
|
||||
fn memory_staging_record(&self, candidate_id: &str) -> Result<InternalMemoryStagingEntry> {
|
||||
validate_memory_candidate_id(candidate_id)?;
|
||||
self.store
|
||||
.get_memory_staging_record(&self.workspace_id, candidate_id)?
|
||||
@@ -1613,7 +1613,7 @@ impl MemoryAuthority for SqliteWorkspaceAuthority {
|
||||
candidate_id: &str,
|
||||
raw_json: &str,
|
||||
source_path: Option<&str>,
|
||||
) -> Result<MemoryStagingEntry> {
|
||||
) -> Result<InternalMemoryStagingEntry> {
|
||||
validate_memory_candidate_id(candidate_id)?;
|
||||
validate_json_object(raw_json, "raw_json")?;
|
||||
let imported_at = now_rfc3339();
|
||||
@@ -2634,8 +2634,8 @@ fn memory_document_from_record(record: MemoryDocumentRecord) -> MemoryDocument {
|
||||
}
|
||||
}
|
||||
|
||||
fn memory_staging_from_record(record: MemoryStagingRecord) -> MemoryStagingEntry {
|
||||
MemoryStagingEntry {
|
||||
fn memory_staging_from_record(record: MemoryStagingRecord) -> InternalMemoryStagingEntry {
|
||||
InternalMemoryStagingEntry {
|
||||
candidate_id: record.candidate_id,
|
||||
raw_json: record.raw_json,
|
||||
source_path: record.source_path,
|
||||
@@ -3330,7 +3330,7 @@ VALUES ('workspace-test', 'ticket', 4);
|
||||
assert_eq!(incoming_relation.items.len(), 1);
|
||||
assert_eq!(incoming_relation.items[0].id, "00000000001J5");
|
||||
let summary_page = authority
|
||||
.list_ticket_page(TicketListPageRequest {
|
||||
.list_ticket_page(TicketListProjectionRequest {
|
||||
states: vec!["planning".to_string(), "ready".to_string()],
|
||||
limit: Some(1),
|
||||
cursor: None,
|
||||
@@ -3338,7 +3338,7 @@ VALUES ('workspace-test', 'ticket', 4);
|
||||
.unwrap();
|
||||
assert_eq!(summary_page.items.len(), 1);
|
||||
assert!(summary_page.page.has_more);
|
||||
let mismatched_summary_cursor = authority.list_ticket_page(TicketListPageRequest {
|
||||
let mismatched_summary_cursor = authority.list_ticket_page(TicketListProjectionRequest {
|
||||
states: vec!["done".to_string()],
|
||||
limit: Some(1),
|
||||
cursor: summary_page.page.next_cursor,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -36,7 +36,7 @@ pub mod workspace_signing_identity;
|
||||
mod workspace_subscription;
|
||||
|
||||
pub use authority::{
|
||||
MemoryAuthority, MemoryDocument, MemoryStagingEntry, MemoryStagingResolution,
|
||||
InternalMemoryStagingEntry, MemoryAuthority, MemoryDocument, MemoryStagingResolution,
|
||||
ObjectiveAuthority, SqliteWorkspaceAuthority, TicketAuthority, TicketMergeRevisionSource,
|
||||
WorkspaceAuthority,
|
||||
};
|
||||
|
||||
@@ -1,19 +1,29 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
pub use server_api::{
|
||||
ObjectiveDetail, ObjectiveEventDetail, ObjectiveLinkedTicketSummary, ObjectiveResourceSummary,
|
||||
ObjectiveSummary, QueryPage,
|
||||
InvalidProjectRecord, MergeRequestListItem, MergeRequestListResponse,
|
||||
MergeRequestRefDiagnostic, ObjectiveDetail, ObjectiveEventDetail, ObjectiveLinkSummary,
|
||||
ObjectiveLinkedTicketSummary, ObjectiveQueryItem, ObjectiveQueryRequest,
|
||||
ObjectiveQueryResponse, ObjectiveResourceSummary, ObjectiveShowRequest, ObjectiveSummary,
|
||||
QueryPage, TicketActionEligibility,
|
||||
TicketAssignmentPrincipal as TicketAssignmentPrincipalSummary, TicketAssignmentSummary,
|
||||
TicketDetail, TicketDetailDerivedRelation as DerivedTicketRelation,
|
||||
TicketDetailRelation as TicketRelation, TicketDetailRelationBlocker as TicketRelationBlocker,
|
||||
TicketDetailRelationNotice as TicketRelationNotice,
|
||||
TicketDetailRelationView as TicketRelationView, TicketEventDetail, TicketEvidenceEvent,
|
||||
TicketEvidenceSummary, TicketListItemSummary as TicketSummary, TicketListResponse,
|
||||
TicketMergeRequestSummary, TicketQueryItem, TicketQueryRequest, TicketQueryResponse,
|
||||
TicketRoleAssignmentSummary, TicketShowRequest,
|
||||
};
|
||||
|
||||
const SUMMARY_BODY_LIMIT: usize = 240;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct ProjectRecordList<T> {
|
||||
pub items: Vec<T>,
|
||||
pub invalid_records: Vec<InvalidProjectRecord>,
|
||||
pub record_authority: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct TicketSummaryPage {
|
||||
pub items: Vec<TicketSummary>,
|
||||
pub page: QueryPage,
|
||||
@@ -21,418 +31,67 @@ pub struct TicketSummaryPage {
|
||||
pub record_authority: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct InvalidProjectRecord {
|
||||
pub label: String,
|
||||
pub reason: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct TicketSummary {
|
||||
pub id: String,
|
||||
pub resource_key: String,
|
||||
pub title: String,
|
||||
pub state: String,
|
||||
pub priority: String,
|
||||
pub updated_at: Option<String>,
|
||||
pub queued_by: Option<String>,
|
||||
pub queued_at: Option<String>,
|
||||
pub workspace_action_priority: String,
|
||||
pub record_source: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
|
||||
pub struct TicketListPageRequest {
|
||||
#[serde(default)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Default)]
|
||||
pub struct TicketListProjectionRequest {
|
||||
pub states: Vec<String>,
|
||||
#[serde(default)]
|
||||
pub limit: Option<usize>,
|
||||
#[serde(default)]
|
||||
pub cursor: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct TicketListResponse {
|
||||
pub workspace_id: String,
|
||||
pub limit: usize,
|
||||
pub items: Vec<TicketSummary>,
|
||||
pub page: QueryPage,
|
||||
pub invalid_records: Vec<InvalidProjectRecord>,
|
||||
pub record_authority: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct TicketDetail {
|
||||
pub id: String,
|
||||
pub resource_key: String,
|
||||
pub title: String,
|
||||
pub state: String,
|
||||
pub readiness: Option<String>,
|
||||
pub priority: String,
|
||||
pub created_at: Option<String>,
|
||||
pub updated_at: Option<String>,
|
||||
pub item_revision: String,
|
||||
pub queued_by: Option<String>,
|
||||
pub queued_at: Option<String>,
|
||||
pub repository_key: Option<String>,
|
||||
pub ref_selector: Option<String>,
|
||||
pub risk_flags: Vec<String>,
|
||||
pub body: String,
|
||||
pub body_truncated: bool,
|
||||
pub event_count: usize,
|
||||
pub events: Vec<TicketEventDetail>,
|
||||
pub event_page: QueryPage,
|
||||
pub artifact_count: usize,
|
||||
pub artifacts: Vec<String>,
|
||||
pub relations: TicketRelationView,
|
||||
pub linked_objectives: Vec<ObjectiveLinkSummary>,
|
||||
pub implementation_reports: Vec<TicketEvidenceEvent>,
|
||||
pub assignments: Vec<TicketRoleAssignmentSummary>,
|
||||
pub current_coder: Option<TicketAssignmentSummary>,
|
||||
pub assignment_diagnostics: Vec<String>,
|
||||
pub action_eligibility: TicketActionEligibility,
|
||||
pub merge_request: Option<TicketMergeRequestSummary>,
|
||||
pub evidence: TicketEvidenceSummary,
|
||||
pub resolution: Option<String>,
|
||||
pub record_source: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct TicketEventDetail {
|
||||
pub sequence: usize,
|
||||
pub event_ref: String,
|
||||
pub kind: String,
|
||||
pub author: Option<String>,
|
||||
pub at: Option<String>,
|
||||
pub status: Option<String>,
|
||||
pub from: Option<String>,
|
||||
pub to: Option<String>,
|
||||
pub reason: Option<String>,
|
||||
pub state_field: Option<String>,
|
||||
pub heading: Option<String>,
|
||||
pub body: Option<String>,
|
||||
pub attributes: std::collections::BTreeMap<String, String>,
|
||||
pub references: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct TicketRelation {
|
||||
pub ticket_id: String,
|
||||
pub kind: String,
|
||||
pub target: String,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub target_resource_key: Option<String>,
|
||||
pub note: Option<String>,
|
||||
pub author: String,
|
||||
pub at: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct DerivedTicketRelation {
|
||||
pub source_ticket: String,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub source_resource_key: Option<String>,
|
||||
pub inverse_kind: String,
|
||||
pub forward_kind: String,
|
||||
pub note: Option<String>,
|
||||
pub author: String,
|
||||
pub at: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct TicketRelationBlocker {
|
||||
pub blocking_ticket: String,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub blocking_resource_key: Option<String>,
|
||||
pub reason_kind: String,
|
||||
pub relation_kind: String,
|
||||
pub note: Option<String>,
|
||||
pub blocking_state: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct TicketRelationNotice {
|
||||
pub related_ticket: String,
|
||||
pub kind: String,
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct TicketRelationView {
|
||||
pub outgoing: Vec<TicketRelation>,
|
||||
pub incoming: Vec<DerivedTicketRelation>,
|
||||
pub blockers: Vec<TicketRelationBlocker>,
|
||||
pub notices: Vec<TicketRelationNotice>,
|
||||
}
|
||||
|
||||
impl From<ticket::TicketRelationView> for TicketRelationView {
|
||||
fn from(value: ticket::TicketRelationView) -> Self {
|
||||
Self {
|
||||
outgoing: value
|
||||
.outgoing
|
||||
.into_iter()
|
||||
.map(|relation| TicketRelation {
|
||||
ticket_id: relation.ticket_id,
|
||||
kind: relation.kind.as_str().to_string(),
|
||||
target: relation.target,
|
||||
target_resource_key: None,
|
||||
note: relation.note,
|
||||
author: relation.author,
|
||||
at: relation.at,
|
||||
})
|
||||
.collect(),
|
||||
incoming: value
|
||||
.incoming
|
||||
.into_iter()
|
||||
.map(|relation| DerivedTicketRelation {
|
||||
source_ticket: relation.source_ticket,
|
||||
source_resource_key: None,
|
||||
inverse_kind: relation.inverse_kind,
|
||||
forward_kind: relation.forward_kind.as_str().to_string(),
|
||||
note: relation.note,
|
||||
author: relation.author,
|
||||
at: relation.at,
|
||||
})
|
||||
.collect(),
|
||||
blockers: value
|
||||
.blockers
|
||||
.into_iter()
|
||||
.map(|blocker| TicketRelationBlocker {
|
||||
blocking_ticket: blocker.blocking_ticket,
|
||||
blocking_resource_key: None,
|
||||
reason_kind: blocker.reason_kind,
|
||||
relation_kind: blocker.relation_kind.as_str().to_string(),
|
||||
note: blocker.note,
|
||||
blocking_state: blocker.blocking_state.as_str().to_string(),
|
||||
})
|
||||
.collect(),
|
||||
notices: value
|
||||
.notices
|
||||
.into_iter()
|
||||
.map(|notice| TicketRelationNotice {
|
||||
related_ticket: notice.related_ticket,
|
||||
kind: notice.kind.as_str().to_string(),
|
||||
message: notice.message,
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
pub(crate) fn ticket_relation_view_from_domain(
|
||||
value: ticket::TicketRelationView,
|
||||
) -> TicketRelationView {
|
||||
TicketRelationView {
|
||||
outgoing: value
|
||||
.outgoing
|
||||
.into_iter()
|
||||
.map(|relation| TicketRelation {
|
||||
ticket_id: relation.ticket_id,
|
||||
kind: relation.kind.as_str().to_string(),
|
||||
target: relation.target,
|
||||
target_resource_key: None,
|
||||
note: relation.note,
|
||||
author: relation.author,
|
||||
at: relation.at,
|
||||
})
|
||||
.collect(),
|
||||
incoming: value
|
||||
.incoming
|
||||
.into_iter()
|
||||
.map(|relation| DerivedTicketRelation {
|
||||
source_ticket: relation.source_ticket,
|
||||
source_resource_key: None,
|
||||
inverse_kind: relation.inverse_kind,
|
||||
forward_kind: relation.forward_kind.as_str().to_string(),
|
||||
note: relation.note,
|
||||
author: relation.author,
|
||||
at: relation.at,
|
||||
})
|
||||
.collect(),
|
||||
blockers: value
|
||||
.blockers
|
||||
.into_iter()
|
||||
.map(|blocker| TicketRelationBlocker {
|
||||
blocking_ticket: blocker.blocking_ticket,
|
||||
blocking_resource_key: None,
|
||||
reason_kind: blocker.reason_kind,
|
||||
relation_kind: blocker.relation_kind.as_str().to_string(),
|
||||
note: blocker.note,
|
||||
blocking_state: blocker.blocking_state.as_str().to_string(),
|
||||
})
|
||||
.collect(),
|
||||
notices: value
|
||||
.notices
|
||||
.into_iter()
|
||||
.map(|notice| TicketRelationNotice {
|
||||
related_ticket: notice.related_ticket,
|
||||
kind: notice.kind.as_str().to_string(),
|
||||
message: notice.message,
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct ObjectiveLinkSummary {
|
||||
pub id: String,
|
||||
pub resource_key: String,
|
||||
pub title: String,
|
||||
pub state: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct TicketEvidenceEvent {
|
||||
pub event_ref: String,
|
||||
pub sequence: usize,
|
||||
pub kind: String,
|
||||
pub at: Option<String>,
|
||||
pub author: Option<String>,
|
||||
pub excerpt: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct TicketAssignmentSummary {
|
||||
pub assignment_id: String,
|
||||
pub runtime_id: String,
|
||||
pub worker_id: String,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub worker_resource_key: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct TicketRoleAssignmentSummary {
|
||||
pub assignment_id: String,
|
||||
pub role: String,
|
||||
pub principal: TicketAssignmentPrincipalSummary,
|
||||
pub assigned_by: String,
|
||||
pub assigned_at: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[serde(tag = "kind", rename_all = "snake_case")]
|
||||
pub enum TicketAssignmentPrincipalSummary {
|
||||
User {
|
||||
account_id: String,
|
||||
},
|
||||
Worker {
|
||||
runtime_id: String,
|
||||
worker_id: String,
|
||||
},
|
||||
WorkspaceAgent {
|
||||
agent_key: String,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct TicketActionEligibility {
|
||||
pub can_assign_orchestrator: bool,
|
||||
pub can_unassign_orchestrator: bool,
|
||||
pub can_queue: bool,
|
||||
pub can_start_manual_coder: bool,
|
||||
pub queue_tickets: Vec<String>,
|
||||
pub blockers: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct TicketMergeRequestSummary {
|
||||
pub merge_request_id: String,
|
||||
pub repository_key: String,
|
||||
pub state: String,
|
||||
pub review_status: String,
|
||||
pub selector_from: Option<String>,
|
||||
pub selector_to: String,
|
||||
pub updated_at: String,
|
||||
pub current_subject_ref: Option<String>,
|
||||
pub review_subject_ref: Option<String>,
|
||||
pub review_requested_at: Option<String>,
|
||||
pub review_submitted_at: Option<String>,
|
||||
pub review_excerpt: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct MergeRequestRefDiagnostic {
|
||||
pub code: String,
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct MergeRequestListItem {
|
||||
pub summary: TicketMergeRequestSummary,
|
||||
pub ticket_ids: Vec<String>,
|
||||
pub thread_event_count: usize,
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub ref_diagnostics: Vec<MergeRequestRefDiagnostic>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct MergeRequestListResponse {
|
||||
pub items: Vec<MergeRequestListItem>,
|
||||
pub next_cursor: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
|
||||
pub struct TicketEvidenceSummary {
|
||||
pub has_merge_request: bool,
|
||||
pub has_current_subject_ref: bool,
|
||||
pub has_review_request: bool,
|
||||
pub has_commit: bool,
|
||||
pub review_status: Option<String>,
|
||||
pub approved_current_subject: bool,
|
||||
pub review_after_rescope: bool,
|
||||
pub unresolved_request_changes: bool,
|
||||
pub complete_for_integration: bool,
|
||||
pub missing: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
|
||||
pub struct TicketQueryRequest {
|
||||
pub query: Option<String>,
|
||||
#[serde(default)]
|
||||
pub states: Vec<String>,
|
||||
#[serde(default)]
|
||||
pub event_kinds: Vec<String>,
|
||||
#[serde(default)]
|
||||
pub evidence: Vec<String>,
|
||||
pub review_status: Option<String>,
|
||||
#[serde(default)]
|
||||
pub attention: Vec<String>,
|
||||
pub related_ticket_id: Option<String>,
|
||||
pub relation_kind: Option<String>,
|
||||
pub linked_objective_id: Option<String>,
|
||||
pub updated_after: Option<String>,
|
||||
pub updated_before: Option<String>,
|
||||
pub sort: Option<String>,
|
||||
pub limit: Option<usize>,
|
||||
pub cursor: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct TicketQueryItem {
|
||||
pub id: String,
|
||||
pub resource_key: String,
|
||||
pub title: String,
|
||||
pub state: String,
|
||||
pub readiness: Option<String>,
|
||||
pub priority: String,
|
||||
pub created_at: Option<String>,
|
||||
pub updated_at: Option<String>,
|
||||
pub item_revision: String,
|
||||
pub workspace_action_priority: String,
|
||||
pub matched_fields: Vec<String>,
|
||||
pub snippet: Option<String>,
|
||||
pub matching_event: Option<TicketEvidenceEvent>,
|
||||
pub linked_objective_ids: Vec<String>,
|
||||
pub linked_objective_keys: Vec<String>,
|
||||
pub relation_count: usize,
|
||||
pub blocker_count: usize,
|
||||
pub unresolved_blocker_count: usize,
|
||||
pub unresolved_review_count: usize,
|
||||
pub evidence: TicketEvidenceSummary,
|
||||
pub merge_request: Option<TicketMergeRequestSummary>,
|
||||
pub current_coder: Option<TicketAssignmentSummary>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct TicketQueryResponse {
|
||||
pub items: Vec<TicketQueryItem>,
|
||||
pub page: QueryPage,
|
||||
pub record_authority: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
|
||||
pub struct TicketShowRequest {
|
||||
pub event_limit: Option<usize>,
|
||||
pub event_cursor: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
|
||||
pub struct ObjectiveQueryRequest {
|
||||
pub query: Option<String>,
|
||||
#[serde(default)]
|
||||
pub states: Vec<String>,
|
||||
pub linked_ticket_id: Option<String>,
|
||||
pub updated_after: Option<String>,
|
||||
pub updated_before: Option<String>,
|
||||
pub sort: Option<String>,
|
||||
pub limit: Option<usize>,
|
||||
pub cursor: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct ObjectiveQueryItem {
|
||||
pub id: String,
|
||||
pub resource_key: String,
|
||||
pub title: String,
|
||||
pub state: String,
|
||||
pub created_at: Option<String>,
|
||||
pub updated_at: Option<String>,
|
||||
pub matched_fields: Vec<String>,
|
||||
pub snippet: Option<String>,
|
||||
pub linked_ticket_count: usize,
|
||||
pub linked_tickets: Vec<String>,
|
||||
pub linked_ticket_keys: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct ObjectiveQueryResponse {
|
||||
pub items: Vec<ObjectiveQueryItem>,
|
||||
pub page: QueryPage,
|
||||
pub record_authority: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
|
||||
pub struct ObjectiveShowRequest {
|
||||
pub event_limit: Option<usize>,
|
||||
pub event_cursor: Option<String>,
|
||||
}
|
||||
|
||||
pub(crate) fn summarize_body(body: &str) -> String {
|
||||
let summary = body
|
||||
.lines()
|
||||
|
||||
+1653
-1226
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user