Skip to content

Commit

Permalink
releng/make-binary.sh: use containerized image builds
Browse files Browse the repository at this point in the history
Using podman to containerize the production of release assets avoids
potential leakage of personal information. To support this, the
containerized build script has been modified to separate the repo path
at /zbm from a "build" directory (previously /zbm/contrib/docker was
hard coded, now it's just the default choice). The releng script creates
a temporary directory to serve as the "build" path, populates configs,
and runs the build container with the current repo at /zbm and the
temporary directory at /build. The outputs are copied as before, with
the EFI executable standing alone and the kernel/initramfs components
stored in a gzipped tarball.

If the releng script does not find the expected builder image
(zbm-builder by default, but this can be passed as a second argument to
the script), it will invoke `podman build` to create the image.
  • Loading branch information
ahesford committed Jul 20, 2021
1 parent 4166967 commit cfa0455
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 69 deletions.
15 changes: 12 additions & 3 deletions contrib/docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,28 @@

# Use the official Void Linux container
FROM voidlinux/voidlinux:latest
ARG ZBM_COMMIT_HASH

# Ensure everything is up-to-date
RUN xbps-install -Suy xbps && xbps-install -uy

# Prefer an LTS version over whatever Void thinks is current
RUN echo "ignorepkg=linux" > /etc/xbps.d/10-nolinux.conf \
&& echo "ignorepkg=linux-headers" >> /etc/xbps.d/10-nolinux.conf

# Install components necessary to build the image
RUN xbps-query -Rp run_depends zfsbootmenu | xargs xbps-install -y
RUN xbps-install -y linux linux-headers zfs gummiboot-efistub
RUN xbps-install -y linux5.10 linux5.10-headers zfs gummiboot-efistub

# Record a commit hash if one was provided
RUN if [ -n "${ZBM_COMMIT_HASH}" ]; then echo "${ZBM_COMMIT_HASH}" > /etc/zbm-commit-hash; fi

# Copy the build script
COPY zbm-build.sh /zbm-build.sh

# To replace the default ZFSBootMenu tree, bind-mount over /zbm
VOLUME /zbm

# Make sure a configuration exists or copy the default, then create the images
CMD /zbm-build.sh
# Run the build script with no arguments by default
ENTRYPOINT [ "/zbm-build.sh" ]
CMD [ ]
20 changes: 16 additions & 4 deletions contrib/docker/zbm-build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,31 @@ error() {
if ls -Aq /zbm | grep -q . >/dev/null 2>&1; then
# If /zbm is not empty, make sure it looks like it has what we need
[ -d /zbm/90zfsbootmenu ] || error "missing path /zbm/90zfsbootmenu"
[ -d /zbm/contrib/docker ] || error "missing path /zbm/contrib/docker"
[ -x /zbm/bin/generate-zbm ] || error "missing executable /zbm/bin/generate-zbm"
else
# If /zbm is empty, clone the upstream repo into it
xbps-install -Sy git
git clone --depth=1 https://github.com/zbm-dev/zfsbootmenu /zbm
git clone https://github.com/zbm-dev/zfsbootmenu /zbm

# If the run specifies $ZBM_COMMIT_HASH, check out the hash
# Get a default value for ZBM_COMMIT_HASH from /etc/zbm-commit-hash
if [ -z "${ZBM_COMMIT_HASH}" ] && [ -r "/etc/zbm-commit-hash" ]; then
read -r ZBM_COMMIT_HASH < /etc/zbm-commit-hash
fi

if [ -n "${ZBM_COMMIT_HASH}" ]; then
if ! ( cd /zbm && git checkout -q "${ZBM_COMMIT_HASH}" ); then
error "failed to checkout commit, aborting"
fi
fi
fi

BUILDROOT="${1:-/zbm/contrib/docker}"
[ -d "${BUILDROOT}" ] || error "Build root does not appear to exist"

# Make sure that dracut can find the ZFSBootMenu module
ln -sf /zbm/90zfsbootmenu /usr/lib/dracut/modules.d/90zfsbootmenu

BUILDROOT="/zbm/contrib/docker"

if [ ! -e "${BUILDROOT}/config.yaml" ]; then
# If there is no provided config, copy the default
cp "${BUILDROOT}/config.yaml.default" "${BUILDROOT}/config.yaml"
Expand Down
134 changes: 72 additions & 62 deletions releng/make-binary.sh
Original file line number Diff line number Diff line change
@@ -1,102 +1,112 @@
#!/bin/bash
# vim: softtabstop=2 shiftwidth=2 expandtab

error() {
echo "ERROR:" "$@"
exit 1
}

cleanup() {
test -d "${temp}" && rm -rf "${temp}"
test -d "${buildtmp}" && rm -rf "${buildtmp}"
unset buildtmp
exit
}

release="${1?ERROR: no release version specified}"
unset buildtmp
trap cleanup EXIT INT TERM
temp="$( mktemp -d )"

if [ ! -d /usr/lib/dracut ]; then
echo "ERROR: missing /usr/lib/dracut"
exit 1
fi
# Accept release with or without a leading "v"
release="${1#v}"

DRACUTBIN="$( command -v dracut )"
if [ ! -x "${DRACUTBIN}" ]; then
echo "ERROR: missing dracut script"
exit 1
fi
case "${release}" in
"") error "usage: $0 <release> [buildtag]" ;;
*/*) error "release must NOT contain a forward slash" ;;
*) ;;
esac

assets="$( realpath -e releng)/assets/${release}"
if [ -d "${assets}" ]; then
rm -f "${assets}"/*
else
mkdir -p "${assets}"
fi
buildtag="${2:-localhost/zbm-builder:$(date '+%Y%m%d')}"
if ! podman inspect "${buildtag}" >/dev/null 2>&1; then
if ! bldctx="$( realpath -e contrib/docker )"; then
error "missing contrib/docker, cannot create image ${buildtag}"
fi

if ZBM_COMMIT_HASH="$(git rev-parse HEAD)" && [ -n "${ZBM_COMMIT_HASH}" ]; then
build_args=( "--build-arg=ZBM_COMMIT_HASH=${ZBM_COMMIT_HASH}" )
else
build_args=()
fi

cp -a /usr/lib/dracut "${temp}"
cp "${DRACUTBIN}" "${temp}/dracut"
if ! podman build -t "${buildtag}" "${build_args[@]}" "${bldctx}"; then
error "failed to create builder image"
fi
fi

cp -Rp etc/zfsbootmenu/dracut.conf.d "${temp}"
buildtmp="$( mktemp -d )"

cat << EOF > "${temp}/dracut.conf.d/release.conf"
omit_drivers+=" amdgpu radeon nvidia nouveau i915 "
omit_dracutmodules+=" qemu qemu-net crypt-ssh nfs lunmask network network-legacy kernel-network-modules "
embedded_kcl="rd.hostonly=0"
release_build=1
zfsbootmenu_teardown+=" $( realpath contrib/xhci-teardown.sh ) "
EOF
mkdir -p "${buildtmp}/dracut.conf.d"

_dracut_mods="${temp}/dracut/modules.d"
if [ -d "${_dracut_mods}/90zfsbootmenu" ] ; then
if ! rm -rf "${_dracut_mods}/90zfsbootmenu" ; then
echo "Unable to remove ${_dracut_mods}/90zfsbootmenu"
exit 1
fi
# Copy default dracut configuration and include a release-specific config
if ! cp etc/zfsbootmenu/dracut.conf.d/* "${buildtmp}/dracut.conf.d"; then
error "failed to copy dracut configuration"
fi

ln -s "$(realpath -e 90zfsbootmenu)" "${_dracut_mods}"
ln -s "$(realpath -e bin/generate-zbm)" "${temp}/generate-zbm"
cat <<-EOF > "${buildtmp}/dracut.conf.d/release.conf"
zfsbootmenu_teardown+="/zbm/contrib/xhci-teardown.sh"
install_optional_items+=" /etc/zbm-commit-hash "
omit_drivers+=" amdgpu radeon nvidia nouveau i915 "
omit_dracutmodules+=" network network-legacy kernel-network-modules "
omit_dracutmodules+=" qemu qemu-net crypt-ssh nfs lunmask "
embedded_kcl="rd.hostonly=0"
release_build=1
EOF

yamlconf="${buildtmp}/config.yaml"

yamlconf="${temp}/local.yaml"
cp etc/zfsbootmenu/config.yaml "${yamlconf}"
build="${temp}/build"
if ! cp etc/zfsbootmenu/config.yaml "${yamlconf}"; then
error "failed to copy default ZFSBootMenu configuration"
fi

arch="$( uname -m )"
BUILD_EFI="false"

case "${arch}" in
x86_64)
BUILD_EFI="true"
;;
*)
;;
x86_64) BUILD_EFI="true" ;;
*) ;;
esac

zbmtriplet="zfsbootmenu-${arch}-v${release}"

# Modify the YAML configuration for the containerized build
yq-go eval ".Components.Enabled = true" -i "${yamlconf}"
yq-go eval ".Components.Versions = false" -i "${yamlconf}"
yq-go eval ".Components.ImageDir = \"${build}\"" -i "${yamlconf}"
yq-go eval ".Components.ImageDir = \"/build/${zbmtriplet}\"" -i "${yamlconf}"
yq-go eval ".EFI.Enabled = ${BUILD_EFI}" -i "${yamlconf}"
yq-go eval ".EFI.Versions = false" -i "${yamlconf}"
yq-go eval ".EFI.ImageDir = \"${build}\"" -i "${yamlconf}"
yq-go eval ".EFI.ImageDir = \"/build/uefi\"" -i "${yamlconf}"
yq-go eval ".Global.ManageImages = true" -i "${yamlconf}"
yq-go eval ".Global.DracutConfDir = \"${temp}/dracut.conf.d\"" -i "${yamlconf}"
yq-go eval ".Global.DracutFlags = [ \"--local\", \"--no-early-microcode\" ]" -i "${yamlconf}"
yq-go eval ".Global.DracutConfDir = \"/build/dracut.conf.d\"" -i "${yamlconf}"
yq-go eval ".Global.DracutFlags = [ \"--no-early-microcode\" ]" -i "${yamlconf}"
yq-go eval ".Kernel.CommandLine = \"loglevel=4 nomodeset\"" -i "${yamlconf}"
yq-go eval "del(.Global.BootMountPoint)" -i "${yamlconf}"
yq-go eval "del(.Kernel.CommandLine)" -i "${yamlconf}"

if ! ( cd "${temp}" && PATH=./dracut:${PATH} ./generate-zbm \
--version "${release}" \
--config "${yamlconf}" \
--cmdline "loglevel=4 nomodeset" ) ; then
# For the containerized build, use current repo by mounting at /zbm
# Custom configs and outputs will be in the temp dir, mounted at /build
podman run --rm -v ".:/zbm:ro" -v "${buildtmp}:/build" "${buildtag}" "/build" || exit 1

echo "ERROR: Unable to create images"
exit 1
if ! assets="$( realpath -e releng )/assets/${release}"; then
error "unable to define path to built assets"
fi

if [ -d "${assets}" ]; then
rm -f "${assets}"/*
else
mkdir -p "${assets}"
fi

# EFI file is currently only built on x86_64
if [ "${BUILD_EFI}" = "true" ]; then
mv "${build}/vmlinuz.EFI" "${assets}/zfsbootmenu-${arch}-v${release}.EFI"
cp "${buildtmp}/uefi/vmlinuz.EFI" "${assets}/${zbmtriplet}.EFI" || exit 1
fi

# Components are always built
components="${build}/zfsbootmenu-${arch}-v${release}"
mkdir -p "${components}"
mv "${build}/initramfs-bootmenu.img" "${components}"
mv "${build}/vmlinuz-bootmenu" "${components}"

( cd "${build}" && tar czvf "${assets}/zfsbootmenu-${arch}-v${release}.tar.gz" "$( basename "${components}" )" ) || exit 1
( cd "${buildtmp}" && tar czvf "${assets}/${zbmtriplet}.tar.gz" "${zbmtriplet}" ) || exit 1

0 comments on commit cfa0455

Please sign in to comment.