Publishing Nightly Builds

Having users run “nightly” builds is a great way to get rapid feedback
on current development activities. One key way to get this kind of
feedback is to make it as easy as possible for people to install the
nightly builds, and to keep updated. The F-Droid tools now let you
automate this whole process for apps that are setup on GitLab CI.

The F-Droid nightly repos are built on top of the standard Android
~/.android/debug.keystore that the Android tools automatically
generate. That signing key is used to sign the nightly builds as well
as the repo index. This is meant to be easy to setup and manage, but
it does not provide the same level of security as a standard
F-Droid repo!

Since this is about smoothing the development process, it also makes
sense to reuse a shared debug.keystore among your team. That way,
all debug builds are interchangeable. This makes debugging certain
problems a lot easier since you can keep the app state when installing
your own debug builds, for example, to add logging.

Automatic Version Codes

With nightly builds, the normal logic for setting versionCode in git
for each release no longer makes sense. In order for Android to treat
each new build as a possible update, the versionCode must increase,
but that does not make sense to commit to git each time. So there
needs to be some automatic logic for setting versionCode:

git commit count (git rev-list --first-parent --count HEAD)
provides some hints of where in the code the build was made from

For many apps, some combo will make the most sense. For F-Droid, we
have a variable DB_VERSION for the internal database. We only
handle upgrading the database, never downgrading. So that needs to be
the most important part of the versionCode. Any build with
DB_VERSION = 77 should not be upgraded by any build with
DB_VERSION = 75. Then the minor part is the commit count, so it
looks like (7502543, 7502544, 7702601, etc). with DB_VERSION as the
first two digits, then a 0-padded commit count as the last 5 digits.

Configuring GitLab CI

This assumes that the app is already setup with .gitlab-ci.yml and
builds are running on GitLab CI. This also works for forks of the
main project that has the .gitlab-ci-yml.

Run fdroid nightly --show-secret-var in the local git repo that
is being setup, e.g. fdroid/fdroidclient. It will print out the
SSH Public Key. Using --show-secret-var will make it print out
base 64 text to be pasted into secret variable called
DEBUG_KEYSTORE. Careful! That text is the entire
debug.keystore, so protect it accordingly!

In that new project, add the SSH Public Key derived from your
debug.keystore as a Deploy Key in your Repository Settings, e.g.
https://gitlab.com/eighthave/fdroidclient-nightly/settings/repository

In the CI/CD Settings of the project being built, paste that into
GitLab CI Secret Variable called DEBUG_KEYSTORE, e.g.
https://gitlab.com/eighthave/fdroidclient/settings/ci_cd

Then in that same page, in the Protected section, set up your
master branch to limit the possibility of leaking the
debug.keystore. If master cannot be force-pushed, then any
attempts to get the stored secrets are permanently written to the
git history. Without that protection, someone with push access
could push a commit in a branch to print out the secrets, then
remove that commit to hide their actions.

Add a deploy stage to your .gitlab-ci.yml that produces only
the build to publish to the nightly, then runs fdroid
nightly. For example:

Set a GitHub Deploy Key for
https://github.com/zom/zom-android-nightly by going to
https://github.com/zom/zom-android-nightly/settings/keys. The
public SSH key is printed out by running:

fdroid nightly --keystore im.zom.messenger-debug.keystore

check Allow write access in the GitHub Deploy Key settings

To print out the secret variable contents, use --show-secret-var.
Careful! That text is the entire debug.keystore, so protect it
accordingly! This prints out base64 text to be pasted into a
Travis CI “Environment Variable” in
https://travis-ci.org/zom/Zom-Android/settings. Call the variable
DEBUG_KEYSTORE and make sure “Display value in build log” is
OFF.