standard-version icon indicating copy to clipboard operation
standard-version copied to clipboard

feat(Java): add support for Java projects which use Maven or Gradle

Open dwmkerr opened this issue 4 years ago • 22 comments

(I've also published a blog post on how to use this for Java here Supercharge your Java Projects with Conventional Commits, Semantic Versioning and Semantic Releases)

What is the problem this is addressing?

This project is amazing, I use it all the time both personally and professionally. However, I use more than just Node.js, and find myself missing standard-version in every other language. Although by default this project assume Node.js, 99.9% of the code is not Node specific. Creating the changelog, committing, checking for the changes, deciding how to bump, dry runs, etc etc.

Although there does exist a mechanism to update files in a custom way with updaters, I think many people do not use this feature.

This small change means that with just a few extra lines, we can support Java projects out-of-the-box. That potentially adds a massive number of people who can use the library. It adds no new dependencies. If I search for 'standard version java' I find nothing relevant, there is no equivalent tool.

I'd love any feedback on this PR, this would help me enormously in my own projects, but I understand it somewhat muddies the API as you could do this with custom updaters.

This is also a non-breaking change and will not affect any existing projects or use cases.

Here are the changes:

Adds support for Java projects which use the 'Maven' build system, by simply setting the flags as below

image

In the Maven world, the pom.xml is basically your package.json.

Adds support for Java projects which use the 'Gradle' build system, by simply setting the flags as below

npx standard-version --packageFiles build.gradle --bumpFiles build.gradle

Fixed a bug in resolveUpdaterObjectFromArgument which led to a cryptic error message in a failing test

Before:

image

After:

image

dwmkerr avatar May 15 '20 07:05 dwmkerr

would be nice to change the regex to support " around version (apart from single quotes) in gradle files like

version = "0.2.4"

hashd avatar May 19 '20 21:05 hashd

@hashd very good point - have updated the code now and tested it works. Thanks for the suggestion!

dwmkerr avatar May 20 '20 03:05 dwmkerr

Thanks for the PR. I'm also wondering if we should maintain these additional logic here? My preference is to make it pluggable so that the logics can live in any repo

stevemao avatar May 20 '20 04:05 stevemao

Yes this is exactly the conversation I want to check with you. Basically the effort required to support another language in most cases is trivial - regex against a file, replace a version. All of the great stuff in this library around managing the commits, the changelog, etc etc is universal. Now there is the approach of custom-updaters, as is present now, but that seems to be much more project specific.

Something like a pom.xml, gradle.build, AssemblyVersion.cs or whatever is going to work the same way in any project. But the more we add, the more we bloat this codebase. So finding some way to make this pluggable would make sense.

The only challenge will be making it work for a codebase which isn't already node.js. Because (for example) Java projects won't have a package.json which you can npm install a plugin into, so ideally the whole thing should still be able to work with a single npx command, such as:

npx standard-version --plugin pom

Or something like this.

Any thoughts on what might be the best way to go?

dwmkerr avatar May 20 '20 05:05 dwmkerr

Yes this is exactly the conversation I want to check with you. Basically the effort required to support another language in most cases is trivial - regex against a file, replace a version. All of the great stuff in this library around managing the commits, the changelog, etc etc is universal. Now there is the approach of custom-updaters, as is present now, but that seems to be much more project specific.

Something like a pom.xml, gradle.build, AssemblyVersion.cs or whatever is going to work the same way in any project. But the more we add, the more we bloat this codebase. So finding some way to make this pluggable would make sense.

The only challenge will be making it work for a codebase which isn't already node.js. Because (for example) Java projects won't have a package.json which you can npm install a plugin into, so ideally the whole thing should still be able to work with a single npx command, such as:

npx standard-version --plugin pom

Or something like this.

Any thoughts on what might be the best way to go?

Yep, would prefer a solution which avoids a package.json in a Java maven/gradle project

hashd avatar May 20 '20 13:05 hashd

Hi there, for the maven implementation, it may be safer to use maven version plugin instead of raw replacement. mvn versions:set -DnewVersion=x.x.x This would work better with maven multi-module project as well. In any case, nice work ! And I would love to see this released :)

uguy avatar Jun 08 '20 16:06 uguy

@uguy that would be a conventional way to do it in Java, but has the issue which is that it would require Maven to be installed on the machine this runs on. What's nice about this approach is that there is no need for the Java tooling to be present. Also if we call out to another process we need to check error codes etc etc, whereas this approach uses all of the existing mechanisms (you get the file as a string, manipulate it, that's it, the existing code paths take care of the rest).

dwmkerr avatar Jun 09 '20 01:06 dwmkerr

