Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in

How do you programmatically set a version for a plugin based upon SCM string?

Carl Myers
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 10, 2014

Complete code is here: https://github.com/palantir/stashbot/commit/afeb73a6231b82da1d570d92671769437ac8e572

Short version is, In my POM, I want to do this:

-    <version>1.3.3-dev</version>

+    <version>${git.commit.id.describe}</version>

There is a maven plugin which sets that property (https://github.com/ktoso/maven-git-commit-id-plugin)

 

The code as it appears in my link compiles, runs unit tests, and packages correctly, but when I try to install the plugin I get this stack trace:

[INFO] [talledLocalContainer] 2014-11-10 09:49:13,446 ERROR [UpmAsynchronousTaskManager:thread-2] admin @B8N96Ux589x520x0 1t2xn9a 127.0.0.1 "POST /rest/plugins/1.0/ HTTP/1.1" c.a.p.loaders.ScanningPluginLoader Because of the following exception:
[INFO] [talledLocalContainer] com.atlassian.plugin.PluginParseException: Unable to process plugin to generate OSGi manifest
[INFO] [talledLocalContainer]   at com.atlassian.plugin.osgi.factory.transform.stage.GenerateManifestStage.execute(GenerateManifestStage.java:201) ~[atlassian-plugins-osgi-3.2.9.jar:na]
[INFO] [talledLocalContainer]   at com.atlassian.plugin.loaders.ScanningPluginLoader.deployPluginFromUnit(ScanningPluginLoader.java:155) [atlassian-plugins-core-3.2.9.jar:na]
[INFO] [talledLocalContainer]   at com.atlassian.plugin.loaders.ScanningPluginLoader.loadFoundPlugins(ScanningPluginLoader.java:117) [atlassian-plugins-core-3.2.9.jar:na]
[INFO] [talledLocalContainer]   at com.atlassian.plugin.loaders.PermissionCheckingPluginLoader.loadFoundPlugins(PermissionCheckingPluginLoader.java:30) ~[atlassian-plugins-core-3.2.9.jar:na]
[INFO] [talledLocalContainer]   at com.atlassian.plugin.manager.DefaultPluginManager.scanForNewPlugins(DefaultPluginManager.java:734) ~[atlassian-plugins-core-3.2.9.jar:na]
[INFO] [talledLocalContainer]   at com.atlassian.plugin.manager.DefaultPluginManager.installPlugins(DefaultPluginManager.java:683) ~[atlassian-plugins-core-3.2.9.jar:na]
[INFO] [talledLocalContainer]   at com.atlassian.stash.internal.plugin.ClusteredPluginController.installPlugins(ClusteredPluginController.java:95) ~[stash-platform-3.3.0.jar:na]
[INFO] [talledLocalContainer]   at com.atlassian.upm.core.install.PluginArtifactInstallerImpl$1.doInTransaction(PluginArtifactInstallerImpl.java:55) ~[na:na]
[INFO] [talledLocalContainer]   at com.atlassian.upm.core.install.PluginArtifactInstallerImpl$1.doInTransaction(PluginArtifactInstallerImpl.java:50) ~[na:na]
[INFO] [talledLocalContainer]   at com.atlassian.sal.core.transaction.HostContextTransactionTemplate$1.doInTransaction(HostContextTransactionTemplate.java:25) ~[sal-core-2.12.4.jar:na]
[INFO] [talledLocalContainer]   at com.atlassian.stash.internal.sal.spi.HostContextAccessorImpl.doInTransaction(HostContextAccessorImpl.java:27) ~[stash-platform-3.3.0.jar:na]
[INFO] [talledLocalContainer]   at com.atlassian.sal.core.transaction.HostContextTransactionTemplate.execute(HostContextTransactionTemplate.java:21) ~[sal-core-2.12.4.jar:na]
[INFO] [talledLocalContainer]   at com.atlassian.upm.core.install.PluginArtifactInstallerImpl.installPlugins(PluginArtifactInstallerImpl.java:49) ~[na:na]
[INFO] [talledLocalContainer]   at com.atlassian.upm.core.install.AbstractPluginInstallHandler.installSingleArtifact(AbstractPluginInstallHandler.java:94) ~[na:na]
[INFO] [talledLocalContainer]   at com.atlassian.upm.core.install.JarPluginInstallHandler.installPluginInternal(JarPluginInstallHandler.java:47) ~[na:na]
[INFO] [talledLocalContainer]   at com.atlassian.upm.core.install.AbstractPluginInstallHandler.installPlugin(AbstractPluginInstallHandler.java:48) ~[na:na]
[INFO] [talledLocalContainer]   at com.atlassian.upm.core.install.DefaultPluginInstallationService.execute(DefaultPluginInstallationService.java:111) ~[na:na]
[INFO] [talledLocalContainer]   at com.atlassian.upm.core.install.DefaultPluginInstallationService.install(DefaultPluginInstallationService.java:87) ~[na:na]
[INFO] [talledLocalContainer]   at com.atlassian.upm.install.UpmPluginInstallationService.install(UpmPluginInstallationService.java:94) ~[na:na]
[INFO] [talledLocalContainer]   at com.atlassian.upm.core.rest.resources.install.InstallTask.installFromFile(InstallTask.java:123) ~[na:na]
[INFO] [talledLocalContainer]   at com.atlassian.upm.core.rest.resources.install.InstallFromFileTask.executeTask(InstallFromFileTask.java:38) ~[na:na]
[INFO] [talledLocalContainer]   at com.atlassian.upm.core.rest.resources.install.InstallTask.call(InstallTask.java:60) ~[na:na]
[INFO] [talledLocalContainer]   at com.atlassian.upm.core.rest.resources.install.InstallTask.call(InstallTask.java:34) ~[na:na]
[INFO] [talledLocalContainer]   at com.atlassian.upm.core.rest.async.AsynchronousTaskManager$1.call(AsynchronousTaskManager.java:78) ~[na:na]
[INFO] [talledLocalContainer]   at com.atlassian.upm.core.rest.async.AsynchronousTaskManager$1.call(AsynchronousTaskManager.java:73) ~[na:na]
[INFO] [talledLocalContainer]   at com.atlassian.sal.core.executor.ThreadLocalDelegateCallable.call(ThreadLocalDelegateCallable.java:42) ~[sal-core-2.12.4.jar:na]
[INFO] [talledLocalContainer]   at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334) ~[na:1.7.0_25]
[INFO] [talledLocalContainer]   at java.util.concurrent.FutureTask.run(FutureTask.java:166) ~[na:1.7.0_25]
[INFO] [talledLocalContainer]   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) ~[na:1.7.0_25]
[INFO] [talledLocalContainer]   at java.lang.Thread.run(Thread.java:724) ~[na:1.7.0_25]
[INFO] [talledLocalContainer]   ... 88 frames trimmed
[INFO] [talledLocalContainer] Caused by: java.lang.IllegalArgumentException: Plugin version '${git.commit.id.describe}' is required and must be able to be parsed as an OSGi version - MAJOR.MINOR.MICRO.QUALIFIER
[INFO] [talledLocalContainer]   at com.atlassian.plugin.osgi.factory.transform.stage.GenerateManifestStage.validateOsgiVersionIsValid(GenerateManifestStage.java:296) ~[atlassian-plugins-osgi-3.2.9.jar:na]
[INFO] [talledLocalContainer]   ... 30 common frames omitted

