servatrice/.ci/docker.sh
ebbit1q 79501a4af7
fix the uid and gid of the user in the docker container (#4610)
* fix the uid and gid of the user in the container

this fixes this error:
unsafe repository ('/src' is owned by someone else)
this caused the hash to go missing in the version number

* add --interactive option to .ci/docker.sh

* add --dir to .ci/compile.sh

* fix up the comments on the ci scripts

* add extra comment to docker.sh
2022-04-18 19:04:49 -04:00

163 lines
4.6 KiB
Bash

#!/bin/bash
# This script is to be used by the ci environment from the project root directory, do not use it from somewhere else.
# Creates or loads docker images to use in compilation, creates RUN function to start compilation on the docker image.
# <arg> sets the name of the docker image, these correspond to directories in .ci
# --get loads the image from a previously saved image cache, will build if no image is found
# --build builds the image from the Dockerfile in .ci/$NAME
# --save stores the image, if an image was loaded it will not be stored
# --interactive immediately starts the image interactively for debugging
# --set-cache <location> sets the location to cache the image or for ccache
# requires: docker
# uses env: NAME CACHE BUILD GET SAVE INTERACTIVE (correspond to args: <name> --set-cache <cache> --build --get --save --interactive)
# sets env: RUN CCACHE_DIR IMAGE_NAME RUN_ARGS RUN_OPTS BUILD_SCRIPT
# exitcode: 1 for failure, 2 for missing dockerfile, 3 for invalid arguments
export BUILD_SCRIPT=".ci/compile.sh"
project_name="cockatrice"
save_extension=".tar.gz"
image_cache="image"
ccache_cache=".ccache"
# Read arguments
while [[ $# != 0 ]]; do
case "$1" in
'--build')
BUILD=1
shift
;;
'--get')
GET=1
shift
;;
'--interactive')
INTERACTIVE=1
shift
;;
'--save')
SAVE=1
shift
;;
'--set-cache')
CACHE=$2
if ! [[ -d $CACHE ]]; then
echo "could not find cache path: $CACHE" >&2
return 3
fi
shift 2
;;
*)
if [[ $1 == -* ]]; then
echo "unrecognized option: $1"
return 3
fi
NAME="$1"
shift
;;
esac
done
# Setup
if ! [[ $NAME ]]; then
echo "no build name given" >&2
return 3
fi
export IMAGE_NAME="${project_name,,}_${NAME,,}" # lower case
docker_dir=".ci/$NAME"
if ! [[ -r $docker_dir/Dockerfile ]]; then
echo "could not find Dockerfile in $docker_dir" >&2
return 2 # even if the image is cached, we do not want to run if there is no way to build this image
fi
if ! [[ $CACHE ]]; then
echo "cache dir is not set!" >&2
else
if ! [[ -d $CACHE ]]; then
echo "could not find cache dir: $CACHE" >&2
mkdir -p "$CACHE"
unset GET # the dir is empty
fi
if [[ $GET || $SAVE ]]; then
img_dir="$CACHE/$image_cache"
img_save="$img_dir/$IMAGE_NAME$save_extension"
if ! [[ -d $img_dir ]]; then
echo "could not find image dir: $img_dir" >&2
mkdir -p "$img_dir"
fi
fi
export CCACHE_DIR="$CACHE/$ccache_cache"
if ! [[ -d $CCACHE_DIR ]]; then
echo "could not find ccache dir: $CCACHE_DIR" >&2
mkdir -p "$CCACHE_DIR"
fi
fi
# Get the docker image from previously stored save
if [[ $GET ]]; then
if [[ $img_save ]] && docker load --input "$img_save"; then
echo "loaded image"
docker images
unset BUILD # do not overwrite the loaded image with build
unset SAVE # do not overwrite the stored image with the same image
if [[ $(find "$CCACHE_DIR" -type f -print -quit) ]]; then # check contents of ccache
echo "setting ccache to readonly"
export RUN_ARGS="$RUN_ARGS -e CCACHE_READONLY=1 -e CCACHE_NOSTATS=1" # do not overwrite ccache
else
echo "ccache is empty: $(find "$CCACHE_DIR")" >&2
fi
else
echo "could not load cached image, building instead" >&2
BUILD=1
fi
fi
# Build the docker image from dockerfile
if [[ $BUILD ]]; then
if docker build --tag "$IMAGE_NAME" "$docker_dir"; then
echo "built image"
docker images
else
echo "could not build image $IMAGE_NAME" >&2
return 1
fi
fi
# Save docker image to cache (compressed)
if [[ $SAVE ]]; then
if [[ $img_save ]] && docker save --output "$img_save" "$IMAGE_NAME"; then
echo "saved image to: $img_save"
else
echo "could not save image $IMAGE_NAME" >&2
fi
fi
# Set compile function, runs the compile script on the image, passes arguments to the script
function RUN ()
{
echo "running image:"
if docker images | grep "$IMAGE_NAME"; then
local args=(--mount "type=bind,source=$PWD,target=/src")
args+=(--workdir "/src")
args+=(--user "$(id -u):$(id -g)")
if [[ $CCACHE_DIR ]]; then
args+=(--mount "type=bind,source=$CCACHE_DIR,target=/.ccache")
args+=(--env "CCACHE_DIR=/.ccache")
fi
docker run "${args[@]}" $RUN_ARGS "$IMAGE_NAME" bash "$BUILD_SCRIPT" $RUN_OPTS "$@"
return $?
else
echo "could not find docker image: $IMAGE_NAME" >&2
return 3
fi
}
# for debugging, start the docker image interactively instead of building
# starts immediately, does not require sourcing or RUN
if [[ $INTERACTIVE ]]; then
export BUILD_SCRIPT="-i"
export RUN_ARGS="$RUN_ARGS -it"
RUN
fi