Files
DDI/scripts/build-release.sh
T

139 lines
4.7 KiB
Bash
Executable File

#!/usr/bin/env bash
# SPDX-License-Identifier: Apache-2.0
#
# Builds release artefacts: static binaries for each target platform, one
# tarball per binary and platform (binary, its systemd unit for
# /usr/local/bin, LICENSE and LICENSES/), and SHA256SUMS.
#
# Usage: scripts/build-release.sh [-o OUTDIR] [-p "linux/amd64 linux/arm64"]
#
# Names and version come from the environment (set by the Makefile, ADR 0018):
# VERSION, COMMIT, BUILD_DATE, PRODUCT, DISPLAY_NAME,
# BIN_SERVER, BIN_AGENT_DNS, BIN_AGENT_DHCP, KEYGEN_ACCOUNT_ID, KEYGEN_PUBLIC_KEY
# The web UI must be built beforehand (make web); the script refuses to build
# a server release without it.
set -euo pipefail
readonly MODULE="git.beugsiud.de/beug.k/DDI"
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}"
KEYGEN_ACCOUNT_ID="${KEYGEN_ACCOUNT_ID:?KEYGEN_ACCOUNT_ID must be set (see Makefile)}"
KEYGEN_PUBLIC_KEY="${KEYGEN_PUBLIC_KEY:?KEYGEN_PUBLIC_KEY must be set (see Makefile)}"
outdir="dist"
platforms="linux/amd64 linux/arm64"
usage() {
sed -n '4,14p' "$0" | sed 's/^# \{0,1\}//'
}
while getopts ":o:p:h" opt; do
case "$opt" in
o) outdir="$OPTARG" ;;
p) platforms="$OPTARG" ;;
h)
usage
exit 0
;;
*)
usage >&2
exit 2
;;
esac
done
cd "$(git rev-parse --show-toplevel)"
VERSION="${VERSION:-$(git describe --tags --always --dirty 2>/dev/null || echo dev)}"
COMMIT="${COMMIT:-$(git rev-parse HEAD 2>/dev/null || echo unknown)}"
# Commit time keeps builds reproducible.
BUILD_DATE="${BUILD_DATE:-$(git log -1 --format=%cI 2>/dev/null || date -u +%Y-%m-%dT%H:%M:%SZ)}"
if [[ ! -f web/dist/index.html ]]; then
echo "web/dist/index.html missing: build the web UI first (make web)" >&2
exit 1
fi
for value in "$VERSION" "$COMMIT" "$BUILD_DATE" "$PRODUCT" "$DISPLAY_NAME" \
"$BIN_SERVER" "$BIN_AGENT_DNS" "$BIN_AGENT_DHCP"; do
if [[ "$value" == *"'"* ]]; then
echo "build variables must not contain single quotes: ${value}" >&2
exit 1
fi
done
# -X values are single-quoted so that names may contain spaces; go build
# splits -ldflags with shell-like quoting.
ldflags="-s -w"
add_x() { ldflags+=" -X '${MODULE}/$1=$2'"; }
add_x internal/buildinfo.Version "$VERSION"
add_x internal/buildinfo.Commit "$COMMIT"
add_x internal/buildinfo.Date "$BUILD_DATE"
add_x internal/brand.Product "$PRODUCT"
add_x internal/brand.DisplayName "$DISPLAY_NAME"
add_x internal/brand.ServerBinary "$BIN_SERVER"
add_x internal/brand.AgentDNSBinary "$BIN_AGENT_DNS"
add_x internal/brand.AgentDHCPBinary "$BIN_AGENT_DHCP"
add_x internal/brand.ConfigDir "/etc/${PRODUCT}"
add_x internal/brand.StateDir "/var/lib/${PRODUCT}"
add_x internal/brand.LogDir "/var/log/${PRODUCT}"
# Only the server links the license package; the agents ignore these flags.
add_x server/internal/license.EmbeddedAccountID "$KEYGEN_ACCOUNT_ID"
add_x server/internal/license.EmbeddedPublicKey "$KEYGEN_PUBLIC_KEY"
# binary name -> package
declare -A packages=(
["$BIN_SERVER"]="./server/cmd/ddi-server"
["$BIN_AGENT_DNS"]="./agent/cmd/ddi-agent-dns"
["$BIN_AGENT_DHCP"]="./agent/cmd/ddi-agent-dhcp"
)
workdir="$(mktemp -d)"
trap 'rm -rf "$workdir"' EXIT
rm -rf "$outdir"
mkdir -p "$outdir"
# systemd units for binaries in /usr/local/bin (ADR 0024); each tarball
# carries the unit of its binary.
units="${workdir}/units"
scripts/render-units.sh /usr/local/bin "$units"
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}"
stage="${workdir}/${name}"
mkdir -p "$stage"
echo "building ${name}"
CGO_ENABLED=0 GOOS="$goos" GOARCH="$goarch" \
go build -trimpath -buildvcs=false -ldflags "$ldflags" \
-o "${stage}/${bin}" "${packages[$bin]}"
# Unit and license texts: LICENSE says which license covers what
# (the server is proprietary, the unit files are Apache-2.0).
cp "${units}/${bin}.service" "${stage}/${bin}.service"
cp LICENSE "${stage}/LICENSE"
mkdir -p "${stage}/LICENSES"
cp LICENSES/*.txt "${stage}/LICENSES/"
chmod 0755 "${stage}" "${stage}/LICENSES" "${stage}/${bin}"
chmod 0644 "${stage}/${bin}.service" "${stage}/LICENSE" "${stage}/LICENSES/"*.txt
# Reproducible tarball: fixed order, owner and timestamps.
tar --sort=name --owner=0 --group=0 --numeric-owner \
--mtime="$BUILD_DATE" -C "$workdir" -cf - "$name" |
gzip -n -9 >"${outdir}/${name}.tar.gz"
done
done
(cd "$outdir" && sha256sum -- *.tar.gz >SHA256SUMS)
echo "artefacts in ${outdir}:"
cat "${outdir}/SHA256SUMS"