Jenkins Pipeline Plugin -- getting and building dependencies - maven

I'm brand new to Jenkins, and my searches are turning up so little that I think I just don't get the terminology yet.
I have a project I want to build with Jenkins Pipelines. It's a Java/maven project, in a GIT repository. It depends on two other Java/maven projects of mine, also in GIT repositories.
How do I explain this relationship to Jenkins?
Let's simplify. Say I have ProjectA that depends on ProjectB. I can get Jenkins to build ProjectB no problem. I can even archive the jar if I want, so a compiled copy of ProjectB is stored in my Jenkins server.
But no matter what I do, ProjectA fails to build with
[ERROR] Failed to execute goal on project ProjectA: Could not resolve dependencies for project ProjectA: The following artifacts could not be resolved: ProjectB:jar:0.9: Failure to find ProjectB:jar:0.9 in https://repo.maven.apache.org/maven2 was cached in the local repository, resolution will not be reattempted until the update interval of central has elapsed or updates are forced -> [Help 1]
This HAS to be super simple, I just can't figure out what I even need to search for.
My Jenkinsfile in ProjectA looks like this right now:
pipeline {
agent {
docker {
image 'maven:3-alpine'
args '-v /root/.m2:/root/.m2'
}
}
stages {
stage('Build') {
steps {
build 'ProjectB'
sh 'mvn -B -DskipTests clean package'
}
}
}
}

Project A is independent of Project B. Archiving them in Jenkins does not put them anywhere that Maven can recognize and use them as a dependency. You have to make sure your maven job knows how to find them. There are a couple options.
You could publish to a repository like artifactory. Then Maven just needs to be configured to look at that repo.
You could use the Jenkins REST API, or even just the uri to find and download the artifact into the workspace if your new build.
You can use the Copy Artifact plugin to pull the artifact from another build into your workspace so you can use it.
Or, since it is a pipeline, you can build both pieces in different stages of the same pipeline.
If the libararies you are building in Job B are only specifically used for job A, I would consider just building it all in the same pipeline. But sometimes it still makes more sense to use some kind of external repository to publish your libraries, then just configure maven to look at that repo to find your dependencies. I usually would use that option, but it does take more software and more setup.

Related

Multi-Module local jar dependencies - Jenkins Pipeline

I need to build a Java project on Maven. I am working on a multi-module Maven project that's built on the Jenkins Pipeline in the Nexus repository. I have a few libraries that are not available on the Nexus repository. I can't manually upload the libraries. I am building this project on a pipeline.
What I did:
I created a folder named jars in the project root of the Git hub repository and manually put all the jar files that are not available on Nexus. In the dependency, I referenced all these local jars as in the dependency parameters.
In the repositories, I gave the URL of the git hub repo of the jar folder. The Jenkins were not able to pick the libraries. I am getting the following error: dependency: dependency version - Build Error - Could not build for non-released dependencies and I am getting an error for all the jars that are in the jars folder. I tried putting the jars folder in src/main/resources but still getting the same error.
How can I reference this jar folder so that the Jenkins Pipeline can take it? I don't have control over the Jenkins / Scripts that are involved. I am a developer just building it on the Pipeline.
P.S: I don't have access to the internet at my company to post the POM or Build Failure errors.
Adding more details:
It's built on the Pipeline. There are two repositories: Nexus 2 and Nexus 3. The particular libraries are not available on Nexus 3 and pipeline takes the build only on Nexus 3.
We have raised a request to upload those libraries but it's not going to happen anytime soon. The Jenkins Pipelines takes it's files from the Github repository and builds the Java project using Maven. I don't have control to a pipeline or any of the scripts in Jenkins.
We downloaded all the libraries that are not available and put that in a folder in git hub. There are 4 cycles in the Pipeline. Github Cycle / Jenkins Cycle / Deployment Cycle / Release Cycle.
Github Cycle: In this cycle, it follows three stages. It takes the code from the code, builds it. It builds the snapshot and uploads it to Nexus repo. In these 2 stages, it was able to successfully build by taking the code from the GitHub and builds it and artifact generated. Third stage: It's really strange as in this stage, it again builds and build getting failed in this stage citing code for Non Released Dependencies for the jars that are uploaded in the git hub.
What might be the reason for this: When it can build in the first two stages of the Github cycle and getting failed in the third stage for Build Failure for non-released dependencies.
The pipeline is designed in such a way that it looks only on Nexus 3 and build during each phase of the cycle.
In the repositories, I gave the URL of the git hub repo of the jar
folder
That does not work because your lib folder is not a valid Maven repository.
How can I reference this jar folder so that the Jenkins Pipeline can
take it?
You have some options:
Set up custom Maven repository manager. You can use Nexus
Repository Manager or JFrog Artifactory or something else.
It will give you the greatest flexibility and allow to do a lot more
in the future. Downside is, you will need to have the infrastructure
to run this which usually comes with some sort of maintenance cost.
Install the bundles in Maven's local repo from the jar folder you already have. There are two ways you can do that:
Via script in Jenkins Pipeline that runs before your build and calls mvn install-file ... for each library in your jar folder. You can find the exact syntax for this command on Apache Maven Install Plugin site
By changing your build and calling the install-file goal of the maven-install-plugin in earlier build phase. I've personally
never done that but this answer suggests it's possible.
remove the files from the jar folder and create a wrapper project for each of them which does nothing but install the jar in
the local maven repository. Make sure those are the first modules to
run in your multi-module project.

