Description
When tycho-versions-plugin:set-version is invoked with -f <path> where <path> is absolute and contains .. segments, the property named by -Dproperties= is not written to the pom, even though the mojo logs the change as applied and exits with BUILD SUCCESS.
All other updates (project/version, project/parent/version, Bundle-Version, feature.xml) are written correctly, so the reactor is left in an inconsistent state: the pom's <version> is the new version while the property still holds the old one. In our build this silently poisoned a target-platform-configuration that references the target definition artifact at ${ourVersion}, and the failure surfaced much later, in an unrelated-looking form:
[ERROR] resolve target artifact com.example:target-definition:0.0.1-SNAPSHOT:no classifier failed!
Could not resolve target platform specification artifact com.example:target-definition:target:0.0.1-SNAPSHOT: [...]
Such a path is easy to end up with unintentionally: any script that locates the reactor relative to its own location, rather than to the working directory, produces one.
Steps to reproduce
Two-module pom reactor. parent/pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
<myVersion>1.0.0-SNAPSHOT</myVersion>
</properties>
<modules>
<module>child</module>
</modules>
</project>
parent/child/pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.example</groupId>
<artifactId>parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>child</artifactId>
<packaging>pom</packaging>
</project>
Then, from any directory:
mvn -f /abs/path/to/parent/../parent \
org.eclipse.tycho:tycho-versions-plugin:5.0.3:set-version \
-DnewVersion=2.0.0 -Dproperties=myVersion
Expected
parent/pom.xml contains <myVersion>2.0.0</myVersion>, as it does when -f is normalized.
Actual
parent/pom.xml contains <version>2.0.0</version> but still <myVersion>1.0.0-SNAPSHOT</myVersion>. The build succeeds and the log claims the change was made:
[INFO] from /abs/path/to/parent/pom.xml
[INFO] pom.xml//project/properties/[ myVersion ] 1.0.0-SNAPSHOT => 2.0.0
[INFO] pom.xml//project/version: 1.0.0-SNAPSHOT => 2.0.0
[INFO] pom.xml//project/parent/version: 1.0.0-SNAPSHOT => 2.0.0
[INFO] pom.xml//project/version: 1.0.0-SNAPSHOT => 2.0.0
[INFO] pom.xml//project/version: 1.0.0-SNAPSHOT => 2.0.0
[INFO] BUILD SUCCESS
What triggers it
Tested by running the reproducer once per -f value, restoring the poms in between:
-f argument |
property written |
parent (relative) |
yes |
parent/../parent (relative, with ..) |
yes |
/abs/path/to/parent (absolute, normalized) |
yes |
/abs/path/to/parent/../parent |
no |
/abs/path/to/somewhere/else/../../parent |
no |
Relative paths are unaffected, presumably because Maven normalizes them when resolving against the working directory.
A child module is required: with a single-project reactor (no <modules>), -f /abs/path/to/solo/../solo writes the property correctly.
Possible cause
The root project is processed twice, once under each spelling of its path. The failing invocation logs three Making changes in lines for this two-project reactor, the root appearing both as given on the command line and canonicalized:
[INFO] Making changes in /abs/path/to/parent/../parent <-- root, as passed to -f
[INFO] Making changes in /abs/path/to/parent/child
[INFO] Making changes in /abs/path/to/parent <-- root again, canonicalized
The working invocation logs only two, with no duplicate:
[INFO] Making changes in /abs/path/to/parent
[INFO] Making changes in /abs/path/to/parent/child
Consistently with that, the failing invocation reports one project/version change more than the working one (five changes instead of four, otherwise identical), and its from line names the canonicalized path while -f was given the .. form.
So the root pom seems to be reachable under two different File keys — once as passed on the command line, once canonicalized when the child resolves its parent via <relativePath>..</relativePath> — yielding two in-memory documents for one file. Both get the project/version change, which is why that one survives; the property change apparently ends up on the instance that is not written last, and is lost. The assignment of the property change to one particular instance is inference on my part; the duplicate processing above is directly observable. I have not read the code.
If that is the mechanism, canonicalizing the pom file when a project is registered — so both lookups collide on one entry — should fix it.
Affected versions
Reproduced with tycho-versions-plugin 5.0.3, 5.0.2 and 4.0.13, on Maven 3.9.16, OpenJDK 25.0.3, Linux. Note that no Tycho packaging or the Tycho extension is needed — plain pom modules are enough.
Workaround
Normalize the path before passing it to -f, for example -f "$(readlink -f "$dir")".
Suggestion
Independently of the fix: reporting a change in the log and then not persisting it is what made this expensive to diagnose. Failing (or at least warning) when a recorded change cannot be written would have pointed straight at the cause.
Description
When
tycho-versions-plugin:set-versionis invoked with-f <path>where<path>is absolute and contains..segments, the property named by-Dproperties=is not written to the pom, even though the mojo logs the change as applied and exits withBUILD SUCCESS.All other updates (
project/version,project/parent/version,Bundle-Version,feature.xml) are written correctly, so the reactor is left in an inconsistent state: the pom's<version>is the new version while the property still holds the old one. In our build this silently poisoned atarget-platform-configurationthat references the target definition artifact at${ourVersion}, and the failure surfaced much later, in an unrelated-looking form:Such a path is easy to end up with unintentionally: any script that locates the reactor relative to its own location, rather than to the working directory, produces one.
Steps to reproduce
Two-module pom reactor.
parent/pom.xml:parent/child/pom.xml:Then, from any directory:
mvn -f /abs/path/to/parent/../parent \ org.eclipse.tycho:tycho-versions-plugin:5.0.3:set-version \ -DnewVersion=2.0.0 -Dproperties=myVersionExpected
parent/pom.xmlcontains<myVersion>2.0.0</myVersion>, as it does when-fis normalized.Actual
parent/pom.xmlcontains<version>2.0.0</version>but still<myVersion>1.0.0-SNAPSHOT</myVersion>. The build succeeds and the log claims the change was made:What triggers it
Tested by running the reproducer once per
-fvalue, restoring the poms in between:-fargumentparent(relative)parent/../parent(relative, with..)/abs/path/to/parent(absolute, normalized)/abs/path/to/parent/../parent/abs/path/to/somewhere/else/../../parentRelative paths are unaffected, presumably because Maven normalizes them when resolving against the working directory.
A child module is required: with a single-project reactor (no
<modules>),-f /abs/path/to/solo/../solowrites the property correctly.Possible cause
The root project is processed twice, once under each spelling of its path. The failing invocation logs three
Making changes inlines for this two-project reactor, the root appearing both as given on the command line and canonicalized:The working invocation logs only two, with no duplicate:
Consistently with that, the failing invocation reports one
project/versionchange more than the working one (five changes instead of four, otherwise identical), and itsfromline names the canonicalized path while-fwas given the..form.So the root pom seems to be reachable under two different
Filekeys — once as passed on the command line, once canonicalized when the child resolves its parent via<relativePath>..</relativePath>— yielding two in-memory documents for one file. Both get theproject/versionchange, which is why that one survives; the property change apparently ends up on the instance that is not written last, and is lost. The assignment of the property change to one particular instance is inference on my part; the duplicate processing above is directly observable. I have not read the code.If that is the mechanism, canonicalizing the pom file when a project is registered — so both lookups collide on one entry — should fix it.
Affected versions
Reproduced with
tycho-versions-plugin5.0.3, 5.0.2 and 4.0.13, on Maven 3.9.16, OpenJDK 25.0.3, Linux. Note that no Tycho packaging or the Tycho extension is needed — plainpommodules are enough.Workaround
Normalize the path before passing it to
-f, for example-f "$(readlink -f "$dir")".Suggestion
Independently of the fix: reporting a change in the log and then not persisting it is what made this expensive to diagnose. Failing (or at least warning) when a recorded change cannot be written would have pointed straight at the cause.