-
Notifications
You must be signed in to change notification settings - Fork 37
Nexus \ OSSRH \ Maven Central
Every JIPP has a Maven settings file set up that specifies our local Nexus instance as cache for Maven Central.
Important
In Jiro this works out of the box for the default pod templates. No additional configuration is required for Freestyle and Pipeline jobs. For custom containers, see the following section.
You need to add the settings-xml
volume, as shown below. Please note, the m2-repo
volume is required as well, otherwise /home/jenkins/.m2/repository
is not writable.
Note
In custom containers the user.home
environment variable needs to be set to /home/jenkins
via MAVEN_OPTS, otherwise settings.xml
and settings-security.xml
can not be found.
pipeline {
agent {
kubernetes {
label 'my-agent-pod'
yaml """
apiVersion: v1
kind: Pod
spec:
containers:
- name: maven
image: maven:alpine
tty: true
command:
- cat
env:
- name: "MAVEN_OPTS"
value: "-Duser.home=/home/jenkins"
volumeMounts:
- name: settings-xml
mountPath: /home/jenkins/.m2/settings.xml
subPath: settings.xml
readOnly: true
- name: m2-repo
mountPath: /home/jenkins/.m2/repository
volumes:
- name: settings-xml
secret:
secretName: m2-secret-dir
items:
- key: settings.xml
path: settings.xml
- name: m2-repo
emptyDir: {}
"""
}
}
stages {
stage('Run maven') {
steps {
container('maven') {
sh 'mvn -version'
}
}
}
}
}
If your project does not have its own repo on Nexus yet, then open a HelpDesk issue and specify what project you'd like a Nexus repo for.
If your project does have its own repo on Nexus already, then you can use Maven (or Gradle) to deploy artifacts to repo.eclipse.org.
Note
On our cluster-based infra (Jiro), a separate Maven settings file for deployment to Nexus is not required. All information is contained in the default Maven settings file located at /home/jenkins/.m2/settings.xml
, which does not need to be specified explicitly in your job configuration.
You need to add the settings-xml
volume, as shown below. Please note, the m2-repo
volume is required as well, otherwise /home/jenkins/.m2/repository is not writable
.
Note
In custom containers the user.home
environment variable needs to be set to /home/jenkins
via MAVEN_OPTS, otherwise settings.xml
and settings-security.xml
can not be found.
pipeline {
agent {
kubernetes {
label 'my-agent-pod'
yaml """
apiVersion: v1
kind: Pod
spec:
containers:
- name: maven
image: maven:alpine
tty: true
command:
- cat
env:
- name: "MAVEN_OPTS"
value: "-Duser.home=/home/jenkins"
volumeMounts:
- name: settings-xml
mountPath: /home/jenkins/.m2/settings.xml
subPath: settings.xml
readOnly: true
- name: settings-security-xml
mountPath: /home/jenkins/.m2/settings-security.xml
subPath: settings-security.xml
readOnly: true
- name: m2-repo
mountPath: /home/jenkins/.m2/repository
volumes:
- name: settings-xml
secret:
secretName: m2-secret-dir
items:
- key: settings.xml
path: settings.xml
- name: settings-security-xml
secret:
secretName: m2-secret-dir
items:
- key: settings-security.xml
path: settings-security.xml
- name: m2-repo
emptyDir: {}
"""
}
}
stages {
stage('Run maven') {
steps {
container('maven') {
sh 'mvn clean deploy'
}
}
}
}
}
Deploying artifacts to OSSRH (OSS Repository Hosting provided by Sonatype) requires an account at OSSRH. It is also required to sign all artifacts with GPG. The Eclipse IT team will set this up for the project.
Please open a HelpDesk issue for this first.
Note
On our cluster-based infra (Jiro), a separate Maven settings file for deployment to OSSRH is not necessary. All information is contained in the default Maven settings file located at /home/jenkins/.m2/settings.xml
, which does not need to be specified explicitly in your job configuration.
If you are using a custom container, please see https://wiki.eclipse.org/Jenkins#Custom_container_on_Jiro_3**
Steps | Screenshots |
---|---|
1. Insert secret-subkeys.asc as secret file in job |
|
2. Import GPG keyring with --batch and trust the keys non-interactively in a shell build step (before the Maven call)gpg --batch --import "${KEYRING}"
for fpr in $(gpg --list-keys --with-colons | awk -F: '/fpr:/ {print $10}' | sort -u);
do
echo -e "5\ny\n" | gpg --batch --command-fd 0 --expert --edit-key $fpr trust;
done |
|
3. If a newer GPG version (> 2.1+) is used, --pinentry-mode loopback needs to be added as GPG argument in the pom.xml.<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
<configuration>
<gpgArguments>
<arg>--pinentry-mode</arg>
<arg>loopback</arg>
</gpgArguments>
</configuration>
</execution>
</executions>
</plugin> |
This is a simple pipeline job, that allows to test the GPG signing.
pipeline {
agent any
tools {
maven 'apache-maven-latest'
jdk 'adoptopenjdk-hotspot-jdk8-latest'
}
stages {
stage('Build') {
steps {
sh "mvn -B -U archetype:generate -DgroupId=com.mycompany.app -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false"
sh '''cat >my-app/pom.xml <<EOL
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>my-app</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
<configuration>
<gpgArguments>
<arg>--pinentry-mode</arg>
<arg>loopback</arg>
</gpgArguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
EOL'''
withCredentials([file(credentialsId: 'secret-subkeys.asc', variable: 'KEYRING')]) {
sh 'gpg --batch --import "${KEYRING}"'
sh 'for fpr in $(gpg --list-keys --with-colons | awk -F: \'/fpr:/ {print $10}\' | sort -u); do echo -e "5\ny\n" | gpg --batch --command-fd 0 --expert --edit-key ${fpr} trust; done'
}
sh "mvn -B -f my-app/pom.xml clean verify"
sh 'gpg --verify my-app/target/my-app-1.0-SNAPSHOT.jar.asc'
}
}
}
}
When you are using a custom container on Jiro, you will need to add the settings-xml
and settings-security-xml
volumes, as shown below.
Please note:
- the m2-repo volume is required as well, otherwise
/home/jenkins/.m2/repository
is not writable - the
toolchains-xml
volume is optional, but added for completeness - you also might need to add additional volumes like
volume-known
-hosts (as described here: https://wiki.eclipse.org/Jenkins#How_do_I_deploy_artifacts_to_download.eclipse.org.3F)
pipeline {
agent {
kubernetes {
label 'my-agent-pod'
yaml """
apiVersion: v1
kind: Pod
spec:
containers:
- name: maven
image: maven:alpine
tty: true
command:
- cat
volumeMounts:
- name: settings-xml
mountPath: /home/jenkins/.m2/settings.xml
subPath: settings.xml
readOnly: true
- name: toolchains-xml
mountPath: /home/jenkins/.m2/toolchains.xml
subPath: toolchains.xml
readOnly: true
- name: settings-security-xml
mountPath: /home/jenkins/.m2/settings-security.xml
subPath: settings-security.xml
readOnly: true
- name: m2-repo
mountPath: /home/jenkins/.m2/repository
volumes:
- name: settings-xml
secret:
secretName: m2-secret-dir
items:
- key: settings.xml
path: settings.xml
- name: toolchains-xml
configMap:
name: m2-dir
items:
- key: toolchains.xml
path: toolchains.xml
- name: settings-security-xml
secret:
secretName: m2-secret-dir
items:
- key: settings-security.xml
path: settings-security.xml
- name: m2-repo
emptyDir: {}
"""
}
}
stages {
stage('Run maven') {
steps {
container('maven') {
sh 'mvn -version'
}
}
}
}
}
Error message | Solution |
---|---|
gpg: signing failed: Not a tty |
GPG version > 2.1 is used and --pinentry-mode loopback needs to be added to the maven-gpg-plugin config in the pom.xml (see above). |
gpg: invalid option "--pinentry-mode" |
GPG version < 2.1 is used and --pinentry-mode loopback needs to be removed from the maven-gpg-plugin config in the pom.xml |
gpg: no default secret key: No secret key or gpg: signing failed: No secret key
|
GPG keyring needs to be imported (see above) |
To sign artifacts with Gradle, the following needs to be done:
-
Import the GPG Keyring as described above
-
Add the GPG Passphrase to the build with a secret binding (type: secret text, variable: PASSPHRASE). Please file a ticket to get the passphrase added to the Jenkins instance.
-
Use
GnupgSignatory
by callinguseGpgCmd()
in the signing tasksigning { useGpgCmd() sign <something> }
-
Use pinentry-mode loopback and no-tty config properties by appending it to
~/.gnupg/gpg.conf
-
Call Gradle with the following parameters:
-Psigning.gnupg.keyId=<key_id>
-Psigning.gnupg.passphrase=${PASSPHRASE}
-Psigning.gnupg.executable=gpg
See also: https://docs.gradle.org/current/userguide/signing_plugin.html#sec:using_gpg_agent
There are two ways of "releasing" from OSSRH to Maven Central.
- a) you can create an OSSRH account (https://issues.sonatype.org/secure/#!default.jspa) and ask for permissions for your user on the JIRA issue that was created when your project requested access to OSSRH. With the given permissions you can access the Nexus UI at oss.sonatype.org and release via the UI.
- b) you can release "headless" (e.g. with a build job) via the nexus-staging-maven-plugin (see https://github.com/sonatype/nexus-maven-plugins/tree/main/staging/maven-plugin#release, see also the rc-* CLI commands)
See also: https://central.sonatype.org/publish/release/#locate-and-examine-your-staging-repository