Speeding up jenkins builds - java

One of the most time consuming task Jenkins makes during every build is to download the artifacts into his local repository which it deletes.
While deleting my artifacts is fine. I don't understand the necessity in deleting 3rd party artifacts which were previously downloaded into it's local maven repository(.m2).
Is there any way to prevent Jenkins from deleting the local repository before build.
Thanks

You should install a Maven repository manager (MRM) like Sonatype Nexus, JFrog Artifactory or Apache Archiva and the downloads will be local to your network and very fast. Using a MRM is pretty much considered a necessity for any useful usage of Maven or any build tool with declarative dependency management since it allows you to cache artifacts as well as upload your own libraries and share them acros you developers as well as you CI builds.
If that is still not enough you can disable the private repository deletion per build or even use one shared repository per build, but that reduces the stability of the build since you are now mixing between builds and therefore introducing interdependencies.

While I agree with Manfred's recommendation to use a Maven repository manage I'd also recommend looking at how you manage the Maven local repository:
Prevent Jenkins from Installing Artifact to Local Maven Repository
When is it safe to delete the local Maven repository?
Ivy, Ant, Jenkins - Is it good idea to to a <ivy:cleancache> on Jenkins builds?
Maven does not normally purge the local repository, I'm guessing you have a periodic task that does this.

Related

Add jar into Maven project

I want to use this jar in a Maven project.
https://github.com/downloads/2checkout/2checkout-java/twocheckout-java-latest.jar
I know that the proper way is to add this jar into my local repository but I can't do this into every development machine. Is there any Maven plugin that can download this jar file and add it into my project?
There are only 3 options in a case like this:
Convince the people of the project to put their releases in Maven Central. See Guide to uploading artifacts to the Central Repository for more information on that.
Install a Maven proxy (e.g. Sonatype Nexus, see http://www.sonatype.org/nexus/) and upload the artifact manually. Each developer on the project can point to that proxy and will get the artifact.
Use the maven-install plugin to have each developer install the jar on his own local repository.
You can add below dependency into your pom.xml
<dependency>
<groupId>com.twocheckout</groupId>
<artifactId>twocheckout-java</artifactId>
<version>0.1.0</version>
</dependency>
The usual way to deal with this sort of situation is to use a shared repository such as nexus or artifactory. You configure the nexus repository to serve the locally-uploaded artifacts and you configure your pom to point to your nexus repository as one of the repositories where the artifact may be found. Then, you install the problematic artifact to the nexus repository (rather than every developer's local repository).
If desired, you can also configure your nexus to be a proxy for Maven Central (and all other repositories that you use) and have your pom configured to look only there. This results in a cache of all the artifacts that you use being held locally, which can improve performance and availability for your team (if they are co-located). This can be especially important if you have a dependency on a SNAPSHOT version that is stored in a remote repository.
The best way is to have a proxy repository installed in your corporate LAN and deploy these kind of jars in to "hosted" repositories. Then editing your settings.xml to have this as your repository.
The choice of local proxy varies from using a NAS based shared drive to using repository managers like 'Nexus' or 'Artefactory'.
This way you can easily distribute the artefacts across developers and all other users.

Android library to work with local maven repository

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

Maven - How to Install/Deploy timestamped SNAPSHOTS

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.

Using cached artifacts in Maven to avoid redundant builds?

I have a Maven 3 multi-module project (~50 modules) which is stored in Git. Multiple developers are working on this code and building it, and we also have automated build machines that run cold builds on every push.
Most individual changelogs alter code in a fairly small number of modules, so it's a waste of time to rebuild the entire source tree with every change. However, I still want the final result of running the parent project build to be the same as if it had built the entire codebase. And I don't want to start manually versioning modules, as this would become a nightmare of criss-crossing version updates.
What I would like to do is add a plugin which intercepts some step in build or install, and takes a hash of the module contents (ideally pulled from Git), then looks in a shared binary repository for an artifact stored under that hash. If one is found, it uses that artifact and doesn't even execute the full build. If it finds nothing in the cache it performs the build as normal, then stores its artifact in the cache. It would also be good to rebuild any modules which have dependencies (direct or transient) which themselves had a cache miss.
Is there anything out there which does anything like this already? If not, what would be the cleanest way to go about adding it to Maven? It seems like plugins might be able to accomplish it, but for a couple pieces I'm having trouble finding the right way to attach to Maven. Specifically:
How can you intercept the "install" goal to check the cache, and only invoke the module's 'native' install goal on a cache miss?
How should a plugin pass state from one module to another regarding which cache misses have occurred in order to force rebuilds of dependencies with changes?
I'm also open to completely different ways to achieve the same end result (fewer redundant builds) although the more drastic the solution the less value it has for me in the near term.
I have previously implemented a more complicated solution with artifact version manipulation and deployment to private Maven repository. However, I think this will fit your needs better and is somewhat more simple:
Split your build into multiple builds (e.g., with a single build per module using maven -pl argument).
Setup parent-child relationships between these builds. (Bamboo even has additional support for figuring out Maven dependencies, but I'm not sure how it works.)
Configure Maven settings.xml to use a different local repository location - specify a new directory inside your build working directory. See docs: https://maven.apache.org/guides/mini/guide-configuring-maven.html
Use mvn install goal to ensure newly built artifacts are added to local repository
Use Bamboo artifact sharing to expose built artifacts from local repository - you should probably filter this to include only the package(s) you're interested in
Set dependent builds to download all artifacts from parent builds and put them into proper subdirectory of local repository (which is customized to be in working directory)
This should even work for feature branch builds thanks to the way Bamboo handles parent-child relations for branch builds.
Note that this implies that Maven will redownload all other dependencies, so you should use a proxy private Maven repository on local network, such as Artifactory or Nexus.
If you want, I can also describe the more complicated scenario I've already implemented that involves modifying artifact versions and deploying to private Maven repository.
The Jenkins plugin allows you to manage/minimize dependent builds
whenever a SNAPSHOT dependency is built (determined by Maven)
after other projects are built (manually via Jenkins jobs)
And if you do a 'mvn deploy' to save the build into your corporate Maven repo then you don't have to worry about dependencies when builds run on slave Jenkins machines. The result is that no module is ever built unless it or one of its dependencies has changed.
Hopefully you can apply these principles to a solution with Bamboo.

maven - automatically build local dependencies

Currently my deploy workflow involves manually (i.e. in a script) cd-ing into each maven project directory and running mvn install. The problem is for local resources, i.e. other in-house code that I've written and am actively developing/maintaining, I don't know how to tell maven to build those resources itself when they are missing. Ideally each time I need to re-package the top level application it will rebuild any libraries it depends on that have at least one file modified.
If your (multi-module) project uses other in-house resources, what you actually need might not be to rebuild all those resources all the time, but to use a local maven repository. It can be a simple repository where resources are deployed using ssh or an HTTP transport (see the deploy plugin), or a real artifact manager such as Archiva, Artifactory or Nexus.
A repository manager does more than just hold your deployed artifacts, it can also clean the obsolete snapshots once the corresponding release has been made, and serve as a local cache for other repositories, including central.
Have a parent POM which contains all your modules. When you build the parent, all the modules that are part of parent POM file will be build as well.
You can inherit many things from the parent as long as you have the parent in your child.
Consider setting up Jenkins to automatically build your code. Jenkins has a useful feature that will rebuild projects that depend on newly built artifacts. Builds can be automatically triggered by simply committing your code.
If you're using several development machines (or working in a team) combine Jenkins with Nexus (Other options:Artifactory, Archiva) to provide a common store for shared artifacts. These tools are were designed to support Maven builds.

Categories