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

feat: Submodule commit processing #1082

Open
wants to merge 23 commits into
base: main
Choose a base branch
from
Open

Conversation

lehmanju
Copy link

@lehmanju lehmanju commented Mar 7, 2025

So #1058 inspired me to try submodule support myself. It is not intended to be "better" or "replace" @yudjinn 's efforts. Since this feature is a blocker for me anyway I might as well put some time into it.

Copy link

welcome bot commented Mar 7, 2025

Thanks for opening this pull request! Please check out our contributing guidelines! ⛰️

@codecov-commenter
Copy link

codecov-commenter commented Mar 7, 2025

Codecov Report

Attention: Patch coverage is 25.27473% with 68 lines in your changes missing coverage. Please review.

Project coverage is 40.67%. Comparing base (729aa47) to head (9e8b649).

Files with missing lines Patch % Lines
git-cliff/src/lib.rs 0.00% 26 Missing ⚠️
git-cliff-core/src/repo.rs 0.00% 23 Missing ⚠️
git-cliff-core/src/changelog.rs 53.66% 19 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1082      +/-   ##
==========================================
- Coverage   41.42%   40.67%   -0.74%     
==========================================
  Files          21       21              
  Lines        1811     1859      +48     
==========================================
+ Hits          750      756       +6     
- Misses       1061     1103      +42     
Flag Coverage Δ
unit-tests 40.67% <25.28%> (-0.74%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@yudjinn
Copy link

yudjinn commented Mar 7, 2025

Nice! So for a given commit range of the containing repo, this returns all submodules that changed within those commits, and their deltas between them?

@yudjinn
Copy link

yudjinn commented Mar 7, 2025

This is actually an improvement and "replaces" some of what I was trying to do, and I'm super happy to see it ☺️ if I have time this weekend I'll try to use this as the basis for the releases instead of my other way

@lehmanju
Copy link
Author

lehmanju commented Mar 7, 2025

Well, this iteration sort of actually works! However, the submodule path is not correct ...
context.json

I used openstack/openstack for testing btw, that repository does seem like the ultimate stresstest.

@lehmanju
Copy link
Author

lehmanju commented Mar 7, 2025

So that is fixed as well, only config option, documentation and code cleanup/review are missing.

@orhun
Copy link
Owner

orhun commented Mar 7, 2025

This is some good stuff. Let me know when this is ready for review :)

Copy link
Author

@lehmanju lehmanju left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure about some naming conventions and what should be tested/where. other than that its finished but still needs some testing with a real changelog template.

@@ -55,7 +55,7 @@ serde_json = "1.0.137"
bincode = "2.0.0-rc.3"
serde_regex = "1.1.0"
tera = "1.20.0"
indexmap = { version = "2.7.1", optional = true }
indexmap = { version = "2.7.1", features = ["serde"] }
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this isn't optional anymore since Release uses it for submodule commits. maybe use hashmap instead? my reasoning was that its used in Repository as well, so keep it consistent

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we use hashmap then the items are not ordered which is probably not something that we want.

Also why enable the serde feature?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

serde is needed now because Release needs to be serializable and as a consequence indexmap .

@lehmanju lehmanju changed the title feat(repo): get submodule repositories with commit ranges feat: Submodule commit processing Mar 7, 2025
@lehmanju lehmanju marked this pull request as ready for review March 7, 2025 21:48
@lehmanju lehmanju requested a review from orhun as a code owner March 7, 2025 21:48
Copy link
Owner

@orhun orhun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks nice!

Some things to do:

  • Add fixture tests to ensure the functionality
  • Update documentation about the new configuration option

@@ -55,7 +55,7 @@ serde_json = "1.0.137"
bincode = "2.0.0-rc.3"
serde_regex = "1.1.0"
tera = "1.20.0"
indexmap = { version = "2.7.1", optional = true }
indexmap = { version = "2.7.1", features = ["serde"] }
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we use hashmap then the items are not ordered which is probably not something that we want.

Also why enable the serde feature?

@lehmanju
Copy link
Author

Thanks for the review! I'll have time to address your comments in about a week.

Copy link
Author

@lehmanju lehmanju left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did a bunch of fixes:

  • added fixture test
  • fixed first/last commit bug (submodule commit range now correct)
  • fixed commit preprocessing for submodule commits

@orhun would appreciate another review.

.commit_id
.clone()
.and_then(|commit_id| repository.find_commit(&commit_id));
let commit_range = first_commit.zip(last_commit);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This commit range generation was initially wrong, I needed to use the tag commit id from the previous and current release.

