Browse Source

Container build system

news
Martin Mareš 1 year ago
parent
commit
cdb06b320c
  1. 4
      cobuild/000-setup.sh
  2. 13
      cobuild/010-service.d/hrochobot.service
  3. 4
      cobuild/010-service.d/run.sh
  4. 4
      cobuild/Dockerfile.top
  5. 6
      cobuild/try
  6. 73
      common/build
  7. 152
      common/lib.sh
  8. 50
      common/run

4
cobuild/000-setup.sh

@ -0,0 +1,4 @@
progress "Installing Hrochobot"
cd /build/src
pip install .

13
cobuild/010-service.d/hrochobot.service

@ -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

@ -0,0 +1,4 @@
progress "Configuring hrochobot.service"
install-config hrochobot.service /etc/systemd/system/
systemctl enable hrochobot

4
cobuild/Dockerfile.top

@ -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

@ -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

@ -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

@ -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

@ -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…
Cancel
Save