As you can see, even if I could get the output to be of the form "W.X.Y.Z", it still wouldn't work because it isn't getting the substituted string, it is getting the version as "${git.commit.id.description}".  I want to control my versions without making commits to the pom.xml and generating a merge conflict between branches.  Is this just impossible with maven?  I noticed the stash source itself seems to do exactly this and make a horrific 118 line merge conflict any time they update their version (as of 3.3.0):

find . -type f -name 'pom.xml' | xargs grep -RHne '<version>3.3.0</version>' | wc -l
118


This seems "less than optimal"?

3 answers

1 accepted

Comments for this post are closed

Community moderators have prevented the ability to post new answers.

Post a new question

0 votes
Answer accepted
Carl Myers
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
January 23, 2015

OK, guys, I've figured out a better way, at long last!  Turns out maven has this profile bullshit which can be bent to your will if applied carefully.  See this excerpt from my pom.xml:


<profiles>
	<profile>
		<id>gitversion</id>
		<properties>
			<domainVersion>${env.DOMAIN_VERSION}</domainVersion>
		</properties>
		<activation>
			<property>
				<name>env.DOMAIN_VERSION<name>
			</property>
		</activation>
	</profile>
	<profile>
		<id>defaultversion</id>
		<properties>
			<domainVersion>0.0.1-DEV</domainVersion>
		</properties>
		<activation>
			<property>
				<name>!env.DOMAIN_VERSION<name>
			</property>
		</activation>
	</profile>
