use crate::api::Api;
use crate::client::{ApiRequest, ApiResponse, Client};
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct Reviewer {
pub user: User,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct User {
pub name: String,
}
#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PullRequestPostPayload {
pub title: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
pub from_ref: RefInfo,
pub to_ref: RefInfo,
#[serde(skip_serializing_if = "Option::is_none")]
pub reviewers: Option<Vec<Reviewer>>,
}
#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RefInfo {
pub id: String,
pub repository: RepositoryInfo,
}
#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RepositoryInfo {
pub slug: String,
pub project: ProjectInfo,
}
#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ProjectInfo {
pub key: String,
}
#[derive(Debug)]
pub struct PullRequestPost {
client: Client,
project_key: String,
repository_slug: String,
pull_request: PullRequestPostPayload,
}
impl ApiRequest for PullRequestPost {
type Output = PullRequestPostPayload;
async fn send(&self) -> ApiResponse<Self::Output> {
let request_uri = format!(
"api/latest/projects/{}/repos/{}/pull-requests",
self.project_key, self.repository_slug
);
self.client
.post::<Self>(
&request_uri,
&serde_json::to_string(&self.pull_request).unwrap(),
)
.await
}
}
impl Api {
pub fn pull_request_post(
self,
project_key: &str,
repository_slug: &str,
pull_request: &PullRequestPostPayload,
) -> PullRequestPost {
PullRequestPost {
client: self.client,
project_key: project_key.to_owned(),
repository_slug: repository_slug.to_owned(),
pull_request: pull_request.to_owned(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_can_serialize() {
let pull_request = PullRequestPostPayload {
title: "Test PR".to_string(),
description: Some("Test description".to_string()),
from_ref: RefInfo {
id: "refs/heads/feature".to_string(),
repository: RepositoryInfo {
slug: "test-repo".to_string(),
project: ProjectInfo {
key: "TEST".to_string(),
},
},
},
to_ref: RefInfo {
id: "refs/heads/main".to_string(),
repository: RepositoryInfo {
slug: "test-repo".to_string(),
project: ProjectInfo {
key: "TEST".to_string(),
},
},
},
reviewers: Some(vec![Reviewer {
user: User {
name: "testuser".to_string(),
},
}]),
};
let json = serde_json::to_string(&pull_request).unwrap();
assert_eq!(
json,
r#"{"title":"Test PR","description":"Test description","fromRef":{"id":"refs/heads/feature","repository":{"slug":"test-repo","project":{"key":"TEST"}}},"toRef":{"id":"refs/heads/main","repository":{"slug":"test-repo","project":{"key":"TEST"}}},"reviewers":[{"user":{"name":"testuser"}}]}"#
);
}
#[test]
fn it_can_serialize_partially() {
let pull_request = PullRequestPostPayload {
title: "Test PR".to_string(),
description: None,
from_ref: RefInfo {
id: "refs/heads/feature".to_string(),
repository: RepositoryInfo {
slug: "test-repo".to_string(),
project: ProjectInfo {
key: "TEST".to_string(),
},
},
},
to_ref: RefInfo {
id: "refs/heads/main".to_string(),
repository: RepositoryInfo {
slug: "test-repo".to_string(),
project: ProjectInfo {
key: "TEST".to_string(),
},
},
},
reviewers: None,
};
let json = serde_json::to_string(&pull_request).unwrap();
assert_eq!(
json,
r#"{"title":"Test PR","fromRef":{"id":"refs/heads/feature","repository":{"slug":"test-repo","project":{"key":"TEST"}}},"toRef":{"id":"refs/heads/main","repository":{"slug":"test-repo","project":{"key":"TEST"}}}}"#
);
}
}