Override URL to nexus repository specified in pom.xml - maven

I have web project which I am going to deploy to nexus repository after successful build on jenkins. Currently in project in pom.xml I have following configuration as below where host and port to nexus repository is hardcoded:
<profiles>
<profile>
<id>deploy-snapshot</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<distributionManagement>
<snapshotRepository>
<id>snapshots</id>
<name>Repository for snapshots</name>
<url>http://ip1:port1/nexus/content/repositories/snapshots</url>
</snapshotRepository>
</distributionManagement>
</profile>
</profiles>
My goal is override nexus url from jenkins without any changes in pom.xml, because currently that configuration in pom.xml is used on another environment which cannot be reconfigured.
It would be good to know in which way it can be done on jenkins taking into account that in future I am going to make similar for other job which will be in charge of deploying npm packages.
I've looked into following jenkins plugin https://wiki.jenkins.io/display/JENKINS/Nexus+Artifact+Uploader, but not sure that this one is actual one, also not sure that plugin will be good for zip archives for npm build.

That was requested in 2008(!) with Make the issue 295: "distributionManagement.site.url configurable from the command line"
In your case, check if passing the property altDeploymentRepository would help:
-DaltDeploymentRepository=...
More precisely, as in "Maven deploy:deploy using -DaltDeploymentRepository"
-DaltDeploymentRepository=releaseRepository::default::http://your.repo.url
"defaut" is the maven2 layout ("legacy" is for maven 1)

In order to overwrite it, you can set it in settings.xml file

In the version of Jenkins I'm using, which is ver. 1.602, if you configure your project as a Maven project, you can specify a "Deploy artifacts to Maven repostitory" post build action for which you can indicate the destination repository.

Related

GitHub packages: Single Maven repository for GitHub organization

I would like to use GitHub packages to store Maven artifacts for several repositories in a GitHub organization. Currently, it appears that for each project, a separate (Maven) repository configuration entry is required to point to that (GitHub) repository's Maven repository:
<repository>
<id>github</id>
<name>GitHub OWNER Apache Maven Packages</name>
<url>https://maven.pkg.github.com/OWNER/REPOSITORY</url>
</repository>
The corresponding configuration for the Maven project that would be published is:
<distributionManagement>
<repository>
<id>github</id>
<name>GitHub OWNER Apache Maven Packages</name>
<url>https://maven.pkg.github.com/OWNER/REPOSITORY</url>
</repository>
</distributionManagement>
Is there a way to configure the packages to all go to a single REPOSITORY? Setting the REPOSITORY to either a different existing or non-existing (GitHub) repository in the organization fails the build, as does removing the /REPOSITORY entirely
Personal Access Token
secrets.GITHUB_TOKEN is defined by default but it is only sufficient to deploy to the current repository.
To make it work across repositories you'll need to define a new Personal Access Token in:
Settings > Developer Settings > Personal Access Tokens.
Select write:packages for the scope and all the repo scopes should be automatically selected for you.
Repository / Organisation secrets
Next, define a secret in your organisation or each of the repositories you need to publish packages from.
Give it a name (i.e. DEPLOY_GITHUB_TOKEN) and set its value to the Personal Access Token created in the previous step.
Repository secrets are defined in repository Settings > Secrets. There's a similar section for the organisation.
GitHub Action
Finally, make sure you pass your Personal Access Token to the deployment step as an environment variable called GITHUB_TOKEN.
In the example below, it's set to the value of the DEPLOY_GITHUB_TOKEN secret defined in the previous step.
name: Build
on:
release:
types: [created]
jobs:
build:
name: Build & Deploy
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v2
- name: Set up JDK 1.8
uses: actions/setup-java#v1
with:
java-version: 1.8
- name: Build with Maven
run: mvn --batch-mode --update-snapshots install
- name: Deploy to GitHub
run: mvn --batch-mode -DskipTests -DuseGitHubPackages=true deploy
env:
GITHUB_TOKEN: ${{ secrets.DEPLOY_GITHUB_TOKEN }}
Since I used a dedicated Maven profile for the GitHub package repository distribution management, I also activated it with -DuseGitHubPackages=true.
Maven profile
In the profile example below, I configured distribution management to use the external/shared repository vlingo/vlingo-platform just like suggested in #Danny Varod's answer.
<!-- pom.xml -->
<project>
<!-- ... -->
<profiles>
<profile>
<id>github</id>
<activation>
<property>
<name>useGitHubPackages</name>
<value>true</value>
</property>
</activation>
<distributionManagement>
<repository>
<id>github</id>
<name>GitHub Packages</name>
<url>https://maven.pkg.github.com/vlingo/vlingo-platform</url>
</repository>
</distributionManagement>
</profile>
</profiles>
</project>
Cross posted from: https://dev.to/jakub_zalas/how-to-publish-maven-packages-to-a-single-github-repository-3lkc
A working example can be found in vlingo repositories: https://github.com/vlingo/vlingo-platform/packages
For people who are just looking to avoid specifying the <repository> tag multiple times:
Apparently, GitHub DOES NOT care about what repository you set when pulling packages from the Registry. When pulling, the package index is based on the organization level, not the repository level.
You can just do this if you want to pull packages from multiple repositories that are within the same organization:
<repository>
<id>github</id>
<name>GitHub OWNER Apache Maven Packages</name>
<url>https://maven.pkg.github.com/Your-Orgnazation/JUST-ENTER-ANYTHING-HERE</url>
</repository>
NOTE: You still need the Personal Token to pull the packages across repositories. You just don't have to specify the <repository> tag multiple times.
I solved this a while back by creating an empty repository named maven-packages or something like that and publishing all the Maven packages from all the organization's repositories to this one repository.
This enabled configuring a single Maven repository (in addition to Maven-central) locally, on build machine and in deployment environment for pulling Maven-library dependencies.
I don't have this code (was at a previous workplace and now I use Python), however, I recall using the mvn deploy command line for this as documented here:
mvn deploy:deploy-file -DpomFile=<path-to-pom> \
-Dfile=<path-to-file> \
-DrepositoryId=<id-to-map-on-server-section-of-settings.xml> \
-Durl=<url-of-the-repository-to-deploy>
and I modified the pom.xml during the build to insert the correct deploy repository's details, so the publishing could only be done via the build (and to add pre-release details to the pre-releases' version number). This also enabled adding an additional repository for external stable releases (to be published to Maven-central).
See configuration here.

