Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: add change log script to the workspace #1505

Merged
merged 4 commits into from
Sep 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ members = [
"scripts/check-docs",
"scripts/fuel-core-version",
"scripts/versions-replacer",
"scripts/change-log",
"wasm-tests",
]

Expand Down Expand Up @@ -80,6 +81,8 @@ trybuild = "1.0.85"
uint = { version = "0.9.5", default-features = false }
which = { version = "6.0.0", default-features = false }
zeroize = "1.7.0"
octocrab = { version = "0.39", default-features = false }
dotenv = { version = "0.15", default-features = false }

# Dependencies from the `fuel-core` repository:
fuel-core = { version = "0.35.0", default-features = false, features = [
Expand Down
16 changes: 11 additions & 5 deletions scripts/change-log/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
[package]
name = "change-log"
version = "0.1.0"
edition = "2021"
version = { workspace = true }
authors = { workspace = true }
edition = { workspace = true }
homepage = { workspace = true }
license = { workspace = true }
publish = false
repository = { workspace = true }
rust-version = { workspace = true }

[dependencies]
regex = { workspace = true }
dotenv = "0.15"
tokio = { workspace = true, features = ["full"] }
octocrab = "0.39"
dotenv = { workspace = true }
tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
octocrab = { workspace = true, features = ["default"] }
61 changes: 36 additions & 25 deletions scripts/change-log/src/get_full_changelog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ pub struct ChangelogInfo {
pub bullet_point: String,
pub migration_note: String,
pub release_notes: String,
pub pr_number: u64,
pub pr_title: String,
pub pr_author: String,
pub pr_url: String,
pub _pr_number: u64,
pub _pr_title: String,
pub _pr_author: String,
pub _pr_url: String,
}

pub fn capitalize(s: &str) -> String {
Expand All @@ -36,11 +36,11 @@ pub async fn get_changelog_info(
.list_pulls(commit_sha.to_string())
.send()
.await?;

if pr_info.items.is_empty() {
return Err("No PR found for this commit SHA".into());
}

let pr = &pr_info.items[0];

// Skip PRs from the user "fuel-service-user"
Expand All @@ -53,7 +53,7 @@ pub async fn get_changelog_info(
.as_ref()
.map_or("misc", |title| title.split(':').next().unwrap_or("misc"))
.to_string();
let is_breaking = pr.title.as_ref().map_or(false, |title| title.contains("!"));
let is_breaking = pr.title.as_ref().map_or(false, |title| title.contains('!'));

let title_description = pr
.title
Expand All @@ -64,7 +64,11 @@ pub async fn get_changelog_info(
let pr_number = pr.number;
let pr_title = title_description.clone();
let pr_author = pr.user.as_ref().map_or("", |user| &user.login).to_string();
let pr_url = pr.html_url.as_ref().map_or("", |url| url.as_str()).to_string();
let pr_url = pr
.html_url
.as_ref()
.map_or("", |url| url.as_str())
.to_string();

let bullet_point = format!(
"- [#{}]({}) - {}, by @{}",
Expand All @@ -73,8 +77,8 @@ pub async fn get_changelog_info(

let breaking_changes_regex = Regex::new(r"(?s)# Breaking Changes\s*(.*)").unwrap();
let breaking_changes = breaking_changes_regex
.captures(&pr.body.as_ref().unwrap_or(&String::new()))
.map_or_else(|| String::new(), |cap| {
.captures(pr.body.as_ref().unwrap_or(&String::new()))
.map_or_else(String::new, |cap| {
cap.get(1).map_or(String::new(), |m| {
m.as_str()
.split("\n# ")
Expand All @@ -87,8 +91,8 @@ pub async fn get_changelog_info(

let release_notes_regex = Regex::new(r"(?s)In this release, we:\s*(.*)").unwrap();
let release_notes = release_notes_regex
.captures(&pr.body.as_ref().unwrap_or(&String::new()))
.map_or_else(|| String::new(), |cap| {
.captures(pr.body.as_ref().unwrap_or(&String::new()))
.map_or_else(String::new, |cap| {
cap.get(1).map_or(String::new(), |m| {
m.as_str()
.split("\n# ")
Expand All @@ -101,7 +105,10 @@ pub async fn get_changelog_info(

let migration_note = format!(
"### [{} - {}]({})\n\n{}",
pr_number, capitalize(&title_description), pr_url, breaking_changes
pr_number,
capitalize(&title_description),
pr_url,
breaking_changes
);

Ok(ChangelogInfo {
Expand All @@ -110,10 +117,10 @@ pub async fn get_changelog_info(
bullet_point,
migration_note,
release_notes,
pr_number,
pr_title,
pr_author,
pr_url,
_pr_number: pr_number,
_pr_title: pr_title,
_pr_author: pr_author,
_pr_url: pr_url,
})
}

Expand All @@ -124,12 +131,16 @@ pub async fn get_changelogs(
base: &str,
head: &str,
) -> Result<Vec<ChangelogInfo>, Box<dyn std::error::Error>> {
let comparison = octocrab.commits(owner, repo).compare(base, head).send().await?;

let comparison = octocrab
.commits(owner, repo)
.compare(base, head)
.send()
.await?;

let mut changelogs = Vec::new();

for commit in comparison.commits {
match get_changelog_info(&octocrab, owner, repo, &commit.sha).await {
match get_changelog_info(octocrab, owner, repo, &commit.sha).await {
Ok(info) => changelogs.push(info),
Err(e) => {
println!("Error retrieving PR for commit {}: {}", commit.sha, e);
Expand All @@ -155,7 +166,7 @@ pub fn generate_changelog(changelogs: Vec<ChangelogInfo>) -> String {
let mut breaking_chores = Vec::new();
let mut migration_notes = Vec::new();
let mut summary_set: HashSet<String> = HashSet::new();

for changelog in &changelogs {
if changelog.is_breaking {
match changelog.pr_type.as_str() {
Expand All @@ -175,20 +186,20 @@ pub fn generate_changelog(changelogs: Vec<ChangelogInfo>) -> String {
}

if !changelog.release_notes.is_empty() && !summary_set.contains(&changelog.release_notes) {
summary_set.insert(format!("{}", changelog.release_notes.clone()));
summary_set.insert(changelog.release_notes.clone().to_string());
}
}

if !summary_set.is_empty() {
content.push_str("# Summary\n\nIn this release, we:\n");
let mut summary_lines: Vec<String> = summary_set.into_iter().collect();
summary_lines.sort();
for line in summary_lines {
content.push_str(&format!("{}\n", line));
}
content.push_str("\n");
content.push('\n');
}

// Generate the breaking changes section
if !breaking_features.is_empty() || !breaking_fixes.is_empty() || !breaking_chores.is_empty() {
content.push_str("# Breaking\n\n");
Expand Down
2 changes: 1 addition & 1 deletion scripts/change-log/src/get_latest_release.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use octocrab::Octocrab;
use dotenv::dotenv;
use octocrab::Octocrab;

pub async fn get_latest_release_tag() -> Result<String, Box<dyn std::error::Error>> {
dotenv().ok();
Expand Down
16 changes: 12 additions & 4 deletions scripts/change-log/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,30 @@
mod get_full_changelog;
mod get_latest_release;

use get_full_changelog::{get_changelogs, generate_changelog, write_changelog_to_file};
use get_full_changelog::{generate_changelog, get_changelogs, write_changelog_to_file};
use get_latest_release::get_latest_release_tag;
use octocrab::Octocrab;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
dotenv::dotenv().ok();
let github_token = std::env::var("GITHUB_TOKEN").expect("GITHUB_TOKEN is not set in the environment");
let github_token =
std::env::var("GITHUB_TOKEN").expect("GITHUB_TOKEN is not set in the environment");
let repo_owner = std::env::var("GITHUB_REPOSITORY_OWNER").expect("Repository owner not found");
let repo_name = std::env::var("GITHUB_REPOSITORY_NAME").expect("Repository name not found");

let octocrab = Octocrab::builder().personal_token(github_token).build()?;

let latest_release_tag = get_latest_release_tag().await?;

let changelogs = get_changelogs(&octocrab, &repo_owner, &repo_name, &latest_release_tag, "master").await?;
let changelogs = get_changelogs(
&octocrab,
&repo_owner,
&repo_name,
&latest_release_tag,
"master",
)
.await?;

let full_changelog = generate_changelog(changelogs);

Expand Down
Loading