</profiles>

Now, if you run your build like this:

DOMAIN_VERSION=`git describe --abbrev=12` atlas-mvn ...

You will get what I suggested above - or if you don't want to use tags and instead want to use branches, you can even do this:

DOMAIN_VERSION="`git symbolic-ref HEAD | sed -e 's/refs\/heads\///g' | sed -e 's/\//-/g'`-`git log --oneline | wc -l`-g`git rev-parse --short=12 HEAD`" atlas-mvn ...

And of course, if you don't set DOMAIN_VERSION, you get the placeholder version, which is fine for dev/desktop builds.  Add DOMAIN_VERSION to your build scripts, season to taste.

You get the idea.  No more "commits just to make tags" bullshit.  No more "commits just to update a version number in your pom".  FINALLY.

The entire rest of the maven world:  start using this.  seriously.  your welcome.

Or stop using maven.  That'd work too.

 

1 vote
brainicorn
Atlassian Team
Atlassian Team members are employees working across the company in a wide variety of roles.
November 27, 2014

You can't change the version of a module via a property set in a plugin. This is because maven has to load the project in the reactor before it can run any plugins, and to load the project, it has to determine the version of all of the modules.

Now, on the point about merge conflicts due to pom versions....  this is 90% of the reason I wrote the jgitflow-maven-plugin. It enables you to use the git flow workflow, and more importantly, avoids merge conflicts by tracking pom versions in your different branches and syncing them before merges.

It's also the only plugin that I know of that "reloads" an internal reactor when versions change instead of forcing you to use a second maven run or a separate checkout like the maven release plugin does.

Hope that helps.

-JD

 

Carl Myers
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
December 1, 2014

Well it helps a little, in that it solidifies in my mind that maven is a fucking travesty and has absolutely fucked this pooch in unspeakable ways. I tried to make the jgitflow-maven-plugin to work a while back and ran into all sorts of problems but it's been over a year so maybe I should try it again. I might accept this answer if followup if I have trouble. I still think storing version numbers in POMs checked in is broken beyond reckoning.

Carl Myers
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
January 4, 2015

