1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
|
#!/bin/sh
set -eu
this="$(readlink -e "${0}")"
# assign defaults
project_dir="$(dirname "$(dirname "${this}")")"
debian_tag="${DEBIAN_TAG:-sid}"
usage() {
cat << EOF
Usage: $(basename "${this}") [OPTION]... [ACTION]
Run tests or create package in a podman (or docker) container
Options:
-h print this usage and exit
-C PROJECT_DIR change to PROJECT_DIR (default: ${project_dir})
-t DEBIAN_TAG debian release tag (default: ${debian_tag})
-c CONTAINER_CMD container runner command (default: podman)
Actions:
help print this usage and exit
package create debian package artifacts
test run tests (default)
Example:
$(basename "${this}") -C ~/code/git-buildpackage -t trixie package
EOF
}
die() { { echo "ERROR: ${*}"; usage; } >&2; exit 1; }
# convenience wrapper
container_build() {
${container_cmd} build \
--force-rm="${DOCKER_BUILD_FORCE_RM:-false}" \
--no-cache="${DOCKER_BUILD_NO_CACHE:-false}" \
"${@}"
}
# take path to project dir; build docker image for base
base_build() {
(
cd "${project_dir}"
[ -f .gitignore ] && cat .gitignore
[ -f .gitmodules ] && sed -nr 's|\s+path = (.+)|\1|gp' .gitmodules
cat <<EOF
${this##"${PWD}"/}
*.buildinfo
*.changes
*.deb
*.dsc
*.tar.xz
.dockerignore
.git*
EOF
) > "${project_dir}/.dockerignore"
container_build \
--pull="${DOCKER_BUILD_PULL:-false}" \
--build-arg="FROM_IMAGE=debian:${debian_tag}" \
-t "gbp-base:${debian_tag}" -f- "${project_dir}" <<'EOF'
ARG FROM_IMAGE
FROM ${FROM_IMAGE}
ENV DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true
WORKDIR /workdir/project
RUN set -euvx \
&& export DEBIAN_FRONTEND=noninteractive \
&& apt-get update -y \
&& apt-get -y --no-install-recommends upgrade \
&& apt-get -y --no-install-recommends install \
build-essential devscripts equivs \
&& apt-get clean
COPY debian debian
RUN mk-build-deps -r -i debian/control -t 'apt-get -y -o Debug::pkgProblemResolver=yes --no-install-recommends'
# To avoid constantly invalidating previous container layers, run the slow
# dependency installation early and copy files (along with any changed files)
# later
COPY . .
RUN groupadd luser && useradd -g luser luser && chown -R luser:luser ..
USER luser
EOF
rm -vf "${project_dir}/.dockerignore"
}
# run tests
gbp_test() {
base_build
# Build another image, this time with .git so that the tests.component tests
# aren't skipped, and with additional packages needed to run the full test
# suite.
container_build \
-t "gbp-test:${debian_tag}" -f- "${project_dir}" <<EOF
FROM gbp-base:${debian_tag}
USER 0:0
RUN git config --global safe.directory '*'
VOLUME /workdir/project
RUN set -euvx \
&& export DEBIAN_FRONTEND=noninteractive \
&& apt-get update -y \
&& apt-get -y --no-install-recommends upgrade \
&& apt-get -y --no-install-recommends install curl flake8 \
&& apt-get clean
EOF
for L in C.UTF-8 C; do
${container_cmd} run --rm -ie"TEST_LOCALE=${L}" \
--mount="type=bind,source=${project_dir},target=/workdir/project" \
"gbp-test:${debian_tag}" sh <<'EOF'
set -euvx
export CI=true
make all+net
make -C docs
EOF
done
}
# create debian package artifacts, copy to host
gbp_package() {
base_build
${container_cmd} run --rm -iu0:0 \
--mount="type=bind,source=${PWD},target=/mnt/host-volume" \
"gbp-base:${debian_tag}" sh <<EOF
set -euvx
dpkg-buildpackage -j$(nproc) -sa -us -uc
find .. -maxdepth 1 -mindepth 1 -type f \
-exec chown -v $(id -u):$(id -g) {} + \
-a -exec cp -vat /mnt/host-volume {} +
EOF
}
while getopts ":hC:t:c:" opt; do
case $opt in
h) usage; exit 0;;
C) project_dir="$(readlink -e "${OPTARG}")"
[ -d "${project_dir}" ] || die "bad project dir ${OPTARG}";;
t) debian_tag="${OPTARG}";;
c) container_cmd="${OPTARG}";;
:) die "missing argument: -${OPTARG}";;
\?) die "bad option: -${OPTARG}";;
esac
done
# Set default container command
container_cmd="${container_cmd:-podman}"
# Set default container command value if none set
case "${container_cmd}" in
docker|podman) ;;
*) die "container command is expected to be one of 'docker' or 'podman'" ;;
esac
shift $((OPTIND - 1))
case "${1:-test}" in
'help') usage; exit 0;;
'test') gbp_test; exit ${?};;
'package') gbp_package; exit ${?};;
*) die "bad action: ${1}";;
esac
|