GitHub packages: Single Maven repository for GitHub organization - maven

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.

Related

Why are settings.xml and pom.xml are not directing Maven to deploy to Artifactory?

I am trying to point Maven to a local Artifactory (OSS) repo (both on my Mac) so I can build code provided by a vendor. I have created an empty Maven local repo and virtual repo in Artifactory, and can use Generate Settings to create the snippets. My ID and encrypted password seem to be working OK in ~/.m2/settings.xml
I have updated the code's pom.xml file and that seems to be causing Maven to resolve from Artifactory.
No matter how I configure in ~/.m2/settings.xml or in the master settings.xml or with -Dmaven.repo.local, Maven wants to deploy to a disk path to the local repo.
If I specify a partial path, Maven says "Using local repository at " a path consisting of the code's home + the path I said.
If I specify a path starting with a / (root), Maven says "Using local repository at /whatever"
I want to specify "https://localhost/artifactory/reponame" so Maven will deploy there. Artifactory generates snippets that contain that kind of URL. But since a URL doesn't start with a /, Maven insists on prepending the code home location to the URL, which of course is nonsense.
There must be some combo of and or <distributionManagement> <repository> <id>central</id> <name> <url>https://localhost/artifactory/... that makes this work. What am I missing?
pom.xml snippet:
<distributionManagement>
<repository>
<id>central</id>
<name>LocalMac-releases</name>
<url>https://localhost/artifactory/TBX</url>
</repository>
<snapshotRepository>
<id>snapshots</id>
<name>LocalMac-snapshots</name>
<url>https://localhost/artifactory/TBX</url>
</snapshotRepository>
</distributionManagement>
Master settings.xml snippet: localRepository is commented out so it takes the default. When commented in whatever I enter does take effect... combined with ${user.home}.
<!-- localRepository
| The path to the local repository maven will use to store artifacts.
|
| Default: ${user.home}/.m2/repository
<localRepository>/path/to/local/repo</localRepository>
-->

Cannot build Maven project module in CI due to unknown version in parent POM

I recently updated my Spring Boot apps development setup for a multi-module maven project
MainProject
AMQP
APIGateway
EurekaServer
Customer
Fraud
Then I have this structure in GitLab:
Group - Main Folder
Infra - Subgroup
EurekaServer - project repository
APIGateway - project repository
Services - Subgroup
AMQP - project repository
Shared - Subgroup
Customer - project repository
Fraud - project repository
Now I'd like to build the EurekaServer in CI but it needs to know where to locate the parent POM (which is only stored in my local machine). How can I configure this to GitLab so that succeeding build to other modules can lookup into the registry for the parent POM and other dependency modules? Should I create a repository only for the parent POM and pull that in the CI job?
I found this question during my research but this only works in local machine.
Maven Modules + Building a Single Specific Module
UPDATE:
I have this existing configuration for both the parent and module POMs.
<repositories>
<repository>
<id>gitlab-maven</id>
<url>https://gitlab.com/api/v4/groups/GROUP-ID/-/packages/maven</url>
</repository>
</repositories>
<distributionManagement>
<repository>
<id>gitlab-maven</id>
<url>https://gitlab.com/api/v4/projects/PROJECT-ID/packages/maven</url>
</repository>
<snapshotRepository>
<id>gitlab-maven</id>
<url>https://gitlab.com/api/v4/projects/PROJECT-ID/packages/maven</url>
</snapshotRepository>
</distributionManagement>
First, from the project root folder I executed this command to push the parent artifact into the registry
mvn deploy -N -s settings.xml and succeeded.
Next, build docker image for the module (AMQP). Here's the CI config
stages:
- deploy
push-to-registry:
stage: deploy
image: maven:3.8.1-jdk-11-slim
script:
- mvn deploy -s settings.xml
tags:
- configuration
and this is the error log
[FATAL] Non-resolvable parent POM com.xyz:services:1.0-SNAPSHOT for com.xyz.module:amqp:[unknown-version]: Failure to find com.xyz:services:pom:1.0-20220114.024427-3 in https://gitlab.com/api/v4/groups/GROUP_ID/-/packages/maven was cached in the local repository, resolution will not be reattempted until the update interval of gitlab-maven has elapsed or updates are forced and 'parent.relativePath' points at wrong local POM # line 5, column 11
Based on this documentation:
https://maven.apache.org/pom.html#Inheritance
Reference to local file is optional.
Notice the relativePath element. It is not required, but may be used as a signifier to Maven to first search the path given for this project's parent, before searching the local and then remote repositories.
So, you have to deploy the parent POM project first.
And after this, your sub-modules will be able to resolve the parent POM dependency.
Just make sure, there is access to the maven repository which stores parent POM.
Using GitLab Package Registry
If the project uses GitLab Package Registry for publishing artifacts, use
group-level-maven-endpoint
or
instance-level-maven-endpoint
for Maven repository configuration.
The project-level-endpoint configuration will not allow sharing artifacts.
Reference
https://docs.gitlab.com/ee/user/packages/maven_repository/

Override URL to nexus repository specified in pom.xml

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.

Deploy from Maven to Nexus got error: ReasonPhrase:Forbidden

http://numberformat.wordpress.com/2011/05/18/nexus-repository/
I am following the above link to setup Maven and Nexus, everything new. I couldn't left a new comment there so I post here.
After so long, I am in another company, when I tried to setup a simple sample in my local PC, I got this error in "mvn deploy" to the simple Maven my-app sample. I installed the simple Nexus Open Source w/o Tomcat.
[WARNING] Could not transfer metadata com.mycompany.app:my-app:1.0-SNAPSHOT/maven-metadata.xml from/to snapshots (localhost:8081/nexus/content/repositories/snapshots): Access denied to: localhosts:8081/nexus/content/repositories/snapshots/com/mycompany/app/my-app/1.0-SNAPSHOT/maven-metadata.xml , ReasonPhrase:Forbidden.
In your settings.xml located in MAVEN_HOME/conf you have to add in servers section
<server>
<id>nexus-releases</id>
<username>deploy</username>
<password>123456</password>
</server>
And in your pom must looks like
<distributionManagement>
<repository>
<id>nexus-releases</id>
<url>http://localhost:8081/nexus/content/repositories/releases</url>
</repository>
</distributionManagement>
Ids have to be the same.
Richard Seddon resolved my issue in nexus-users group.
Add this to nonProxyHosts:
localhost
You need to be authorized to run deployment. This is done by having the server section in your settings.xml. Check out the Nexus eval guide, specifically the publishing section and the sample projects in there for more detail.

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.

Resources