How to build dependent projects using Bit Bucket pipeline

I am trying to get my build working with pipeline using maven . I have two bit bucket repositories for two maven projects. repository1 -> project1 repository2 -> project2. project2 has dependency on project1. Now I dont have problem in building project1 as it doesn't has dependency on any projects. But when I try to build project2 using pipeline build is failing because maven is not finding the project1 artifact.
I got to know that every pipeline runs within a docker image. So my guess is that pipelines for project1 and project2 are running in 2 separate docker images. Because of this when I run pipeline for project2 maven is not finding project1 artifact in local repository. One way to fix this is hosting a maven remote repo for my project artifacts and adding the repo in POM of project2. But i don't want to host a maven repo. I want maven to pick the artifact from local repo. How to get this working?
I'm sorry that no one ever answered this question for you. Setting up BitBucket Pipelines to use private maven repositories requires you to create a custom settings.xml file in the pipeline and then invoking maven with that file specified.
You can't just put a settings.xml file in your source code repository as it would put your credentials at risk. Instead, you can create a settings.xml file and set credentials from BitBucket Pipelines Secure environment variables.
It's pretty straightforward once you see it in action. I actually wrote an extensive guide on how to completely setup BitBucket Pipelines with Maven repositories that shows specifically how to do this in a secure manner.

How to fail a Maven build if a certain artifact already exists

How can I fail the build if a certain artifact does exist in the repository? The Maven Wagon Plugin has an "exists" goal, but not the opposite.
The reason for my question is as follows.
My Maven project goes through an automated build pipeline, which ends in a release stage. This stage performs an automated release through a mvn deploy -P release, after setting the release version with a mvn versions:set -DremoveSnapshot. The stage is triggered manually (since not every push should result in a release).
The mvn deploy will fail if the artifact to be uploaded is already in the repository. But this failure would come very late, during the last stage of the pipeline, while existence in the repository could be checked much earlier.
In order to get fail-fast behavior I would like to check if the artifact that would be released has not already been uploaded to Nexus. I want to do this in the first stage of the pipeline, which only performs a mvn package -P releasable. Preferably the "releasable" profile would make Maven do this check automatically during the "validate" phase of the default lifecycle.
The mvn deploy will fail if the artifact to be uploaded is already in the repository
Note: only if you upload as a "RELEASE", not a "SNAPSHOT".
Your build could check first if that release version exists:
mvn dependency:get -Dartifact=g:a:v -o -DrepoUrl=file://path/to/your/repo
If that gav (group-artifact-version) does exists, then you don't proceed with the rest of the build.
To keep that in a pom.xml, you can use:
activation profile, activated by a properties.
said property would be set by a first build step (or even before in the lifecycle) call to mvn dependency:get using the maven-dependency-plugin task.
dependency:get simply puts the artifact in the local repository if it exists.
I'm not sure how to fail the build from that point, since checking the local repo is not good enough.
You can check if the dependency artifact exists in the local maven repo.

Maven: how can I skip building artifacts which exist in central repo?

My situation: I have project which contains several Maven modules. I make changes to one of them. Suddenly I find out, that my project is no longer possible to be built because of the errors in other modules. To fix this I need to run SVN UPDATE and rebuilt the project.
My assumption: probably, during the build process of my module some of the artifacts are taken from central repository and have the most newest version, while others are still outdated and taken from my local repo.
A question: I don't want to rebuild my project each time someone updates ANOTHER Maven module. I want to download the already built artefacts from the central repository without rebuilding them by myself. Is it possible?
You can tell Reactor which modules to build. In your case when you only change a single module and want to speed up the build you can pass -pl (Project Location) parameter to maven. For example:
mvn -pl module-with-changes
That will build single module, while taking other dependencies from your local Maven Repository or download from Central (whatever is the latest). That said, if you already ran mvn install for whole project and other artifacts have not been updated in Central repository, then Maven will see your local artifacts as latest and will not re-download them.
Another issue you might get with -pl parameter is when other modules in your project depend on the module that you are building. If there is a problem in dependent module you will not see it by building only the dependency model. To avoid that you can pass -amd (Also Make Dependents). Like this:
mvn -pl module-with-changes -amd
That will trigger the build for module-with-changes + modules that depend on module-with-changes + their dependents.
You can get more info about Reactor parameters from here:
http://www.sonatype.com/people/2009/10/maven-tips-and-tricks-advanced-reactor-options/

How can I copy artifacts with all dependencies from one maven repository into another?

Here is my use case: I am building a project that can only read from Repository A. I have permission to add any artifacts I want into this repository, but I don't have administrative rights to manage Repository A. Unfortunately, this repository currently lacks most of the artifacts I need.
Copying artifacts with dependencies from repo1.maven.org into this Repository A using maven deploy:deploy-file is time consuming. Is there a tool that handles this problem for me?
I could even build a hybrid project (maven project with both repositories) for purposes of copying. But I am restricted to using Repository A for the production projects automated build and run.
I would do it in such way, that I would first create new repository for the project, filled with all artifacts needed to build it, and then I would write the script that would generate maven deploy command for each file inside, that not exists in Repository A.

Resources