]> git.pld-linux.org Git - projects/cleanbuild.git/blobdiff - bin/cleanbuild-docker.sh
Refactor: Add is_bool helper
[projects/cleanbuild.git] / bin / cleanbuild-docker.sh
index 861c74d8b9fd5cb46154286363c896630a80a873..cd6641f947c58d9246e2cef8794bff0fb6fbd886 100755 (executable)
@@ -9,17 +9,23 @@ PROGRAM=${0##*/}
 : ${TRACING=false}
 : ${WITH=}
 : ${WITHOUT=}
-: ${KEEP_CONTAINER=false}
+: ${KEEP_CONTAINER=true}
 : ${TMPFS="4G"}
+: ${EXEC=false}
 
 dir=$(pwd)
 image=registry.gitlab.com/pld-linux/cleanbuild
 topdir=$dir/rpm
 home=/home/builder
 
+notice() {
+       echo >&2 "[cleanbuild:notice]: $*"
+}
+
 die() {
-       echo >&2 "$0: $*"
-       exit 1
+       local rc=${2:-1}
+       echo >&2 "[cleanbuild:error]: $1"
+       exit $rc
 }
 
 is_no() {
@@ -40,6 +46,10 @@ is_no() {
        esac
 }
 
+is_bool() {
+       [ "$1" = "true" -o "$1" = "false" ] || die "Invalid boolean value: $1"
+}
+
 tmpfs() {
        if is_no "${TMPFS:-true}" || [ "$TMPFS" = "0" ]; then
                return
@@ -48,48 +58,82 @@ tmpfs() {
        echo "--tmpfs $home/rpm/BUILD:rw,exec,nosuid,size=$TMPFS"
 }
 
+have_container() {
+    local name="$1" id
+
+    id=$(docker ps -a -f "label=cleanbuild=$name" --format '{{.ID}}')
+
+    test -n "$id"
+}
+
 create_container() {
-       # cleanup first
-       docker kill $name >/dev/null 2>&1 || :
-       docker rm $name >/dev/null 2>&1 || :
+       if ! $KEEP_CONTAINER; then
+               notice "Clean up old container: $name"
+               docker kill $name >/dev/null 2>&1 || :
+               docker rm $name >/dev/null 2>&1 || :
+       fi
 
        install -d $topdir/logs
 
        # start the container
-       docker run --name=$name -d \
-               -w $home \
-               -v $topdir:$home/rpm \
-               -v $dir:$home/cleanbuild \
-               -v $dir/cache/poldek:/var/cache/poldek \
-               -v $dir/cache/ccache/$PACKAGE_NAME:$home/.ccache \
-               --label=cleanbuild=$name \
-               $(tmpfs) \
-               $image >/dev/null
-
-       # set the homedir
+       if ! have_container "$PACKAGE_NAME"; then
+               TMPFS_SIZE=$TMPFS \
+               PACKAGE_NAME=$PACKAGE_NAME \
+               docker-compose run --rm -d \
+                       --name=$name \
+                       --workdir=$home/rpm/packages/$PACKAGE_NAME \
+                       --label=cleanbuild=$PACKAGE_NAME \
+                       cleanbuild
+       fi
+
+       UID=$(id -u)
+       GID=$(id -g)
+       notice "Setup builder user ($UID:$GID)"
+
        docker exec --user=root -w / $name usermod -d $home builder
 
-       # these paths need to be accessible for builder
-       docker exec --user=root -w / $name sh -c "cd $home && chown builder:builder rpm rpm/logs rpm/BUILD .ccache"
+       if [ "$UID" -gt 0 ]; then
+               docker exec --user=root -w / $name usermod -u $UID builder
+       fi
+       if [ "$GID" -gt 0 ]; then
+               docker exec --user=root -w / $name groupmod -g $GID builder
+       fi
+
+       notice "Setup permissions"
+       docker exec --user=root -w / $name sh -c "cd $home && chown builder:builder . rpm rpm/logs rpm/BUILD rpm/RPMS rpm/packages .ccache"
 
        if [ ! -d $topdir/rpm-build-tools ]; then
-               docker exec $name builder --init-rpm-dir
+               notice "Initialize rpm-build-tools"
+               docker exec -w / $name builder --init-rpm-dir
        fi
 }
 
+enter_container() {
+       notice "Entering container for $PACKAGE_NAME"
+       docker exec --user=root -it $name bash
+}
+
 package_prepare() {
-       # fetch sources and install deps
+       notice "Fetch sources and install dependencies"
        if [ -d $topdir/packages/$PACKAGE_NAME ]; then
                # chown, as it might be different owner (root) modified outside container
+               notice "Fix ownership of existing package directory"
                docker exec --user=root -w / $name chown -R builder:builder $home/rpm/packages/$PACKAGE_NAME
        fi
-       docker exec $name builder -g $PACKAGE_NAME
 
-       # prevent network access like pld builders do
-       $NETWORKING || docker exec --user=root -w / $name setfacl -m u:builder:--- /etc/resolv.conf
+       notice "Fetch package sources"
+       docker exec --user=root -w / $name setfacl -x u:builder /etc/resolv.conf
+       docker exec -w / $name builder -g $PACKAGE_NAME
+
+       if ! $NETWORKING; then
+               notice "Disable networking: Prevent network access for user builder like PLD Linux builders"
+               docker exec --user=root -w / $name setfacl -m u:builder:--- /etc/resolv.conf
+       fi
 
-       git_tag=$(GIT_DIR=$topdir/packages/$PACKAGE_NAME/.git git describe --tags --always)
+       notice "Find latest tag on the branch"
+       git_tag=$(docker exec -w / -e GIT_DIR=$home/rpm/packages/$PACKAGE_NAME/.git $name git describe --tags --always)
        buildlog=rpm/logs/${git_tag#auto/*/}.log
+       notice "Build log: $buildlog"
 }
 
 package_build() {
@@ -97,28 +141,32 @@ package_build() {
        set -- -nn ${WITH:+--with "${WITH# }"} ${WITHOUT:+--without "${WITHOUT# }"} "$PACKAGE_NAME"
 
        while true; do
-               # install deps
-               docker exec $name builder -g -R "$@"
-               # remove .la dependencies
+               notice "Install dependencies"
+               docker exec -w / -t $name builder -g -R "$@"
+               notice "Remove .la dependencies"
                docker exec --user=root -w / $name $home/cleanbuild/bin/cleanup-la
-               # reset findunusedbr state after deps install
+               notice "Reset findunusedbr state after deps install"
                docker exec --user=root -w / $name $home/cleanbuild/bin/findunusedbr -c / $home/rpm/packages/$PACKAGE_NAME/$PACKAGE_NAME.spec
 
-               # actual build
-               docker exec $name cleanbuild/bin/teeboth $buildlog builder -bb --define '__spec_clean_body %{nil}' "$@" && rc=$? || rc=$?
+               notice "Build package"
+               docker exec -w $home $name cleanbuild/bin/teeboth $buildlog builder -bb --define '__spec_clean_body %{nil}' "$@" && rc=$? || rc=$?
+               # Kill processes on Ctrl+C
+               if [ "$rc" = 255 ]; then
+                       docker exec -w / $name pkill -e -u builder
+                       die "Aborted" $rc
+               fi
 
                findbr=$PACKAGE_NAME.findbr.log
-               builddir=$(docker exec $name sh -c 'test ! -d rpm/BUILD/* || echo rpm/BUILD/*')
+               builddir=$(docker exec -w $home $name sh -c 'test ! -d rpm/BUILD/* || echo rpm/BUILD/*')
                if [ -z "$builddir" ]; then
-                       echo >&2 "No build dir. Build failed?"
-                       exit 6
+                       die "No build dir. Build failed?" 6
                fi
-               # need root to run poldek
+               notice "Execute findbr"
                docker exec --user=root -w / $name sh -c "cd $home && cleanbuild/bin/findbr $builddir $buildlog" > $findbr
 
                installed_something=false
                while read pkg msg; do
-                       ./addbr rpm/packages/$PACKAGE_NAME/$PACKAGE_NAME.spec "$pkg" "$msg" || continue
+                       bin/addbr rpm/packages/$PACKAGE_NAME/$PACKAGE_NAME.spec "$pkg" "$msg" || continue
                        installed_something=true
                done < $findbr
                rm -f $findbr
@@ -126,10 +174,11 @@ package_build() {
                # go for another try
                $installed_something && continue
 
+               notice "Execute findunusedbr"
                docker exec --user=root -w / $name $home/cleanbuild/bin/findunusedbr -c / $home/rpm/packages/$PACKAGE_NAME/$PACKAGE_NAME.spec
 
                if [ $rc -eq 0 ] && ! $KEEP_CONTAINER; then
-                       # finished ok, cleanup
+                       notice "Finished ok, cleanup container"
                        docker kill $name >/dev/null && docker rm $name >/dev/null || :
                fi
 
@@ -140,7 +189,7 @@ package_build() {
 
 parse_options() {
        local t
-       t=$(getopt -o 'x' --long 'network,no-tmpfs,notmpfs,tmpfs:,keep-container,with:,without:' -n "$PROGRAM" -- "$@")
+       t=$(getopt -o 'x' --long 'network,exec,no-tmpfs,notmpfs,tmpfs:,keep-container:,with:,without:' -n "$PROGRAM" -- "$@")
        [ $? != 0 ] && exit $?
        eval set -- "$t"
 
@@ -152,6 +201,9 @@ parse_options() {
                --network)
                        NETWORKING=true
                        ;;
+               --exec)
+                       EXEC=true
+                       ;;
                --no-tmpfs|--notmpfs)
                        TMPFS=false
                        ;;
@@ -160,15 +212,17 @@ parse_options() {
                        TMPFS="$1"
                        ;;
                --keep-container)
-                       KEEP_CONTAINER=true
+                       shift
+                       is_bool "$1"
+                       KEEP_CONTAINER=$1
                        ;;
                --with)
                        shift
-                       WITH="$WITH $1"
+                       WITH="$WITH,$1"
                        ;;
                --without)
                        shift
-                       WITHOUT="$WITHOUT $1"
+                       WITHOUT="$WITHOUT,$1"
                        ;;
                --)
                        shift
@@ -181,7 +235,7 @@ parse_options() {
                shift
        done
 
-       test "$#" -eq 1 || die "package not specified or excess arguments"
+       test "$#" -eq 1 || die "Package not specified or excess arguments"
        PACKAGE_NAME="${1%.spec}"
 }
 
@@ -190,6 +244,10 @@ main() {
 
        $TRACING && set -x
        local name="cleanbuild-$PACKAGE_NAME"
+       if $EXEC; then
+               enter_container
+               return
+       fi
        create_container
        package_prepare
        package_build
This page took 0.043007 seconds and 4 git commands to generate.