#!/bin/sh # receive one package to be built from the build-list whose dependencies # are already satisfied or which breaks a dependency cycle # accepts a comma separated list of prefered packages as the first argument # exit code shows state of success: # 0: ok, I gave you an assignment # 1: come back (shortly) later - I was running already # 2: come back later - there are still packages to be built, # but currently none has all its dependencies ready # 3: come back after the next run of get-package-updates - currently # there are no pending packages # shellcheck source=conf/default.conf . "${0%/*}/../conf/default.conf" # TODO: honor manual build order of tool-chain: # toolchain build order: linux-api-headers->glibc->binutils->gcc->binutils->glibc mkdir -p "${work_dir}/package-states" hand_out_assignment() { # we don't care anymore if an older version of this package was # "locked" or "broken" find "${work_dir}/package-states" -maxdepth 1 -regextype grep \ -regex '.*/'"$(str_to_regex "$1")"'\(\.[^.]\+\)\{3\}\.\(locked\|broken\)' \ -not -regex '.*/'"$(str_to_regex "$1.$2.$3.$4.")"'[^.]\+' \ -delete # move that build order to the end of the build-list sed -i ' /^'"$(str_to_regex "$1 $2 $3 $4")"'$/ { $ b d } $ a '"$1 $2 $3 $4" \ "${work_dir}/build-list" # shellcheck disable=SC2016 { printf 'SELECT ' printf '`package_sources`.`%s`,' \ 'pkgbase' 'git_revision' 'mod_git_revision' printf '`upstream_repositories`.`name`,`binary_packages`.`sub_pkgrel`' printf ' FROM `upstream_repositories`' mysql_join_upstream_repositories_package_sources mysql_join_package_sources_build_assignments mysql_join_build_assignments_binary_packages mysql_join_binary_packages_repositories printf ' WHERE `repositories`.`name`="build-list"' printf ' AND `package_sources`.`%s`=from_base64("%s")' \ 'pkgbase' "$(printf '%s' "$1" | base64 -w0)" \ 'git_revision' "$(printf '%s' "$2" | base64 -w0)" \ 'mod_git_revision' "$(printf '%s' "$3" | base64 -w0)" printf ' AND `upstream_repositories`.`name`=from_base64("%s")' \ "$(printf '%s' "$4" | base64 -w0)" printf ' LIMIT 1;\n' } | \ mysql_run_query | \ tr '\t' ' ' { # shellcheck disable=SC2154 echo "${slave}" if [ -r "${work_dir}/package-states/$1.$2.$3.$4.locked" ]; then cat "${work_dir}/package-states/$1.$2.$3.$4.locked" fi } | \ sort -u | \ sponge "${work_dir}/package-states/$1.$2.$3.$4.locked" # shellcheck disable=SC2016 { printf 'UPDATE `build_slaves`' printf ' SET `currently_building` = (' printf ' SELECT `build_assignments`.`id`' printf ' FROM `build_assignments`' mysql_join_build_assignments_package_sources mysql_join_package_sources_upstream_repositories printf ' WHERE' printf ' `package_sources`.`%s` = from_base64("%s") AND' \ 'pkgbase' "$(printf '%s' "$1" | base64 -w0)" \ 'git_revision' "$(printf '%s' "$2" | base64 -w0)" \ 'mod_git_revision' "$(printf '%s' "$3" | base64 -w0)" printf ' `upstream_repositories`.`name` = from_base64("%s")' \ "$(printf '%s' "$4" | base64 -w0)" printf ')' printf ' WHERE `build_slaves`.`name`=from_base64("%s");\n' \ "$(printf '%s' "${slave}" | base64 -w0)" printf 'UPDATE `build_assignments`' mysql_join_build_assignments_package_sources mysql_join_package_sources_upstream_repositories printf ' SET `build_assignments`.`priority`=0' printf ' WHERE' printf ' `package_sources`.`%s` = from_base64("%s") AND' \ 'pkgbase' "$(printf '%s' "$1" | base64 -w0)" \ 'git_revision' "$(printf '%s' "$2" | base64 -w0)" \ 'mod_git_revision' "$(printf '%s' "$3" | base64 -w0)" printf ' `upstream_repositories`.`name` = from_base64("%s");\n' \ "$(printf '%s' "$4" | base64 -w0)" } | \ mysql_run_query exit 0 } if [ -s "${work_dir}/build-master-sanity" ]; then >&2 echo 'Build master is not sane.' exit 1 fi # Create a lock file and a trap. exec 9> "${build_list_lock_file}" if ! flock -n 9; then >&2 echo 'come back (shortly) later - I cannot lock build list.' exit 1 fi exec 8> "${sanity_check_lock_file}" if ! flock -s -n 8; then >&2 echo 'come back (shortly) later - sanity-check running.' exit 1 fi clean_up() { rm -f "${build_list_lock_file}" rm -rf --one-file-system "${tmp_dir}" } tmp_dir=$(mktemp -d 'tmp.get-assignment.XXXXXXXXXX' --tmpdir) trap clean_up EXIT # if we're building something already, hand it out (again) currently_building=$( # shellcheck disable=SC2016 { printf 'SELECT ' mysql_query_select_pkgbase_and_revision mysql_join_build_assignments_build_slaves mysql_join_build_assignments_binary_packages mysql_join_binary_packages_repositories printf ' WHERE `build_slaves`.`name`=from_base64("%s")' \ "$(printf '%s' "${slave}" | base64 -w0)" printf ' AND `repositories`.`name`="build-list"' printf ' LIMIT 1;\n' } | \ mysql_run_query ) if [ -n "${currently_building}" ]; then # shellcheck disable=SC2086 hand_out_assignment ${currently_building} fi # a package with [all dependencies met or which is part of a loop] # and which is currently not being built, ordered by: # 1: we requested it # 2: its priority # 3: is not yet built # 4: was built the longest time ago next_building=$( # shellcheck disable=SC2016 { printf 'SELECT ' printf '`package_sources`.`pkgbase`=from_base64("%s") AS `requested`,' \ "$( printf '%s' "$1" | \ base64 -w0 )" printf '`build_assignments`.`priority`,' printf 'COALESCE(' printf 'MAX(`failed_builds`.`date`),0' printf ') AS `last_trial`,' mysql_query_is_part_of_loop '`build_assignments`.`id`' printf ' AS `part_of_loop`,' mysql_query_select_pkgbase_and_revision mysql_join_build_assignments_binary_packages mysql_join_binary_packages_repositories printf ' LEFT' mysql_join_build_assignments_failed_builds printf ' WHERE `repositories`.`name`="build-list"' printf ' AND NOT EXISTS (' printf ' SELECT *' printf ' FROM `build_slaves`' printf ' WHERE `build_slaves`.`currently_building`=`build_assignments`.`id`' printf ') AND (' printf '`build_assignments`.`is_blocked` IS NULL' printf ' OR' printf ' `package_sources`.`pkgbase`=from_base64("%s")' \ "$( printf '%s' "$1" | \ base64 -w0 )" printf ') AND (' mysql_query_is_part_of_loop '`build_assignments`.`id`' printf ' OR NOT ' mysql_query_has_pending_dependencies '`build_assignments`.`id`' printf ')' printf ' GROUP BY `build_assignments`.`id`' printf ' ORDER BY `requested` DESC, `priority` DESC, `last_trial`, `part_of_loop`, `build_assignments`.`id`' printf ' LIMIT 1;\n' } | \ mysql_run_query | \ sed ' y/\t/ / s/^.* \(\S\+\( \S\+\)\{3\}\)$/\1/ ' ) if [ -n "${next_building}" ]; then # shellcheck disable=SC2086 hand_out_assignment ${next_building} fi # Check if there are any pending packages at all count_pending=$( # shellcheck disable=SC2016 { printf 'SELECT count(*)' printf ' FROM `build_assignments`' mysql_join_build_assignments_binary_packages mysql_join_binary_packages_repositories printf ' WHERE `repositories`.`name`="build-list"' printf ' AND `build_assignments`.`is_blocked` IS NULL' printf ';\n' } | \ mysql_run_query ) if [ "${count_pending}" -eq 0 ]; then >&2 echo 'come back after the next run of get-package-updates - currently there are no pending packages' exit 3 else >&2 echo 'come back later - there are still packages to be built, but currently none has all its dependencies ready' exit 2 fi