summaryrefslogtreecommitdiff
path: root/WORKFLOW.org
blob: 95fdb2570a5091307e12f542f30e3204ff911b93 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#+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.