Publishing/deploying artifacts to JFROG in multi module builds - java

I am working on a multi module project and trying to deploy them to JFROG.
Project Structure goes like this:
project
module-1
pom.xml
module-2
pom.xml
In the parent pom:
<modules>
module-1
module-2
<modules>
I have added <distributionManagement> and added the required details to connect to my artifactory.
Verified that there are no connectivity issues to Artifactory.
Module-1 gives com/abc/def/project/module-1/module-1.pom and com/abc/def/project/module-1/module-1.jar
Module-2 gives com/abc/def/project/module-2/module-2.pom and com/abc/def/project/module-2/module-2.jar
Requirement: I have to push the above pom and jar of both the sub modules to JFROG.
I am using goal - mvn clean deploy from my jenkins pipeline. However it is not working.

The best way to do that is to use the JFrog CLI. With that, you don't have to configure any resolution or deployment repositories in your pom.xml/settings.xml.
You can do that in 4 simple steps:
# Step 1: Install JFrog CLI
curl -fL https://install-cli.jfrog.io | sh
# Step 2: Configure the JFrog platform:
jf c add internal --url=https://acme.jfrog.io --user=jfrog_user --password=jfrog_password
# Step 3: Configure the Maven project
jf mvnc --repo-resolve-releases libs-release --repo-resolve-snapshots libs-snapshot --repo-deploy-snapshots libs-snapshot-local --repo-deploy-releases libs-release-local
# Step 4: Install and publish your Maven project
jf mvn clean install
Additionally, it is recommended to save the build-info in Artifactory.
To do that, set the JFROG_CLI_BUILD_NAME and JFROG_CLI_BUILD_NUMBER environment variables before step 4 and run jf rt build-publish in the end.
Read more:
QuickStart Guide: Maven and Gradle
Running Maven Builds
JFrog CLI Documentation

Related

maven deploying 3rd pom's without jar to nexus repository

When I want to deploy 3rd jars to my nexus 3 repository I use this command:
mvn deploy:deploy-file
-Dfile=<path-to-jar>
-DpomFile=<path-to-pom>
-DrepositoryId=<id-to-map-on-server-section-of-settings.xml>
-Durl=<url-of-the-repository-to-deploy>
but this command works only on jars with pom, and there is many artifacts that have only pom without jar, so i am looking for a way to deploy only pom without a jar file. My maven version is 3.3.9
mvn deploy:deploy-file
-DgroupId=com.xxx.xxx.xxxx
-DartifactId=xxxxx
-Dversion=x.x.x
-DgeneratePom=false
-DrepositoryId=nexus
-Dpackaging=pom
-Dfile=D:/xxx/xxxxx-x.x.x.pom
-DpomFile=D:/xxx/xxxxx-x.x.x.pom
-Durl=http://xxx.xx.xx.xx:8081/repository/thirdparty
-Dfile, is mandatory for Maven deploy-file. Therefore you have to specify a file.
In this case, you can point the same pom file for both -DpomFile and -Dfile.
This works in Nexus OSS version 3.23.0-03 with Maven 3.5.2

Why Maven doesn't install dependencies in multimodule project?

My project structure (multi module) is like this
parent
projectA
projectB
... other modules
parent also actually has a parent (Spring Boot).
I have set up a Jenkins jobs to compile & test on every commit, so it runs:
mvn -f pom.xml clean install
And that all works fine. ProjectB depends on ProjectA (which is like a common classes type of project) and is a Spring boot application. So the dependency information is the regular:
<dependency>
<groupId>Group</groupId>
<artifactId>ProjectA</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
ProjectB has a separate job in Jenkins to build the deployable jar file and deploy it to server. So the command there is:
mvn -f ProjectB/pom.xml clean install antrun:run
This fails with a message like:
[WARNING] The POM for Group:ProjectB:1.0-SNAPSHOT is missing, no dependency information available
...
[ERROR] Failed to execute goal on project host-api: Could not resolve dependencies for project Group:ProjectB:1.0-SNAPSHOT: The following artifacts could not be resolved: Group:ProjectA:jar:1.0-SNAPSHOT...
Now I can resolve this by doing a mvn install in the ProjectA directory - I've tested this and it does resolve the issue.
But my question is why should I have to? Shouldn't Maven figure out it should be installing the jar in the local repo?
Thanks in advance
TL;DR Tell maven about the structure of your project.
When you run the command
mvn -f pom.xml clean install
Then maven uses the reactor to work out the order of the modules, something like the following is output:
[INFO] Reactor build order:
[INFO] ProjectA
[INFO] ProjectB
So Maven first builds project A, then builds project B.
When you run the command:
mvn -f ProjectB/pom.xml clean install antrun:run
Then you have a problem; maven isn't starting from the parent - it's starting from a child. It's not told about the hierarchy of projects needed to be built first.
If you want to build a single project from a maven multimodule project, along with dependencies you should use:
mvn -f pom.xml -pl ProjectB -am install antrun:run
Where:
-pl ProjectB is the "project list" option, it tells maven to build these specific projects
-am is the "also make" option, it tells maven to build any projects that the projects in pl are dependant on
Specify the dependencies build part when you run the build:
Guide to Working with Multiple Modules
So I suppose the rule is, always build the parent project first and then run goals on subprojects afterwards.
The fix for me was to run clean install on the parent project first and then have a second build configuration in Jenkins that ran -f ProjectB/pom.xml antrun:run

