aboutsummaryrefslogtreecommitdiff
path: root/src-tauri/src/github/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src-tauri/src/github/mod.rs')
-rw-r--r--src-tauri/src/github/mod.rs181
1 files changed, 181 insertions, 0 deletions
diff --git a/src-tauri/src/github/mod.rs b/src-tauri/src/github/mod.rs
index 942f0db2..b336ab5c 100644
--- a/src-tauri/src/github/mod.rs
+++ b/src-tauri/src/github/mod.rs
@@ -1,2 +1,183 @@
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(
+ commit
+ .commit
+ .message
+ .split('\n')
+ .next()
+ .unwrap()
+ .to_string(),
+ );
+ }
+
+ 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('\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
+}