I have a Project A which depends on Project B; both are internal projects in active development.
Say the latest Project A release is 1.1.2 which depends on Project B 1.1.1.
Now we are developing Project A 1.2.0 which depends on the Project B 1.2.0 also in development.
<dependency org="my.org" name="projectB" rev="1.2.0" transitive="true" conf="..." changing="true"/>
New intergration builds for Project B 1.2.0 are pushed by the CI server in the common local repository, so thanks to "changing" everyone gets the latest integration builds as soon as they are published.
Say Bob is developing a new feature on Project A which requires some modifications to Project B; he publishes a new shapshot Project B 1.2.0 in his local private repository and his is picked up in the build because is more recent than the one in the common repository. So far all ok.
But if Alice commits something in Project B, the CI server pushes a new 1.2.0 on common repo, which is more recent than the one Bob has locally; now Bob gets the common version which overrides his local changes.
Of course I could use different names (using property files in a clever way that name does not have to end in ivy.xml), something like 1.2.0_snapshot for Bob, as long as Bob needs the local version, and then switch back to 1.2.0 when the common version is ok.
But isn't there a way to force using artifact whose status is "snapshot" (that will always be the status of local builds) over the ones which have "integration" (the ones produced by CI server will always have that status) or higher?
I tried "latest.snapshot" but it takes the integration version, if more recent.
What is the best way to deal with this pattern?
I think you want your local resolver to be in "force mode". Set the force="true" on your local resolver in ivysettings.xml.
See the description of force mode at: http://ant.apache.org/ivy/history/latest-milestone/settings/resolvers.html
Related
Me and my teammate are using Nexus repository to store JAR files that are builded from develop branch before we test it and are ready to release the SNAPSHOT version.
This is our branch structure in the repository:
main - one branch, used just for production code
develop - one branch, used for pre-release code that should be tested before merging in main
feature_xyz - multiple feature branches that are created from develop and where xyz feature should be implemented. It is merged in develop branch.
Example
Imagine there is 2.5.0 released version of one Maven project. We will both create two different feature branches (feature_foo and feature_bar) from develop branch and change the version name to 2.5.1-SNAPSHOT. Me and my teammate want to test the code just locally on our machines, the code is unstable and should not be pulled by the other teammate. That is why we test it first locally.
THE PROBLEM
To run the code locally, we have to have JAR file for the 2.5.1-SNAPSHOT version of that Maven project locally on our machine. But that JAR file will be just built and pushed to the Nexus repository only from develop branch. So in order to test locally, we always have to push at least one new SNAPSHOT version to develop, in order for to Maven be able to download the JAR file from the Nexus repository locally. This code that is pushed to develop is never tested locally and therefore the second teammate should not download that JAR file on his machine. That other teammate is working on 2.5.1-SNAPSHOT version too and that code might be unstable as well. The same problem, in order to test his features locally, he has to do the same as the first one.
Out goal is just to have JAR file downloaded to one teammate's machine with the SNAPSHOT version that he is working on but only with his features inside.
What we did?
We discussed about naming SNAPSHOT versions like this:
2.5.1-SNAPSHOT-1 and 2.5.1-SNAPSHOT-2 and to push them to the Nexus repository like that and use them locally on different machines to be able to test features. After everything is locally tested, we will merge feature_foo and feature_bar branches into develop using just 2.5.1-SNAPSHOT version.
Is there a better solution or in case this is one of them, is there any convention that describes how versions should be named in this case?
Let's assume that we have a project which uses Maven and has some dependencies which are developed in the same company/team or even by the same person. It is clear that when some developer wants to compile the project, the specified dependencies will be fetched from the repo and downloaded locally if they are not there yet.
Now let's assume the following scenario:
The developer does not care about the dependencies and
the version of the dependency is x.x.x.SNAPSHOT => maven will be fetching the latest version from the repo every 24 hours (by default). Problem: if this version is not compatible with your project, basically, you don't even know what happened because you did not change anything in your project. The only possible solution here is to compile and manage the dependency locally.
the version of the dependency is "x.x.x.y" => maven will fetch exactly this version and nothing else. So, to update this dependency I need to change the version. Problem: it seems that it means that every time when this dependency gets some changes and code is pushed to the server the version must be changed. But this sounds just ridiculous.
Possible solution:
It seems that the only possible solution in this case is to handle the internal dependencies manually (get the source from repo and compile locally). However, these two issues are bothering me:
This solution breaks the whole idea of maven which should fetch all the dependencies.
This solution will bring difficulties for the developers who just want to start development on the project, but do not care about those dependencies (because those dependencies are not used in the project part that they are working on).
Is there better solution?
You can also take care about latest stable dependencies by making your maven to work with your own administrated web repo. So you will be sure that all crew has a plugins,frameworks etc. of version needed. Our team uses TeamCity server for building workbanches, .m2/settings.xml is configured to work with our TC server repo as well. And team-lead is controling all versions.
I have an Android app which uses a library of my own. I am developing them at the same time so when I have a change in my library I want to test it in my app as well.
They are setup as different projects since my library will also be used by other developers. The way we work is we build the library using a CI platform adn deploy it to an artifactory server.
Then from the app I reference this library directly through artifactory. This way when my CI platform builds the app, the build process takes the lib from artifactory and CI works smoothly.
This is a good way to work but is a pain in the ass when developing them in parallel, because I have to commit the changes, create a pull request, merge it with the development branch and wait for CI to build it and deploy it on the artifactory server, just so I can test it on the app.
Coming from java EE development, I used maven install, which deploys the artifact in the local maven repo, then I could already use it from my web application.
I want to do soemthing similar, i.e. have gradle deploy my artifact on my local repo, so the artifact on the local repo is updated but not on the remote one. This way I can debug more easily while still keeping the CI setup in place.
But I have no idea how to do this on gradle. The artifactory plugin seems like it only allows deployment on an artifactory server.
any ideas?
If you're using the maven plugin, you can run the install task to deploy the artifacts to your local Maven repo [1]. After you have the Artifacts deployed to your local maven repo, you need to add mavenLocal() [2] as one of the repositories to be able to resolve the dependency. One strategy I use is to always set a custom version for my local copy so that I can be certain that the local version is getting picked up - but if you choose not to do that the dependencies get resolved in the order the repositories are listed (so you'll need to ensure mavenLocal is before your Artifactory server).
[1] https://docs.gradle.org/current/userguide/maven_plugin.html, https://github.com/dcendents/android-maven-gradle-plugin
[2] https://discuss.gradle.org/t/how-to-use-maven-local-repository-for-gradle-build/2244
Env : Maven 3.3.9
Hi,
I have a maven jar module with version as 1.0-SNAPSHOT. When i do mvn install, the jar installed into local repository (~/.m2/repository) does not have timestamp. I agree that its not a common scenario where you would like to have timestamped jars in your ~/.m2/repository repo. But still couple of questions:
Does mvn install append timestamp automatically? Looking for some
configuration way rather than use ${timestamp} in final name.
Does automatic timestamp mechanism applies to mvn deploy?
Is there a way to tell maven to use ~/.m2/repository
itself for mvn deploy?
Thanks,
Rakesh
The mvn install will only put your project into your local cache which means it makes it available for other projects on your machine.
mvn deploy will deploy the artifacts into your remote repository which is usually a corporate repository manager.
In case of a SNAPSHOT this means this artifact has not been finalized and is under developer. This means you can create several states of the same version like 1.0.0-SNAPSHOT. The time stamp which is created during the deployment to a repository manager is intended to have different artifacts available for development. You can control via -U option if you like to use the most recent version of the SNAPSHOT's.
After you feel ready you make a so called release which will set the version to something like 1.0.0 (without SNAPSHOT) which is deployed as well but into a release repository which is immutable.
Furthermore having timestamps in your local cache $HOME/.m2/repository does not make really sense, cause you can control when you install an artifact there and no one else and you should prevent using finalName change cause this is only intended for your target folder and not for your local cache.
And finally using the local cache for mvn deploy does not make sense, cause what is the idea behind that? Best is to start using a repository manager like Nexus, Artifactory or Archiva in particular if your are working in a corporate environment.
In addition to #khmarbaise's answer see the following references:
Maven / Introduction to Repositories:
There are strictly only two types of repositories: local and remote. The local repository refers to a copy on your own installation that is a cache of the remote downloads, and also contains the temporary build artifacts that you have not yet released.
Remote repositories refer to any other type of repository, [...]
Maven: The Complete Reference, 15.2.8. Repositories:
Repositories are remote collections of projects from which Maven uses to populate the local repository of the build system.
Repository - SNAPSHOT Handling reads:
This documentation was targetted at Maven 2.0 alpha 1. It is here only for historical reference and to be updated and integrated into the Maven documentation.
But I didn't find any latest documentation where this has been integrated. (#khmarbaise?)
Timestamped files are not created on install in the local repository for reasons of disk space preservation. However, when a SNAPSHOT is resolved and downloaded, it is saved with its timestamp version number (eg: 0.15-20050401.150432-2).
Understanding Maven Version Numbers
Maven Dependency Resolution - A Repository Perspective
Long story short:
The same snapshot version can be deployed to a remote repository from different hosts, so they have to be distinguished there somehow. And they are distinguished by timestamps (and a build number).
There will be an artifact with a timestamp (and build number) in the local repository only if Maven resolved and, hence, downloaded it from remote.
So:
No.
Yes.
Would break Maven's repositories handling of local vs. remote.
I recently migrated my NetBeans Platform (NBP) based application from Ant to Maven. I pretty much figured Maven out but there's one thing I still cannot get my head around, and that is the version system/convention.
It seems that everyone in the Maven world with a large Maven project consisting of multiple modules uses a parent pom in which they define a version, which is then inherited by all child pom's (i.e. all NBP Modules in Maven NetBeans RCP project).
For instance, take a look at the final result of the example project in the maven book:
http://books.sonatype.com/mvnex-book/reference/optimizing-sect-final-poms.html
You will see one version defined by the parent POM,
<groupId>org.sonatype.mavenbook.optimize</groupId>
<artifactId>simple-parent</artifactId>
<packaging>pom</packaging>
<version>1.0</version>
which is inherited by each child module, by specifying the parent and not using any tag of its own:
<parent>
<groupId>org.sonatype.mavenbook.optimize</groupId>
<artifactId>simple-parent</artifactId>
<version>1.0</version>
</parent>
and for its internal (within the project) dependencies each child module defines this relative to the project:
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>simple-weather</artifactId>
<version>${project.version}</version>
</dependency>
This means that you cannot update one module to a higher version because it will then look for dependencies with the same version number, which don't exist. Not to mention that using a separate version for any of your child modules gives you headaches when using the versions-maven-plugin because you end up micromanaging your dependencies.
This seems to completely go against the AutoUpdate / Lifecycle / Release philosophy of the NetBeans Platform. There I could update one module and generate a new updates.xml ("Package as NBMs") and when uploaded to an AutoUpdate repository, a client will see just that one update. It seems that if you do it the Maven way (mvn nbm:autoupdate), all modules get a version bump so that the whole model of auto updating via modules goes down the drain.
I hope I am mistaken and there is somewhere a feature to restore the great autoupdate functionality that comes with the platform, some kind of extra version number that automatically gets added to the major.minor.revision number or some intelligent way to override OpenIDE-Module-Specification-Version = major.minor.revision in between releases versions. Is there or do I have to release a new version of my application for each tiny update to a client module?
There is no silver bullet.
Keeping the version in one place makes sense when you are releasing the entire thing together eg. when your thing is a webapp. Then it's simpler to just keep the version intact as you are building and deploying stuff together. With Netbeans platform you should think in the same terms. If something is part of your base application you ship, make it the same version for the base app releases and only diverse for patches shipping to customers later on. That's more or less the model netbeans itself has adopted (in ant based codebase though but all modules get a version bump after a major release)
If a plugin or set of plugins is optional or works in multiple versions of the base app or works with multiple different applications put them in a separate repository with their own versioning.
Making a release of single module within a git repository for example (using maven:release) could bring problems of it's own. Eg. when maintaining multiple different branches (patches for older versions etc)
Play with the combination for a bit to see which things suit your workflow and release cycle.
Please note that the final assembly of the application is done in the nbm-application project and not the maven reactor. Maybe the easiest way to manage the dependencies would be to keep the nbm-application final assembly separate (separate maven build, separate git repository).
Keeping each netbeans module in it's own repository allows you to micromanage the versioning but you still need to update the module's pom during release but also as the nbm-application dependency to include the new version in auto update or application. Thus you can separate a plugin release from plugin deployment to customers which can be a good thing. These multiple steps can be automated in your CI server but do add complexity to your builds.
So your mileage may vary based on how your application gets distributed, how tight are your inter-module dependencies etc.