So here is the deal. The jgitflow plugin is the best solution, so I am marking your answer correct, but this situation as a whole is pretty shitty. The best thing to be said is that it is 90%+ the fault of maven being a piece of shit, and gjit also being a piece of shit (more on that later). I finally managed to make it work for me by following this process. If anyone who gives a crap wants this travesty to live on in something more useful, like say the documentation, feel free to move this stuff to the jgitflow-maven-plugin docs (where it should have been anyways probably). First off, the documentation has no "getting started" steps that actually work unless you are very lucky and already know a lot about maven, and it gives you no background about running maven goals, etc. assuming all users must already know how maven's most archaic bits function. In case that is not true, I'll clarify. 1. To add the plugin to a project and use it, do this: a. As the docs DO faithfully say, add the plugin bits to your pom.xml including the configuration block in <plugins> b. As the docs FAIL to say, your version must end in "-SNAPSHOT", even though snapshots are a travesty and should be murdered. 2. Now, to do your first release, check out the master branch specified in your config (or it'll create one for you at whatever commit you have checked out -probably. or explode. or melt your face. or something), and invoke the "start release" target. a. You actually invoke the target named jgitflow-release-start with `mvn jgitflow:release-start`, which the docs assume you will figure out and say nowhere. Replace "mvn" with "atlas-mvn" if appropriate, or whatever you call your maven today. b. This plugin is going to change all your branches (and create them if they don't exist), whether you want it to or not, without asking. I highly recommend creating your master and develop branch in advance. If you aren't doing "real gitflow" and "just want it to shut the fuck up and work", just create develop and master and have them point to the same commit at the time you run the plugin. c. I highly recommend setting <offline>true</offline> so you can at least see what it is doing before it spreads shit to your real repos. You can delete the branches if you don't like it, and try again. e. So, if your version is "1.3.5-SNAPSHOT" and you tell it you are releasing "1.3.5", it will create releases/1.3.5 (if your prefix for release branches is "releases/") and update the pom to have a version of "1.3.5" there, and create a commit on your develop branch changing the version to "1.3.6-SNAPSHOT" (it asks you for that version as well, so you can set it). f. Yes, this is completely interactive. If you want to script it, you can pass -DcrazyLongFuckingRidiculousArgumentsForever for each thing so it doesn't ask, I presume, but I didn't bother. the docs on this part are actually ok. 3. Make any commits before your release, I guess, or whatever, who the hell actually does that? When don't you start and finish a release? Whatever. a. Invoke `mvn jgitflow:finish-release`. Have the release branch it created in the previous step checked out. It'll run a build and do all your tests and shit. b. THEN it creates a commit turning the version from 1.3.5-SNAPSHOT (in our example) to 1.3.5 in your pom, tags that commit as 1.3.5, and deletes the branch. c. THEN it merges the release branch back to master (even if there were NO CHANGES on it besides the poms), and btw, it might make whitespace changes to your pom too with all the bullshit it is doing. d. THEN it creates a commit to develop changing the version to be the same as master (the version you are releasing) to avoid merge conflicts!!!! e. THEN it merges master to develop f. THEN it makes yet another commit on develop changing the version BACK to the pre-merge state (in this instance, 1.3.6-SNAPSHOT). I can't even imagine what it does if more complex changes happen to your POMS during a milestone making this shit blow up, or god forbid you want to actually version a few modules separately in the same repo, or do anything outside the atoms-width narrow view that is gitflow. Let me just finish by saying "The real answer to my question is maven is a broken shadow of a dystopian build future where people have decided not only that you should be a clown, but they should prevent you from NOT being a clown, and it shows perfectly in this. You simply cannot do what I asked, but if one asks very nicely and doesn't do anything the slightest bit crazy, this plugin can help you just barely get by enough that the entire world will not rage quit maven and insist upon a build tool that doesn't suck so much, like ALMOST ANYTHING ELSE. Oh, so here's why jgit is at fault here. I lost about an hour trying to figure out what the EVERLOVING CRAP was going on when my build failed with the error that I had untracked and uncommitted changes when I *TOTALLY DID NOT*. Turns out that `jgit status` and `git status` did not agree. If you get that error and are confused, you should grab the jgit CLI jar and try invoking "java -jar path/to/jgit-cli.jar status" and see if it agrees with git. If it doesn't, you probably need to touch (or untouch) or delete then reset --hard some files or something. Check mtimes, check case sensitivity if you are a poor poor fool on a case-sensitive filesystem (don't do that), etc. This too should be added to the docs for the jgitflow maven plugin if you have the slightest bit of care for the users of the plugin actually accomplishing anything instead of debugging working directory state all day. (or you could file a bug against jgit, whose fault that particular detail most certainly is) Sorry if this sounds harsh, but seriously - it's not your fault, it is how maven is designed, but this whole situation is infuriating, that the plugin just barely works enough that many people will not bother to *really* solve this problem.

0 votes
Carl Myers
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 10, 2014

According to this link: http://www.osgi.org/javadoc/r4v43/core/org/osgi/framework/Version.html#Version(java.lang.String) If I set my tag to "1.2.3.4", so the git describe output is "1.3.4.5-N-gXXXXXXX", the string will be a valid OSGi version becasue the qualifer is any string conposed of (alpha|digit|-|_)+

TAGS
AUG Leaders

Atlassian Community Events