Container build system
This commit is contained in:
		
							parent
							
								
									df44328c35
								
							
						
					
					
						commit
						cdb06b320c
					
				
					 8 changed files with 306 additions and 0 deletions
				
			
		
							
								
								
									
										4
									
								
								cobuild/000-setup.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								cobuild/000-setup.sh
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,4 @@ | |||
| progress "Installing Hrochobot" | ||||
| 
 | ||||
| cd /build/src | ||||
| pip install . | ||||
							
								
								
									
										13
									
								
								cobuild/010-service.d/hrochobot.service
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								cobuild/010-service.d/hrochobot.service
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,13 @@ | |||
| [Unit] | ||||
| Description="Hrochobot" | ||||
| After=network.target | ||||
| 
 | ||||
| [Service] | ||||
| Type=exec | ||||
| ExecStartPre=mkdir -p /data/etc | ||||
| ExecStart=/usr/local/bin/hrochobot | ||||
| Environment=HROCHOBOT_DATA=/data/etc | ||||
| Environment=HROCHOBOT_LOG=/data/log | ||||
| 
 | ||||
| [Install] | ||||
| WantedBy=multi-user.target | ||||
							
								
								
									
										4
									
								
								cobuild/010-service.d/run.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								cobuild/010-service.d/run.sh
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,4 @@ | |||
| progress "Configuring hrochobot.service" | ||||
| 
 | ||||
| install-config hrochobot.service /etc/systemd/system/ | ||||
| systemctl enable hrochobot | ||||
							
								
								
									
										4
									
								
								cobuild/Dockerfile.top
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								cobuild/Dockerfile.top
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,4 @@ | |||
| FROM docker://registry.ks.matfyz.cz/gimli/base:bullseye | ||||
| COPY bin /build/src/bin | ||||
| COPY hrochobot /build/src/hrochobot | ||||
| COPY setup.py /build/src | ||||
							
								
								
									
										6
									
								
								cobuild/try
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										6
									
								
								cobuild/try
									
									
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,6 @@ | |||
| #!/bin/bash | ||||
| set -e | ||||
| common/build cobuild --tag hrochobot-test | ||||
| podman rm -if hrochobot-test | ||||
| podman create --name hrochobot-test --hostname hrochobot-test hrochobot-test | ||||
| podman start hrochobot-test | ||||
							
								
								
									
										73
									
								
								common/build
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										73
									
								
								common/build
									
									
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,73 @@ | |||
| #!/bin/bash | ||||
| set -euo pipefail | ||||
| 
 | ||||
| gen-docker-file () | ||||
| { | ||||
| 	if [ -f $src/Dockerfile.top ] ; then | ||||
| 		cat $src/Dockerfile.top | ||||
| 	fi | ||||
| 
 | ||||
| 	echo "COPY common /build/common" | ||||
| 
 | ||||
| 	for stage in $(cd $src && echo [0-9]*.[a-z]*) ; do | ||||
| 		case $stage in | ||||
| 			*.docker) | ||||
| 				cat $src/$stage | ||||
| 				;; | ||||
| 			*.d|*.sh) | ||||
| 				echo "COPY $src/$stage /build/$stage" | ||||
| 				echo "RUN /build/common/run $stage" | ||||
| 				;; | ||||
| 			*) | ||||
| 				echo >&2 "ERROR: Unrecognized build stage name $stage" | ||||
| 				exit 1 | ||||
| 				;; | ||||
| 		esac | ||||
| 	done | ||||
| 
 | ||||
| 	if [ -f $src/Dockerfile.bottom ] ; then | ||||
| 		cat $src/Dockerfile.bottom | ||||
| 	fi | ||||
| 
 | ||||
| 	echo "RUN rm -rf /build /data" | ||||
| } | ||||
| 
 | ||||
