diff --git a/MANIFEST.in b/MANIFEST.in index 4034d1c9b6b7871d4f6b01d5376d7293388a1548..1a582cbe3f3088c6997ff1516a6870b7c3562530 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,3 +1,3 @@ include LICENSE README.rst buildout.cfg version.txt -recursive-include doc conf.py *.rst +recursive-include doc conf.py *.rst *.sh recursive-include bob/devtools/data *.md *.yaml *condarc *.pem matplotlibrc diff --git a/doc/ci.rst b/doc/ci.rst new file mode 100644 index 0000000000000000000000000000000000000000..73540209ee64b9e967d4b271b8f636fe6e2ed179 --- /dev/null +++ b/doc/ci.rst @@ -0,0 +1,17 @@ +.. vim: set fileencoding=utf-8 : + +.. _bob.devtools.ci: + + +========================================== + Instructions for CI machine installation +========================================== + +This document contains instructions for CI machine installation from sources. + + +.. toctree:: + :maxdepth: 2 + + linux + macos diff --git a/doc/index.rst b/doc/index.rst index 9a5f8ba7c0db6c8fcfa87ec0e42cff0a97da0ebe..c99f0a5fa85e5c3cb149c0ed09a8f19e750f33e7 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -17,6 +17,7 @@ Documentation release api + ci Indices and tables diff --git a/doc/links.rst b/doc/links.rst index 021350c1af4db81289616a50c1228b1f6a2f09b9..7e2f8a143104e5a3323cc0cdabb8bf28f2fff525 100644 --- a/doc/links.rst +++ b/doc/links.rst @@ -3,3 +3,6 @@ .. Place here references to all citations in lower case .. _bob: https://www.idiap.ch/software/bob +.. _shell executor: https://docs.gitlab.com/runner/executors/shell.html +.. _gitlab runner: https://docs.gitlab.com/runner/install/osx.html +.. _docker for mac: https://docs.docker.com/docker-for-mac/install/ diff --git a/doc/linux.rst b/doc/linux.rst new file mode 100644 index 0000000000000000000000000000000000000000..4074f19f0d11ea334d4308a78c953fb6a149c2f1 --- /dev/null +++ b/doc/linux.rst @@ -0,0 +1,123 @@ +.. vim: set fileencoding=utf-8 : + +.. _bob.devtools.ci.linux: + +============================ + Deploying a Linux-based CI +============================ + +This document contains instructions to build and deploy a new bare-OS CI for +Linux. Instructions for deployment assume a freshly installed machine, with +Debian 9.x running. Our builds use Docker images. We also configure +docker-in-docker to enable to run docker builds (and other tests) within docker +images. + + +Docker and Gitlab-runner setup +------------------------------ + +Just follow the advices from https://medium.com/@tonywooster/docker-in-docker-in-gitlab-runners-220caeb708ca + + +Hosts section +============= + +We re-direct calls to www.idiap.ch to our internal server, for speed. Just add +this to `/etc/hosts`: + +.. code-block:: sh + + $ echo "" >> /etc/hosts + $ echo "#We fake www.idiap.ch to keep things internal" >> /etc/hosts + $ echo "172.31.100.235 www.idiap.ch" >> /etc/hosts + $ echo "2001:620:7a3:600:0:acff:fe1f:64eb www.idiap.ch" >> /etc/hosts + + +Gitlab runner configuration +=========================== + +We are currently using this: + +.. code-block:: ini + + concurrent = 4 + check_interval = 10 + + [[runners]] + name = "docker" + output_limit = 102400 + url = "https://gitlab.idiap.ch/ci" + token = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + executor = "docker" + limit = 4 + builds_dir = "/local/builds" + cache_dir = "/local/cache" + [runners.docker] + tls_verify = false + image = "continuumio/conda-concourse-ci" + privileged = false + disable_cache = false + volumes = ["/var/run/docker.sock:/var/run/docker.sock", "/local/cache"] + extra_hosts = ["www.idiap.ch:172.31.100.235"] + [runners.cache] + Insecure = false + + [[runners]] + name = "docker-build" + output_limit = 102400 + executor = "shell" + shell = "bash" + url = "https://gitlab.idiap.ch/ci" + token = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + limit = 4 + builds_dir = "/local/builds" + cache_dir = "/local/cache" + + +Crontabs +======== + +.. code-block:: sh + + # crontab -l + MAILTO="" + @reboot /root/docker-cleanup-service.sh + 0 0 * * * /root/docker-cleanup.sh + + +The `docker-cleanup-service.sh` is: + +.. code-block:: sh + + #!/usr/bin/env sh + + # Continuously running image to ensure minimal space is available + + docker run -d \ + -e LOW_FREE_SPACE=30G \ + -e EXPECTED_FREE_SPACE=50G \ + -e LOW_FREE_FILES_COUNT=2097152 \ + -e EXPECTED_FREE_FILES_COUNT=4194304 \ + -e DEFAULT_TTL=60m \ + -e USE_DF=1 \ + --restart always \ + -v /var/run/docker.sock:/var/run/docker.sock \ + --name=gitlab-runner-docker-cleanup \ + quay.io/gitlab/gitlab-runner-docker-cleanup + +The `docker-cleanup.sh` is: + +.. code-block:: sh + + #!/usr/bin/env sh + + # Cleans-up docker stuff which is not being used + + # Exited machines which are still dangling + #Caches are containers that we do not want to delete here + #echo "Cleaning exited machines..." + #docker rm -v $(docker ps -a -q -f status=exited) + + # Unused image leafs + echo "Removing unused image leafs..." + docker rmi $(docker images --filter "dangling=true" -q --no-trunc) diff --git a/doc/macos-ci-install/admin-install.sh b/doc/macos-ci-install/admin-install.sh new file mode 100755 index 0000000000000000000000000000000000000000..c0b195f80b4ee24b7533aef90080fc0a669966df --- /dev/null +++ b/doc/macos-ci-install/admin-install.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash + +# Installs basic software on a fresh macOS installation that requires admin +# priviledges. + +# VARIABLES - edit to your requirements +MACOS_VERSION="${1}" +USERNAME="${2}" + +# -------------------- +# Don't edit past this +# -------------------- + +# gets the current path leading to this script +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" + +echo "Setting up date and time..." +${DIR}/datetime.sh + +echo "Updating the current system and disabling automatic updates..." +${DIR}/system-update.sh + +echo "Installing Xcode Command-Line (CLI) tools..." +${DIR}/xcode-cli-tools.sh + +echo "Installing macOS ${MACOS_VERSION} SDK..." +${DIR}/install-sdk.sh ${MACOS_VERSION} + +echo "Setting up special idiap.ch host..." +${DIR}/idiap-host.sh + +echo "Installing homebrew and build-time dependencies...":w +${DIR}/setup-paths.sh +${DIR}/install-homebrew.sh ${USER} + +echo "Installing (or updating) gitlab runner..." +{DIR}/install-gitlab-runner.sh diff --git a/doc/macos-ci-install/datetime.sh b/doc/macos-ci-install/datetime.sh new file mode 100755 index 0000000000000000000000000000000000000000..03ca91db809b7c0b3e37182333a6181a41cd3c14 --- /dev/null +++ b/doc/macos-ci-install/datetime.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +# run more easily. +# -e will cause the script to exit immediately if any command within it exits non 0 +# -o pipefail : this will cause the script to exit with the last exit code run. +# In tandem with -e, it will return the exit code of the first +# failing command. +set -eox pipefail + +systemsetup -setusingnetworktime on +systemsetup -settimezone Europe/Zurich +systemsetup -setnetworktimeserver time.euro.apple.com. + diff --git a/doc/macos-ci-install/idiap-host.sh b/doc/macos-ci-install/idiap-host.sh new file mode 100755 index 0000000000000000000000000000000000000000..21bbaf7ea0e46c4544a357ad846a8f718c8af737 --- /dev/null +++ b/doc/macos-ci-install/idiap-host.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +if [[ `grep -c "www.idiap.ch" /etc/hosts` != 0 ]]; then + echo "Not updating /etc/hosts - www.idiap.ch is already present..." +else + echo "Updating /etc/hosts..." + echo "" >> /etc/hosts + echo "#We fake www.idiap.ch to keep things internal" >> /etc/hosts + echo "172.31.100.235 www.idiap.ch" >> /etc/hosts + echo "2001:620:7a3:600:0:acff:fe1f:64eb www.idiap.ch" >> /etc/hosts +fi diff --git a/doc/macos-ci-install/install-gitlab-runner.sh b/doc/macos-ci-install/install-gitlab-runner.sh new file mode 100755 index 0000000000000000000000000000000000000000..adba3c69edb37959f448dae9a220b479ffc4a6c0 --- /dev/null +++ b/doc/macos-ci-install/install-gitlab-runner.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +set -eox pipefail +LOCATION=/usr/local/bin/gitlab-runner +curl --output ${LOCATION} https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-darwin-amd64 +chmod +x ${LOCATION} diff --git a/doc/macos-ci-install/install-homebrew.sh b/doc/macos-ci-install/install-homebrew.sh new file mode 100755 index 0000000000000000000000000000000000000000..200abb3a229c28b5f6f39c6f73e85778f7e4df52 --- /dev/null +++ b/doc/macos-ci-install/install-homebrew.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +set -x + +if [[ $EUID == 0 ]]; then + # changes path setup for all users, puts homebrew first + sed -e '/^\/usr\/local/d' -i .orig /etc/paths + echo -e "/usr/local/bin\n/usr/local/sbin\n/usr/local/opt/coreutils/libexec/gnubin\n$(cat /etc/paths)" > /etc/paths + + # restarts to install brew as non-root user + exec su ${1} -c "$(which bash) ${0}" +fi + +ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" </dev/null +brew=/usr/local/bin/brew + +${brew} install curl git coreutils bash-completion highlight neovim tmux htop python3 +${brew} link --force curl #keg-only recipe +${brew} cask install mactex diff --git a/doc/macos-ci-install/install-sdk.sh b/doc/macos-ci-install/install-sdk.sh new file mode 100755 index 0000000000000000000000000000000000000000..64a7e3fb8996425c1ac7d2cc3abad14a51b4d0b5 --- /dev/null +++ b/doc/macos-ci-install/install-sdk.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +# Installs the relevant SDK + +# gets the current path leading to this script +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" + +if [ ! -r "MacOSX${1}.sdk.tar.xz" ]; then + echo "Downloading macOS ${1} SDK..." + curl -L -o ${DIR}/MacOSX${1}.sdk.tar.xz https://github.com/phracker/MacOSX-SDKs/releases/download/10.13/MacOSX${1}.sdk.tar.xz +else + echo "File MacOSX${1}.sdk.tar.xz is already here, skip download" +fi + +if [ ! -d /opt ]; then mkdir /opt; fi +cd /opt +tar xfJ "${DIR}/MacOSX${1}.sdk.tar.xz" +ln -s /opt/MacOSX${1}.sdk /Library/Developer/CommandLineTools/SDKs/ diff --git a/doc/macos-ci-install/setup-paths.sh b/doc/macos-ci-install/setup-paths.sh new file mode 100755 index 0000000000000000000000000000000000000000..644e2651792aa790dd432f162c9f1078effb28c4 --- /dev/null +++ b/doc/macos-ci-install/setup-paths.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +set -x + +# changes path setup for all users, puts homebrew first +sed -e '/^\/usr\/local/d' -i .orig /etc/paths +sed -e '/^\/Library\/TeX\/texbin/d' -i .orig /etc/paths +echo -e "/usr/local/bin\n/usr/local/sbin\n/usr/local/opt/coreutils/libexec/gnubin\n/Library/TeX/texbin\n$(cat /etc/paths)" > /etc/paths diff --git a/doc/macos-ci-install/system-update.sh b/doc/macos-ci-install/system-update.sh new file mode 100755 index 0000000000000000000000000000000000000000..2d7d8e577ad026bdbdab25ca07c57dea070abd51 --- /dev/null +++ b/doc/macos-ci-install/system-update.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +set -eox pipefail + +# read into array ${RECOMMENDED[@]}, a filtered list of available and +# recommended software updates +self=`basename $0` +TMPFILE=`mktemp -t ${self}` || exit 1 +softwareupdate -l | grep -e '^\s\+\*' | sed -e 's/^[ \*]*//g' > ${TMPFILE} + +# starts of strings of installables we don't care about +BLACKLIST=() +BLACKLIST+=('iBook') +BLACKLIST+=('iTunes') +BLACKLIST+=('Install macOS') + +cat ${TMPFILE} | while read k; do + update="yes" + for l in "${BLACKLIST[@]}"; do + if [[ "${k}" == ${l}* ]]; then + update="no" + fi + done + if [[ "${update}" == "yes" ]]; then + echo "Updating $k..." + touch /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress + softwareupdate --verbose --install "${k}" + rm /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress + else + echo "Ignoring update for $k..." + softwareupdate --ignore "${k}" + fi +done +rm -f ${TMPFILE} + +# We don't want our system changing on us or restarting to update. Disable +# automatic updates. +echo "Disable automatic updates…" +softwareupdate --schedule off diff --git a/doc/macos-ci-install/xcode-cli-tools.sh b/doc/macos-ci-install/xcode-cli-tools.sh new file mode 100755 index 0000000000000000000000000000000000000000..a11a5263ccae3ad8c10abeee565660adbde90916 --- /dev/null +++ b/doc/macos-ci-install/xcode-cli-tools.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +set -eox pipefail + +# create the placeholder file that's checked by CLI updates' .dist code +# in Apple's SUS catalog +touch /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress + +# find the CLI Tools update +PROD=$(softwareupdate -l | grep "\*.*Command Line" | tail -n 1 | awk -F"*" '{print $2}' | sed -e 's/^ *//' | tr -d '\n') +# install it +softwareupdate -i "$PROD" --verbose + +rm /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress diff --git a/doc/macos.rst b/doc/macos.rst new file mode 100644 index 0000000000000000000000000000000000000000..7a700add7b50d11cfcc17c19ed1f77605415cc02 --- /dev/null +++ b/doc/macos.rst @@ -0,0 +1,101 @@ +.. vim: set fileencoding=utf-8 : + +.. _bob.devtools.ci.macos: + + +============================ + Deploying a macOS-based CI +============================ + +This document contains instructions to build and deploy a new bare-OS CI for +macOS. Instructions for deployment assume a freshly installed machine. + + +.. note:: + + For sanity, don't use an OS with lower version number than the macOS SDK + code that will be installed (currently 10.9). There may be undesired + consequences. You may use the latest OS version in case of doubt, but by + default we recommend the one before the last stable version, for stability. + So, if the current version is 10.14, a good base install would use 10.13. + + +Building the reference setup +---------------------------- + +0. Make sure the computer name is correctly set or execute the following on the + command-line, as an admin user:: + + $ sudo scutil --get LocalHostName + ... + $ sudo scutil --get HostName + ... + $ sudo scutil --get ComputerName + ... + + # if applicable, run the following commands + + $ sudo scutil --set LocalHostName "<hostname-without-domain-name>" + $ sudo scutil --set HostName "<fully-qualified-domain-name>" + $ sudo scutil --set ComputerName "<fully-qualified-domain-name>" + +1. Disable all energy saving features. Go to "System Preferences" then "Energy + Saver": + + - Enable "Prevent computer from sleeping..." + - Disable "Put hard disks to sleep when possible" + - Leave "Wake for network access" enabled + - You may leave the display on sleep to 10 minutes +2. Create a new user (without administrative priviledges) called ``gitlab``. + Choose a password to protect access to this user. In "Login Options", + select this user to auto-login, type its password to confirm +3. Enable SSH access to the machine by going on ``System Preferences``, + ``Sharing`` and then selecting ``Remote Login``. Make sure only users on the + ``Administrators`` group can access the machine. +4. Create as many ``Administrator`` users as required to manage the machine +5. Login as administrator of the machine (so, not on the `gitlab` account). As + that user, run the ``admin-install.sh`` script (after copying this repo from + https://gitlab.idiap.ch/bob/bob.devtools via a zip file download):: + + $ cd + $ unzip ~/Downloads/bob.devtools-master.zip + $ cd bob.devtools-master/doc/macos-ci-install + $ sudo ./admin-install.sh 10.9 gitlab + + Check that script for details on what is installed and the order. You may + execute pieces of the script by hand if something fails. In that case, + please investigate why it fails and properly fix the scripts so the next + install runs more smoothly. +6. Enter as gitlab user and install/configure the `gitlab runner`_: + + Configure the runner for `shell executor`_, with local caching. As + ``gitlab`` user, execute on the command-line:: + + $ gitlab-runner stop + $ vi .gitlab-runner/config.toml + $ gitlab-runner start + + Once that is set, your runner configuration should look like this (remove + comments if gitlab does not like them):: + + concurrent = 8 # set this to the number of cores available + check_interval = 10 # do **not** leave this to zero + + [[runners]] + name = "<runner-name>" # use a suggestive name + output_limit = 102400 # this value is in kb, so we mean 100 mb + url = "https://gitlab.idiap.ch" # this is our gitlab service + token = "abcdefabcdefabcdefabcdefabcdef" # this is specific to the conn. + executor = "shell" # select this + builds_dir = "/Users/gitlab/builds" # set this or bugs occur + cache_dir = "/Users/gitlab/caches" # this is optional, but desirable + shell = "bash" +7. While at the gitlab user, install `Docker for Mac`_. Ensure to set it up to + start at login. In "Preferences > Filesystem Sharing", ensure that + `/var/folders` is included in the list (that is the default location for + temporary files in macOS). +8. Reboot the machine. At this point, the gitlab user should be auto-logged and + the runner process should be executing. Congratulations, you're done! + + +.. include:: links.rst