@@ -300,6 +355,9 @@ fn process_repository<'a>(
previous_release.previous = None;
release.previous = Some(Box::new(previous_release));
previous_release = release.clone();
if recurse_submodules {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because previous release is needed, I moved this to the bottom of the for loop. Else it wouldn't be initialized.

///
/// Maps submodule path to a list of commits.
#[serde(rename = "submodule_commits")]
pub submodule_commits: Option<HashMap<String, Vec<Commit<'a>>>>,
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to Hashmap because indexmap serde implementation doesn't preserve order anyway and order doesn't matter.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed the Option<> wrapping and used an empty hashmap instead. results in a cleaner API during templating.

@@ -186,6 +145,58 @@ impl<'a> Changelog<'a> {
Ok(())
}

fn process_commit_list(
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is new, because commit preprocessing now needs to be done for release commits AND submodule commits.

@lehmanju
Copy link
Author

There does seem to be something wrong with the fixture tests in general: https://github.com/orhun/git-cliff/actions/runs/13907737767/job/38914649566#step:3:913

@lehmanju
Copy link
Author

The more I test this in a real scenario the more corner cases I find:
unreleased and first release don't contain any submodule commits although they should

Copy link
Owner

@orhun orhun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good! Left some comments that I believe will make the implementation/documentation better.

The fixtures should be fixed in #1099 - ignore the ones that are failing for now.

Comment on lines +25 to +33
{% for submodule_path, commits in submodule_commits %}
### {{ submodule_path | upper_first }}
{% for group, commits in commits | group_by(attribute="group") %}
#### {{ group | upper_first }}
{% for commit in commits %}
- {{ commit.message | upper_first }}\
{% endfor %}
{% endfor %}
{% endfor %}\n
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! Can you create a new documentation section (Usage > Submodules) and mention this snippet along with the configuration option? I think doing that would help with the visibility of this new template value.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would be more readable if you can add newlines between submodule commits, etc. And maybe consider using pushd & popd

@@ -64,6 +64,15 @@ following context is generated to use for templating:
"commit_id": "a440c6eb26404be4877b7e3ad592bfaa5d4eb210 (release commit)",
"timestamp": 1625169301,
"repository": "/path/to/repository",
"submodule_commits": {
"<relative/submodule_path/in/repository>": [
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you checked how this path is affected e.g. when running inside another directory in a monorepo?


### recurse_submodules

`recurse_submodules` is an **optional** boolean value that indicates whether git-cliff should read and process commits of submodules. This only considers submodules at the toplevel (depth 1). These commits can then be accessed by the variable `submodule_commits` during [templating](/docs/templating/context).
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
`recurse_submodules` is an **optional** boolean value that indicates whether git-cliff should read and process commits of submodules. This only considers submodules at the toplevel (depth 1). These commits can then be accessed by the variable `submodule_commits` during [templating](/docs/templating/context).
`recurse_submodules` is an _optional_ boolean value that indicates whether **git-cliff** should read and process commits of submodules. This only considers submodules at the toplevel (depth 1). These commits can then be accessed by the variable `submodule_commits` during [templating](/docs/templating/context).

.map(|commits| commits.iter().map(Commit::from).collect());

let submodule_path = sub_repo.path().to_string_lossy().into_owned();
// (submodule_path, Vec<Commit>)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// (submodule_path, Vec<Commit>)
// Returns a (submodule_path, Vec<Commit>)

Comment on lines +172 to +174
/// Returns submodule repositories for a given commit range.
///
/// Returns submodule repositories for a given commit range.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// Returns submodule repositories for a given commit range.
///
/// Returns submodule repositories for a given commit range.
/// Returns submodule repositories for a given commit range.

.zip(Some(range))
}
});
// (repository, commit_range)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if these comments are useful. You can also derive these types via your LSP most of the time. Maybe remove them or add a sentence for explanation, if necessary.

@@ -46,6 +49,15 @@ pub struct Repository {
changed_files_cache_path: PathBuf,
}

/// Range of commits in a submodule.
pub struct SubmoduleRange {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Derive Debug etc. if possible.

debug!("Processing the commits...");
for release in self.releases.iter_mut() {
Self::process_commit_list(&mut release.commits, &self.config.git)?;
for submodule_commit_vec in release.submodule_commits.values_mut() {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
for submodule_commit_vec in release.submodule_commits.values_mut() {
for submodule_commits in release.submodule_commits.values_mut() {

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants