From 6c815c7b204e2bdba9011121123e00aeaadaff41 Mon Sep 17 00:00:00 2001 From: David Thurstenson Date: Wed, 11 Jan 2017 17:38:27 -0600 Subject: [PATCH] Adding info to automating android app build page --- Automating Android App Builds.wiki | 103 ++++++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 1 deletion(-) diff --git a/Automating Android App Builds.wiki b/Automating Android App Builds.wiki index acdfaf5..03ce2f8 100644 --- a/Automating Android App Builds.wiki +++ b/Automating Android App Builds.wiki @@ -79,8 +79,109 @@ The only things changed from the original are all in `ExecStart=`: Check the systemd-nspawn manpage for more info. +To start your container, run `systemctl start systemd-nspawn@containername.service`. Confirm it's running with `machinectl list` and `systemctl status systemd-nspawn@containername.service`. + ===Reference=== * https://wiki.archlinux.org/index.php/Systemd-nspawn ---- -(wip) +==Interacting With Your New Container== + +When your systemd-nspawn is booted, most interaction is done using `machinectl(1)`. I will only be covering what's necessary for this setup. Check machinectl's manpage for more detailed info. + +To get a shell: + +{{{class="prettyprint" +# machinectl shell user@containername +}}} + +This will bypass the login prompt, and start user's shell. If no user is specified, you will be logged in as root. + +The actual building is done by a script in the container. This means we need either a) a way to execute that script from outside the container, or b) put the script on a timer within the container. Since I don't want the container running the whole time, I opted for option A. This allows the machine to be started and stopped as necessary. + +To execute the script from outside the container: + +{{{class="prettyprint" +# machinectl shell user@containername /path/to/script +}}} + +Note: This path is relative to the root of the container, not of the host. + +All that's left is to make a service unit for this command. Here's how my unit stands at the time of writing: + +{{{class="prettyprint" +# /etc/systemd/system/build-aos-sync.service +[Unit] +Description=Build latest commit of AsteroidOS Sync +Requires=systemd-nspawn@asteroid.service +After=systemd-nspawn@asteroid.service + +[Service] +Type=oneshot +ExecStart=/usr/bin/machinectl shell thurstylark@asteroid /home/thurstylark/buildapp.sh +}}} + +This unit is set up to boot our container automatically by using `Requires=` and `After=`. This way, we don't have to manage how our container is started. This also enables us to manually trigger a build by starting this unit. + +The last part of the actual automation is done with a timer for our new service. It doesn't have to be super complicated, but you can tweak it how you like it: + +{{{class="prettyprint" +# /etc/systemd/system/build-aos-sync.timer +[Unit] +Description=Timer for automated AsteroidOS Sync build + +[Timer] +OnCalendar=daily + +[Install] +WantedBy=timers.target +}}} + +This timer is set for `OnCalendar=daily`, which will trigger every day at midnight. When the timer triggers, it will start our service, which will start our container if it's not already started, then it will run our build script. More options for this timer can be found in the `systemd.timer` manpage. + +---- +==Build Script== + +The last peice of the puzzle for this is to actually compile the app in question. Before any of this can be done or tested, your Android build environment should be set up. Check the Android Building page for more info. + +Here's the script I ended up with: + +{{{class"prettyprint linenums" +#!/bin/bash + +pkgname=asteroid-os-sync +project_root=/home/thurstylark/AsteroidOSSync +bind_mount=/home/thurstylark/output +output=$project_root/app/build/outputs/apk/app-debug.apk + +build_app() { + # Reference: https://developer.android.com/studio/build/building-cmdline.html + cd $project_root + git remote update + if [[ "$(git rev-parse @)" == "$(git rev-parse @{u})" ]]; then + echo "App up to date." >&2 + exit 0 + else + git pull origin master + rm -r app/src/main/res/values-ca-rES@valencia/ + ANDROID_HOME=/opt/android-sdk ./gradlew assembleDebug + fi + + copy_output +} + +pkgver() { + cd $project_root + printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)" +} + +copy_output() { + cp ${output} ${bind_mount}/${pkgname}-$(pkgver).apk +} + +build_app +}}} + +This script is not incredibly intelligent, but it gets the job done. One thing to point out is the test on line 11. This if statement checks whether our local copy of the git repo is up to date. If it's up to date, the script exits with a little message. This way we are only building if there are changes to be built. + +I also use `copy_output()` to rename the resulting apk with the revision number and short commit id (compiled using `pkgver()`) for clarity.