Local Nexus Repository Acting Like A Proxy For Some Maven Artifacts

I am using my own version of the Nexus web app repository installed on my local machine. I have Nexus configured with only one repository, the one where I store my snapshots:
http://localhost:8081/nexus/content/repositories/MySnapshots/
Note that after the Nexus installation I removed all the default repositories and added just my own. (Perhaps this was a bad idea?)
When I do a mvn clean install I noticed that some of the 3rd party artifacts are downloading straight from the remote repository. For example, here is one of the output lines from the build:
Downloading: http://repo.maven.apache.org/maven2/com/sun/org/apache/xml/internal/resolver/...
The strange thing is that I see other artifacts are going through my local Nexus to ultimately get to the artifact:
Downloading: http://localhost:8081/nexus/content/repositories/MySnapshots/org/apache/maven/wagon/wagon-provider-api...
Notice how the first part of the download url is my local repository but everything after MySnapshots is from apache.org.
It's almost like my Nexus repository is acting like a proxy to maven.apache.org for some artifact downloads but for others it goes straight to the source.
Can anyone tell me why this is happening?
I would't be bothered so much by this if all my builds succeeded all the time but sometimes, when I am compile large projects, I get build failures due to not being able to find an artifact.
For example, when I try to build another project that depends on eclipse jdt stuff I get the following error:
Downloading: http://localhost:8081/nexus/content/repositories/MySnapshots/eclipse/jdt/core/eclipse.jdt.core
Could not find artifact eclipse.jdt.core:eclipse.jdt.core
I am not sure if this means that my Nexus is not configured properly or if there really is no artifact eclipse.jdt.com. If the downloads were not going through my local Nexus repository I would then investigate the pom/settings.xml files. Instead this makes me wonder if it's due to my Nexus configuration.
If you would like to see my settings.xml for Maven and my pom file for the project I am building when I see this you can view them here:
settings.xml: http://pastebin.com/NvLr5bEA
pom.xml: http://pastebin.com/PJ0P3RaK
If you like to use the local nexus as a proxy as usual than you have to configure the settings.xml like this:
<mirrors>
<mirror>
<!--This sends everything else to /public -->
<id>nexus</id>
<mirrorOf>*</mirrorOf>
<url>http://localhost:8081/nexus/content/groups/public</url>
</mirror>
</mirrors>
<profiles>
<profile>
<id>nexus</id>
<!--Enable snapshots for the built in central repo to direct -->
<!--all requests to nexus via the mirror -->
<repositories>
<repository>
<id>central</id>
<url>http://central</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<url>http://central</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
<activeProfiles>
<!--make the profile active all the time -->
<activeProfile>nexus</activeProfile>
</activeProfiles>
The tricky thing is the mirror thing which reroutes every call to the configured nexus instance.
Things you mentioned like eclipse parts can be problematic, cause only a few artifacts are available via maven central. Furthermore you should leave the defaults like maven central, release repository and the snapshots repository unchanged, cause these are the repository you need.
I don't think its a proxy issue , upto my understanding for the first case when it is downloading from Maven Central Repo , it might be possible that same artifact is not available in your nexus repository , that's why it is going to Maven Central Repo.
In the second case it is available in your nexus so reactor didn't try to download it from Maven Central Repo.

Maven release plugin deploy issue

My versions:
Maven 3.0.4
Jenkins 1.499
Nexus 2.2
maven-release-plugin 3.2
jdk 1.6
AIX 6.1
settings.xml
<server>
<id>snapshots</id>
<username>deploy</username>
<password>pass123</password>
</server>
<server>
<id>releases</id>
<username>deploy</username>
<password>pass123</password>
</server>
I have a lot of builds running in Jenkins which use the maven deploy plugin and upload artifacts to the Nexus repo. Since the same user is able to deploy snapshots we can eliminate user roles/permissions issue in Nexus. (I still gave admin role to this user for testing)
Company parent POM
<distributionManagement>
<repository>
<id>releases</id>
<url>http://myserver/repositories/releases</url>
<layout>default</layout>
</repository>
<snapshotRepository>
<id>snapshots</id>
<url>http://myserver/repositories/snapshots</url>
<layout>default</layout>
</snapshotRepository>
</distributionManagement>
Project POM
<scm>
<connection>scm:svn:http://svnserver/tags/1.2.3</connection>
<developerConnection>scm:svn:http://svnserver/tags/1.2.3</developerConnection>
</scm>
I have confirmed the /target/checkout/ in the Jenkins workspace contains the latest POM. Also added <distributionManagement> inside the project POM
Now when I run maven release plugin from within Jenkins using mvn release:perform I am still getting this:
Deployment failed: repository element was not specified in the POM inside
distributionManagement element or in -DaltDeploymentRepository=id::layout
::url parameter
release:prepare shows no errors
The SVN tag gets created as expected
Then during deploy, it fails with the above error
Like I mentioned, snapshot deployment happens frequently and without error, so settings.xml, distributionManagement and Nexus permissions all seem to be in order.
I am able to access http://myserver/repositories/releases manually
I have checked with mvn help:effective-pom and mvn help:effective-settings and things seem to be in order
Any ideas ?
The error message is very explicit. There is NO distributionManagement in your POM. So you potentially are no inherting from the parent pom.
Run
mvn help:effective-pom
in the project you are trying to deploy and check. Or alternatively look at the effective POM in your IDE (Eclipse or whatever).
Then figure out the correct parent pom to use or potentially insert the distribtionManagement segment as desired.

How to tell Maven to ignore a dependency if failed to resolve it?

I have a dependency which I have installed in Maven local repository and is being used locally but is not available on deployment server. I use that dependency using Class.forName(...) so there will be no problem if it's missed from classpath on deployment server.
Is there any way to tell Maven to ignore a dependency if it failed to resolve it?
I doesn't seem that <scope> or <optional> can solve this problem, but it may be possible to do it with <profiles> if there is any way to activate/deactivate a profile based on dependencies availability.
Short answer: no.
Long answer: Once dependency is declared - either in common part or in an active profile - it must be resolvable when Maven attempts it; otherwise the build fails.
If maven allowed the requested behavior, the reproducibility of build would suffer a lot.
If obscurity and irreproducibility is not an issue for you, here is a hint how to do it:
call external ant from your pom.xml, using either exec-maven-plugin or maven-antrun-plugin
in the ant code, use artifact:dependencies from Maven Ant Tasks
wrap it in ant-contrib's trycatch block
In any case, I strongly discourage including such things into maven build. Having it as separate functionality, invoked via ant from commandline, might often be enough.
assuming the missing dependency is only important in the local environment you can use a combination of profile and activation via your .m2/settings.xml
You remove the dependency from your general dependencies and move it as a referenced dependency into a profile of your pom.xml (Project level profile) and activate the profile through your m2/settings.xml.
You may also remove the dependency completly from your pom.xml and move the dependency into a profile which resides in your .m2/settings.xml (User level profile)
see the introduction to profiles section
another way which fits your needs maybe better
The activation of the above mentioned profile based on the presence of the file in .m2/repository/local/dependency/1.0.0-Snapshot/local.jar
<profiles>
<profile>
<activation>
<file>
<exists>/home/user/.m2/repository/local/dependency/1.0.0-Snapshot/local.jar</exists>
</file>
</activation>
...
</profile>
</profiles>
Bizarrely, I had a problem with maven where it would say "cannot resolve dependency" (of some weird transitive dependency that didn't exist anymore), but it only failed with that error message if my ~/.m2/settings.xml had a
got my jars from a local repository
<profiles>
<profile>
<id>nexus</id>
<repositories>
<repository>
<id>a name</id>
<url>http://somewhere/local/a</url>
</repository>
If I changed it to mirror, it would not fail.
<mirrors>
<mirror>
<id>a name</id>
<name>an awesome description</name>
<url>http://some/where/local</url>
<mirrorOf>external:*</mirrorOf>
(same repo). Go figure.
Please try to exclude the dependencies from the POM
<executions>
<execution>
<id>***failed dependency Id***</id>
</execution>
</executions>

Howto disable mirror repository in maven settings

In my maven ~./.m2/settings.xml I have defined a mirror and some repositories:
<mirrors>
<mirror>
<id>someid</id>
.....
</mirro>
</mirrors>
...
<profiles>
<profile>
<id>default</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<repositories>
<repository> <id>repo....</id>
....
</profile>
</profiles>
This works fine.
There are some projects where I want do disable the mirror and the default profile.
I know that i can define a seperate profile for the repositories, but i don't know how I can tell the maven eclipse plugin not to use the default profile or a specific profile.
Also: how can I change the mirror for a project?
Unfortunately this is impossible with single settings.xml. There is feature request in Maven JIRA, vote for this!
JIRA ticket MNG-3525
Pull Request to implement the feature
Workaround is to have two settings.xml and running maven with selected configuration:
mvn -s my-settings.xml
Copy the settings.xml file, remove the mirror entry and tell maven to use with the --settings file command line option.
Use XSLT or a command line tool like XMLStarlet to automate the process:
xmlstarlet ed -N 's=http://maven.apache.org/SETTINGS/1.0.0' --delete "//s:mirror" settings.xml
prints a new settings.xml file to stdout which doesn't contain any mirror settings.
Update: The XML namespace has recently changed. Make sure you use the same string as the one at the top of the file. Kudos to Roman Ivanov for pointing this out.
Multiple settings.xml is not necessary I think to do this.
It is possible to control mirrors using profiles.
I can use a property for my repository id for example a suffix ${repo-suffix}
$ mvn help:effective-pom | grep "<distributionManagement>" -A 3
<distributionManagement>
<repository>
<id>deployment${repo-suffix}</id>
<name>Internal Releases</name>
Then I can add repo-suffix to a profile for example to give it value -1.
<profile>
<id>my-profile</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<repo-suffix>-1</repo-suffix>
...
This way I now have a dynamically defined repository id in pom files.
$ mvn help:effective-pom | grep "<distributionManagement>" -A 3
<distributionManagement>
<repository>
<id>deployment-1</id>
<name>Internal Releases</name>
For these this deployment-1 repository I can define mirrors in my settings.xml. This is effectively the same as being able to put a mirror in a profile.
The entries in settings.xml applies to all the maven projects on the system and thus is not meant to be tailored for individual projects.
If you want different projects to have different profiles, then you should specify them in the project's pom. You need not have <profiles> section in your ~/m2/settings.xml.
As for <mirrors> they apply to repositories that you want to mirror. You can choose which repositories need to be mirrored, but not which projects should use the mirror and which should not. You can always run the project in offline mode, if you do not want it to download from a remote repository.

Resources