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(Java): add support for Java projects which use Maven or Gradle #591

Open
wants to merge 20 commits into
base: master
Choose a base branch
from

Conversation

dwmkerr
Copy link

@dwmkerr dwmkerr commented May 15, 2020

(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 dwmkerr force-pushed the feat/add-java-maven-support branch from f54b00d to 7e85e22 Compare May 15, 2020
@dwmkerr dwmkerr force-pushed the feat/add-java-maven-support branch from 7e85e22 to 8d68c46 Compare May 15, 2020
@dwmkerr dwmkerr changed the title feat(Java): add support for pom.xml files for Java Maven projects feat(Java): add support for Java projects May 15, 2020
@dwmkerr dwmkerr changed the title feat(Java): add support for Java projects feat(Java): add support for Java projects which use Maven May 18, 2020
@dwmkerr dwmkerr changed the title feat(Java): add support for Java projects which use Maven feat(Java): add support for Java projects which use Maven or Gradle May 19, 2020
@dwmkerr dwmkerr force-pushed the feat/add-java-maven-support branch from 39bf112 to a6b423c Compare May 19, 2020
lib/updaters/index.js Outdated Show resolved Hide resolved
lib/updaters/index.js Outdated Show resolved Hide resolved
@hashd
Copy link

@hashd hashd commented May 19, 2020

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

version = "0.2.4"

@dwmkerr
Copy link
Author

@dwmkerr dwmkerr commented May 20, 2020

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

lib/updaters/index.js Show resolved Hide resolved
@stevemao
Copy link
Member

@stevemao stevemao commented May 20, 2020

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

@dwmkerr
Copy link
Author

@dwmkerr dwmkerr commented May 20, 2020

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?

@hashd
Copy link

@hashd hashd commented May 20, 2020

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

@uguy
Copy link

@uguy uguy commented Jun 8, 2020

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 :)

@dwmkerr
Copy link
Author

@dwmkerr dwmkerr commented Jun 9, 2020

@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).

lib/updaters/types/pom.js Outdated Show resolved Hide resolved
@DrCox1911
Copy link

@DrCox1911 DrCox1911 commented Aug 2, 2020

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.

@dwmkerr
Copy link
Author

@dwmkerr dwmkerr commented Sep 8, 2020

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!

@UnleashSpirit
Copy link

@UnleashSpirit UnleashSpirit commented Oct 16, 2020

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.

@dwmkerr
Copy link
Author

@dwmkerr dwmkerr commented Oct 21, 2020

@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?

@jeacott
Copy link

@jeacott jeacott commented Oct 24, 2020

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.

@dwmkerr
Copy link
Author

@dwmkerr dwmkerr commented Oct 26, 2020

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!

@UnleashSpirit
Copy link

@UnleashSpirit UnleashSpirit commented Nov 10, 2020

@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 ?)

@rach1416
Copy link

@rach1416 rach1416 commented Mar 7, 2021

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
Copy link

@rach1416 rach1416 commented Mar 7, 2021

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

@UnleashSpirit
Copy link

@UnleashSpirit UnleashSpirit commented Apr 15, 2021

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" }
  ]
}

@anragab
Copy link

@anragab anragab commented Apr 25, 2021

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

@UnleashSpirit
Copy link

@UnleashSpirit UnleashSpirit commented Apr 25, 2021

@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 ...

@dwmkerr
Copy link
Author

@dwmkerr dwmkerr commented Apr 26, 2021

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!

@linuxninja39
Copy link

@linuxninja39 linuxninja39 commented Apr 2, 2022

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?

@TimothyJones
Copy link

@TimothyJones TimothyJones commented Jun 25, 2022

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.

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

Successfully merging this pull request may close these issues.

None yet