class

Beryl::Apply::PoudriereBuild

Inherits Beryl::Apply::Primitive < Reference < Object

Primitive poudriere-build : maintient un dépôt pkg poudriere à la dernière MINEURE d'un majeur FreeBSD figé, construit depuis un ou plusieurs OVERLAYS de ports, et publie l'alias par ABI (FreeBSD:<major>:<arch> → set courant) pour un client agnostique à la version (url: https://…/${ABI}).

Idempotent & réconciliateur. À chaque apply :

. compare la dernière release de la branche (FreebsdRelease.latest_by_branch) à ce que vise l'alias ; . pour chaque overlay : clone s'il est absent, sinon mise à jour git en AVANCE RAPIDE uniquement (fetch + merge --ff-only, cf. plus bas), enregistrement dans poudriere s'il ne l'est pas (poudriere ports -c -p <name> -m null -M <path>) ; . compare le commit de chaque overlay à celui du dernier build RÉUSSI (fichier d'état <pkgdir>/.beryl-build-<major>.overlays, une ligne <name> <commit>, écrit par le script de build seulement en fin de succès, juste après le repointage de l'alias).

Nouvelle mineure OU commit d'overlay différent (ou état inconnu) → build en DÉTACHÉ (daemon -f + log + lock anti-double-build), qui crée la jail au besoin, met à jour l'arbre default, poudriere bulk avec TOUS les overlays (-O a -O b, accumulés par poudriere) et la réunion des build-lists (-f x -f y, idem), retire les paquets périmés (poudriere pkgclean : ni listés ni dépendances, ex. un port renommé ; catalogue reconstruit), puis repointe l'alias et enregistre les commits construits. Rien de changé → skip.

Git : avance rapide seulement, jamais reset --hard sur un overlay. Des modifications suivies non commitées, une branche autre que celle attendue ou un historique divergé → Failed avec message (rien n'est écrasé). Des commits locaux non poussés (en avance) sont conservés et construits (signalés). Les fichiers non suivis (ex. un script local) n'empêchent rien. En dry-run, le commit distant est lu par git ls-remote (rien n'est modifié).

major FIGÉ (ex. "15") : suit 15.0 → 15.1 → 15.2 (même ABI, sûr) mais JAMAIS un saut de majeur (16.0 = nouvelle ABI). Pour ouvrir 16 : une 2ᵉ instance major: 16 → l'alias FreeBSD:16:amd64 cohabite ; un client bascule quand SA base passe en 16.

- poudriere-build:
    major: "15"
    overlays:
      - name: maison                  # nom de l'arbre poudriere (-O)
        pkglist: /usr/local/etc/poudriere.d/maison-pkglist
      - name: partenaire
        git: https://github.com/example/ports-overlay  # optionnel : clone + MAJ
        branch: production            # optionnel (défaut : branche courante / distante par défaut)
        path: /usr/local/poudriere/partenaire-ports # optionnel (défaut : /usr/local/poudriere/<name>-ports)
        pkglist: /usr/local/etc/poudriere.d/partenaire-pkglist   # optionnel
    reapply: /usr/local/etc/poudriere.d/reapply-base-patches.sh  # optionnel
    schedule: "0 3 * * 0"         # optionnel : build planifié (cron)
    ports_branch: quarterly       # optionnel : branche de l'arbre de ports

ports_branch : branche git de l'arbre de ports de base (ports), mise en place avant chaque build. quarterly = branche du trimestre EN COURS (2026Q4…), calculée par le script lui-même à chaque build — le build planifié avance donc tout seul d'un trimestre à l'autre, comme le dépôt officiel quarterly des serveurs (repli sur le trimestre précédent tant que la nouvelle branche n'est pas publiée). Autre valeur = nom de branche fixe (main…). Absent = branche laissée telle quelle. Changer de branche reconstruit presque tout (versions différentes).

schedule (5 champs cron) : pose sur le builder un script /usr/local/etc/poudriere.d/beryl-build-<majeur>.sh et une entrée /usr/local/etc/cron.d/beryl-poudriere-<majeur> qui relancent LE MÊME build que beryl sync (verrou partagé, overlays gérés mis à jour en avance rapide, arbre de ports frais → correctifs de sécurité), sur la mineure visée au dernier apply. Régénérés à chaque apply. Échec signalé par mail (sortie de cron), détail dans le journal des builds.

Champs d'un overlay : name obligatoire ; sans git, l'overlay n'est pas mis à jour par beryl (son commit est tout de même suivi si path est un dépôt git) ; path par défaut = chemin enregistré dans poudriere, sinon /usr/local/poudriere/<name>-ports. Au moins une pkglist est requise (par overlay et/ou au niveau du step).

Ancien schéma, toujours accepté tel quel (un seul overlay) :

- poudriere-build:
    major: "15"
    pkglist: /usr/local/etc/poudriere.d/maison-pkglist
    overlay: maison               # obligatoire (nom de l'arbre overlay)

Constants

CRON_DIR = "/usr/local/etc/cron.d"
DEFAULT_PKGDIR = "/usr/local/poudriere/data/packages"
OVERLAY_ROOT = "/usr/local/poudriere"
POUDRIERE_ETC = "/usr/local/etc/poudriere.d"

Class methods

alias_name(major : String, arch : String) : String

Alias par ABI : "FreeBSD:15:amd64". Pur.

Source
branch_script(ports_branch : String) : String

Clone / met à jour / enregistre un overlay ; renvoie son état, ou un StepResult d'échec. Fragment shell (dans build_script) qui place l'arbre de ports ($PTDIR) sur la branche voulue. quarterly : trimestre courant calculé À L'EXÉCUTION (date UTC), repli sur le précédent si la branche n'existe pas encore. L'arbre poudriere est un clone superficiel à branche unique : la branche est ajoutée aux refspecs (sans quoi poudriere ports -u ne la mettrait jamais à jour), puis récupérée et suivie. Pur.

Source
build_script(version : String, arch : String, ports : String, overlays : Array(String), pkglists : Array(String), pkgdir : String, reapply : String | Nil, commits : Hash(String, String) | Nil = nil, state : String | Nil = nil, ports_branch : String | Nil = nil) : String

Script de build (lancé en détaché sur le builder). Pur, exposé pour test. overlays : noms des arbres passés en -O ; pkglists : fichiers passés en -f ; commits : {overlay => commit} écrit dans state après succès (nil = pas d'état à écrire).

Source
jail_name(version : String, arch : String) : String

"15.1" + amd64 → "fbsd151amd64". Pur, exposé pour test.

Source
parse_state(text : String) : Hash(String, String)

Fichier d'état → {nom => commit}. Pur.

Source
parse_trees(text : String) : Hash(String, String)

Sortie de poudriere ports -lq → {arbre => chemin}. Pur.

Source
release_lookup

Source des dernières releases par majeur — injectable pour les tests.

Source
release_lookup=(release_lookup : Proc(Hash(Int32, String)))

Source des dernières releases par majeur — injectable pour les tests.

Source
scheduled_script(version : String, arch : String, ports : String, overlays : Array(ScheduledOverlay), pkglists : Array(String), pkgdir : String, reapply : String | Nil, ports_branch : String | Nil = nil) : String

Script du build PLANIFIÉ (cron) : le MÊME build que celui lancé par beryl sync (build_script), précédé du verrou partagé et de la mise à jour en avance rapide des overlays gérés par beryl, suivi de l'enregistrement des commits réellement construits (lus à l'exécution). Reconstruit la mineure visée au dernier apply ; une NOUVELLE mineure reste l'affaire de beryl sync (qui régénère ce script). Pur.

Source
set_name(version : String, arch : String, ports : String) : String

Nom du set poudriere : "fbsd151amd64-default". Pur.

Source
set_version(setname : String, major : String, arch : String, ports : String) : String | Nil

Reconstruit la version depuis un nom de set ("fbsd151amd64-default" + major "15" → "15.1"). nil si le nom ne correspond pas. Pur.

Source
state_path(pkgdir : String, major : String) : String

Fichier d'état des commits construits, à côté du lock et du log.

Source

Instance methods

apply(shell : Shell, params : Hash(String, YAML::Any), dry_run : Bool, context : Context) : StepResult

params est le hash brut du step YAML (ex: {"packages" => [...]}), déjà interpolé par l'Executor. context porte les infos dérivées du host (cf. Context).

Source
name

Nom kebab-case utilisé comme clé de step dans les recettes (« pkg-install », « service-enable », …).

Source

Nested types