e-gineering / gitflow-helper-maven-plugin

An extension and plugin that teaches Maven to work well with gitflow projects and CI servers.
Apache License 2.0
76 stars 21 forks source link

How to resolve update of stage as dependency? #50

Closed darwink closed 7 years ago

darwink commented 7 years ago

Since you have release version in the stage deployment repository, if project A is on branch release/1.0, project B has project A 1.0 as dependency, how can developers of project B get the latest project A 1.0 locally? It's not snapshot version, so command mvn -U will not work, right? Any other option?

bvarner commented 7 years ago

I have my nexus repository setup to include the timestamp function on the stage repository.

I've not run into a situation with mvn -U doesn't resolve the newer build.

Are you asking before you try things out, or have you actually run into an issue here?

Edited: I don't have the timestamp set to 'true' on my stage repo.

darwink commented 7 years ago

Could you give me more detailed examples of your version number policy? I think the difference is the timestamp part, what you did to make it happen for the stage repository?

I'm using nexus as repository, too. Do you configure your stage repository as release maven repository that allows redeployment? If yes, how to update your local maven cache with same release version 1.0? mvn -U is only for updating snapshot packages.

See examples below: The first time run mvn clean package in projectB root directory will get the latest 1.0 version of projectA to maven local cache. Then run mvn deploy in projectA root directory to deploy a new 1.0 version to stage repository. Then the second time run mvn clean package in projectB root directory will not get the updated 1.0 version of projectA since the version is same. Maven local cache is not updated in the end. projectB dependency part of pom.xml: <dependencies> <dependency> <groupId>com.test</groupId> <artifactId>projectA</artifactId> <version>1.0</version> </dependency> </dependencies>

bvarner commented 7 years ago

I use the following definitions for my repositories.

<release.repository>foouser::default::https://nexus.host.name/nexus/content/repositories/releases::false</release.repository>
<stage.repository>foouser::default::https://nexus.host.name/nexus/content/repositories/test-releases::false</stage.repository
<snapshot.repository>foouser::default::https://nexus.host.name/nexus/content/repositories/snapshots::true</snapshot.repository>

Note the last parameter, the uniqueness field. I have release and repository set to not force things be uploaded as 'unique', unlike the snapshot repository.

If you have 'unique' set to 'true', it will append the timestamp to your nexus artifact version internally in nexus, and will keep more than one artifact at the given GAV. Maven clients will pull the most recent one.

If you have 'unique' set to 'false' it does not append the timestamp to the nexus artifact version inernally, and only hosts the one artifact at the GAV. Subsequent builds publishing to the same GAV will overwrite the existing artifact (which will have a new SHA).

My 'stage' repository is configured as a release repo that allows redeploy.

I then have all my nexus builds on my CI server using -U by default. Our development team mostly uses wrapper tools around maven, (and some of us weirdos like me) use shell scripts that wrap the normal 'mvn' command with a set of things to add to it.

I understand that your concern is that it only updates 'snapshot' repositories, but that's inaccurate (at least with maven >= 3.1) based on all my digging around (and practical experience). The documentation says:

 -U,--update-snapshots                  Forces a check for missing
                                        releases and updated snapshots on
                                        remote repositories

I totally understand where your confusion is with this wording. At least as of maven-core 3.1 the ArtifactResolutionRequest has a little method called setForceUpdate(boolean) this is set to the value returned by MavenExecutionRequest.isUpdateSnapshots(), which gets set to true if you -U on the command line.

So at the aether / remote repository resolution level, there is no difference between a 'release' and 'snapshot' remote repository with a force update. My experience has been that this includes validating the checksums on release artifacts. If you're actually seeing something different than this, it would be nice to see an example and necessary screenshots / logs to show what's happening. Otherwise the only comment I can offer is, 'I use -U on all my CI jobs. I use -U on my local invocations, and it's worked for me.'

bvarner commented 7 years ago

So this is where I get to eat some crow.

In actually testing this out today... -U doesn't seem to force the local repository to re-update the test release (stage) version. How strange.

One workaround I did find, is using the maven-depencency-plugin to purge and re-resolve the local dependencies. This had the desired effect, albeit it's a lot of network traffic & disk I/O unless you specify what it is you're trying to re-resolve.

My full command line looked like this: mvn dependency:purge-local-repository clean install

You can adjust the behavior of the purge-local-repository with the -Dinclude option to limit the purge to only your upstream dependencies using the gitflow plugin.

Perhaps what we should do, is have the build extension be aware of upstream gitflow dependencies, and purge those automatically if they resolve to the same remote repo as the stageRepo for the current project?

I'll be leaving this ticket open, since -U clearly doesn't do what I was hoping. All the upstream libraries I've been building with this plugin have very short release branch lifecycles (we don't do long running releases on those) and have avoided this issue up to now.

bvarner commented 7 years ago

The solution in 1.7.0 works well with CI servers like jenkins, and with remotely resolved dependencies. It also seems to play nice if I do a local build of the upstream release version and 'install' it to my local repo. (that local build becomes 'sticky', so I can test changes with the upstream project without other folks merging and having newer builds missing my changes resolving from the remote).

There's a bit of discipline that will be required from users if they expect to be doing local and remote development of upstream things. In which case, doing an explicit purge of the known dependency may be the right move. :-)