I recently had to setup a maven like repository for a client. Of course there are the standard hosted solutions with JFrog and Sonatype. These solutions work very well and both companies are very profession. However, managing the credentials is always tricky when you have different hosting domains. Since we were already using Github it is always simpler and more secure if you can use one security domain.
It turns out that Github provides a concept called packages. Packages provide storage space for dependencies. One of the type of packages that are supported is maven. I tried it out and it seems to work very well with bndtools.
To be able to release to a maven repository with the proper Maven metadata it is necessary to set the -pom
and -groupid
instructions. When this information is present, bnd will automatically create the required pom and other things that
Maven needs for a release. If you set the proper OSGi headers, then this metadata is of sufficient quality to
release to Maven central, including sources and javadoc.
Therefore, enter the following information in the cnf/build.bnd
file:
-pom: version=5.2.0-SNAPSHOT
-groupid: biz.aQute.bnd
If you remove the -SNAPSHOT
from the pom version, the artifact is released to the release repo. If the
-SNAPSHOT
is present, it will pushed to the snapshot repo. For this example, we make the snapshot and
release repo the same.
The Githun Maven package URL has the following structure:
https://maven.pkg.github.com/<userid or organization>/<repository>
Let’s define a macro in cnf/build.bnd
to not get caught in spelling errors:
releaserepo = https://maven.pkg.github.com/Bndtools/bnd
You need to create a repository. This is a Maven Bnd Repository. I recently added a ‘Insert Plugin’
menu entry in Bndtools when you’re in a bnd file. You can use this to insert a Maven Bnd Repository
in the cnf/build.bnd
file.
-plugin: \
... existing plugins
aQute.bnd.repository.maven.provider.MavenBndRepository;\
snapshotUrl ='${releaserepo}';\
releaseUrl ='${releaserepo}';\
noupdateOnRelease =true;\
name =Github
We need to provide bnd with the userid and password. Since we want to prepare this build for
a CI build, we use environment variables to parameterize them. Again in the build.bnd
:
pwd = ${env;REPOSITORY_PASSWORD;}
usr = ${env;REPOSITORY_USERNAME;}
We then need to setup the credentials for the communication:
-connection-settings: \
${if;${pwd};server;-dummy};id='${releaserepo}';username=${usr};password=${pwd}, \
-bnd
The last thing remaining in the cnf/build.bnd
file is to tell bnd what the release repo is:
-releaserepo: Github
To authenticate you need to create a Github token. You can create such a token at the
Personal access tokens page.
You need to create a personal token that can write packages
. This personal token is the password,
the user id is your Github user id. The token is only shown to you once. (On the Mac, you can store
them as a Note in your Keychain.) Before you run the Gradle build, you can set the credentials:
$ export REPOSITORY_USERNAME=<github username>
$ export REPOSITORY_PASSWORD=<github access token to write packages>
You can now test the releasing from command line:
$ ./gradlew release
Some remaining notes:
.m2/settings.xml
or .bnd/settings.xml
but a release should
always be done from the CI server to make sure it does not depend on the local system. This makes the
environment variables more useful.cnf/build.bnd
file you can also define it in a new file
in the cnf/ext
directory. If you do this, make sure to put a suffix on the -plugin
to make it
unique, otherwise it likely gets overwritten in another file that defines plugins. For example,
name it -plugin.github
. All files in the cnf/ext
directory are parsed included before the
cnf/build.bnd
file.