clawdie-iso/scripts/poudriere/poudriere-build.sh
Sam & Claude 2dac2d108d feat(poudriere): lean scripts for first-party pkg.clawdie.si build server
Turns the manual Phase 2–3 runbook (docs/POUDRIERE-BUILD-SERVER.md) into
repeatable, idempotent steps for the mother-build host — the package half of
the trusted supply chain (layered-soul HIVE-ONBOARDING §10).

- poudriere-setup.sh: verify-then-act setup. Validates root, FreeBSD version
  format, pkg/openssl, and that the ZFS pool exists BEFORE acting; then installs
  poudriere, generates the repo signing key (0400), writes poudriere.conf (only
  if absent), and creates the build jail + ports tree. Re-running skips anything
  already present.
- poudriere-build.sh: validates jail, ports tree, and each origin (category/name
  + Makefile present) before `poudriere bulk`; repo is signed automatically via
  PKG_REPO_SIGNING_KEY.
- clawdie-repo.conf.in: client repo template (signature_type pubkey) + the
  first-party-only priority note.
- README.md: the three-step flow and conventions.

Style matches live/operator-session/hw-report: POSIX sh, set -u, fixed PATH,
strict arg parsing, minimal checks (only what is acted upon). Host provisioning
(ZFS/base/network) stays in the runbook — these assume a FreeBSD host with a
pool. sh -n clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 17:22:28 +02:00

72 lines
2.3 KiB
Bash
Executable file

#!/bin/sh
# Build one or more ports into the first-party repo with poudriere, then refresh
# repo metadata (signed via PKG_REPO_SIGNING_KEY in poudriere.conf). Validates
# the jail, ports tree, and each origin before building. Run as root.
set -u
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
export PATH
BASEFS="${POUDRIERE_BASEFS:-/usr/local/poudriere}"
JAIL="${POUDRIERE_JAIL:-clawdie-amd64}"
PTREE="${POUDRIERE_PTREE:-clawdie}"
usage() {
cat <<EOF
Usage: poudriere-build.sh [--jail NAME] [--ports NAME] ORIGIN [ORIGIN ...]
Builds each ORIGIN (category/name, e.g. sysutils/colibri) in the clean jail and
publishes signed packages to the first-party repo.
Options (or POUDRIERE_* env):
--jail NAME build jail (default: ${JAIL})
--ports NAME ports tree (default: ${PTREE})
-h, --help show this help
EOF
}
die() {
echo "ERROR: $*" >&2
exit 1
}
have() {
command -v "$1" >/dev/null 2>&1
}
while [ "$#" -gt 0 ]; do
case "$1" in
--jail) JAIL="${2:?--jail needs a value}"; shift 2 ;;
--ports) PTREE="${2:?--ports needs a value}"; shift 2 ;;
-h|--help) usage; exit 0 ;;
--) shift; break ;;
-*) echo "ERROR: unknown option: $1" >&2; usage >&2; exit 2 ;;
*) break ;;
esac
done
[ "$#" -ge 1 ] || { echo "ERROR: need at least one ORIGIN" >&2; usage >&2; exit 2; }
# --- verify, then act -------------------------------------------------------
[ "$(id -u)" -eq 0 ] || die "must run as root."
have poudriere || die "poudriere not found; run poudriere-setup.sh first."
poudriere jail -i -j "${JAIL}" >/dev/null 2>&1 || die "jail '${JAIL}' not found; run poudriere-setup.sh."
poudriere ports -l | awk 'NR>1 {print $1}' | grep -Fxq "${PTREE}" || die "ports tree '${PTREE}' not found."
_ports_root="${BASEFS}/ports/${PTREE}"
for _origin in "$@"; do
case "${_origin}" in
*/*) ;;
*) die "origin '${_origin}' must be category/name (e.g. sysutils/colibri)." ;;
esac
[ -f "${_ports_root}/${_origin}/Makefile" ] || \
die "port '${_origin}' not found under ${_ports_root}."
done
poudriere bulk -j "${JAIL}" -p "${PTREE}" "$@" || die "bulk build failed."
echo ""
echo "Build complete. Signed repo at:"
echo " ${BASEFS}/data/packages/${JAIL}-${PTREE}"
echo "Serve that directory over nginx at pkg.clawdie.si (see README.md)."