#!/bin/bash # _____ _ _ # | __|___ ___ ___ _| |___ _____| |_ ___ ___ ___ # | __| _| -_| -_| . | . | | . | . | | -_| # |__| |_| |___|___|___|___|_|_|_|___|___|_|_|___| # # Freedom in the Cloud # # Script used to run builds for continuous integration # # License # ======= # # Copyright (C) 2018-2019 Bob Mottram <bob@freedombone.net> # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. PROJECT_NAME='freedombone' INSTALL_DIR=/root/build-ci code_repo=https://code.freedombone.net/bashrc target="$1" web_dir=/var/www/html build_info= if [ "$2" ]; then web_dir="$2" build_info="$3" fi function check_for_reboot { filename="$1" if [ ! -f "$filename" ]; then return fi if grep -q "AppException: command failed: \\['mkfs'" "$filename"; then rm "$filename" systemctl reboot -i fi } function remove_ci_daemon { ci_target="$1" ci_build_info="$2" ci_extra= if [ "$ci_build_info" ]; then ci_extra="-${ci_build_info}" fi birbci --remove "${PROJECT_NAME}-${ci_target}${ci_extra}" } function create_ci_daemon { ci_target="$1" ci_build_info="$2" ci_extra= if [ "$ci_build_info" ]; then ci_extra="-${ci_build_info}" fi script_filename="/etc/birbci/${PROJECT_NAME}-${ci_target}${ci_extra}.sh" install_name="${PROJECT_NAME}-${ci_target}${ci_extra}" ci_run="/etc/birbci/${install_name}-ci-run.sh" remove_ci_daemon "${ci_target}" "${ci_build_info}" { echo '#!/bin/bash'; echo 'set -e'; echo 'set -x'; echo "cp /usr/local/bin/${PROJECT_NAME}-ci ${ci_run}"; echo "${ci_run} ${ci_target} ${web_dir} ${ci_build_info}"; echo "rm ${ci_run}"; } > "$script_filename" chmod +x "$script_filename" birbci --repo "${code_repo}/freedombone" --branch stretch --script "${script_filename}" -w "${web_dir}/index.html" --synchronous yes --install "${install_name}" --build-log yes --rebootonfail yes } if [ ! "$1" ]; then exit 1 fi if [[ "$1" == 'remove'* ]]; then sed -i '/birbci-cron/d' /etc/crontab arch=$(uname -a) if [[ "$arch" == *'x86'* || "$arch" == *'amd64'* ]]; then remove_ci_daemon amd64 remove_ci_daemon amd64 onion remove_ci_daemon i386 meshclient fi remove_ci_daemon cubieboard2 remove_ci_daemon cubieboard2 onion remove_ci_daemon a20-olinuxino-lime2 remove_ci_daemon a20-olinuxino-lime2 onion remove_ci_daemon banana-pro remove_ci_daemon banana-pro onion remove_ci_daemon beagleboneblack remove_ci_daemon beagleboneblack onion remove_ci_daemon beagleboneblack mesh remove_ci_daemon cubietruck remove_ci_daemon cubietruck onion while true do # shellcheck disable=SC2009 active_builds=$(ps aux | grep "birbci -d" | grep -vc "grep") # shellcheck disable=SC2086 if [ $active_builds -gt 0 ]; then kill_pid=$(pgrep "birbci" | head -n 1) kill -9 "$kill_pid" else break fi done rm -rf /root/.tmp_${PROJECT_NAME}_build* rm -rf /etc/birbci/* exit 0 fi if [[ "$1" == 'setup'* ]]; then # install birbci if [ -d /etc/birbci ]; then rm -rf /etc/birbci fi if [ -d "$INSTALL_DIR" ]; then rm -rf "$INSTALL_DIR" fi mkdir /etc/birbci mkdir -p "$INSTALL_DIR" git clone "${code_repo}/birbci" "$INSTALL_DIR/birbci" cd "$INSTALL_DIR/birbci" || exit 2 make install # setup the web server { echo ' server {'; echo ' listen 80 default_server;'; echo ' listen [::]:80 default_server;'; echo ''; echo ' root /var/www/html;'; echo ' server_name _;'; echo ''; echo ' index index.html;'; echo ''; echo ' location / {'; echo " try_files \$uri \$uri/ =404;"; echo ' }'; echo ''; echo ' location /downloads {'; echo ' autoindex on;'; echo ' }'; echo ''; echo ' location ^~ /.well-known/ {'; echo ' allow all;'; echo ' }'; echo '}'; } > /etc/nginx/sites-available/default fi # Now add some builds if [[ "$1" == 'setuptest' ]]; then create_ci_daemon a20-olinuxino-lime2 exit 0 fi if [[ "$1" == 'setup' ]]; then arch=$(uname -a) if [[ "$arch" == *'x86'* || "$arch" == *'amd64'* ]]; then create_ci_daemon amd64 create_ci_daemon amd64 onion create_ci_daemon i386 meshclient fi create_ci_daemon cubieboard2 create_ci_daemon cubieboard2 onion create_ci_daemon a20-olinuxino-lime2 create_ci_daemon a20-olinuxino-lime2 onion create_ci_daemon banana-pro create_ci_daemon banana-pro onion create_ci_daemon beagleboneblack create_ci_daemon beagleboneblack onion create_ci_daemon beagleboneblack mesh create_ci_daemon cubietruck create_ci_daemon cubietruck onion exit 0 fi extra='--sata sda2' if [[ "$target" == 'beaglebone'* || "$target" == 'amd'* || "$target" == 'i386'* || "$target" == 'x86'* ]]; then extra='' fi targetstr="${target}" if [ "$build_info" ]; then targetstr="${target}-${build_info}" fi downloads_directory=${web_dir}/downloads/${targetstr} source_directory=/etc/birbci/${PROJECT_NAME}-${targetstr} build_directory=/etc/birbci/${PROJECT_NAME}-${targetstr}-build if [ ! -d "$source_directory" ]; then echo "$source_directory" echo 'Source directory not found' exit 35 fi if [ -d "${build_directory}" ]; then rm -rf "${build_directory}" fi mkdir -p "${build_directory}" if [ ! -d "${downloads_directory}" ]; then mkdir -p "${downloads_directory}" fi build_log_filename="${web_dir}/buildlog_${PROJECT_NAME}-${targetstr}.txt" if [ -f "$build_log_filename" ]; then # keep a copy of the previous log for reference # if the build failed last time mv "$build_log_filename" "${build_log_filename}.prev" fi echo 'No build results yet' > "$build_log_filename" chmod 755 "$build_log_filename" chown www-data:www-data "$build_log_filename" # install from the source directory cd "${source_directory}" || exit 1 git stash git pull make install cd "${build_directory}" || exit 1 if [ ! "$build_info" ]; then if ! /usr/local/bin/${PROJECT_NAME}-image -t "${target}" ${extra} --ci yes --build-log "${build_log_filename}"; then check_for_reboot "${build_log_filename}" exit 10 fi else if [[ "$build_info" == 'onion' ]]; then if ! /usr/local/bin/${PROJECT_NAME}-image -t "${target}" ${extra} --onion yes --ci yes --build-log "${build_log_filename}"; then check_for_reboot "${build_log_filename}" exit 20 fi fi if [[ "$build_info" == 'mesh'* ]]; then if ! /usr/local/bin/${PROJECT_NAME}-image -t "${target}" -v "${build_info}" ${extra} --ci yes --build-log "${build_log_filename}"; then check_for_reboot "${build_log_filename}" exit 30 fi fi fi echo $"Compressing image with 2 threads" >> "$build_log_filename" if ! xz --no-warn --verbose --keep --threads=2 -3 "${build_directory}"/*.img >> "$build_log_filename"; then exit 40 fi # shellcheck disable=SC2115,SC2086 rm -rf ${downloads_directory}/* echo "mv ${build_directory}/*.xz ${downloads_directory}/" >> "$build_log_filename" # shellcheck disable=SC2115,SC2086 if ! mv ${build_directory}/*.xz ${downloads_directory}/; then exit 50 fi cd "$source_directory" || exit 36735 git log -n 1 > "$downloads_directory/commit.txt" # shellcheck disable=SC2115,SC2086,SC2129 git log -n 1 >> "$build_log_filename" echo $"Removing image file" >> "$build_log_filename" # shellcheck disable=SC2115,SC2086 ls -l ${build_directory}/*.img >> "$build_log_filename" # shellcheck disable=SC2115,SC2086 rm ${build_directory}/*.img echo $"Changing permissions on ${downloads_directory} to www-data" >> "$build_log_filename" chown -R www-data:www-data "${downloads_directory}" echo $"$(date) Build installed to website" >> "$build_log_filename" exit 0