[MNG-5913] Allow defining aliases for existing server configurations in settings.xml#2333
[MNG-5913] Allow defining aliases for existing server configurations in settings.xml#2333slawekjaranowski wants to merge 11 commits into
Conversation
|
This needs to be made sure will not break Maven 3, as same settings is shared by both currently. |
7230d9e to
563d2e2
Compare
unit test, looks ok for me. I tested with: |
|
ok, who is willing to work on it with me? I hope such feature will be valuable. |
|
Well, settings with current 3.9.9 are NOT read: Or this is "ok"? Is settings loaded partially or discaded? |
|
I am willing to jump in as Njord does something similar, but my concern is that Maven 3.x is not "forgiving" while readint |
it is correct because 3.9.x does not have it yet |
I hope we can have next version of settings schema for 3.9.x ... so if someone update own settings alos will use newer version of Maven |
Pankraz76
left a comment
There was a problem hiding this comment.
already very nice.
please give last dedication, to reach infinitive higher-order function.
a959fb0 to
e0b3b6b
Compare
|
@gnodet @Pankraz76 last suggestions applied |
|
@michael-o @cstamas I refreshed a PR 😄 with last suggestions to build pass I need fixes in modello - in progress |
|
Will check next week... |
| .id(id) | ||
| .aliases(List.of()) | ||
| .build()); | ||
| } |
There was a problem hiding this comment.
This looks very ugly. It is the clien't responsibility to traverse the Settings object, no?
There was a problem hiding this comment.
It is the core of change.
Based on additional tag - aliases we create a next server instance in memory on server list.
So all others plugins tools will see destination list of servers original declared in settings and created based on aliases tag.
There was a problem hiding this comment.
I do remember that Modello allows to add Java code to Settings. Why can't we inject/improve the code in the model directly?
There was a problem hiding this comment.
so you propose to override a getServers method directly in modelo?
There was a problem hiding this comment.
@michael-o
It will be impossible (in easy way) to implement in code settings.mdo, we use velocity templates to generate code for 4.x and for 3.x.
There was a problem hiding this comment.
Share the spot where this is done. Modello made it possible :-(
There was a problem hiding this comment.
Share the spot where this is done. Modello made it possible :-(
There is two templates for generating output from modello files:
https://github.com/apache/maven/blob/master/src/mdo/model.vm
https://github.com/apache/maven/blob/master/src/mdo/model-v3.vm
I see some of code in settings.mdo so will look again
There was a problem hiding this comment.
I don't see a way to provide such code in settings.mdo
There was a problem hiding this comment.
@michael-o any other remarks as implementation in modelo is not easy
aliases will be for simple case - when all items from server should be the same - it is the most common case. |
|
Looking into now. |
|
Here is the magic: maven/api/maven-api-settings/src/main/mdo/settings.mdo Lines 282 to 294 in 388337b Why not change it and make as easy as possible? |
it is implementation of method
I need to change a method |
gnodet
left a comment
There was a problem hiding this comment.
Thanks for working on this, @slawekjaranowski -- this is a frequently requested feature (MNG-5913 is from 2016!) and the approach of expanding aliases into synthetic Server entries during settings building is a clean way to make it transparent to the rest of Maven.
I reviewed the full diff carefully. The overall design is sound: alias expansion happens before validation (so duplicate-id detection catches alias clashes with explicit servers), and the !isProjectSettings guard in the impl builder correctly prevents alias expansion for project settings. A few findings below.
Bug: copy-paste error in test assertions (both compat and impl)
Both testSettingsWithServersAndAliases test methods assert server11.getAliases().isEmpty() on the line where server12.getAliases() should be checked. The test still passes because server11 happens to have empty aliases too, but the assertion is not verifying what it claims to.
Missing edge-case validation: alias equals own server id
The current implementation does not validate that an alias is different from the server's own id. If a user writes <id>server-1</id><aliases><alias>server-1</alias></aliases>, the expansion would produce a duplicate server-1 entry. The validator would catch it as a duplicate-id warning, but it would be clearer to reject it earlier with a specific message like "alias must not equal the server's own id".
Missing edge-case validation: same alias used by multiple servers
If two servers both declare <alias>shared</alias>, the expansion produces two servers with id shared. Again, the validator catches this as a duplicate, but the error message ("duplicate server with id shared") does not help the user understand that the problem is in their alias configuration. A dedicated check in the expansion step could produce a more actionable message.
Missing test: alias equals server id of another explicitly declared server (the settings-servers-3 scenario with assertion)
testSettingsWithDuplicateServersIds does test this path and checks for the warning, which is good. But it would also be valuable to test that the correct server configuration wins (the explicitly declared one vs. the alias-expanded one), since the order in the list determines which one downstream code picks up.
Review by Claude Code on behalf of @gnodet
| return settings; | ||
| } | ||
|
|
||
| private List<Server> serversByIds(List<Server> servers) { |
There was a problem hiding this comment.
Consider adding validation here (or at least in the validator) that an alias does not equal the server's own id, and that the same alias string is not used by multiple servers. The existing duplicate-id check in DefaultSettingsValidator will catch both cases, but the resulting error message ("duplicate server with id X") does not help the user understand whether the problem is in their <aliases> configuration. A more specific message during alias expansion would be more actionable.
For example:
private List<Server> serversByIds(List<Server> servers) {
Set<String> allIds = new HashSet<>();
return servers.stream()
.flatMap(server -> {
if (!allIds.add(server.getId())) {
// will be caught by validator
}
return Stream.concat(
Stream.of(server),
server.getAliases().stream().map(alias -> {
if (alias.equals(server.getId())) {
// report: alias must differ from server id
}
if (!allIds.add(alias)) {
// report: alias clashes with another server/alias
}
return serverAlias(server, alias);
}));
})
.toList();
}This is a suggestion for a potential follow-up rather than a blocker.
There was a problem hiding this comment.
I will look at it
There was a problem hiding this comment.
@gnodet I have added a validation for server.aliases
Please look again
| <field> | ||
| <name>aliases</name> | ||
| <version>1.3.0+</version> | ||
| <description>List of additional server aliases. For each alias, an additional server will be generated by copying the entire configuration, but using a different ID. |
There was a problem hiding this comment.
Minor: The description mentions "an additional server will be generated by copying the entire configuration" -- it may be worth noting that the <aliases> list itself is NOT copied to the generated server entries (they get an empty aliases list). This is important for users to understand: aliases are not transitive.
There was a problem hiding this comment.
description reformat to include info about empty aliases in generated servers
6abdb32 to
d30e576
Compare
gnodet
left a comment
There was a problem hiding this comment.
Summary
This is a frequently requested feature (MNG-5913, open since 2015, 3 votes, 6 watchers). The approach of expanding aliases into synthetic Server entries during settings building is clean and transparent to the rest of Maven.
Design: Sound. Alias expansion happens after validation (so conflict detection works correctly), and the !isProjectSettings guard in the impl builder correctly prevents expansion for project settings. Downstream code (e.g. DefaultRepositorySystemSessionFactory) iterates getServers() unchanged — no modifications needed outside the settings builder/validator.
Backward compatibility: Acceptable. Older Maven versions warn about the unrecognized <aliases> tag but continue processing all other settings correctly.
Previous review findings (copy-paste test bug, missing alias-vs-self/alias-vs-alias validation): addressed in commits d1916cc7 and 803b8170. A few new findings below — mostly minor wording and validation gaps.
Fully automatic review from Claude Code
| <description>List of additional server aliases. For each alias, an additional server will be generated. | ||
| Genearte servers items will have the same configuration as the original one, but with the ID specified in this list | ||
| and with an empty aliases list. | ||
| This is useful when the same credentials should be used for multiple servers.</description> |
There was a problem hiding this comment.
Typo: "Genearte" → "Generated". Also minor wording improvement for clarity.
| <description>List of additional server aliases. For each alias, an additional server will be generated. | |
| Genearte servers items will have the same configuration as the original one, but with the ID specified in this list | |
| and with an empty aliases list. | |
| This is useful when the same credentials should be used for multiple servers.</description> | |
| <description>List of additional server aliases. For each alias, an additional server entry will be generated | |
| with the same configuration as the original one, but with the ID replaced by the alias | |
| and with an empty aliases list. | |
| This is useful when the same credentials should be used for multiple servers.</description> |
|
|
||
| for (int i = 0; i < servers.size(); i++) { | ||
| Server server = servers.get(i); | ||
| for (String alias : server.getAliases()) { |
There was a problem hiding this comment.
Consider adding validation for empty or blank alias strings before the uniqueness check. An <alias></alias> or <alias> </alias> entry would silently produce a server with an empty/blank ID, which would cause hard-to-diagnose issues downstream.
Something like:
validateStringNotEmpty(problems, "servers.server[" + i + "].aliases", alias, server.getId());before the serverIds.add check.
Same applies to the compat validator.
| BuilderProblem.Severity.WARNING, | ||
| "servers.server[" + i + "].aliases", | ||
| server.getId(), | ||
| "must be unique for all servers id but found duplicate alias " + alias); |
There was a problem hiding this comment.
Minor grammar: "for all servers id" reads awkwardly.
| "must be unique for all servers id but found duplicate alias " + alias); | |
| "must be unique across all server ids and aliases but found duplicate alias " + alias); |
| } | ||
|
|
||
| settingsValidator.validate(settings, problems); | ||
| settings.setServers(serversByIds(settings.getServers())); |
There was a problem hiding this comment.
serversByIds() uses Stream.toList() which returns an unmodifiable list. The Modello-generated setServers() stores the reference directly, so any downstream code calling getServers().add(...) would throw UnsupportedOperationException.
This is likely fine since settings aren't mutated after building, but if safety is preferred, consider wrapping: new ArrayList<>(serversByIds(...)) (would need the import).
803b817 to
2ef5b3c
Compare
gnodet
left a comment
There was a problem hiding this comment.
Follow-up review — Slawek addressed the main feedback from the previous round (renamed ids to aliases, simplified serversByIds with Stream.concat + helper, .toList(), List.of(), added validation and comprehensive tests). Nice work!
One issue needs fixing before merge (see inline), plus a minor style nit.
Fully automatic review from Claude Code — this review does not replace specialized review tools such as CodeRabbit, Sourcery, or SonarCloud.
| </models> | ||
| <params> | ||
| <param>forcedIOModelVersion=1.2.0</param> | ||
| <param>forcedIOModelVersion=1.3.0</param> |
There was a problem hiding this comment.
The compat/maven-settings module is missing <pluralExceptions> in its modello configuration — both api/maven-api-settings/pom.xml and impl/maven-support/pom.xml have it:
<pluralExceptions>
<aliases>alias</aliases>
</pluralExceptions>Without it, modello auto-depluralize "aliases" by stripping the trailing s, producing addAliase() / removeAliase() instead of the correct addAlias() / removeAlias(). The tests already confirm this — they call server.addAliase(...). Once this ships in a release, that method name becomes permanent public API.
The XML parsing is unaffected (the reader/writer in maven-support has the correct config and uses <alias>), but the compat Java API will have an ungrammatical method name forever.
There was a problem hiding this comment.
good catch - thanks
| } | ||
|
|
||
| if (isProjectSettings) { |
There was a problem hiding this comment.
Nit: these two blocks are mutually exclusive — combining into if/else would make that obvious.
| } | |
| if (isProjectSettings) { | |
| } else { |
…in settings.xml Add the next tag ids to the server in settings.xml Additional server will be created in memory by SettingsBuilder, so the generated configuration should be transparent to other as Settings#getServers() will return complete list.
…ion in `settings.mdo`.
2ef5b3c to
811aa80
Compare
Add the next tag ids to the server in settings.xml
Additional server will be created in memory by SettingsBuilder, so the generated configuration should be transparent to other as Settings#getServers() will return complete list.
https://issues.apache.org/jira/browse/MNG-5913