aboutsummaryrefslogtreecommitdiff
path: root/src-tauri/src/github
diff options
context:
space:
mode:
authorGeckoEidechse <40122905+GeckoEidechse@users.noreply.github.com>2023-03-27 18:10:46 +0200
committerGitHub <noreply@github.com>2023-03-27 16:10:46 +0000
commit4cdfc0ea04844681de078d26f44321cb3c3b05c5 (patch)
tree0c4c4a6bd6c94f5f34706adbf9b7d3f2562c3a3f /src-tauri/src/github
parent3529654c9c84342c3273302a6cc684916358315b (diff)
downloadFlightCore-4cdfc0ea04844681de078d26f44321cb3c3b05c5.tar.gz
FlightCore-4cdfc0ea04844681de078d26f44321cb3c3b05c5.zip
feat: Generate FlightCore release notes (#188)
* feat: Generate FlightCore release notes * fix: Remove leftover comment * fix: Add missing semantic commit type * fix: Re-add newlines accidentally removed in merge * refactor: Remove contributors section Will re-add a proper implementation in a later PR. * fix: Revert accidentally modified line * docs: Update comments * fix: Use correct user-agent * fix: Put unknown commits into "Other" section Previously they were just dropped * refactor: Move constant string array to right file * fix: Remove debug prints * refactor: Move lib import to start of file * refactor: Use wrapper type kinda needed by selector in frontend. Allows for still passing full object to backend for future extensability * fix: Generate missing wrapper TS interface * fix: Add title and message to notification * refactor: Move constant to consts file * fix: Fix formatting * fix: Remove unnecessary property declaration
Diffstat (limited to 'src-tauri/src/github')
-rw-r--r--src-tauri/src/github/mod.rs176
1 files changed, 176 insertions, 0 deletions
diff --git a/src-tauri/src/github/mod.rs b/src-tauri/src/github/mod.rs
index 942f0db2..87ea629c 100644
--- a/src-tauri/src/github/mod.rs
+++ b/src-tauri/src/github/mod.rs
@@ -1,2 +1,178 @@
pub mod pull_requests;
pub mod release_notes;
+
+use app::constants::{APP_USER_AGENT, FLIGHTCORE_REPO_NAME, SECTION_ORDER};
+use serde::{Deserialize, Serialize};
+use std::collections::HashMap;
+use ts_rs::TS;
+
+#[derive(Serialize, Deserialize, Debug, Clone, TS)]
+#[ts(export)]
+pub struct Tag {
+ name: String,
+}
+
+/// Wrapper type needed for frontend
+#[derive(Serialize, Deserialize, Debug, Clone, TS)]
+#[ts(export)]
+pub struct TagWrapper {
+ label: String,
+ value: Tag,
+}
+
+#[derive(Debug, Deserialize)]
+struct CommitInfo {
+ sha: String,
+ commit: Commit,
+}
+
+#[derive(Debug, Deserialize)]
+struct Commit {
+ message: String,
+}
+
+#[derive(Debug, Deserialize)]
+struct Comparison {
+ commits: Vec<CommitInfo>,
+}
+
+/// Get a list of tags on the FlightCore repo
+#[tauri::command]
+pub fn get_list_of_tags() -> Result<Vec<TagWrapper>, String> {
+ // Set the repository name.
+
+ // Create a `reqwest` client with a user agent.
+ let client = reqwest::blocking::Client::builder()
+ .user_agent(APP_USER_AGENT)
+ .build()
+ .unwrap();
+
+ // Fetch the list of tags for the repository as a `Vec<Tag>`.
+ let tags_url = format!("https://api.github.com/repos/{}/tags", FLIGHTCORE_REPO_NAME);
+ let tags: Vec<Tag> = client.get(&tags_url).send().unwrap().json().unwrap();
+
+ // Map each `Tag` element to a `TagWrapper` element with the desired label and `Tag` value.
+ let tag_wrappers: Vec<TagWrapper> = tags
+ .into_iter()
+ .map(|tag| TagWrapper {
+ label: tag.name.clone(),
+ value: tag,
+ })
+ .collect();
+
+ Ok(tag_wrappers)
+}
+
+/// Use GitHub API to compare two tags of the same repo against each other and get the resulting changes
+#[tauri::command]
+pub fn compare_tags(first_tag: Tag, second_tag: Tag) -> Result<String, String> {
+ // Fetch the list of commits between the two tags.
+
+ // Create a `reqwest` client with a user agent.
+ let client = reqwest::blocking::Client::builder()
+ .user_agent(APP_USER_AGENT)
+ .build()
+ .unwrap();
+
+ let repo = "R2NorthstarTools/FlightCore";
+
+ let mut full_patch_notes = "".to_string();
+
+ let mut patch_notes: Vec<String> = [].to_vec();
+ println!("{}", repo);
+ // let repo = "R2Northstar/NorthstarLauncher";
+ let comparison_url = format!(
+ "https://api.github.com/repos/{}/compare/{}...{}",
+ repo, first_tag.name, second_tag.name
+ );
+
+ let comparison: Comparison = client.get(&comparison_url).send().unwrap().json().unwrap();
+ let commits = comparison.commits;
+
+ // Display the list of commits.
+ println!(
+ "Commits between {} and {}:",
+ first_tag.name, second_tag.name
+ );
+
+ // Iterate over all commits in the diff
+ for commit in commits {
+ println!(
+ " * {} : {}",
+ commit.sha,
+ commit.commit.message.split('\n').next().unwrap()
+ );
+ patch_notes.push(format!(
+ "{}",
+ commit.commit.message.split('\n').next().unwrap()
+ ));
+ }
+
+ full_patch_notes += &generate_flightcore_release_notes(patch_notes);
+
+ Ok(full_patch_notes.to_string())
+}
+
+/// Generate release notes in the format used for FlightCore
+fn generate_flightcore_release_notes(commits: Vec<String>) -> String {
+ let grouped_commits = group_commits_by_type(commits);
+ let mut release_notes = String::new();
+
+ // Go over commit types and generate notes
+ for commit_type in SECTION_ORDER {
+ if let Some(commit_list) = grouped_commits.get(commit_type) {
+ if !commit_list.is_empty() {
+ let section_title = match commit_type {
+ "feat" => "**Features:**",
+ "fix" => "**Bug Fixes:**",
+ "docs" => "**Documentation:**",
+ "style" => "**Styles:**",
+ "refactor" => "**Code Refactoring:**",
+ "build" => "**Build:**",
+ "test" => "**Tests:**",
+ "chore" => "**Chores:**",
+ _ => "**Other:**",
+ };
+
+ release_notes.push_str(&format!("{}\n", section_title));
+
+ for commit_message in commit_list {
+ release_notes.push_str(&format!("- {}\n", commit_message));
+ }
+
+ release_notes.push_str("\n");
+ }
+ }
+ }
+
+ release_notes
+}
+
+/// Group semantic commit messages by type
+/// Commmit messages that are not formatted accordingly are marked as "other"
+fn group_commits_by_type(commits: Vec<String>) -> HashMap<String, Vec<String>> {
+ let mut grouped_commits: HashMap<String, Vec<String>> = HashMap::new();
+ let mut other_commits: Vec<String> = vec![];
+
+ for commit in commits {
+ let commit_parts: Vec<&str> = commit.splitn(2, ":").collect();
+ if commit_parts.len() == 2 {
+ let commit_type = commit_parts[0].to_lowercase();
+ let commit_description = commit_parts[1].trim().to_string();
+
+ // Check if known commit type
+ if SECTION_ORDER.contains(&commit_type.as_str()) {
+ let commit_list = grouped_commits.entry(commit_type.to_string()).or_default();
+ commit_list.push(commit_description);
+ } else {
+ // otherwise add to list of "other"
+ other_commits.push(commit.to_string());
+ }
+ } else {
+ other_commits.push(commit.to_string());
+ }
+ }
+ grouped_commits.insert("other".to_string(), other_commits);
+
+ grouped_commits
+}