standard-version is exactly what I need, but for Java project (and in the future Lua projects for an PC game I'm modding). Is this integration in the base version still on the table? It would be so awesome to use standard-version for other programming projects as well.

DrCox1911 avatar Aug 02 '20 19:08 DrCox1911

I'm more than happy to update the PR, and also to use xmldom if preferred, just waiting on input from a maintainer to know if we're going to go down this route. It looks like there are other PRs which also would leverage this approach to widen the potential use cases for the library. I'd love it if we can get this in - I'd like to have standard-version as a pretty much standard part of my workflow for every project!

dwmkerr avatar Sep 08 '20 04:09 dwmkerr

Hello, I'm also very interested with this feature for java. I tried it on your repo with npx @dwmkerr/standard-version --prerelease rc --packageFiles pom.xml --bumpFiles pom.xml It work with <version>1.1.0</version> But did not work with <version>1.1.0-rc.0</version>

I have this message : "Failed to read the tag in your pom file - is it present?"

Another remark, it did not bump child module pom.xml, only the parent.

UnleashSpirit avatar Oct 16 '20 15:10 UnleashSpirit

@eemeli sorry for the delay I've been slammed - xmldom seems to work great. There is only one potential issue - as it reads into what is essentially an AST then writes back out, the user's pom.xml can end up having a bunch of other changes. For example, if someone has re-indented xml attributes to line up nicely, these changes will be lost.

The benefit is definitely more robust handling of XML so I think that outweighs the single consequence - it'll essentially 'standardise' your XML.

Do you think this would be worth noting the in the docs?

@UnleashSpirit I believe the current version will now fix your issue, would you mind letting me know?

dwmkerr avatar Oct 21 '20 15:10 dwmkerr

Im wondering if this variant can accommodate the usual maven extensions (ie qualifier/buildnumber) to semver? Fwiw Im not really interested in the version bump functionality, but I am interested in running this via docker or directly as a github action, independent of maven/gradle.

jeacott avatar Oct 24 '20 02:10 jeacott

Good points @jeacott am happy to take any suggestions, basically as long as the project maintainers think the overall approach/feature is useful to have!

dwmkerr avatar Oct 26 '20 06:10 dwmkerr

@dwmkerr I try again just now command : npx @dwmkerr/standard-version@latest --prerelease rc --packageFiles pom.xml --bumpFiles pom.xml

Same result if <version>2.0.0</version> It works, bump to 2.1.0-rc.0 But if <version>2.0.0-rc.0</version> Same message Failed to read the <version> tag in your pom file - is it present? and the version becomes 1.1.0-rc.0

And it still bumping only parent pom.xml and not module's one (or do I have to list them all in the command ? is yes, how ?)

UnleashSpirit avatar Nov 10 '20 10:11 UnleashSpirit

Hi, great work. I was wondering if there is anyway to create the tag of format x.y.z and not vx.y.z(v prefixed) as in the case of default

rach1416 avatar Mar 07 '21 20:03 rach1416

Hi, great work. I was wondering if there is anyway to create the tag of format x.y.z and not vx.y.z(v prefixed) as in the case of default

Nevermind, I found the solution I had to pass --tag-prefix= parameter

rach1416 avatar Mar 07 '21 20:03 rach1416

Does this PR is still alive ? I found why the npx @dwmkerr/standard-version@latest did not work, the @lastest is not the master so the code not the same as here (no xmldoc) With the real last version, the master banch and not the latest npm published, the bump problem with prerelease rc is resolved. For the maven sub module, as you don't use mvn cli, which is a good idea, I have a proposition. Update the pom.js and use .versionrc as here. It's kind of a workaround but still good (at least for me)

// updaters/types/pom.js
function getDocAndVersionNode(contents) {
  const doc = new DOMParser().parseFromString(contents)
  const nodes = doc.documentElement.childNodes
  let parentNodes = null
  for (let i = 0; i < nodes.length; ++i) {
    const node = nodes[i]
    if (node.nodeName === 'version') return { doc, node }
    if (node.nodeName === 'parent') parentNodes = node.childNodes
  }
  // Maven sub-module
  if (parentNodes) {
    for (let i = 0; i < parentNodes.length; ++i) {
      const node = parentNodes[i]
      if (node.nodeName === 'version') return { doc, node }
    }
  }
  return { doc }
}
// .versionrc.json
{
  "packageFiles": [
    { "filename": "pom.xml", "type": "pom" }
  ],
  "bumpFiles": [
    { "filename": "pom.xml", "type": "pom" },
    { "filename": "module_a/pom.xml", "type": "pom" },
    { "filename": "module_b/pom.xml", "type": "pom" }
  ]
}

UnleashSpirit avatar Apr 15 '21 10:04 UnleashSpirit

@dwmkerr @UnleashSpirit The command mvn versions:set -DnewVersion={{version}} would also update its child modules.

anragab avatar Apr 25 '21 16:04 anragab

@dwmkerr @UnleashSpirit The command mvn versions:set -DnewVersion={{version}} would also update its child modules.

But it brings maven cli dependency which we want to avoid ...

UnleashSpirit avatar Apr 25 '21 16:04 UnleashSpirit

Hi all - again I'm more than happy to update the PR from latest, I just want to get a steer from the project maintainers on whether this is likely to go in or whether they want to keep it separate, I'm fine either way just want to confirm before I update!

dwmkerr avatar Apr 26 '21 03:04 dwmkerr

It looks like it's been a minute on this, but I'd love to see java supported. Any updates? Anything I can do to help?

linuxninja39 avatar Apr 02 '22 15:04 linuxninja39

Hi there! Since standard-version is deprecated, I've forked it here. I'm keen to bring in updaters for common frameworks to the fork, and I've proposed a guideline to do so in this RFC here - I was able to write the proposed guideline thanks in large part to the excellent discussion on this PR so far - thanks very much! Further discussion welcome on that RFC.

if you're still interested in this feature, a PR against the fork would be very welcome.

TimothyJones avatar Jun 25 '22 03:06 TimothyJones