F-Droid Adventure

The Android port of Lagrange needed an F-Droid repository so automatic updates could be handled by F-Droid. This turned out to be quite an adventure.

Failure #1

I have no previous experience with any of this, so I went reading the F-Droid documentation. Aha, there's a tool called Repomaker that can be used to create your own app repositories and host them on Git or some other server. Great! I'll just go and download this... web app? Must be some sort of Electron thingy. Well, it's available on Flathub so I'll just grab that.

Except it doesn't run. Oh, you need to manually tell it to use the `org.gnome.Sdk` runtime when you launch the Flatpak. Weird, but OK, I guess. Now it starts, but there's a constant spew of log messages. Hmm.

I go in to add the APK and set the metadata, but then I hit a wall. Turns out, the Flatpak version is broken and it can't upload any files:

Failure #2

Ok then, Repomaker can also be run in a Python virtualenv. Great! I follow the guide, install the dependencies, and try to run the app, but it complains about a missing "webview" module and exits. Hmm. I guess some of the dependencies aren't right or are still missing, but I have no idea how to fix this.

Failure #3

On to the next option: Docker. After all, what could be a better solution to dependency problems than to distribute an entire disk image with everything included and run it in a virtual environment.

Now it begins to dawn on me how Repomaker actually works. It's literally composed of a packaged database/web server, running a Django Python app on top. You have to access it via "https://localhost/" using a web browser. This seems like extreme overkill to make a desktop app, but I suppose it was intended to be run online like a web site? Oh well, let's roll with it.

Now things seem to be going smoother. What would be a good Git service to host this on? Codeberg Pages, of course! I go to configure the Git storage in Repomaker and enter the details for my Codeberg "pages" repository.

And it fails. Repomaker does not seem to understand Codeberg at all, and does not let me set it as a Git storage.

Oh well, I'll just use GitHub... I create a new repository on GitHub ("skyjake/lagrange-fdroid") and finally manage to get something uploaded.

But hold on, I'm able to define multiple Git storage mirrors. This is neat, let's try GitLab, too. I add the new storage, but for some reason the repo contents never end up being uploaded to GitLab. The log output from Repomaker is full of GitLab authentication errors. Something went wrong... Fine, let's disable GitLab and just go with GitHub.

Now I have something that works so I announce it on Mastodon. But soon after people start hitting this bug:

Turns out, Repomaker left obsolete and incorrect repository mirror addresses in the metadata, causing F-Droid to randomly fail when trying to install the app. The only workaround is for everybody to manually disable the spurious mirrors in the Lagrange repository settings. This is quite unacceptable.

Failure #4

I'm trying to view the new F-Droid repository in a web browser, since that's the default way of sharing it so others can install it. But it doesn't work right because "raw.githubusercontent.com" only serves HTML as plain text. To serve a functional web page, you need to use GitHub Pages.

OK, then. Let's try to set up another F-Droid repository on "skyjake/skyjake.github.io". I enter the details in Repomaker but mind-bogglingly it manages to mangle the repository URL into "skyjake/skyjakehub.io". Is there some brain-dead string replacement to get rid of all ".git"s?

This is a dead end, too.

Success!

Obviously this Repomaker app is not the finest piece of engineering, but could there be a way to fix the metadata somehow? The user-facing UI provides no recourse here. But hey, this is a web app. I'll just dive into the database and see where's that incorrect URL.

I spin up an interactive Bash shell in the Docker image and run `psql`. After digging around in the tables a bit, I see where the URLs are stored. A couple of UPDATE commands should do the trick.

This actually does work! As long as I don't touch the storage configuration in the web UI, the corrected URLs seem to take effect. I can actually get data uploaded into the "skyjake/skyjake.github.io" repository, and it becomes visible at "https://skyjake.github.io".

But there's still those blasted extra mirrors in the metadata. How can I get rid of them? The mirrors don't seem to be defined anywhere in the PostgreSQL database. I guess it's time to go grepping through the Repomaker Python sources. Unfortunately, the searching doesn't turn up anything relevant.

Eventually I realize that the repository is actually managed by a Python module called "fdroidserver" that is installed as a dependency. I run another Bash shell in the Docker image and locate the sources of the fdroidserver module. Aha! Here in "/usr/local/lib/python3.7/dist-packages/index.py" it generates the metadata of the repository and retrieves the mirrors from... somewhere. But it doesn't matter. I'll just clear the mirrors list here and the metadata will be correct, since I don't need any mirrors.

But Docker images are read-only data. How can I edit this "index.py" file? The solution turns out to be issuing extra commands in Repomaker's "docker-compose.yml" configuration that is used to run the images. I end up adding a simple in-place "sed" invocation that forces `mirrors` in fdroidserver's "index.py" to be an empty list.

Now, finally, when I edit the app in the Repomaker web UI, it uploads the data to "skyjake.github.io" and it has the correct metadata. And even the web page works:

The End

While I did have some degree of fun digging around, none of this should've been necessary. There should be a simple CLI tool that you can use to manually generate the repo and upload it wherever you want. (Perhaps there is and I just didn't find it?)

Let's see how long this hacked-up Repomaker manages to keep working right...

📅 2022-01-11

🏷 Lagrange, Android

CC-BY-SA 4.0