Files
DDI/scripts/build-packages.sh
T
sir_melonchenandClaude Opus 5.5 73a1001d80
ci / Go (lint, test, vuln) (push) Successful in 3m45s
ci / End-to-end (server, agents, BIND, Kea) (push) Successful in 3m8s
ci / Protobuf (push) Successful in 8s
ci / Web (lint, test, audit, build) (push) Successful in 1m24s
ci / Shell and licence headers (push) Successful in 9s
ci / Release build (dry run) (push) Successful in 2m57s
ci / Integration (real BIND and Kea) (push) Failing after 2m10s
ci / Development environment (compose) (push) Successful in 15s
chore: neutral default package maintainer
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 00:49:13 +02:00

159 lines
5.1 KiB
Bash
Executable File

#!/usr/bin/env bash
# SPDX-License-Identifier: Apache-2.0
#
# Builds .deb and .rpm packages with nfpm from the release tarballs in DIST
# (made by scripts/build-release.sh) and rewrites DIST/SHA256SUMS to cover
# tarballs and packages (ADR 0024).
#
# Usage: scripts/build-packages.sh [-d DIST] [-p "linux/amd64 linux/arm64"]
#
# Each package holds the binary from its tarball as /usr/bin/<binary>, the
# systemd unit rendered for /usr/bin and the license text. Names and version
# come from the environment (Makefile, ADR 0018): VERSION, PRODUCT,
# DISPLAY_NAME, BIN_SERVER, BIN_AGENT_DNS, BIN_AGENT_DHCP. NFPM names the
# nfpm binary (default: nfpm from PATH, installed by scripts/ci/install-tools.sh).
# Optional: PKG_MAINTAINER, PKG_VENDOR, PKG_HOMEPAGE.
set -euo pipefail
PRODUCT="${PRODUCT:-ddi-suite}"
DISPLAY_NAME="${DISPLAY_NAME:-DDI-Suite}"
BIN_SERVER="${BIN_SERVER:-ddi-server}"
BIN_AGENT_DNS="${BIN_AGENT_DNS:-ddi-agent-dns}"
BIN_AGENT_DHCP="${BIN_AGENT_DHCP:-ddi-agent-dhcp}"
NFPM="${NFPM:-nfpm}"
dist="dist"
platforms="linux/amd64 linux/arm64"
usage() {
sed -n '4,16p' "$0" | sed 's/^# \{0,1\}//'
}
while getopts ":d:p:h" opt; do
case "$opt" in
d) dist="$OPTARG" ;;
p) platforms="$OPTARG" ;;
h)
usage
exit 0
;;
*)
usage >&2
exit 2
;;
esac
done
root="$(git rev-parse --show-toplevel)"
cd "$root"
if ! command -v "$NFPM" >/dev/null; then
echo "nfpm not found (set NFPM or run scripts/ci/install-tools.sh)" >&2
exit 1
fi
VERSION="${VERSION:-$(git describe --tags --always --dirty 2>/dev/null || echo dev)}"
BUILD_DATE="${BUILD_DATE:-$(git log -1 --format=%cI 2>/dev/null || date -u +%Y-%m-%dT%H:%M:%SZ)}"
# Package versions must be semantic versions: v1.2.3 -> 1.2.3; anything else
# (a commit hash, "dev") becomes a 0.0.0 pre-release that sorts below every
# real release.
if [[ "$VERSION" =~ ^v?([0-9]+\.[0-9]+\.[0-9]+([-+][0-9A-Za-z.+-]*)?)$ ]]; then
pkg_version="${BASH_REMATCH[1]}"
else
pkg_version="0.0.0-dev.$(tr -c '0-9A-Za-z.\n' '.' <<<"$VERSION")"
fi
# Reproducible timestamps inside the packages.
SOURCE_DATE_EPOCH="$(date -u -d "$BUILD_DATE" +%s 2>/dev/null || echo 0)"
export SOURCE_DATE_EPOCH
declare -A descriptions=(
["$BIN_SERVER"]="${DISPLAY_NAME} management server (IPAM, DNS and DHCP)"
["$BIN_AGENT_DNS"]="${DISPLAY_NAME} agent for BIND 9"
["$BIN_AGENT_DHCP"]="${DISPLAY_NAME} agent for Kea DHCPv4"
)
declare -A licenses=(
["$BIN_SERVER"]="LICENSES/LicenseRef-DDI-Proprietary.txt"
["$BIN_AGENT_DNS"]="LICENSES/Apache-2.0.txt"
["$BIN_AGENT_DHCP"]="LICENSES/Apache-2.0.txt"
)
declare -A license_names=(
["$BIN_SERVER"]="Proprietary"
["$BIN_AGENT_DNS"]="Apache-2.0"
["$BIN_AGENT_DHCP"]="Apache-2.0"
)
workdir="$(mktemp -d)"
trap 'rm -rf "$workdir"' EXIT
# Git Bash on Windows (development): nfpm.exe needs Windows paths.
if command -v cygpath >/dev/null; then
workdir="$(cygpath -m "$workdir")"
fi
export PRODUCT DISPLAY_NAME BIN_SERVER BIN_AGENT_DNS BIN_AGENT_DHCP
scripts/render-units.sh /usr/bin "$workdir/units"
PKG_MAINTAINER="${PKG_MAINTAINER:-${DISPLAY_NAME} <maintainer@example.invalid>}"
PKG_VENDOR="${PKG_VENDOR:-$DISPLAY_NAME}"
PKG_HOMEPAGE="${PKG_HOMEPAGE:-https://git.beugsiud.de/beug.k/DDI}"
# render_config NAME ARCH SRC_DIR LICENSE DESCRIPTION > nfpm.yaml
render_config() {
local -a subst=(
PKG_NAME "$1" PKG_ARCH "$2" PKG_SRC_DIR "$3" PKG_LICENSE "$4" PKG_DESCRIPTION "$5"
PKG_VERSION "$pkg_version" PKG_MAINTAINER "$PKG_MAINTAINER" PKG_VENDOR "$PKG_VENDOR"
PKG_HOMEPAGE "$PKG_HOMEPAGE" PKG_SCRIPTS_DIR "$root/deploy/nfpm"
)
local -a expr=()
local i value
for ((i = 0; i < ${#subst[@]}; i += 2)); do
value="${subst[i + 1]}"
# The values end up in sed replacements and double-quoted YAML.
if [[ "$value" == *[\|\&\\\"]* ]]; then
echo "unsafe value for ${subst[i]}: ${value}" >&2
exit 2
fi
expr+=(-e "s|@${subst[i]}@|${value}|g")
done
sed "${expr[@]}" deploy/nfpm/package.yaml.in
}
for platform in $platforms; do
goos="${platform%/*}"
goarch="${platform#*/}"
for bin in "$BIN_SERVER" "$BIN_AGENT_DNS" "$BIN_AGENT_DHCP"; do
name="${bin}_${VERSION}_${goos}_${goarch}"
tarball="${dist}/${name}.tar.gz"
if [[ ! -f "$tarball" ]]; then
echo "missing ${tarball}: run make release first" >&2
exit 1
fi
src="${workdir}/${name}"
mkdir -p "$src"
tar -xzf "$tarball" -C "$workdir" "${name}/${bin}"
mv "${workdir}/${name}/${bin}" "${src}/binary"
cp "$workdir/units/${bin}.service" "${src}/unit.service"
cp "${licenses[$bin]}" "${src}/LICENSE"
render_config "$bin" "$goarch" "$src" "${license_names[$bin]}" "${descriptions[$bin]}" >"${src}/nfpm.yaml"
if grep -q '@[A-Z_]*@' "${src}/nfpm.yaml"; then
echo "unreplaced placeholder in the nfpm configuration of ${name}" >&2
exit 1
fi
for packager in deb rpm; do
echo "packaging ${bin} ${pkg_version} ${goarch} (${packager})"
"$NFPM" package --config "${src}/nfpm.yaml" --packager "$packager" --target "$dist/" >/dev/null
done
done
done
(
cd "$dist"
shopt -s nullglob
sha256sum -- *.tar.gz *.deb *.rpm >SHA256SUMS
)
echo "artefacts in ${dist}:"
cat "${dist}/SHA256SUMS"