use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type")]
pub enum JiraAuth {
OAuth2 {
client_id: String,
client_secret: String,
access_token: String,
refresh_token: Option<String>,
},
Basic {
email: String,
api_token: String,
},
PersonalAccessToken {
token: String,
},
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct JiraConfig {
pub base_url: String,
pub auth: JiraAuth,
#[serde(default = "default_timeout")]
pub timeout_secs: u64,
#[serde(default = "default_max_retries")]
pub max_retries: u32,
#[serde(default = "default_rate_limit")]
pub rate_limit_per_minute: u32,
}
fn default_timeout() -> u64 {
30
}
fn default_max_retries() -> u32 {
3
}
fn default_rate_limit() -> u32 {
100
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Issue {
pub id: String,
pub key: String,
pub fields: IssueFields,
#[serde(rename = "self")]
pub self_url: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct IssueFields {
pub summary: String,
pub description: Option<String>,
#[serde(rename = "issuetype")]
pub issue_type: IssueType,
pub status: Status,
pub priority: Option<Priority>,
pub assignee: Option<User>,
pub reporter: Option<User>,
pub project: Project,
#[serde(default)]
pub labels: Vec<String>,
#[serde(default)]
pub components: Vec<Component>,
pub created: String,
pub updated: String,
#[serde(flatten)]
pub custom_fields: HashMap<String, serde_json::Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct IssueType {
pub id: String,
pub name: String,
pub description: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Status {
pub id: String,
pub name: String,
pub description: Option<String>,
#[serde(rename = "statusCategory")]
pub status_category: StatusCategory,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StatusCategory {
pub id: i32,
pub key: String,
pub name: String,
#[serde(rename = "colorName")]
pub color_name: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Priority {
pub id: String,
pub name: String,
#[serde(rename = "iconUrl")]
pub icon_url: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct User {
#[serde(rename = "accountId")]
pub account_id: String,
#[serde(rename = "displayName")]
pub display_name: String,
#[serde(rename = "emailAddress")]
pub email_address: Option<String>,
pub active: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Project {
pub id: String,
pub key: String,
pub name: String,
pub description: Option<String>,
#[serde(rename = "projectTypeKey")]
pub project_type_key: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Component {
pub id: String,
pub name: String,
pub description: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CreateIssueRequest {
pub fields: CreateIssueFields,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CreateIssueFields {
pub project: ProjectRef,
pub summary: String,
pub description: Option<String>,
#[serde(rename = "issuetype")]
pub issue_type: IssueTypeRef,
#[serde(skip_serializing_if = "Option::is_none")]
pub assignee: Option<UserRef>,
#[serde(skip_serializing_if = "Option::is_none")]
pub priority: Option<PriorityRef>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub labels: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub components: Vec<ComponentRef>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProjectRef {
pub key: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct IssueTypeRef {
pub name: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UserRef {
#[serde(rename = "accountId")]
pub account_id: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PriorityRef {
pub name: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ComponentRef {
pub name: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UpdateIssueRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub fields: Option<HashMap<String, serde_json::Value>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub update: Option<HashMap<String, Vec<UpdateOperation>>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "operation", content = "value")]
pub enum UpdateOperation {
#[serde(rename = "add")]
Add(serde_json::Value),
#[serde(rename = "set")]
Set(serde_json::Value),
#[serde(rename = "remove")]
Remove(serde_json::Value),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct JqlSearchRequest {
pub jql: String,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "startAt")]
pub start_at: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "maxResults")]
pub max_results: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub fields: Option<Vec<String>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct JqlSearchResponse {
pub total: u32,
#[serde(rename = "startAt")]
pub start_at: u32,
#[serde(rename = "maxResults")]
pub max_results: u32,
pub issues: Vec<Issue>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Board {
pub id: u64,
pub name: String,
#[serde(rename = "type")]
pub board_type: String,
#[serde(rename = "self")]
pub self_url: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Sprint {
pub id: u64,
pub name: String,
pub state: String,
#[serde(rename = "startDate")]
pub start_date: Option<String>,
#[serde(rename = "endDate")]
pub end_date: Option<String>,
#[serde(rename = "originBoardId")]
pub origin_board_id: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WebhookEvent {
pub timestamp: i64,
#[serde(rename = "webhookEvent")]
pub webhook_event: String,
#[serde(rename = "issue_event_type_name")]
pub issue_event_type_name: Option<String>,
pub user: Option<User>,
pub issue: Option<Issue>,
pub changelog: Option<Changelog>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Changelog {
pub id: String,
pub items: Vec<ChangelogItem>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ChangelogItem {
pub field: String,
#[serde(rename = "fieldtype")]
pub field_type: String,
#[serde(rename = "fieldId")]
pub field_id: Option<String>,
pub from: Option<String>,
#[serde(rename = "fromString")]
pub from_string: Option<String>,
pub to: Option<String>,
#[serde(rename = "toString")]
pub to_string: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ErrorResponse {
#[serde(rename = "errorMessages")]
pub error_messages: Vec<String>,
pub errors: HashMap<String, String>,
}
#[derive(Debug, Clone)]
pub struct RateLimitInfo {
pub remaining: u32,
pub limit: u32,
pub reset_at: i64,
}