I started off my journey as a poor innocent developer thinking that the world of open source code distribution in the JVM would be simple. 2 days later and I just finally released code after setting up my own custom Maven server on a DigitalOcean droplet. To be fair I was too lazy to go through the whole process of setting up a Maven central repo. And some of you might have thought about Jitpack which would have been an option if I was doing standard JVM libraries, but I'm releasing Kotlin Multiplatform libraries and Jitpack builds your libraries on their server for distribution, which makes it so that building iOS binaries are not supported.
Every time I looked into how I could possibly distribute my libraries I found it to be such an uphill battle that I'd just quit. This most recent time I was determined. I figured there had to be a reasonable way to do it otherwise there wouldn't be like millions of libraries out there for Java. The God's honest truth is that sadly there is not a simple mainstream way.
After a long jacuzzi with my phone in hand reading every possible thing I could find on Maven, I, very fortunately, stumbled across this blog post which describes the awesomeness that is Reposilite. This is an awesome open source maven hosting website that you can self host. With the ability to run in docker, it's like a 3 minute process to get up and running. Huge kudos to the team that built it. Seriously it's the only project that actually seems to make some sense with the exception of Jitpack in the JVM dependency management ecosystem. How is Java a top 5 languages in the world and they have the most antiquated dependency management system.
I don't really want this post to be a tutorial on setting up Reposilite because they actually do a great job of explaining that in their docs, I do however want to cover a few supplemental elements that took me a little bit to find namely how to setup publishing properly in your project.
How to Configure Your Gradle Build for Publishing
Note: I'm not an expert on this, I am still learning, so if there's a better way feel free to let me know, but this is what worked for me.
When setting up a Kotlin Multiplatform library I have a block like this in my gradle.build.kts
. Do note this is Kts flavored Gradle not groovy, so your script might be a bit different.
plugins {
...
id("maven-publish") // needed to get the maven publish command
}
group = "com.somegroupname"
version="0.1.0" // this will be the version of your library when it's in your maven repo
// this is the block responsible for pushing your library up to your maven repo
publishing {
val mavenUser: String by project
val mavenPassword: String by project
repositories {
maven {
setUrl("https://yourDomain/releases")
authentication {
create("basic", BasicAuthentication::class.java)
}
credentials {
username = mavenUser
password = mavenPassword
}
}
}
}
Do note that the mavenUser
and mavenPassword
variables are coming from my ~/.gradle/gradle.properties
file. This way it's highly unlikely that you'd ever accidentally commit those credentials to a repo. and we use the delegate by project
as nice syntactic sugar to retrieve those values automatically.
with this configuration block added to your gradle build file you should be able to run the ./gradlew publish
command. Or you can do it from your IDE... However you prefer and this will push your library live.
Also note if you are running this on a non secured http server you have to add a bit more code on the side where you are trying to pull your dependencies. I wouldn't recommend having a non secure HTTP server, but if you are like me, and wanted to test things on localhost before deploying to a server it is useful to do so.
here's how to include it when over an unsecure http connection:
repositories {
...
maven("http://localhost:3000") { // or whatever port you set your local server to run on
isAllowInsecureProtocol = true
}
}