diff --git a/examples/merge_branch.rs b/examples/merge_branch.rs new file mode 100644 index 00000000..daa5fcf2 --- /dev/null +++ b/examples/merge_branch.rs @@ -0,0 +1,16 @@ +use octocrab::Octocrab; + +#[tokio::main] +async fn main() -> octocrab::Result<()> { + let token = std::env::var("GITHUB_TOKEN").expect("GITHUB_TOKEN env variable is required"); + + let octocrab = Octocrab::builder().personal_token(token).build()?; + octocrab + .repos("XAMPPRocky", "octocrab") + .merge("feature/1", "master") + .commit_message("This is a custom merge-commit message") + .send() + .await?; + + Ok(()) +} diff --git a/src/api/repos.rs b/src/api/repos.rs index f3a5d0a1..29753300 100644 --- a/src/api/repos.rs +++ b/src/api/repos.rs @@ -11,6 +11,7 @@ pub mod events; mod file; pub mod forks; mod generate; +mod merges; mod pulls; pub mod releases; mod stargazers; @@ -23,6 +24,7 @@ pub use branches::ListBranchesBuilder; pub use commits::ListCommitsBuilder; pub use file::{DeleteFileBuilder, GetContentBuilder, UpdateFileBuilder}; pub use generate::GenerateRepositoryBuilder; +pub use merges::MergeBranchBuilder; pub use pulls::ListPullsBuilder; pub use releases::ReleasesHandler; pub use stargazers::ListStarGazersBuilder; @@ -563,4 +565,25 @@ impl<'octo> RepoHandler<'octo> { let response = self.crab._get(uri).await?; Ok(response.status().is_success()) } + + /// Merges `head` into the `base` branch. + /// ```no_run + /// # async fn run() -> octocrab::Result<()> { + /// + /// // Merges a feature branch into the master branch. + /// octocrab::instance() + /// .repos("owner", "repo") + /// .merge("feature", "master") + /// .send() + /// .await?; + /// # Ok(()) + /// # } + /// ``` + pub fn merge( + &self, + head: impl Into, + base: impl Into, + ) -> MergeBranchBuilder<'octo, '_> { + MergeBranchBuilder::new(self, head, base) + } } diff --git a/src/api/repos/merges.rs b/src/api/repos/merges.rs new file mode 100644 index 00000000..b10c8588 --- /dev/null +++ b/src/api/repos/merges.rs @@ -0,0 +1,42 @@ +use super::*; + +#[derive(serde::Serialize)] +pub struct MergeBranchBuilder<'octo, 'r> { + #[serde(skip)] + handler: &'r RepoHandler<'octo>, + head: String, + base: String, + #[serde(skip_serializing_if = "Option::is_none")] + commit_message: Option, +} + +impl<'octo, 'r> MergeBranchBuilder<'octo, 'r> { + pub fn new( + handler: &'r RepoHandler<'octo>, + head: impl Into, + base: impl Into, + ) -> Self { + Self { + handler, + head: head.into(), + base: base.into(), + commit_message: None, + } + } + + /// The message to use for the merge commit. + pub fn commit_message(mut self, commit_message: impl Into) -> Self { + self.commit_message = Some(commit_message.into()); + self + } + + /// Sends the actual request. + pub async fn send(self) -> Result { + let route = format!( + "/repos/{owner}/{repo}/merges", + owner = self.handler.owner, + repo = self.handler.repo + ); + self.handler.crab.post(route, Some(&self)).await + } +} diff --git a/src/models/repos.rs b/src/models/repos.rs index b0412474..b636a97a 100644 --- a/src/models/repos.rs +++ b/src/models/repos.rs @@ -333,3 +333,13 @@ pub struct GitTag { pub url: Url, pub message: String, } + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[non_exhaustive] +pub struct MergeCommit { + pub url: Url, + pub sha: String, + pub node_id: String, + pub html_url: String, + pub comments_url: String, +}