#+title: Workflow #+author: cashmere * Overview This repository contains custom FreeBSD ports. The goal is to build and test them in an isolated jail using the standard FreeBSD tooling rather than ad-hoc =make DISTFILES=...= invocations. * Tool choice: poudriere After comparing the common FreeBSD port building tools: - *poudriere* :: The standard tool for building and testing ports in isolated jails. Supports ZFS, overlays, reproducible bulk builds, and =testport= for individual ports. Best fit for this workflow. - *synth* :: A lighter alternative, but less commonly used for custom port trees and lacks the overlay/jail flexibility of poudriere. - *portmaster* / plain =make= :: Good for installing packages on a live system, but do not provide isolated build environments, so they do not solve the "rebuild everything from source" problem. * Layout #+begin_example ~/ports ├── devel/ │ ├── bash-language-server/ │ ├── just-lsp/ │ ├── nixd/ │ ├── py-rassumfrassum/ │ ├── pyrefly/ │ └── yaml-language-server/ ├── distfiles/ # shared distfiles cache ├── misc/ │ └── kimi-code/ ├── security/ │ └── pinentry-emacs/ ├── WORKFLOW.org # this file └── .agent-shell/ └── poudriere.conf # reference config #+end_example Each category directory (=devel/=, =security/=, etc.) mirrors the top-level layout of the official Ports Collection. * Setup instructions ** 1. Install poudriere #+begin_src sh doas pkg install -y poudriere #+end_src ** 2. Configure poudriere #+begin_src sh doas cp ~/ports/.agent-shell/poudriere.conf /usr/local/etc/poudriere.conf #+end_src Key settings: - =ZPOOL=zroot= :: reuse the existing ZFS pool. - =DISTFILES_CACHE=/home/cashmere/ports/distfiles= :: share the distfiles already collected in this repo. - =PACKAGE_FETCH_BRANCH=quarterly= and =PACKAGE_FETCH_URL=pkg+https://pkg.FreeBSD.org/FreeBSD:15:amd64= :: tell poudriere to fetch official binary packages for dependencies instead of compiling everything from source. Important: the official ports tree (=/usr/ports=) must be kept on the same quarterly branch as the binary repository. See step 4 below. ** 3. Create a build jail Use a jail matching the host version (15.1-RELEASE at the time of writing): #+begin_src sh doas poudriere jail -c -j 151amd64 -v 15.1-RELEASE -a amd64 #+end_src ** 4. Create a ports tree overlay The base tree must track the same quarterly branch as the binary package repository configured in step 2. For FreeBSD 15.1 amd64 the current quarterly branch is =2026Q3=. #+begin_src sh # Base tree from the official ports collection doas poudriere ports -c -p base -m null -M /usr/ports # Overlay pointing at this repository doas poudriere ports -c -p custom -m null -M /home/cashmere/ports #+end_src Then tell poudriere to use the overlay: #+begin_src sh doas poudriere ports -u -p base doas poudriere ports -u -p custom #+end_src To switch an existing =/usr/ports= checkout to quarterly: #+begin_src sh cd /usr/ports git config --global --add safe.directory /usr/ports git fetch origin 2026Q3 git checkout -B 2026Q3 FETCH_HEAD #+end_src After that, update with: #+begin_src sh cd /usr/ports && git pull origin 2026Q3 #+end_src * Building a port The easiest port to validate the workflow is =devel/py-rassumfrassum= (pure Python, small dependency tree). To build and test it in the isolated jail: #+begin_src sh doas poudriere testport -j 151amd64 -p base -O custom -o devel/py-rassumfrassum #+end_src For a bulk build of a list: #+begin_src sh cat > /tmp/pkglist <<'EOF' devel/py-rassumfrassum EOF doas poudriere bulk -j 151amd64 -p base -O custom -f /tmp/pkglist #+end_src Once =py-rassumfrassum= builds cleanly, heavier ports like =devel/pyrefly= can be added to the list. Avoid using =security/pinentry-emacs= as a smoke test — it depends on =editors/emacs=, which pulls in a very large dependency tree (X11, GCC, etc.). * Validated workflow The following commands have been executed successfully: 1. First run (populated the empty jail with Python dependencies): #+begin_src sh doas poudriere testport -j 151amd64 -p base -O custom -o devel/py-rassumfrassum #+end_src Result: success, build time ~6 seconds. 2. Second run (reproducibility check): #+begin_src sh doas poudriere testport -j 151amd64 -p base -O custom -o devel/py-rassumfrassum #+end_src #+RESULT: success, build time ~3 seconds. 3. Node-based port with binary package prefetching: #+begin_src sh doas poudriere testport -j 151amd64 -p base -O custom -o devel/bash-language-server #+end_src #+RESULT: success. All official-tree dependencies (=www/node24=, =devel/cmake-core=, =devel/icu=, =dns/c-ares=, etc.) were fetched as binary packages; only =devel/bash-language-server= from the custom overlay was built from source.