aboutsummaryrefslogtreecommitdiff
path: root/src-tauri
diff options
context:
space:
mode:
authorGeckoEidechse <40122905+GeckoEidechse@users.noreply.github.com>2023-05-08 15:24:33 +0200
committerGitHub <noreply@github.com>2023-05-08 15:24:33 +0200
commit0262255b0dfb598376f1e7063cc98bfd6eace410 (patch)
tree4ca45f5fcffc4976b112f29244abd0f471417a08 /src-tauri
parentbe9b0d32dd13d66027083f0fcfa8b4e05eb2d134 (diff)
downloadFlightCore-0262255b0dfb598376f1e7063cc98bfd6eace410.tar.gz
FlightCore-0262255b0dfb598376f1e7063cc98bfd6eace410.zip
feat: Generate Northstar release notes (#277)
* feat: Allow selecting project to generate release notes for * fix: Add missing TypeScript bindings * feat: Pass project to backend on tag compare * fix: Check for unsupported project * feat: Allow fetching tags from Northstar repo * fix: Formatting and fixing typo * feat: Copy over Northstar release note generation from previous PR * refactor: Use Tag struct instead of string Allows for extendability in the future * fix: Use proper user-agent for web request * fix: Remove debug log prints * refactor: Use separete function for FlightCore release note generation One function for each FlightCore and Northstar * feat: Make CommitAuthor optional to deal with rebase commits that don't have a PR linked * fix: Address clippy issues * fix: Remove debug prints * docs: Add comments * refactor: Move import to top of source file
Diffstat (limited to 'src-tauri')
-rw-r--r--src-tauri/bindings/Project.ts3
-rw-r--r--src-tauri/src/constants.rs3
-rw-r--r--src-tauri/src/github/mod.rs135
3 files changed, 137 insertions, 4 deletions
diff --git a/src-tauri/bindings/Project.ts b/src-tauri/bindings/Project.ts
new file mode 100644
index 00000000..a0f00bb8
--- /dev/null
+++ b/src-tauri/bindings/Project.ts
@@ -0,0 +1,3 @@
+// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
+
+export type Project = "FlightCore" | "Northstar"; \ No newline at end of file
diff --git a/src-tauri/src/constants.rs b/src-tauri/src/constants.rs
index 8c88df1e..6e294e55 100644
--- a/src-tauri/src/constants.rs
+++ b/src-tauri/src/constants.rs
@@ -48,3 +48,6 @@ pub const REFRESH_DELAY: Duration = Duration::from_secs(5 * 60);
// Flightcore repo name and org name on GitHub
pub const FLIGHTCORE_REPO_NAME: &str = "R2NorthstarTools/FlightCore";
+
+// Northstar release repo name and org name on GitHub
+pub const NORTHSTAR_RELEASE_REPO_NAME: &str = "R2Northstar/Northstar";
diff --git a/src-tauri/src/github/mod.rs b/src-tauri/src/github/mod.rs
index b336ab5c..12729de2 100644
--- a/src-tauri/src/github/mod.rs
+++ b/src-tauri/src/github/mod.rs
@@ -1,7 +1,10 @@
pub mod pull_requests;
pub mod release_notes;
-use app::constants::{APP_USER_AGENT, FLIGHTCORE_REPO_NAME, SECTION_ORDER};
+use app::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;
@@ -12,6 +15,13 @@ 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)]
@@ -24,6 +34,7 @@ pub struct TagWrapper {
struct CommitInfo {
sha: String,
commit: Commit,
+ author: Option<CommitAuthor>,
}
#[derive(Debug, Deserialize)]
@@ -32,13 +43,18 @@ struct Commit {
}
#[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() -> Result<Vec<TagWrapper>, String> {
+pub fn get_list_of_tags(project: Project) -> Result<Vec<TagWrapper>, String> {
// Set the repository name.
// Create a `reqwest` client with a user agent.
@@ -47,8 +63,14 @@ pub fn get_list_of_tags() -> Result<Vec<TagWrapper>, String> {
.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", FLIGHTCORE_REPO_NAME);
+ 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.
@@ -65,7 +87,14 @@ pub fn get_list_of_tags() -> Result<Vec<TagWrapper>, String> {
/// 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> {
+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.
@@ -181,3 +210,101 @@ fn group_commits_by_type(commits: Vec<String>) -> HashMap<String, Vec<String>> {
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();
+
+ // 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('/')
+ .rev()
+ .next()
+ .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()
+}