summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Combrink <37848204+RobinCombrink@users.noreply.github.com>2024-04-09 07:05:42 +0200
committerGitHub <noreply@github.com>2024-04-09 07:05:42 +0200
commit7a5c5a58949a3faca8231f50229fccb97d18bc50 (patch)
tree4be8e1ed7e2fc5b424b9415968cdcffd974822db
parent67c316f86999ce36626ea8940519eb9a9c63392f (diff)
feat: Add `generate_release_notes`: (#588)
* feat: Add generate-notes URL handler: /repos/{owner}/{repo}/releases/generate-notes * Update src/api/repos/releases.rs * Fix the doc example for generate_release_notes --------- Co-authored-by: Robin-Combrink <robin@skynamo.com> Co-authored-by: XAMPPRocky <4464295+XAMPPRocky@users.noreply.github.com>
-rw-r--r--src/api/repos/releases.rs120
-rw-r--r--src/models/repos.rs7
-rw-r--r--tests/generate_release_notes_test.rs61
-rw-r--r--tests/resources/generate_release_notes.json4
4 files changed, 192 insertions, 0 deletions
diff --git a/src/api/repos/releases.rs b/src/api/repos/releases.rs
index 9c84d99..68ee479 100644
--- a/src/api/repos/releases.rs
+++ b/src/api/repos/releases.rs
@@ -150,6 +150,26 @@ impl<'octo, 'r> ReleasesHandler<'octo, 'r> {
self.parent.crab.get(route, None::<&()>).await
}
+ /// Generates [`crate::models::repos::ReleaseNotes`] which describe
+ /// a [`crate::models::repos::Release`]
+ /// ```no_run
+ /// # async fn run() -> octocrab::Result<()> {
+ /// let release_notes = octocrab::instance()
+ /// .repos("owner", "repo")
+ /// .releases()
+ /// .generate_release_notes("0.1.0")
+ /// .send()
+ /// .await?;
+ /// # Ok(())
+ /// # }
+ /// ```
+ pub fn generate_release_notes<'tag_name>(
+ &self,
+ tag_name: &'tag_name (impl AsRef<str> + ?Sized),
+ ) -> GenerateReleaseNotesBuilder<'_, '_, '_, 'tag_name, '_, '_, '_> {
+ GenerateReleaseNotesBuilder::new(self, tag_name.as_ref())
+ }
+
/// Streams the binary contents of an asset.
/// ```no_run
/// # async fn run() -> octocrab::Result<()> {
@@ -454,3 +474,103 @@ impl<'octo, 'repos, 'handler, 'tag_name, 'target_commitish, 'name, 'body>
self.handler.parent.crab.patch(route, Some(&self)).await
}
}
+
+/// A builder pattern struct for updating releases.
+///
+/// created by [`ReleasesHandler::generate_release_notes`].
+#[derive(serde::Serialize)]
+pub struct GenerateReleaseNotesBuilder<
+ 'octo,
+ 'repos,
+ 'handler,
+ 'tag_name,
+ 'previous_tag_name,
+ 'target_commitish,
+ 'configuration_file_path,
+> {
+ #[serde(skip)]
+ handler: &'handler ReleasesHandler<'octo, 'repos>,
+ tag_name: &'tag_name str,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ previous_tag_name: Option<&'previous_tag_name str>,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ target_commitish: Option<&'target_commitish str>,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ configuration_file_path: Option<&'configuration_file_path str>,
+}
+
+impl<
+ 'octo,
+ 'repos,
+ 'handler,
+ 'tag_name,
+ 'previous_tag_name,
+ 'target_commitish,
+ 'configuration_file_path,
+ >
+ GenerateReleaseNotesBuilder<
+ 'octo,
+ 'repos,
+ 'handler,
+ 'tag_name,
+ 'previous_tag_name,
+ 'target_commitish,
+ 'configuration_file_path,
+ >
+{
+ pub(crate) fn new(
+ handler: &'handler ReleasesHandler<'octo, 'repos>,
+ tag_name: &'tag_name str,
+ ) -> Self {
+ Self {
+ handler,
+ tag_name,
+ previous_tag_name: None,
+ target_commitish: None,
+ configuration_file_path: None,
+ }
+ }
+
+ /// The tag which is used as a starting point for the release notes.
+ pub fn previous_tag_name(
+ mut self,
+ previous_tag_name: &'previous_tag_name (impl AsRef<str> + ?Sized),
+ ) -> Self {
+ self.previous_tag_name = Some(previous_tag_name.as_ref());
+ self
+ }
+
+ /// Specifies the commitish value that determines where the Git tag is
+ /// created from. Can be any branch or commit SHA.
+ /// Unused if the Git [`GenerateReleaseNotesBuilder::tag_name`] exists.
+ pub fn target_commitish(
+ mut self,
+ target_commitish: &'target_commitish (impl AsRef<str> + ?Sized),
+ ) -> Self {
+ self.target_commitish = Some(target_commitish.as_ref());
+ self
+ }
+
+ /// A file path within the repository which contains the configuration settings
+ /// for generating release notes.
+ pub fn configuration_file_path(
+ mut self,
+ configuration_file_path: &'configuration_file_path (impl AsRef<str> + ?Sized),
+ ) -> Self {
+ self.configuration_file_path = Some(configuration_file_path.as_ref());
+ self
+ }
+
+ /// Sends the actual request.
+ pub async fn send(self) -> crate::Result<crate::models::repos::ReleaseNotes> {
+ let route = format!(
+ "/repos/{owner}/{repo}/releases/generate-notes",
+ owner = self.handler.parent.owner,
+ repo = self.handler.parent.repo,
+ );
+
+ let result: Result<crate::models::repos::ReleaseNotes> =
+ self.handler.parent.crab.post(route, Some(&self)).await;
+ return result;
+ }
+}
diff --git a/src/models/repos.rs b/src/models/repos.rs
index 3a85f1e..bf46c7e 100644
--- a/src/models/repos.rs
+++ b/src/models/repos.rs
@@ -318,6 +318,13 @@ pub struct Release {
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
+pub struct ReleaseNotes {
+ pub name: String,
+ pub body: String,
+}
+
+#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
+#[serde(rename_all = "snake_case")]
pub struct Asset {
pub url: Url,
pub browser_download_url: Url,
diff --git a/tests/generate_release_notes_test.rs b/tests/generate_release_notes_test.rs
new file mode 100644
index 0000000..0e80d6f
--- /dev/null
+++ b/tests/generate_release_notes_test.rs
@@ -0,0 +1,61 @@
+/// Tests generating release notes:
+/// /repos/{owner}/{repo}/releases/generate-notes
+mod mock_error;
+use mock_error::setup_error_handler;
+use octocrab::models::repos::ReleaseNotes;
+use octocrab::Octocrab;
+use wiremock::{
+ matchers::{method, path},
+ Mock, MockServer, ResponseTemplate,
+};
+
+async fn setup_api(template: ResponseTemplate) -> MockServer {
+ let mock_server = MockServer::start().await;
+
+ let mocked_path = "/repos/owner/repo/releases/generate-notes";
+
+ Mock::given(method("POST"))
+ .and(path(mocked_path))
+ .respond_with(template)
+ .mount(&mock_server)
+ .await;
+ setup_error_handler(
+ &mock_server,
+ &format!("POST on {mocked_path} was not received"),
+ )
+ .await;
+ mock_server
+}
+
+fn setup_octocrab(uri: &str) -> Octocrab {
+ Octocrab::builder().base_uri(uri).unwrap().build().unwrap()
+}
+
+#[tokio::test]
+async fn should_return_page_with_check_runs() {
+ let owner = "owner";
+ let repo = "repo";
+ let tag_name = "2.0.0";
+ let mocked_response: ReleaseNotes =
+ serde_json::from_str(include_str!("resources/generate_release_notes.json")).unwrap();
+
+ let template = ResponseTemplate::new(200).set_body_json(&mocked_response);
+ let mock_server = setup_api(template).await;
+ let client = setup_octocrab(&mock_server.uri());
+ let result = client
+ .repos(owner, repo)
+ .releases()
+ .generate_release_notes(tag_name)
+ .send()
+ .await;
+
+ assert!(
+ result.is_ok(),
+ "expected successful result, got error: {:#?}",
+ result
+ );
+
+ let response = result.unwrap();
+ assert_eq!(response.name, tag_name);
+ assert_eq!(response.body.is_empty(), false);
+}
diff --git a/tests/resources/generate_release_notes.json b/tests/resources/generate_release_notes.json
new file mode 100644
index 0000000..290d2a6
--- /dev/null
+++ b/tests/resources/generate_release_notes.json
@@ -0,0 +1,4 @@
+{
+ "name": "2.0.0",
+ "body": "**Full Changelog**: https://github.com/XAMPPRocky/octocrab/compare/v0.34.0...v0.34.1"
+} \ No newline at end of file