Move issue creation calls into the jira client
This commit is contained in:
parent
8a7c989f48
commit
194e25dc14
14 changed files with 280 additions and 180 deletions
|
@ -5,6 +5,7 @@ edition = "2021"
|
|||
|
||||
[dependencies]
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
chrono = { workspace = true }
|
||||
reqwest = { workspace = true }
|
||||
http = { workspace = true }
|
||||
|
|
|
@ -47,6 +47,8 @@ pub enum JiraClientError {
|
|||
UrlParseError(#[from] ParseError),
|
||||
#[error(transparent)]
|
||||
ReqwestError(#[from] reqwest::Error),
|
||||
#[error(transparent)]
|
||||
SerdeError(#[from] serde_json::Error),
|
||||
#[error("API Error: {0}")]
|
||||
ApiError(String),
|
||||
}
|
||||
|
@ -97,9 +99,19 @@ impl JiraClient {
|
|||
return Err(JiraClientError::ApiError(error_text));
|
||||
}
|
||||
|
||||
match response.json::<TCommand::TResponse>().await {
|
||||
let plain = match response.bytes().await {
|
||||
Ok(x) => x,
|
||||
Err(reason) => return Err(JiraClientError::ReqwestError(reason)),
|
||||
};
|
||||
|
||||
let value = match is_unit::<TCommand::TResponse>() {
|
||||
true => b"null",
|
||||
false => plain.as_ref(),
|
||||
};
|
||||
|
||||
match serde_json::from_slice::<TCommand::TResponse>(value) {
|
||||
Ok(x) => Ok(x),
|
||||
Err(reason) => Err(JiraClientError::ReqwestError(reason)),
|
||||
Err(reason) => Err(JiraClientError::SerdeError(reason)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -116,3 +128,28 @@ impl JiraClient {
|
|||
Ok(url.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
const fn is_unit<T>() -> bool {
|
||||
size_of::<T>() == 0 && align_of::<T>() == 1
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_is_unit_type() {
|
||||
assert!(is_unit::<()>());
|
||||
assert!(!is_unit::<String>());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deserialize_unit_type() {
|
||||
let value = match is_unit::<()>() {
|
||||
true => b"null".as_ref(),
|
||||
false => b"{}".as_ref(),
|
||||
};
|
||||
|
||||
serde_json::from_slice::<()>(value).unwrap();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
mod issue_create_command;
|
||||
mod issue_transitions_command;
|
||||
mod issue_transitions_update_command;
|
||||
mod search_command;
|
||||
mod self_command;
|
||||
|
||||
pub use issue_create_command::IssueCreateCommand;
|
||||
pub use issue_transitions_command::IssueTransitionsCommand;
|
||||
pub use issue_transitions_update_command::IssueTransitionsUpdateCommand;
|
||||
pub use search_command::SearchCommand;
|
||||
pub use self_command::SelfCommand;
|
||||
|
|
31
crates/libjirac/src/client/commands/issue_create_command.rs
Normal file
31
crates/libjirac/src/client/commands/issue_create_command.rs
Normal file
|
@ -0,0 +1,31 @@
|
|||
use crate::client::{JiraCommand, JiraRequestType};
|
||||
use crate::entities::issue_request::{IssueCreateRequest, IssueCreateResponse};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct IssueCreateCommand {
|
||||
issue: IssueCreateRequest,
|
||||
}
|
||||
|
||||
impl IssueCreateCommand {
|
||||
pub fn new(issue: IssueCreateRequest) -> Self {
|
||||
Self { issue }
|
||||
}
|
||||
}
|
||||
|
||||
impl JiraCommand for IssueCreateCommand {
|
||||
type TResponse = IssueCreateResponse;
|
||||
type TPayload = IssueCreateRequest;
|
||||
const REQUEST_TYPE: JiraRequestType = JiraRequestType::Create;
|
||||
|
||||
fn endpoint(&self) -> String {
|
||||
"/rest/api/2/issue".to_string()
|
||||
}
|
||||
|
||||
fn request_body(&self) -> Option<&Self::TPayload> {
|
||||
Some(&self.issue)
|
||||
}
|
||||
|
||||
fn query_params(&self) -> Option<Vec<(String, String)>> {
|
||||
None
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
use crate::client::{JiraCommand, JiraRequestType};
|
||||
use crate::entities::transitions::Transitions;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct IssueTransitionsCommand {
|
||||
issue_key: String,
|
||||
}
|
||||
|
||||
impl IssueTransitionsCommand {
|
||||
pub fn new(issue_key: &str) -> Self {
|
||||
Self {
|
||||
issue_key: issue_key.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl JiraCommand for IssueTransitionsCommand {
|
||||
type TResponse = Transitions;
|
||||
type TPayload = ();
|
||||
const REQUEST_TYPE: JiraRequestType = JiraRequestType::Read;
|
||||
|
||||
fn endpoint(&self) -> String {
|
||||
format!("/rest/api/3/issue/{}/transitions", self.issue_key)
|
||||
}
|
||||
|
||||
fn request_body(&self) -> Option<&Self::TPayload> {
|
||||
None
|
||||
}
|
||||
|
||||
fn query_params(&self) -> Option<Vec<(String, String)>> {
|
||||
None
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
use crate::client::{JiraCommand, JiraRequestType};
|
||||
use crate::entities::transitions::{IssueTransitionUpdatePayload, IssueTransitionUpdatePayloadId};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct IssueTransitionsUpdateCommand {
|
||||
pub issue_key: String,
|
||||
pub transition: IssueTransitionUpdatePayload,
|
||||
}
|
||||
|
||||
impl IssueTransitionsUpdateCommand {
|
||||
pub fn new(issue_key: &str, transition_id: &str) -> Self {
|
||||
Self {
|
||||
issue_key: issue_key.to_string(),
|
||||
transition: IssueTransitionUpdatePayload {
|
||||
transition: IssueTransitionUpdatePayloadId {
|
||||
id: transition_id.to_string(),
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl JiraCommand for IssueTransitionsUpdateCommand {
|
||||
type TResponse = ();
|
||||
type TPayload = IssueTransitionUpdatePayload;
|
||||
const REQUEST_TYPE: JiraRequestType = JiraRequestType::Create;
|
||||
|
||||
fn endpoint(&self) -> String {
|
||||
format!("/rest/api/3/issue/{}/transitions", self.issue_key)
|
||||
}
|
||||
|
||||
fn request_body(&self) -> Option<&Self::TPayload> {
|
||||
Some(&self.transition)
|
||||
}
|
||||
|
||||
fn query_params(&self) -> Option<Vec<(String, String)>> {
|
||||
None
|
||||
}
|
||||
}
|
|
@ -1,2 +1,4 @@
|
|||
pub mod issue;
|
||||
pub mod issue_request;
|
||||
pub mod search;
|
||||
pub mod transitions;
|
||||
|
|
61
crates/libjirac/src/entities/issue_request.rs
Normal file
61
crates/libjirac/src/entities/issue_request.rs
Normal file
|
@ -0,0 +1,61 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct IssueCreateResponse {
|
||||
pub key: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
pub struct IssueCreateRequest {
|
||||
pub fields: IssueFields,
|
||||
pub update: Option<IssueUpdate>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
pub struct IssueUpdate {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub parent: Option<Vec<ParentUpdate>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
pub struct ParentUpdate {
|
||||
pub add: Parent,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
pub struct Parent {
|
||||
pub key: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct IssueFields {
|
||||
pub project: Project,
|
||||
pub summary: String,
|
||||
pub description: String,
|
||||
#[serde(rename = "issuetype")]
|
||||
pub issue_type: IssueType,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub assignee: Option<Assignee>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub status: Option<Status>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Assignee {
|
||||
pub id: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Project {
|
||||
pub key: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct IssueType {
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Status {
|
||||
pub name: String,
|
||||
}
|
29
crates/libjirac/src/entities/transitions.rs
Normal file
29
crates/libjirac/src/entities/transitions.rs
Normal file
|
@ -0,0 +1,29 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct Transitions {
|
||||
pub transitions: Vec<Transition>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct Transition {
|
||||
pub id: String,
|
||||
pub to: TransitionTarget,
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct TransitionTarget {
|
||||
pub id: String,
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct IssueTransitionUpdatePayload {
|
||||
pub transition: IssueTransitionUpdatePayloadId,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct IssueTransitionUpdatePayloadId {
|
||||
pub id: String,
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue