#!/bin/sh
# This script installs a building environment using sbuild as a
# builder for the "gbp buildpackage" command line. The sbuild
# chroot uses an union FS (ie: AUFS in Jessie and Trusty,
# OverlayFS on newer kernels) as this is the fastest backend,
# and that unionFS scratch disk is stored on tmpfs, as this
# is the fastest way to run sbuild.

# Author: Thomas Goirand <zigo@debian.org>
# License: Apache-2.0

set -e
set -x

OSTACK_RELEASE=newton
BUILDER_SYS_USERNAME="jenkins"
BUILDER_HOMEDIR=/home/jenkins
GITREPO_ROOT=${WORKSPACE}

DISTRO_VENDOR=$(lsb_release --id -s | awk '{print tolower($0)}')
HOST_DISTRO_NAME=$(lsb_release -c -s)

####################
# Parse parameters #
####################
# There's 3 OS name concept concepts here:
# HOST_DISTRO_NAME: the os of the host (example: jessie, xenial)
# SBUILD_CHROOT_DISTRO_NAME: the name of the distro to setup in the chroot (example: jessie, xenial)
# SBUILD_CHROOT_NAME: the name of the chroot we want to setup (example: jessie-newton or jessie-newton-backports)
DO_EXIT="no"
for i in $@ ; do
    case "${1}" in
    "--sbuild-chroot-name")
        if [ -z "${2}" ] ; then echo "Parameter for option --sbuild-chroot-name is missing" > /dev/stderr ; DO_EXIT="yes" ; fi
        SBUILD_CHROOT_NAME="${2}"
        shift
        shift
    ;;
    "--sbuild-chroot-distro-name")
        if [ -z "${2}" ] ; then echo "Parameter for option --sbuild-chroot-distro-name is missing" > /dev/stderr ; DO_EXIT="yes" ; fi
        SBUILD_CHROOT_DISTRO_NAME="${2}"
        shift
        shift
    ;;
    esac
done

if [ -z "${SBUILD_CHROOT_NAME}" ] ; then
    SBUILD_CHROOT_NAME="${HOST_DISTRO_NAME}-${OSTACK_RELEASE}"
fi

if [ -z "${SBUILD_CHROOT_DISTRO_NAME}" ] ; then
    SBUILD_CHROOT_DISTRO_NAME=${HOST_DISTRO_NAME}
fi

if [ ${DO_EXIT} = "yes" ] ; then
    echo "Parameters not validated: will exit now!" > /dev/stderr
    exit 1
fi
########################
# End parse parameters #
########################

# Some configuration stuff
CLOSEST_DEBIAN_MIRROR=http://httpredir.debian.org/debian

PATH=/usr/bin:/usr/sbin:/bin:/sbin
APT="DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends"


disable_init_start () {
    TMPFILE=$(mktemp)
    echo "#!/bin/sh

exit 101

" >${TMPFILE}
    sudo cp ${TMPFILE} /usr/sbin/policy-rc.d
    sudo chmod +x /usr/sbin/policy-rc.d
    rm ${TMPFILE}
}

enable_init_start () {
    sudo rm -f /usr/sbin/policy-rc.d
}

install_all_software () {
    echo "===> Installing required packages to run sbuild"
    sudo apt-get update
    sudo ${APT} git-buildpackage debhelper eatmydata build-essential \
        python-setuptools fakeroot python3-all python-all \
        python3-setuptools pristine-tar dh-autoreconf ssl-cert \
        dh-python dh-systemd python-sphinx sudo debootstrap \
        openstack-pkg-tools lintian lsb-release gem2deb gnupg haveged
    # Jessie needs sbuild from jessie-backports, because it has the
    # $clean_source = 0 option
    if [ "${HOST_DISTRO_NAME}" = "jessie" ] ; then
        DEBIAN_FRONTEND=noninteractive sudo apt-get install -y --no-install-recommends -t jessie-backports sbuild
    # This code thinks anything else than jessie is higher version of sbuild
    else
        DEBIAN_FRONTEND=noninteractive sudo apt-get install -y --no-install-recommends sbuild
    fi
}

configure_dotgitconfig () {
    git config user.name "OpenStack Package Builder"
    git config user.email "openstack-infra@lists.openstack.org"
}

# This key will be used to sign the built package
gen_package_build_key () {
    echo "===> Generating builder's GPG key to sign packages"
    if ! [ -d ${BUILDER_HOMEDIR}/.gnupg ] ; then
        mkdir -p ${BUILDER_HOMEDIR}/.gnupg
        chmod 755 ${BUILDER_HOMEDIR}/.gnupg
    fi
    if ! [ -r ${BUILDER_HOMEDIR}/.gnupg/gpg.conf ] ; then
        echo "keyserver hkp://pool.sks-keyservers.net
personal-digest-preferences SHA256
default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 ZLIB BZIP2 ZIP Uncompressed
cert-digest-algo SHA256
" >${BUILDER_HOMEDIR}/.gnupg/gpg.conf
    fi
    if ! [ -r ${BUILDER_HOMEDIR}/.gnupg/pkgos-gen-key-batchfile ] ; then
        echo "
%echo Generating a basic OpenPGP key
Key-Type: RSA
Key-Length: 4096
Name-Real: Jenkins
Name-Email: ${BUILDER_SYS_USERNAME}@openstack.org
Expire-Date: 0
" >${BUILDER_HOMEDIR}/.gnupg/pkgos-gen-key-batchfile
    fi
    sudo chown -R ${BUILDER_SYS_USERNAME}:${BUILDER_SYS_USERNAME} ${BUILDER_HOMEDIR}/.gnupg
    su ${BUILDER_SYS_USERNAME} -c "gpg --gen-key --batch ${BUILDER_HOMEDIR}/.gnupg/pkgos-gen-key-batchfile"
}

configure_sbuild () {
    echo "===> Setting-up sbuild's GPG key"
    # Setup the gpg key for sbuild
    sudo mkdir -p /root/.gnupg
    sudo chmod 600 /root/.gnupg
    sudo gpg --list-keys
    sudo sbuild-update --keygen

    # Add the builder as a sbuild user
    sudo sbuild-adduser ${BUILDER_SYS_USERNAME}

    echo "===> Creating sbuild's schroot chroot using a directory backend (ie: not tarball)"
    # Create the actual schroot env
    if ! [ -e /var/lib/sbuild/${SBUILD_CHROOT_NAME} ] ; then
        sudo sbuild-createchroot ${SBUILD_CHROOT_DISTRO_NAME} /var/lib/sbuild/${SBUILD_CHROOT_DISTRO_NAME} ${CLOSEST_DEBIAN_MIRROR}
    fi

    # Let's use a RAMDISK for sbuild chroot to build packages:
    # that's much faster than the HDD backend
    echo "===> Mounting /var/lib/schroot/union/{overlay,underlay} using tmpfs to speed-up build"
    TMPFILE=$(mktemp)
    cp /etc/fstab ${TMPFILE}
    echo "tmpfs           /var/lib/schroot/union/overlay        tmpfs defaults        0       0
tmpfs           /var/lib/schroot/union/underlay        tmpfs defaults        0       0" >>${TMPFILE}
    sudo cp ${TMPFILE} /etc/fstab
    rm ${TMPFILE}
    sudo mount /var/lib/schroot/union/overlay
    sudo mount /var/lib/schroot/union/underlay

    echo "===> Fixing-up newly created schroot's chroot config and /etc/git-buildpackage/gbp.conf"
    # Make sure git-buildpackage is using sbuild
    sudo sed -i 's/^[ #\t]*builder[ #\t]*=.*/builder = sbuild -v --no-apt-update/' /etc/git-buildpackage/gbp.conf
    # Disable clean outside of the chroot (note: this actually doesn't work due to a bug,
    # but let's keep it there still, when we found out how to fix git-buildpackage).
    sudo sed -i 's/^[ #\t]*cleaner[ #\t]*=.*/cleaner = \/bin\/true/' /etc/git-buildpackage/gbp.conf

    # Fix from jessie to jessie-newton
    # or jessie to jessie-newton-backports
    if ! [ "${SBUILD_CHROOT_NAME}" = "${SBUILD_CHROOT_DISTRO_NAME}" ] ; then
        # Fetch the full chroot.d filename
        SBUILD_SRC_NAME=$(ls /etc/schroot/chroot.d/${SBUILD_CHROOT_DISTRO_NAME}-amd64-sbuild-*)
        SBUILD_CHROOTD_FN=$(echo ${SBUILD_SRC_NAME} | sed s/${SBUILD_CHROOT_DISTRO_NAME}/${SBUILD_CHROOT_NAME}/)

        mv ${SBUILD_SRC_NAME} ${SBUILD_CHROOTD_FN}
        sed -i s/${SBUILD_CHROOT_DISTRO_NAME}-amd64-sbuild/${SBUILD_CHROOT_NAME}-amd64-sbuild/ ${SBUILD_CHROOTD_FN}
        mv /var/lib/sbuild/${SBUILD_CHROOT_DISTRO_NAME} /var/lib/sbuild/${SBUILD_CHROOT_NAME}
        sed -i "s#/var/lib/sbuild/${SBUILD_CHROOT_DISTRO_NAME}#/var/lib/sbuild/${SBUILD_CHROOT_NAME}#" ${SBUILD_CHROOTD_FN}
    fi

    # Switch from tarball to directory (ie: aufs) based build
    # (again, that's much faster...)
    sudo sed -i -e "s/^[ \t]*type[ \t]*=.*/type=directory/" ${SBUILD_CHROOTD_FN}
    # Tell that we'd like to use AUFS as backend for union FS
    # note that for Stretch and Xenial, we should switch to overlay instead
    case ${HOST_DISTRO_NAME} in
    jessie|trusty)
        UNION_TYPE=aufs
    ;;
    *)
        UNION_TYPE=overlay
    ;;
    esac
    if ! grep -q union-type ${SBUILD_CHROOTD_FN} ; then
        TMPFILE=$(mktemp)
        cp ${SBUILD_CHROOTD_FN} ${TMPFILE}
        echo "union-type=${UNION_TYPE}" >>${TMPFILE}
        sudo cp ${TMPFILE} ${SBUILD_CHROOTD_FN}
        rm ${TMPFILE}
    fi
    # Just to make sure in case union-type was there already (it's normally not there),
    # we overwrite it.
    sudo sed -i -e "s/^[ \t]*union-type[ \t]*=.*/union-type=${UNION_TYPE}/" ${SBUILD_CHROOTD_FN}

    # Configure ~/.sbuildrc to use our new sbuild chroot
    GPG_KEY_ID=$(su jenkins -c "gpg --list-keys ${BUILDER_SYS_USERNAME}" | grep ^pub | awk '{print $2}' | cut -d/ -f2)
    DOT_SBUILDRC_PATH=${BUILDER_HOMEDIR}/.sbuildrc
    if ! [ -r "${DOT_SBUILDRC_PATH}" ] ; then
        echo "\$build_arch_all = 1;
\$build_source = 1;
\$distribution = '"${SBUILD_CHROOT_NAME}"';
# We may run lintian by hand later on
# not need to get git-buildpackage to do it
\$run_lintian = 0;

# We don't want to run clean of source tree before
# entering the chroot, because that would mean we need
# some of the build dependencies.
\$clean_source = 0;

# Needed for sbuild to show output in deb-auto-backports
\$verbose = 1;

# In case we decide to no sign packages, uncomment this:
#\$pgp_options = '-us -uc';

\$key_id = '${GPG_KEY_ID}';

# This is for perl, just leave it...
1;
" >${DOT_SBUILDRC_PATH}
    fi
}

disable_init_start
install_all_software
configure_dotgitconfig
gen_package_build_key
configure_sbuild
enable_init_start