| if [ $# = 0 ] ; then | ||||
| 	echo >&2 "Usage: $0 <src-directory> [<podman build options>]" | ||||
| 	exit 1 | ||||
| fi | ||||
| 
 | ||||
| src=$1 | ||||
| shift | ||||
| 
 | ||||
| if [ ! -v http_proxy ] ; then | ||||
| 	PROXY= | ||||
| 	eval "$(apt-config shell PROXY Acquire::http::proxy)" | ||||
| 	if [ -n "$PROXY" ] ; then | ||||
| 		export http_proxy=$PROXY | ||||
| 	fi | ||||
| fi | ||||
| 
 | ||||
| if [ -v http_proxy -a ! -v https_proxy ] ; then | ||||
| 	export https_proxy=$http_proxy | ||||
| fi | ||||
| 
 | ||||
| CACHE_DIR=${XDG_CACHE_HOME:-$HOME/.cache}/container-build | ||||
| if [ -d $CACHE_DIR ] ; then | ||||
| 	echo "Using cache $CACHE_DIR" | ||||
| else | ||||
| 	echo "Creating cache $CACHE_DIR" | ||||
| 	mkdir -p $CACHE_DIR | ||||
| fi | ||||
| mkdir -p $CACHE_DIR/download | ||||
| 
 | ||||
| gen-docker-file | podman build \ | ||||
| 	--file - \ | ||||
| 	--layers \ | ||||
| 	--http-proxy \ | ||||
| 	--volume=$CACHE_DIR:/root/.cache \ | ||||
| 	"$@" \ | ||||
| 	. | ||||
| 
 | ||||
| echo -n "Cache usage: " | ||||
| du -sh $CACHE_DIR | cut -d '	' -f1 | ||||
							
								
								
									
										152
									
								
								common/lib.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										152
									
								
								common/lib.sh
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,152 @@ | |||
| C_RED="$(echo -e '\e[31m')" | ||||
| C_GREEN="$(echo -e '\e[32m')" | ||||
| C_YELLOW="$(echo -e '\e[33m')" | ||||
| C_NORMAL="$(echo -e '\e[0m')" | ||||
| 
 | ||||
| export DEBIAN_FRONTEND=noninteractive | ||||
| B_APT_UPDATED= | ||||
| 
 | ||||
| progress () | ||||
| { | ||||
| 	echo "${C_GREEN}$1${C_NORMAL}" >&2 | ||||
| } | ||||
| 
 | ||||
| note () | ||||
| { | ||||
| 	echo "${C_YELLOW}$1${C_NORMAL}" >&2 | ||||
| } | ||||
| 
 | ||||
| warn () | ||||
| { | ||||
| 	echo "${C_RED}WARNING: $1${C_NORMAL}" >&2 | ||||
| } | ||||
| 
 | ||||
| die () | ||||
| { | ||||
| 	echo "${C_RED}ERROR: $1${C_NORMAL}" >&2 | ||||
| 	exit 1 | ||||
| } | ||||
| 
 | ||||
| update-pkgs () | ||||
| { | ||||
| 	if [ -z "$B_APT_UPDATED" ] ; then | ||||
| 		apt update | ||||
| 		B_APT_UPDATED=1 | ||||
| 	fi | ||||
| } | ||||
| 
 | ||||
| install-pkgs () | ||||
| { | ||||
| 	update-pkgs | ||||
| 	apt install -y --no-install-recommends --no-install-suggests "$@" | ||||
| } | ||||
| 
 | ||||
| install-config () | ||||
| { | ||||
| 	[ $# = 2 ] || die "Usage: install-config <source> (<target-file> | <target-dir>/)" | ||||
| 	local S=$1 | ||||
| 	local T=$2 | ||||
| 	if [ ${T%/} != $T ] ; then | ||||
| 		T=$T$(basename $S) | ||||
| 	fi | ||||
| 	local B=$BUILD_CONFIG$T | ||||
| 	mkdir -p $(dirname $B) $(dirname $T) | ||||
| 	if [ -f $T ] ; then | ||||
| 		if [ ! -f $B.orig ] ; then | ||||
| 			echo "Backing up $T to $B.orig" | ||||
| 			cp $T $B.orig | ||||
| 		else | ||||
| 			echo "Backup of $T already present in $B.orig" | ||||
| 		fi | ||||
| 	fi | ||||
| 	if [ -f $S ] ; then | ||||
| 		# Just a new file: overwrite | ||||
| 		echo "Overwriting $T" | ||||
| 		cp $S $T | ||||
| 		cp $S $B.new | ||||
| 	elif [ -f $S.orig -a -f $S.new ] ; then | ||||
| 		# Try 3-way merge | ||||
| 		if cmp --quiet $S.new $T ; then | ||||
| 			warn "Skipping merge of $T: changes already present" | ||||
| 		else | ||||
| 			echo "Merging $T" | ||||
| 			if diff3 -m $S.new $S.orig $T >$B.new ; then | ||||
| 				cp $B.new $T | ||||
| 			else | ||||
| 				die "Merge failed, please review $B.new" | ||||
| 			fi | ||||
| 		fi | ||||
| 	else | ||||
| 		die "Do not know how to install config $T" | ||||
| 	fi | ||||
| } | ||||
| 
 | ||||
| sed-config () | ||||
| { | ||||
| 	[ $# = 2 ] || die "Usage: sed-config <target> <sed-script>" | ||||
| 	local T=$1 | ||||
| 	local SCRIPT=$2 | ||||
| 	local B=$BUILD_CONFIG$T | ||||
| 	mkdir -p $(dirname $B) | ||||
| 	[ -f $T ] || die "Want to sed $T, but it is missing" | ||||
| 	if [ ! -f $B.orig ] ; then | ||||
| 		echo "Backing up $T to $B.orig" | ||||
| 		cp $T $B.orig | ||||
| 	else | ||||
| 		echo "Backup of $T already present in $B.orig" | ||||
| 	fi | ||||
| 	sed -ri "$SCRIPT" $T | ||||
| 	cp $T $B.new | ||||
| } | ||||
| 
 | ||||
| pipe-config () | ||||
| { | ||||
| 	[ $# = 1 ] || die "Usage: <command> | pipe-config <target>" | ||||
| 	local TMP=$(mktemp) | ||||
| 	cat >$TMP | ||||
| 	install-config $TMP $1 | ||||
| 	rm $TMP | ||||
| } | ||||
| 
 | ||||
| rm-config () | ||||
| { | ||||
| 	[ $# = 1 ] || die "Usage: rm-config <target>" | ||||
| 	local T=$1 | ||||
| 	local B=$BUILD_CONFIG$T | ||||
| 	if [ -f $T ] ; then | ||||
| 		if [ ! -f $B.orig ] ; then | ||||
| 			echo "Backing up $T to $B.orig" | ||||
| 			cp $T $B.orig | ||||
| 		fi | ||||
| 		echo "Removing $T" | ||||
| 		rm -f $T | ||||
| 	else | ||||
| 		echo "Wanted to remove $T, but it does not exist" | ||||
| 	fi | ||||
| } | ||||
| 
 | ||||
| download () | ||||
| { | ||||
| 	[ $# = 3 ] || die "Usage: download <URL> <hash-type> <hash>" | ||||
| 	local URL=$1 | ||||
| 	local HTYPE=$2 | ||||
| 	local HASH=$3 | ||||
| 	local DEST=$(basename $URL) | ||||
| 	local CACHE=/root/.cache/download | ||||
| 	if [ -d $CACHE ] ; then | ||||
| 		if [ -f $CACHE/$DEST ] ; then | ||||
| 			echo "Using cached $DEST" | ||||
| 		else | ||||
| 			echo "Downloading $URL with caching" | ||||
| 			curl $URL >$CACHE/$DEST.tmp | ||||
| 			mv $CACHE/$DEST.tmp $CACHE/$DEST | ||||
| 		fi | ||||
| 		ln -s $CACHE/$DEST . | ||||
| 	else | ||||
| 		warn "Cache $CACHE not found: downloading directly" | ||||
| 		echo "Downloading $URL" | ||||
| 		curl $URL >$DEST | ||||
| 	fi | ||||
| 	local H=$(${HTYPE}sum $DEST | cut -d' ' -f1) | ||||
| 	[ $H == $HASH ] || die "Mismatched hash: got $H, want $HASH" | ||||
| } | ||||
							
								
								
									
										50
									
								
								common/run
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										50
									
								
								common/run
									
									
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,50 @@ | |||
| #!/bin/bash | ||||
| set -euo pipefail | ||||
| 
 | ||||
| if [ $# != 1 ] ; then | ||||
| 	echo >&2 "Usage: $0 <stage-directory>" | ||||
| 	exit 1 | ||||
| fi | ||||
| 
 | ||||
| STAGE=$1 | ||||
| 
 | ||||
| STAGE=/build/$STAGE | ||||
| BUILD_COMMON=/build/common | ||||
| BUILD_CONFIG=/build/config-tmp | ||||
| . $BUILD_COMMON/lib.sh | ||||
| 
 | ||||
| note "Running $STAGE" | ||||
| 
 | ||||
| if [ ! -v http_proxy -o ! -v https_proxy ] ; then | ||||
| 	warn "No HTTP(S) proxy is set" | ||||
| fi | ||||
| 
 | ||||
| case "$STAGE" in | ||||
| 	*.sh) | ||||
| 		. $STAGE | ||||
| 		exit 0 | ||||
| 		;; | ||||
| 	*.d) | ||||
| 		;; | ||||
| 	*) | ||||
| 		die "Unrecognized stage name $STAGE" | ||||
| esac | ||||
| 
 | ||||
| cd $STAGE | ||||
| 
 | ||||
| if [ -f run.sh ] ; then | ||||
| 	. run.sh | ||||
| else | ||||
| 	for a in [0-9]* ; do | ||||
| 		case "$a" in | ||||
| 			*.sh) | ||||
| 				( . $a ) | ||||
| 				;; | ||||
| 			*.d) | ||||
| 				( cd $a && . run.sh ) | ||||
| 				;; | ||||
| 			*) | ||||
| 				warn "Unrecognized build step file $a" | ||||
| 		esac | ||||
| 	done | ||||
| fi | ||||
		Loading…
	
		Reference in a new issue