You are here

Building a continuous-integration Android build server on FreeBSD: Part two: configuring Gitlab-CI

Not so frequently asked questions and stuff: 

The FreeBSD logoImageImageImage

In this series of blog posts, we're going to create a Android build server for continuous integration on FreeBSD.

  • Part one will explain how to build Android APKs using Gradle on FreeBSD using the Linux emulation.
  • Part two (this post) will explain how to configure Gitlab-CI to be able to run builds automatically for each commit.
  • Part three will explain how to configure Jenkins to be able to run builds and email the APKs to people.

Step 1: Install, configure and register the Gitlab-CI runner

Most of the information of that step comes from the original documentation.

Create a nice user for the runner:

# pw group add -n gitlab-runner
# pw user add -n gitlab-runner -g gitlab-runner -s /usr/local/bin/bash
# mkdir /home/gitlab-runner
# chown gitlab-runner:gitlab-runner /home/gitlab-runner

Download the runner executable (or build it yourself (see the end of the post)), and mark it as such:

# fetch -o /usr/local/bin/gitlab-ci-multi-runner https://gitlab-ci-multi-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-ci-multi-runner-freebsd-amd64
# chmod +x /usr/local/bin/gitlab-ci-multi-runner

Create and chmod the log file:

# touch /var/log/gitlab_runner.log && sudo chown gitlab-runner:gitlab-runner /var/log/gitlab_runner.log

Create the rc-script (/usr/local/etc/rc.d/gitlab_runner):

#!/bin/sh
# PROVIDE: gitlab_runner
# REQUIRE: DAEMON NETWORKING
# BEFORE:
# KEYWORD:

. /etc/rc.subr

name="gitlab_runner"
rcvar="gitlab_runner_enable"

load_rc_config $name

user="gitlab-runner"
user_home="/home/gitlab-runner"
command="/usr/local/bin/gitlab-ci-multi-runner run"
pidfile="/var/run/${name}.pid"

start_cmd="gitlab_runner_start"
stop_cmd="gitlab_runner_stop"
status_cmd="gitlab_runner_status"

gitlab_runner_start()
{
    export USER=${user}
    export HOME=${user_home}
    if checkyesno ${rcvar}; then
        cd ${user_home}
        /usr/sbin/daemon -u ${user} -p ${pidfile} ${command} > /var/log/gitlab_runner.log 2>&1
    fi
}

gitlab_runner_stop()
{
    if [ -f ${pidfile} ]; then
        kill `cat ${pidfile}`
    fi
}

gitlab_runner_status()
{
    if [ ! -f ${pidfile} ] || kill -0 `cat ${pidfile}`; then
        echo "Service ${name} is not running."
    else
        echo "${name} appears to be running."
    fi
}

run_rc_command $1

Set the rc script as being executable:

chmod +x /usr/local/etc/rc.d/gitlab_runner

Register the runner with Gitlab-CI:

# sudo -u gitlab-runner -H /usr/local/bin/gitlab-ci-multi-runner register

Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/ci):
https://gitlab.example.com/ci

Please enter the gitlab-ci token for this runner:
sqzGW7_PgmarZ3FsSsUa

Please enter the gitlab-ci description for this runner:
[androidbuild]: Example Android build machine

Please enter the gitlab-ci tags for this runner (comma separated):
android
Registering runner... succeeded                     runner=sqzGW7_T

Please enter the executor: docker-ssh+machine, docker, docker-ssh, parallels, shell, ssh, virtualbox, docker+machine:
shell

Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!

Enable the runner service and start it:

# sysrc -f /etc/rc.conf "gitlab_runner_enable=YES" 
# service gitlab_runner start

Step 2: add the CI configuration to your Android project

Create a file named .gitlab-ci.yml and configure it to your needs.

before_script:
  - export LD_LIBRARY_PATH="/home/androidbuild/android-sdk-linux/build-tools/23.0.2/lib/"
  - export ANDROID_HOME="/home/androidbuild/android-sdk-linux/"

prod:
  only:
    - master
  script:
    - ./gradlew assembleRelease
  artifacts:
    paths:
      - Example/build/outputs/
    expire_in: 1 week

This example file will trigger a build when branch master is updaded, and it will save the artifacts for one week.

Image

Bonus: compiling the runner ourselves

If there's something I don't like, it's downloading executables from the internet when I can build them myself.
Let's build that Gitlab runner ourselves.

Install golang:

# make -C /usr/ports/lang/go install clean

Create a working go directory structure:

% mkdir -p ~/gowork/src/gitlab.com/gitlab-org/
% cd ~/gowork/src/gitlab.com/gitlab-org/
% setenv GOPATH ~/gowork
% setenv PATH "${PATH}:${GOPATH}/bin"

Get the code from Gitlab (checkout the version you want to build):

% git clone https://gitlab.com/gitlab-org/gitlab-ci-multi-runner.git
% cd gitlab-ci-multi-runner/
% git checkout tags/v1.5.2

Build:

% gmake deps docker
% gmake build_simple
% file "out/binaries/gitlab-ci-multi-runner"
out/binaries/gitlab-ci-multi-runner: ELF 64-bit LSB executable, x86-64, version 1 (FreeBSD), statically linked, not stripped

Install (as root):

# install -m 755 out/binaries/gitlab-ci-multi-runner /usr/local/bin/gitlab-ci-multi-runner

Done.