Remote builds with Gradle
If you have more bandwidth than processing power and memory,
it's very convenient to be able to compile Gradle projects
and even run tests on a remote server.
I've written a simple script called gradle-remote
that you can use in place of the gradle
command.
It will transparently upload your project to the remote server,
run the specified Gradle command and then download
the results back to your local build directory.
Since it uses rsync
to transfer files,
the file changes will be delta compressed – in practice the uploads
are very fast even for large projects.
#!/bin/bash # we need bash, not just posix shell for some types of expansions # search upwards in file hierarchy for build.gradle while [ "$PWD" != / ] && [ ! -f build.gradle ]; do cd "$(dirname "$PWD")" done if ! [ -f build.gradle ]; then printf '%s\n' 'No build.gradle file found' exit 1 fi remote="$GRADLE_REMOTE_SSH" if [ -z "$remote" ]; then printf '%s\n' 'Set GRADLE_REMOTE_SSH to a valid ssh login on your build server' exit 1 fi remotehome="$GRADLE_REMOTE_DIR" if [ -z "$remotehome" ]; then printf '%s\n' 'Set GRADLE_REMOTE_DIR to the place where projects will be stored on the server' exit 1 fi remotedir="$remotehome/${PWD////_}" set -e rsync -ircu --exclude build --exclude .gradle --exclude '**.swp' --delete . "$remote:$remotedir" # https://stackoverflow.com/questions/6592376/prevent-ssh-from-breaking-up-shell-script-parameters # ssh argument expansion is pure unfiltered cancer ssh -t "$remote" "source .profile; " gradle -p "$remotedir" "${@@Q}" " && mkdir -p $remotedir/build" rsync --delete -ircuq "$remote:$remotedir/build" . | (grep -v '/$' || true)
Configuration
The script is configured through environment variables.
Set GRADLE_REMOTE_SSH to a valid ssh login target. For example myserver.net or gradle_builder@example.com.
Set GRADLE_REMOTE_DIR to the base directory in which projects will be stored. You probably want a dedicated user on the server for running the builds, so something like "/home/gradle/projects" will work.
To prevent unused projects using up the disk space, I use a cron job which deletes all project directories older than the specified time.
0 * * * * find /home/gradle/projects -mindepth 1 -maxdepth 1 -type d -mmin +720 -print0 | xargs -0 rm -rf
I have aliased gradle
to gradle-remote
for my shell.
If you ever want to use the real gradle command,
you can invoke it as command gradle
which will bypass alias expansion.
TODO
- Some Gradle naming defaults will depend on the build directory, so it's not completely transparent. This could be fixed by using chroot and bind mounts.
-
The script requires Bash to be installed on client side (not server side). This is necessary to use the
"${@@Q}"
expansion which properly quotes the argument. Why couldn't ssh just give us an optional exec-like interface... :( It might be possible to do something clever using stdin but I'm not sure yet.