Files
jarl/scripts/mkdeb.sh
T
abrown38andClaude Opus 5.5 4d00be53c3
release / release (push) Successful in 7m7s
Split the packages, publish releases from Gitea Actions, release 0.1.0
make deb now builds two packages: jarl-cli (the CLI, its completion and
the ACME hooks, no scripts) and jarl (the server), which depends on
jarl-cli of the same version.

Pushing a v* tag runs .gitea/workflows/release.yml: it tests, builds the
tarballs, the CLI for Linux, macOS and Windows (make cli-dist) and the
.debs for amd64 and arm64, then scripts/gitea-release.sh creates the
Gitea release and uploads the .debs to the Debian package registry, so
servers install and upgrade with apt. The stats package's inode lookup
is split by OS so the CLI builds for Windows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 08:40:56 +00:00

120 lines
4.9 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"
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