diff options
Diffstat (limited to 'src-tauri/src/github/mod.rs')
-rw-r--r-- | src-tauri/src/github/mod.rs | 312 |
1 files changed, 0 insertions, 312 deletions
diff --git a/src-tauri/src/github/mod.rs b/src-tauri/src/github/mod.rs deleted file mode 100644 index 9bc3f834..00000000 --- a/src-tauri/src/github/mod.rs +++ /dev/null @@ -1,312 +0,0 @@ -pub mod pull_requests; -pub mod release_notes; - -use crate::constants::{ - APP_USER_AGENT, FLIGHTCORE_REPO_NAME, NORTHSTAR_RELEASE_REPO_NAME, SECTION_ORDER, -}; -use regex::Regex; -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, -} - -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, TS)] -#[ts(export)] -pub enum Project { - FlightCore, - Northstar, -} - -/// Wrapper type needed for frontend -#[derive(Serialize, Deserialize, Debug, Clone, TS)] -#[ts(export)] -pub struct TagWrapper { - label: String, - value: Tag, -} - -#[derive(Debug, Deserialize)] -pub struct CommitInfo { - pub sha: String, - commit: Commit, - author: Option<CommitAuthor>, -} - -#[derive(Debug, Deserialize)] -struct Commit { - message: String, -} - -#[derive(Debug, Deserialize)] -struct CommitAuthor { - login: 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(project: Project) -> 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(); - - // Switch repo to fetch from based on project - let repo_name = match project { - Project::FlightCore => FLIGHTCORE_REPO_NAME, - Project::Northstar => NORTHSTAR_RELEASE_REPO_NAME, - }; - - // Fetch the list of tags for the repository as a `Vec<Tag>`. - let tags_url = format!("https://api.github.com/repos/{}/tags", 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(project: Project, first_tag: Tag, second_tag: Tag) -> Result<String, String> { - match project { - Project::FlightCore => compare_tags_flightcore(first_tag, second_tag), - Project::Northstar => compare_tags_northstar(first_tag, second_tag), - } -} - -pub fn compare_tags_flightcore(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" => "**Code style changes:**", - "refactor" => "**Code Refactoring:**", - "build" => "**Build:**", - "ci" => "**Continuous integration changes:**", - "test" => "**Tests:**", - "chore" => "**Chores:**", - "i18n" => "**Translations:**", - _ => "**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'); - } - } - } - - let release_notes = release_notes.trim_end_matches('\n').to_string(); - 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 -} - -/// Compares two tags on Northstar repo and generates release notes over the diff in tags -/// over the 3 major repos (Northstar, NorthstarLauncher, NorthstarMods) -pub fn compare_tags_northstar(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 repos = [ - "R2Northstar/Northstar", - "R2Northstar/NorthstarLauncher", - "R2Northstar/NorthstarMods", - ]; - - let mut full_patch_notes = "".to_string(); - let mut authors_set = std::collections::HashSet::new(); - - for repo in repos { - full_patch_notes += &format!("{}\n\n", repo); - - 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 - ); - - log::info!("Compare URL: {}", comparison_url.clone()); - 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 - ); - - // - for commit in commits { - println!( - " * {} : {}", - commit.sha, - turn_pr_number_into_link(commit.commit.message.split('\n').next().unwrap(), repo) - ); - patch_notes.push(turn_pr_number_into_link( - commit.commit.message.split('\n').next().unwrap(), - repo, - )); - - // Store authors in set - if commit.author.is_some() { - authors_set.insert(commit.author.unwrap().login); - } - } - - full_patch_notes += &patch_notes.join("\n"); - full_patch_notes += "\n\n\n"; - } - - // Convert the set to a sorted vector. - let mut sorted_vec: Vec<String> = authors_set.into_iter().collect(); - sorted_vec.sort_by_key(|a| a.to_lowercase()); - - // Define a string to prepend to each element. - let prefix = "@"; - - // Create a new list with the prefix prepended to each element. - let prefixed_list: Vec<String> = sorted_vec.iter().map(|s| prefix.to_owned() + s).collect(); - - full_patch_notes += "**Contributors:**\n"; - full_patch_notes += &prefixed_list.join(" "); - - Ok(full_patch_notes.to_string()) -} - -/// Takes the commit title and repo slug and formats it as -/// `[commit title(SHORTENED_REPO#NUMBER)](LINK)` -fn turn_pr_number_into_link(input: &str, repo: &str) -> String { - // Extract `Mods/Launcher` from repo title - let last_line = repo - .split('/') - .next_back() - .unwrap() - .trim_start_matches("Northstar"); - // Extract PR number - let re = Regex::new(r"#(\d+)").unwrap(); - - // Generate pull request link - let pull_link = format!("https://github.com/{}/pull/", repo); - re.replace_all(input, format!("[{}#$1]({}$1)", last_line, pull_link)) - .to_string() -} |