Jenkins Deploy Artifacts to Nexus using Deploy to Maven Repository

We have a scenario to deploy the artifact generated from maven build to Nexus. The Jenkins job would run goals clean package. The artifact should go to SNAPSHOT repo if the pom.xml has a SNAPSHOT version. If the pom.xml has a release version, the artifact should go to release repo. Any idea how we can achieve this using the Deploy to Maven Repository plugin. As of now I am using the below script in Execute Shell.
#!/bin/bash
var1=$1
var2="SNAPSHOT"
if [[ $(echo "$var1"|grep -i "$var2" | wc -l | tr -d ' ') -gt 0 ]]; then
exit 1
else
exit 0
fi
In Flexible Publish post build action, I am using Execute Shell conditional action. Based on the result of the script, I would execute the Deploy to Maven repository post build action. This can only help to deploy to release repo. Any better way of doing it.
I assume that if you cannot update pom files in repositories, you have two options:
There is a Maven Project plugin, which allows you to add a new post-build action Deploy artifacts to Maven repository. It allows you to set repository URL and name, along with few other options. Setting repository with snapshot policy as a target one will result in successful upload of snapshot artifacts. Note that
the step is available only if build type is Maven build (2/3)
upload will fail with Bad request error if you try to upload release artifact
In case adding a plugin is not an option, you can use dirty hack and alter pom file on-the-fly as the first build step via something like sed. That's risky and should not be used if not absolutely inevitable.
To update all builds at once I'd recommend either use some plugin (Configuration Slicing plugin as an option) or alter config.xml files directly via script from CLI and then use "Reload configuration" in Jenkins.
I believe that this functionality is built into Maven itself; you can specify a different <repository> and <snapshotRepository> in your <distrobutionManagement> block. (See docs)

maven - using local source instead of external dependency

If someone could help me out here it would save me a lot of time.
I maintain an open source library that gets pushed out to a sonatype repository. I make changes to that library a few times a day and push it out to the 1.0_snapshot build using mvn deploy.
Let's call it project1
I work constantly in another project that uses that library let's call it project2.
Right now, whenever i make changes to project 1 or 2, i need to first build and deploy project 1 to the repo, then build project 2 so it downloads a fresh copy of project1.jar
Project2 has Project1 as a dependency in a pom.xml:
<dependency>
<groupId>com.group</groupId>
<artifactId>project1</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
in order to build in a way where all of my changes can be tested, I have to do something like this:
mvn -f ./project1/pom.xml clean deploy
mvn -U -f ./project2/pom.xml clean package
this uploads my project1.jar to sonatype, then project2 downloads the new snapshot and builds it.
This is a simplified picture of what i'm doing on a larger scale, where my compiles take 5 minutes of up and downloads.
Question: What is the proper way to use maven so it knows to use the source of project1 in a dependency in project 2?
IDE:
install m2e in eclipse
import your both projects into workspace
from consumer project (right click > maven > enable workspace resolution)
this will put project2's classes in classpath from its target/classes instead of the actual jar
native straight maven:
You can create a maven project tree, if this two are open source project going through same build cycle it must have one already, if they are not related but related for your usecase then you can temporarily create a maven tree on top of these 2 projects and build the top parent it will build from bottom up in one command
it will find the leaf project, build it install it in maven's cache and now while building projectA it will refer it from maven's cache so no need to deploy to sonatype
You can also point project2 to build using offline mode :
mvn -o package
Then you drop the upload part of the project1 build to the remote repo.
Check the following link: Intro to repositories and How do I configure Maven for offline development?

Jenkins build with differents maven repository

I have an Jenkins build machine with the follow situation:
1. MY_MAVEN_PROJECT
2. MY_MAVEN_PROJECT_BRANCH_1.0
3. MY_MAVEN_PROJECT_ nightly_build
All of these task use a common maven repository located in ~/m2./repository
The problem is that the all builds use the same maven repository,
when I execute the nightly build I’d like to remove also the maven repository, in order to have a very clean situation.
So I was wondering if it is possible to have an situation like this:
1. MY_MAVEN_PROJECT
|_ workspace maven repository (workspace/MY_MAVEN_PROJECT/m2./repository)
2. MY_MAVEN_PROJECT_BRANCH_1.0
|_ workspace maven repository (workspace/ MY_MAVEN_PROJECT_BRANCH_1.0/ m2./repository)
3.MY_MAVEN_PROJECT_ nightly_build
|_ workspace maven repository(workspace/MY_MAVEN_PROJECT_ nightly_build/m2./repository)
Any help is appreciated
In Jenkins > maven build step > advanced settings, there is a checkbox that says "Use private Maven repository".
When this option is checked, Jenkins will tell Maven to use $WORKSPACE/.repository as the local Maven repository. This means each job will get its own isolated Maven repository just for itself.

Categories