Skip to content

mavenCentral

For the first time in a long time I'm publishing a new library to public access. Last time, if I'm not mistaken, I published our Swift lib to CocoaPods, this was 2018, and back in distant 2015 I published an Android one to jcenter. So, I've never suffered as much as in 2022 with mavenCentral.

I'm clearly not the first at this party, I've heard about this from the community more than once, but I didn't think it would be this scary (though what was I even expecting). No, it's not that it's impossible to do, but it's impossible to do simply and beautifully.

For those who've never had such fun and don't understand what the point is. mavenCentral is such a de jure and de facto repository for Maven packages, alternatives to which for public packages don't really exist after the death of the aforementioned jcenter. Both Maven and Gradle naturally understand it out of the box, so the choice has been made for us. Actually mavenCentral isn't so much a repository as such a proxy to real repositories into which you need to publish builds. For example, top 1 mention in Google - Sonatype OSS Hosting Repository, Nexus for open source, in short. Well okay, let's go.

To be able to publish to it you need to:

  • Register in their Jira
  • Create an issue of type "Please register xyz.pavelkorolev.mylibrary" and throw in confirming links. Create an issue in Jira 2022 for the ability to publish a lib, huh? Okay, well clearly some automation works there.
  • A message comes from the bot, says "pavelkorolev.xyz is your domain?", confirm by adding a TXT record with the issue number in DNS. Is it really that important? Well okay, went and added.
  • Write a comment in this issue to reopen it.
  • The bot runs up, says everything is registered, issue closed. (And where to look for the URL for publishing, should I guess it?) At this moment a day has already passed - while you find everything, read and do it. Thank goodness they don't require a passport.

Okay, a place has been allocated for us, now you can insert some typical piece of code in Gradle and everything will work, I thought. Yeah, almost:

  • Add the maven-publish plugin, write a typical config with all data about the library, developer, repositories...
  • Go through all possible repository URLs from all articles, because that very single one wasn't written anywhere
  • (At this point the config is already growing, there's a desire to encapsulate all the publication logic somewhere, you spend time on this too)
  • Add the signing plugin, because mavenCentral is so secure
  • Generate GPG keys with God's help (how to do this on Windows nobody was interested in ever?)
  • Publish these keys on some well-known key servers (TIL such exist too)
  • Go through a bunch of options for how to insert this secret data into configs and not burn it in the repository
  • Learn that Gradle needs some things that GPG doesn't generate by default now, spend a day trying all options from the internet, turns out you can do it completely differently, with one mention in Gradle documentation

From the local machine gradle :lib:publish worked, lib published. Hurray hurray! What's funniest - publishing a lib is not enough, you need to close it (do what?) and release it. And this is done from the Nexus web interface with two separate buttons. You can use a special nexus-publish-plugin, but it didn't work for me right away, and I thought that for such a small lib using a whole special plugin is overkill, so I dropped this idea for now. Maybe I'll come back.

What's even funnier - releasing a lib in Nexus is not enough, you need to make it so information about it syncs to mavenCentral. And how to do this? Very simple, you need to go to that same closed issue in Jira and write something like "Please enable sync to mavenCentral" in free form. Here obviously there's no smell of any automation due to free form, Sonatype, is everything okay with you there? After some time your "request" is processed and approved. The lib finally reaches mavenCentral.

(Here's also a story that I needed to publish a fatJar with all dependencies and how I spent another day on this until I found where to prop it up with a crutch)

Well, and you want it really beautifully, I decide to write a Github Actions pipeline that will do publish itself when I push tags to commits. Another day passed. Went through a couple dozen different solution options, it didn't like my secrets with keys (moreover locally everything worked exactly the same way), finally it worked on Actions too.

Every step is pain, every step is dozens of attempts to guess how everything should look in your setup, documentation both from Sonatype, Gradle, and Github doesn't save. In this war with infrastructures the scariest thing is how long and low-quality your feedback is. You either wait for hours for endless builds and synchronizations, or you solve some 401 error when actually an artifact with the same version already exists, or something else. Of course, professionals will come and say that everything in this process is obvious. I'll agree, when you do it once - it becomes a bit easier, but it's still many times more complex than it should be, by feel.

Notably, at such moments you learn the most. The problem is only that you learn where to lay straw and which path to go so that everything works.