Battling Maven repository hosting
Write your post here.
title: Battling maven repository hosting date: 2014-08-08 08:53:07 categories: - Software tags: - java - note-to-self
Recently I've been working on a closed-source application for a client. It's an Android implementation of a recently invented card game, with both single player and multiplayer modes. I had to write a custom server for it (I chose the Play framework with Scala). The fact that the system had effectively two server implementations --- one for single player coordinating bots, and one for multiplayer --- combined with my lack of experience building such systems meant I created a lot of duplication when implementing the rules of the game.
There were two implementations on the client, one in the mp server, and one in a mp test client. Even though I'd written them in a TDD style and had a good test coverage, there was still a lot of ground for bugs to hide in. Bugs that differed between single player and multiplayer, etc. Worse was the time I'd misinterpreted one of the rules, and had to fix it in several places.
Eventually, I decided to create one library of rules to be used everywhere. The past few days I've been refactoring all the Java code in the client to use one rules package --- then yesterday I ripped it out into its own SBT project. That all went well --- until I sat down to decide where to host the jar artifact.
The entire code base is closed-source, so I couldn't conveniently upload it to Maven Central or some other free open-source host. I Googled around, and heard suggestions including hosting on GitHub, uploading via FTP to a web server, running a dedicated Maven repository manager, etc. I really didn't want to dump the artifacts on GitHub --- it's an abuse of git (and possibly a breach of the GitHub terms of service). And, for various reasons, the other options were not to my liking.
Then I remembered --- I have a Cloudbees subscription! Cloudbees offers free repository hosting (up to a certain size). I set up a repo in Cloudbees, then googled how you deploy from SBT. Very quickly I saw that SBT by itself cannot deploy files via WebDAV. So I found a plugin that could. Five minutes later, I get a dreaded message on the SBT console.
Unresolved dependency...
Its repository was down. I went and found another plugin, installed it, and punched in my Cloudbees details. Another message on the console:
Error uploading file... HTTP 405
I had to Google what an HTTP 405 was. Then I fought, playing with permissions on the Cloudbees repo, credentials on my local machine... but to no avail.
That took a good afternoon to work out that Cloudbees was not worth the effort this time. So I finally decided to try somewhere else. I still did not want to upload to GitHub, so I decided to try uploading to my shared hosting via FTP.
Possibly an hour later, I worked out my hosting provider (VentraIP) does not support SFTP --- only FTP, and SBT does not support FTP.
So I gave up. I deployed my artifacts to the Archiva hosted on my local machine. Thus, builds would never work anywhere but on my local Jenkins instance --- and my boss across the country couldn't compile the Android code to try it himself without considerable effort.
A few sad commit messages appeared in the BitBucket repo.
Then, for some reason, I recalled one more place to host a maven repo --- in an AWS S3 bucket. I googled for a plugin for SBT, immediately found one and installed it. After a bit of fiddling with credentials, the deploy succeeded. Clean console.
Yes! Finally! But can I get the artifacts back again? I opened the bucket to the public (security through obscurity) and put the address into the Android Gradle build. At first, it didn't work --- but it turns out you have to make folders trees explicitly public as well as the bucket itself. Gradle downloaded the library with no complaint, and not long after the server's SBT build did so too.
The commits were counteracted with "build now works globally," and I was finished.
Note to self: use S3 buckets for private maven repo hosting. The sbt-s3-resolver from frugalmechanic works really well.