Files
jarl/scripts/mkdeb.sh
abrown38andClaude Opus 5.5 e1bcb5d479 Give development builds their own Debian package version
make deb versions a build that isn't a release after the last tag:
0.2.0~rc.1+git3.gca0f148, plus the build time (.m<UTC time>) with
uncommitted changes. apt sorts it after that RC and before the next, so
installing it over the RC or an older build is an upgrade and needs no
--reinstall. mkdeb.sh removes older packages of the same architecture
from dist/ so the install globs match one package.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 15:28:18 +00:00

123 lines
5.1 KiB
Bash
Executable File

#!/bin/sh
# Builds Jarl's two Debian packages:
#
# dist/jarl-cli_<version>_<arch>.deb the CLI, to install anywhere:
# /usr/bin/jarl, its bash completion, and /usr/share/doc/jarl-cli/
# (README, CHANGELOG, the CLI, ACME and permissions docs, contrib/ with
# the acme.sh and lego hooks). No scripts: installing it changes nothing
# else on the machine.
# dist/jarl_<version>_<arch>.deb the server, which depends on
# jarl-cli of the same version:
# /usr/bin/jarld and its bash completion
# /usr/lib/systemd/system/{jarl.service,jarl-backup.service,jarl-backup.timer}
# /usr/lib/sysusers.d/jarl.conf, /usr/lib/tmpfiles.d/jarl.conf
# /usr/share/doc/jarl/ (README, CHANGELOG, docs)
# Its scripts (deploy/debian) create the jarl user and directories and
# /etc/jarl/jarl.yaml on the first install, turn on the daily backup
# timer, restart a running jarld on upgrades, and stop both on removal.
# No file in /etc belongs to the package, so an upgrade never asks
# about configuration files.
#
# Until 0.1.0 one package, jarl, held both; jarl-cli takes /usr/bin/jarl
# over from it (Replaces: jarl).
#
# Run through 'make deb' (which sets the variables below); needs only
# dpkg-deb, no root and no debhelper.
#
# Variables: DEB_ARCH (Debian architecture, e.g. amd64, arm64, armhf),
# DEB_VERSION, VERSION, LDFLAGS, GOFLAGS, and DEB_MAINTAINER (default: your
# git name and email).
set -eu
: "${DEB_ARCH:?}" "${DEB_VERSION:?}" "${VERSION:?}" "${LDFLAGS:?}"
GOFLAGS=${GOFLAGS:-}
# Debian architecture -> Go architecture.
goarm=
case "$DEB_ARCH" in
amd64) goarch=amd64 ;;
arm64) goarch=arm64 ;;
armhf) goarch=arm goarm=7 ;;
i386) goarch=386 ;;
ppc64el) goarch=ppc64le ;;
riscv64) goarch=riscv64 ;;
s390x) goarch=s390x ;;
*) echo "mkdeb: unsupported architecture $DEB_ARCH" >&2; exit 1 ;;
esac
if [ -z "${DEB_MAINTAINER:-}" ]; then
name=$(git config user.name 2>/dev/null || true)
email=$(git config user.email 2>/dev/null || true)
DEB_MAINTAINER="${name:-Jarl packager} <${email:-root@localhost}>"
fi
work=dist/deb/${DEB_VERSION}_${DEB_ARCH}
stage=$work/stage
rm -rf "$work"
# Older packages of this architecture (every development build has its
# own version), so 'apt install ./dist/jarl_*_amd64.deb' finds just one.
rm -f dist/jarl_*_"$DEB_ARCH".deb dist/jarl-cli_*_"$DEB_ARCH".deb
mkdir -p "$stage"
# Binaries for the package's architecture (bin/ holds the host's, which
# also generated the completion scripts).
echo "mkdeb: building for linux/$goarch"
# go reads GOFLAGS (-trimpath) from the environment.
export GOFLAGS
GOOS=linux GOARCH=$goarch GOARM=$goarm CGO_ENABLED=0 go build -ldflags "$LDFLAGS" -o "$work/bin/jarld" ./cmd/jarld
GOOS=linux GOARCH=$goarch GOARM=$goarm CGO_ENABLED=0 go build -ldflags "$LDFLAGS" -o "$work/bin/jarl" ./cmd/jarl
# Everything 'make install' would install, then split in two.
make --no-print-directory install-files DESTDIR="$stage" PREFIX=/usr \
UNITDIR=/usr/lib/systemd/system JARLD_BIN="$work/bin/jarld" JARL_BIN="$work/bin/jarl" >/dev/null
cli=$work/jarl-cli
srv=$work/jarl
mkdir -p "$cli/DEBIAN" "$cli/usr/bin" "$cli/usr/share/bash-completion/completions" "$cli/usr/share/doc/jarl-cli/docs"
mv "$stage/usr/bin/jarl" "$cli/usr/bin/"
mv "$stage/usr/share/bash-completion/completions/jarl" "$cli/usr/share/bash-completion/completions/"
mv "$stage/usr/share/doc/jarl/contrib" "$cli/usr/share/doc/jarl-cli/"
cp "$stage/usr/share/doc/jarl/README.md" "$stage/usr/share/doc/jarl/CHANGELOG.md" "$cli/usr/share/doc/jarl-cli/"
for d in cli acme permissions; do
cp "$stage/usr/share/doc/jarl/docs/$d.md" "$cli/usr/share/doc/jarl-cli/docs/"
done
mv "$stage" "$srv"
mkdir -p "$srv/DEBIAN"
for f in postinst prerm postrm; do
install -m 0755 "deploy/debian/$f" "$srv/DEBIAN/$f"
done
# Debian's machine-readable copyright file, from LICENSE.
indent() { sed -e 's/^$/./' -e 's/^/ /' "$1"; }
copyright() {
echo "Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/"
echo "Upstream-Name: jarl"
echo
echo "Files: *"
echo "Copyright: $(sed -n 's/^Copyright (c) //p' LICENSE)"
echo "License: Expat"
indent LICENSE
}
# build PACKAGE ROOT: writes the control file and md5sums and builds the .deb.
build() {
pkg=$1 root=$2 out=dist/${1}_${DEB_VERSION}_${DEB_ARCH}.deb
copyright > "$root/usr/share/doc/$pkg/copyright"
rm -f "$root/usr/share/doc/$pkg/LICENSE"
# Directories 0755 and no group/other write, whatever the build's umask.
find "$root" -type d -exec chmod 0755 {} +
chmod -R go-w "$root"
size=$(du -sk --exclude=DEBIAN "$root" | cut -f1)
sed -e "s/@VERSION@/$DEB_VERSION/g" -e "s/@ARCH@/$DEB_ARCH/" -e "s/@SIZE@/$size/" \
-e "s|@MAINTAINER@|$DEB_MAINTAINER|" "deploy/debian/control-$pkg.in" > "$root/DEBIAN/control"
(cd "$root" && find . -path ./DEBIAN -prune -o -type f -print | sed 's|^\./||' | sort | xargs md5sum) > "$root/DEBIAN/md5sums"
chmod 0644 "$root/DEBIAN/control" "$root/DEBIAN/md5sums"
# Files belong to root in the package, whoever builds it.
dpkg-deb --root-owner-group -Zxz --build "$root" "$out" >/dev/null
echo "mkdeb: wrote $out"
dpkg-deb --info "$out" | sed -n 's/^ \(Package\|Version\|Architecture\|Installed-Size\|Depends\):/ \1:/p'
}
build jarl-cli "$cli"
build jarl "$srv"
rm -rf dist/deb