Skip to content

feat(internal/librarian): populate Java Maven coordinates from defaults#6554

Open
JoeWang1127 wants to merge 29 commits into
mainfrom
feat/group-id-mapping
Open

feat(internal/librarian): populate Java Maven coordinates from defaults#6554
JoeWang1127 wants to merge 29 commits into
mainfrom
feat/group-id-mapping

Conversation

@JoeWang1127

@JoeWang1127 JoeWang1127 commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

The library configuration loader is updated to automatically populate Java Maven coordinates (GroupID and ArtifactID) based on API path prefix mappings defined in default configuration.

When a library's Java module configuration is missing or its GroupID is empty, the loader scans the library's API paths against the default api_path_to_group_id map to resolve the appropriate GroupID and sets the ArtifactID using the standard "google-" naming convention.

Add default mappings in follow up PRs.

For #6513

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces support for mapping API paths to Java group IDs by adding the api_path_to_group_id configuration field and implementing the fillJava function to populate Java-specific defaults (ArtifactID and GroupID) based on matching API path prefixes. The review feedback highlights several critical issues in the fillJava implementation, including non-deterministic prefix matching due to map iteration, potential false matches from path boundary issues, overwriting of existing ArtifactIDs, and the omission of defaulting GenerateGRPC to true. A refactored version of fillJava was suggested to address these concerns.

Comment thread internal/librarian/library.go
@JoeWang1127 JoeWang1127 marked this pull request as ready for review June 27, 2026 13:59
@JoeWang1127 JoeWang1127 requested a review from a team as a code owner June 27, 2026 13:59
@JoeWang1127 JoeWang1127 requested a review from zhumin8 June 27, 2026 13:59
Comment thread internal/librarian/library.go Outdated
Comment thread internal/librarian/library.go Outdated
Comment thread internal/config/language.go Outdated
@JoeWang1127 JoeWang1127 requested a review from zhumin8 June 29, 2026 18:22
Comment thread internal/librarian/library_test.go Outdated
@JoeWang1127 JoeWang1127 requested a review from ianthehat June 30, 2026 20:28
Comment thread internal/librarian/library.go Outdated
if d.Go != nil {
return fillGo(lib, d)
}
if d.Java != nil {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

While you are following the pattern of the surrounding code, the surrounding code is wrong.
At the lowest level, a sequence of mutually exclusive if statements like this should be a switch instead.
At a higher level, why do we have a bunch of fields that seem to be mutually exclusive, do we actually verify that they are somewhere, if not does the order in which they are checked matter, why does Java get higher priority than rust... the fact that all these questions exist implies a fundamental design fault with another API somewhere (probably whatever config.Default is or whatever builds it).
At first glance it looks like there should be a single field in that thing, of an interface that supports a Fill method, rather than what seems like weird type switch and method dispatch block in this code.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

As a first step, I've refactor fillDefaults to use a switch.

I'll create follow up PRs to refactor config.Default struct.

lib.Java = &config.JavaModule{}
}
if lib.Java.GroupID != "" || d.Java.CustomGroupIDs == nil {
return lib

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This seems like a footgun
This method reads like one that is allowed to set multiple fields to their default values, but this return makes the assumption that GroupID is the only field that this will ever be true for.
If I was adding a new default later one I would add it at the bottom of the function and be very confused why it was not always being set...

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Created a helper function to fill group id.

This can make the function easily extend to fill other fields for java library.

Comment thread internal/librarian/library.go Outdated
}
}
if lib.Java.GroupID != "" {
break

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Adding an outer break that depends on an inner break triggering is a code smell, it almost always implies some code that should be extracted to a function and the breaks should be returns instead.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done, replaced the inner break to return.

@JoeWang1127 JoeWang1127 requested a review from ianthehat July 1, 2026 00:04

@ianthehat ianthehat left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One very minor comment, cl is good apart from that.

// fillGroupIDIfEmpty sets the Java group ID on lib if one is not already configured.
// It matches the library's API paths against the custom group ID prefixes in default
// and assigns the first matching group ID.
func fillGroupIDIfEmpty(lib *config.Library, d *config.Default) *config.Library {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

No point returning the lib, it is always the same as the one passed in, don't make the reader guess wether there is a good reason for that.

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.

3 participants