Model declarative FreeBSD source inputs
This commit is contained in:
406
docs/PLAN_4.md
Normal file
406
docs/PLAN_4.md
Normal file
@@ -0,0 +1,406 @@
|
||||
# Fruix on FreeBSD, Path D: Declarative Source Acquisition, Installation Artifacts, and the Road to Self-Hosting
|
||||
|
||||
This document extends `docs/PLAN_3.md` after the completion of Phases 1 through 15.
|
||||
|
||||
The project has now crossed another important threshold:
|
||||
|
||||
- Fruix builds native FreeBSD base artifacts from `/usr/src` into `/frx/store`
|
||||
- the validated boot/runtime path is host-base-free at the deployed system layer
|
||||
- the FreeBSD base is now an explicit declarative Fruix input
|
||||
- side-by-side base versions can coexist in `/frx/store`
|
||||
- Fruix can rebuild, redeploy, and roll back between declared base versions
|
||||
|
||||
That means the next question is no longer whether Fruix can assemble and boot a native FreeBSD system. It can.
|
||||
|
||||
The next question is how to make that native base path **more reproducible, more source-declarative, and more installable**.
|
||||
|
||||
The biggest remaining impurity is now clear:
|
||||
|
||||
- the native base build path still relies on the builder host's ambient `/usr/src`
|
||||
|
||||
That was the right bridge through Phases 13 to 15, but it should not be the long-term source story.
|
||||
|
||||
Accordingly, Plan 4 focuses on three connected goals:
|
||||
|
||||
1. make FreeBSD source acquisition and source identity more declarative
|
||||
2. turn the current image-generation path into a real installation story
|
||||
3. only then move carefully toward self-hosted base builds
|
||||
|
||||
This preserves the Guix-inspired core while continuing to embrace FreeBSD semantics rather than trying to imitate Linux-specific workflows.
|
||||
|
||||
Throughout this plan, the canonical Fruix roots remain:
|
||||
|
||||
- `/frx/store`
|
||||
- `/frx/var`
|
||||
- `/frx/etc`
|
||||
|
||||
The user-facing system remains **Fruix**, with CLI `fruix`, while internal upstream-derived names continue to be renamed selectively rather than mechanically.
|
||||
|
||||
The current real-VM validation constraints still apply unless explicitly relaxed later:
|
||||
|
||||
- approved VM: `90490f2e-e8fc-4b7a-388e-5c26f0157289`
|
||||
- approved A/B VDIs:
|
||||
- `0f1f90d3-48ca-4fa2-91d8-fc6339b95743`
|
||||
- `7061d761-3639-4bec-87f7-2ba1af924eaa`
|
||||
|
||||
---
|
||||
|
||||
## Current State at the Start of Plan 4
|
||||
|
||||
Fruix on FreeBSD already has:
|
||||
|
||||
- a functioning content-addressed store and derivation path under `/frx/store`
|
||||
- daemon-mediated builds with validated FreeBSD isolation concepts
|
||||
- a working declarative FreeBSD operating-system model
|
||||
- validated system closure, rootfs, and image generation through `fruix system ...`
|
||||
- real QEMU and XCP-ng boot validation
|
||||
- a host-base-free native boot/runtime composition built from:
|
||||
- `freebsd-native-kernel`
|
||||
- `freebsd-native-bootloader`
|
||||
- `freebsd-native-runtime`
|
||||
- a declarative `freebsd-base` model that records:
|
||||
- base identity
|
||||
- version label
|
||||
- branch
|
||||
- source root
|
||||
- target and kernel configuration
|
||||
- side-by-side native base versions in `/frx/store`
|
||||
- rollback-friendly redeploy across those declared base versions
|
||||
- a documented decision to continue using host-built native base artifacts for now rather than jumping immediately to guest self-hosting
|
||||
|
||||
The main remaining architectural compromise is now not the runtime/boot artifact split, but the **source boundary**:
|
||||
|
||||
- native FreeBSD base builds still use ambient `/usr/src`
|
||||
- source acquisition is not yet a first-class Fruix-managed input
|
||||
- therefore reproducibility and provenance still stop short of a fully declared source story
|
||||
|
||||
At the same time, Fruix still lacks a real installation workflow beyond image generation and validation harnesses.
|
||||
|
||||
---
|
||||
|
||||
## Guiding Decision for the Next Milestone
|
||||
|
||||
The next major milestone should be:
|
||||
|
||||
- **declarative FreeBSD source acquisition and source pinning first**,
|
||||
- then **native base builds from fetched or materialized source inputs**,
|
||||
- then a **real installation story**,
|
||||
- and only after that, a controlled re-evaluation of self-hosted base builds.
|
||||
|
||||
This means the next work should optimize for:
|
||||
|
||||
- explicit source identity
|
||||
- stronger provenance
|
||||
- side-by-side source revisions
|
||||
- repeatable rebuilds from fetched or materialized source trees
|
||||
- installation artifacts that are operator-usable beyond current validation harnesses
|
||||
|
||||
It should **not** optimize for:
|
||||
|
||||
- jumping straight into guest self-hosting while source identity is still weak
|
||||
- building a large interactive installer before the installation primitives are clear
|
||||
- replacing the current validated host-built native-base path prematurely
|
||||
|
||||
---
|
||||
|
||||
## Phase 16: Make FreeBSD Source Acquisition Declarative
|
||||
|
||||
This is the next architectural pivot after the native base/runtime split.
|
||||
|
||||
The goal is to move from:
|
||||
|
||||
- “build from whatever `/usr/src` is on the host”
|
||||
|
||||
into:
|
||||
|
||||
- “build from a declared FreeBSD source input with explicit provenance.”
|
||||
|
||||
### Intermediate Goal 16.1: Model FreeBSD Source Inputs Explicitly
|
||||
|
||||
**Verification Goal 16.1:** Introduce a first-class Fruix model for FreeBSD source inputs.
|
||||
|
||||
This can be a new `freebsd-source` record, an extension of `freebsd-base`, or another explicit source object, but it should represent at least:
|
||||
|
||||
- source kind:
|
||||
- local checkout snapshot
|
||||
- fetched Git checkout
|
||||
- fetched `src.txz` archive
|
||||
- source URL or local path
|
||||
- branch or release line
|
||||
- commit, tag, or revision when applicable
|
||||
- expected tree or archive hash
|
||||
- any intended patch queue or source transformation layer
|
||||
|
||||
This step should also document how that source object relates to:
|
||||
|
||||
- `freebsd-base`
|
||||
- native kernel/world/runtime/bootloader/headers builds
|
||||
- output identity in `/frx/store`
|
||||
|
||||
**Success Criteria:** Fruix can describe FreeBSD source inputs as explicit declared objects rather than only relying on ambient `/usr/src`.
|
||||
|
||||
### Intermediate Goal 16.2: Fetch or Materialize Source Trees Under Fruix Control
|
||||
|
||||
**Verification Goal 16.2:** Materialize a clean FreeBSD source tree from a declared source input using Fruix-managed fetch/materialization logic.
|
||||
|
||||
The first implementation may be intentionally modest, such as:
|
||||
|
||||
- fetching a Git checkout at a pinned revision from `https://git.FreeBSD.org/src.git`
|
||||
- or downloading a `src.txz` archive and verifying its hash
|
||||
- for example from `https://download.freebsd.org/releases/amd64/15.0-RELEASE/src.txz`
|
||||
- or from snapshot paths such as `https://download.freebsd.org/snapshots/amd64/15.0-STABLE/src.txz`
|
||||
- or snapshotting a local source tree into a content-addressed source artifact with explicit metadata
|
||||
|
||||
This phase should also define where downloaded or temporary source material lives, for example under:
|
||||
|
||||
- `/frx/var/cache/fruix/freebsd-source`
|
||||
|
||||
The important point is that the eventual build input should no longer be “the current mutable host tree” but a **materialized source snapshot with recorded identity**.
|
||||
|
||||
**Success Criteria:** Fruix can fetch or materialize a pinned FreeBSD source tree with recorded provenance and a stable identity suitable for native base builds.
|
||||
|
||||
### Intermediate Goal 16.3: Build Native Base Artifacts From the Declared Source Input
|
||||
|
||||
**Verification Goal 16.3:** Teach the native FreeBSD base build path to consume the declared source artifact rather than ambient `/usr/src`.
|
||||
|
||||
This should preserve the validated Plan-3/Plan-4 deployment story:
|
||||
|
||||
- native kernel
|
||||
- native bootloader slice
|
||||
- native runtime slice
|
||||
- host-base-free validated path
|
||||
|
||||
The goal is not yet to change the successful boot/runtime model, only the **source input boundary**.
|
||||
|
||||
**Success Criteria:** Fruix builds native FreeBSD base artifacts from a declared source input, and the resulting store artifacts record that source identity explicitly.
|
||||
|
||||
---
|
||||
|
||||
## Phase 17: Support Multiple FreeBSD Source Revisions Side by Side
|
||||
|
||||
Once source acquisition is explicit, Fruix should prove that it can treat source revisions the way it already treats declared base versions: as side-by-side inputs rather than in-place mutations.
|
||||
|
||||
### Intermediate Goal 17.1: Support Side-by-Side FreeBSD Source Revisions in `/frx/store`
|
||||
|
||||
**Verification Goal 17.1:** Demonstrate that at least two distinct declared FreeBSD source inputs can coexist and produce distinct native base artifacts in `/frx/store`.
|
||||
|
||||
These can differ by:
|
||||
|
||||
- Git revision
|
||||
- source archive hash
|
||||
- local source snapshot hash
|
||||
- or another explicit source identity boundary
|
||||
|
||||
The goal is to prove that the source declaration, not ambient host state, now drives the base build outputs.
|
||||
|
||||
**Success Criteria:** Fruix can hold at least two distinct FreeBSD source revisions side by side as meaningful native base inputs and outputs.
|
||||
|
||||
### Intermediate Goal 17.2: Rebuild and Boot From Two Distinct Source Revisions
|
||||
|
||||
**Verification Goal 17.2:** Build and boot systems from at least two distinct declared source revisions using the validated native base path.
|
||||
|
||||
This should preserve the current validation strategy:
|
||||
|
||||
- local QEMU/UEFI/TCG where useful
|
||||
- real XCP-ng validation on the approved VM and approved A/B VDI path
|
||||
|
||||
The booted systems do not necessarily need to differ in obvious runtime behavior; the important point is that their source identity and native base outputs differ and are tracked correctly.
|
||||
|
||||
**Success Criteria:** Fruix boots systems built from two distinct declared FreeBSD source revisions and records those revisions in system metadata.
|
||||
|
||||
### Intermediate Goal 17.3: Clarify Source Provenance, Caching, and Update Policy
|
||||
|
||||
**Verification Goal 17.3:** Document and encode the intended policy for:
|
||||
|
||||
- source caching
|
||||
- source refresh/invalidation
|
||||
- patch application if any
|
||||
- tree hashing rules
|
||||
- when a new source identity should or should not invalidate native base outputs
|
||||
|
||||
This step should reduce ambiguity before installation artifacts and later self-hosting experiments depend on these source objects.
|
||||
|
||||
**Success Criteria:** the repo clearly explains how FreeBSD source objects are fetched, cached, identified, invalidated, and consumed by native base builds.
|
||||
|
||||
---
|
||||
|
||||
## Phase 18: Turn System Images Into a Real Installation Story
|
||||
|
||||
Fruix can already produce bootable images. The next step is to make installation itself a first-class Fruix story rather than a manual consequence of image generation.
|
||||
|
||||
### Intermediate Goal 18.1: Define a Minimal Non-Interactive Installation Flow
|
||||
|
||||
**Verification Goal 18.1:** Introduce a minimal installation workflow that can take a Fruix system artifact and install it to a target disk or image in a repeatable way.
|
||||
|
||||
The first version should prefer clarity and automation over interactivity. For example, it may:
|
||||
|
||||
- partition a target disk
|
||||
- create required filesystems
|
||||
- copy or materialize the selected system closure
|
||||
- install boot assets
|
||||
- stage activation/runtime metadata
|
||||
- configure root SSH key or basic operator access
|
||||
|
||||
This first step should be VM-friendly and serial-console-friendly.
|
||||
|
||||
**Success Criteria:** Fruix can perform a repeatable installation of a declarative system onto a target disk or image without relying on ad hoc manual assembly.
|
||||
|
||||
### Intermediate Goal 18.2: Produce a Minimal Installer Environment
|
||||
|
||||
**Verification Goal 18.2:** Produce a small installer environment that can boot into a Fruix-managed install context and perform the installation workflow.
|
||||
|
||||
This environment may initially be one of:
|
||||
|
||||
- a special-purpose disk image
|
||||
- a minimal recovery/install rootfs
|
||||
- a proto-installer medium with only the tools needed for partitioning, filesystem creation, and deployment
|
||||
|
||||
The target here is not a polished live environment. It is a reliable installer substrate.
|
||||
|
||||
**Success Criteria:** Fruix can boot a minimal installer environment and use it to install a selected Fruix system to a target disk.
|
||||
|
||||
### Intermediate Goal 18.3: Build a Bootable Installer ISO
|
||||
|
||||
**Verification Goal 18.3:** Produce a bootable installer ISO for UEFI systems.
|
||||
|
||||
The first ISO can be intentionally narrow in scope. It should be enough to:
|
||||
|
||||
- boot under QEMU and, where practical, on the validated virtualization path
|
||||
- expose the install workflow
|
||||
- install a target Fruix system
|
||||
- leave the machine bootable into the installed system
|
||||
|
||||
A polished graphical or highly interactive installer is not required here.
|
||||
|
||||
**Success Criteria:** Fruix can build a bootable installer ISO that installs a declarative Fruix-on-FreeBSD system.
|
||||
|
||||
---
|
||||
|
||||
## Phase 19: Strengthen System Deployment and Generation Management
|
||||
|
||||
The current deployment model already has the important Guix-like semantic properties at the closure/store layer. This phase is about making that story more operator-facing and less harness-specific.
|
||||
|
||||
### Intermediate Goal 19.1: Define a First-Class Fruix Deployment Workflow
|
||||
|
||||
**Verification Goal 19.1:** Define and document the canonical user-facing deployment workflow for system rebuild, image generation, installation, and rollback.
|
||||
|
||||
This may introduce or refine user-facing commands such as:
|
||||
|
||||
- `fruix system build`
|
||||
- `fruix system image`
|
||||
- future deployment/install/switch subcommands if justified
|
||||
|
||||
The key goal is clarity: operators should have an obvious Fruix way to move between generations and deployments.
|
||||
|
||||
**Success Criteria:** the repo documents a coherent user-facing deployment workflow for system build, install, roll-forward, and rollback.
|
||||
|
||||
### Intermediate Goal 19.2: Model System Generations More Explicitly
|
||||
|
||||
**Verification Goal 19.2:** Make the system-generation story more explicit in metadata and deployment roots.
|
||||
|
||||
This should include deciding how Fruix wants to represent:
|
||||
|
||||
- current system generation
|
||||
- previous system generation
|
||||
- rollback target
|
||||
- GC roots associated with installed systems
|
||||
|
||||
This does not have to copy Guix System mechanically, but it should preserve the same important properties.
|
||||
|
||||
**Success Criteria:** Fruix has a clearer model for installed system generations and rollback roots rather than relying mainly on test-harness knowledge.
|
||||
|
||||
### Intermediate Goal 19.3: Validate Installed-System Rollback as an Operator Workflow
|
||||
|
||||
**Verification Goal 19.3:** Validate rollback through the intended installed-system workflow, not only through build/image test harnesses.
|
||||
|
||||
This step should prove that the installation and generation model work together coherently.
|
||||
|
||||
**Success Criteria:** an installed Fruix system can move between generations using the intended operator-facing deployment model.
|
||||
|
||||
---
|
||||
|
||||
## Phase 20: Controlled Steps Toward Self-Hosted Base Builds
|
||||
|
||||
Only after source identity and installation/deployment boundaries are stronger should Fruix seriously revisit self-hosted base builds.
|
||||
|
||||
### Intermediate Goal 20.1: Validate a Fruix-Managed Development Environment for Native Base Work
|
||||
|
||||
**Verification Goal 20.1:** Ensure that a Fruix-managed system can expose the development/runtime/toolchain environment needed for deeper FreeBSD-native build work.
|
||||
|
||||
This should build on the cleaner runtime/development split already established in Phase 14.
|
||||
|
||||
The goal is not yet full self-hosting; it is to prove that the system can host the tools and profiles needed for that work in a controlled way.
|
||||
|
||||
**Success Criteria:** a Fruix-managed system can expose a usable development environment for native FreeBSD build tasks.
|
||||
|
||||
### Intermediate Goal 20.2: Run Host-Initiated Native Base Builds Inside a Fruix-Managed Environment
|
||||
|
||||
**Verification Goal 20.2:** As an intermediate step, perform native base builds inside a Fruix-managed environment or jail while still using the host as the outer orchestrator.
|
||||
|
||||
This narrows the remaining gap without immediately demanding full guest self-hosting.
|
||||
|
||||
**Success Criteria:** Fruix can build native FreeBSD base artifacts from inside a Fruix-managed build environment, with the host still orchestrating the outer loop.
|
||||
|
||||
### Intermediate Goal 20.3: Reassess and Potentially Prototype Guest Self-Hosted Base Builds
|
||||
|
||||
**Verification Goal 20.3:** Revisit guest self-hosting only after the earlier source/install/deployment goals are complete enough to make that experiment meaningful.
|
||||
|
||||
At that point, the question should be answered with real evidence:
|
||||
|
||||
- what exactly self-hosting would improve
|
||||
- what it would cost in complexity
|
||||
- how it would fit with the source/deployment model already established
|
||||
|
||||
**Success Criteria:** the project either:
|
||||
|
||||
- validates a first controlled guest self-hosted base build, or
|
||||
- records a clear evidence-based decision to continue preferring host-orchestrated native builds.
|
||||
|
||||
---
|
||||
|
||||
## Strategic Notes
|
||||
|
||||
### Why this order?
|
||||
|
||||
This sequence is intended to preserve the most important win from Plan 3 and Phase 15:
|
||||
|
||||
- Fruix already has a native, store-based, rollback-friendly FreeBSD base path
|
||||
|
||||
The next improvement should therefore be to make the **source input** as explicit as the **deployment output** already is.
|
||||
|
||||
After that, Fruix can turn its successful image-generation path into a real installation story. Only then will self-hosting be judged in the right context.
|
||||
|
||||
### Why not jump straight to self-hosting?
|
||||
|
||||
Because at the end of Phase 15, the biggest remaining weakness is not “where the build runs”, but “how explicitly the source is declared and acquired”.
|
||||
|
||||
If self-hosting were attempted immediately, it would mix together:
|
||||
|
||||
- source acquisition problems
|
||||
- toolchain/profile maturity problems
|
||||
- build-environment questions
|
||||
- deployment/installation questions
|
||||
- and virtualization/operator constraints
|
||||
|
||||
That would make debugging and design less clear.
|
||||
|
||||
### Why add installation work before self-hosting?
|
||||
|
||||
Because Fruix should become more usable as a system even if self-hosting remains a later milestone.
|
||||
|
||||
A real installation story would:
|
||||
|
||||
- make the current system model more operator-meaningful
|
||||
- improve validation of generation/deployment semantics
|
||||
- prepare the project for broader VM and eventually hardware use
|
||||
- make later self-hosting experiments easier to stage and reproduce
|
||||
|
||||
### What success will mean
|
||||
|
||||
Success under this plan means the project moves from:
|
||||
|
||||
- “Fruix builds native FreeBSD base artifacts from the host’s current `/usr/src` and boots them successfully”
|
||||
|
||||
into:
|
||||
|
||||
- “Fruix acquires FreeBSD sources declaratively, builds native base artifacts from pinned source inputs, installs systems through a real Fruix workflow, and approaches self-hosting from a much cleaner architectural position.”
|
||||
@@ -1,5 +1,83 @@
|
||||
# Progress
|
||||
|
||||
## 2026-04-03 — Phase 16.1 completed: FreeBSD source inputs are now explicit Fruix objects
|
||||
|
||||
Completed work:
|
||||
|
||||
- added `docs/PLAN_4.md` to define the post-Phase-15 roadmap around:
|
||||
- declarative FreeBSD source acquisition
|
||||
- installation artifacts
|
||||
- the controlled path toward self-hosting
|
||||
- introduced a first-class `freebsd-source` record in `modules/fruix/packages/freebsd.scm` with:
|
||||
- supported kinds:
|
||||
- `local-tree`
|
||||
- `git`
|
||||
- `src-txz`
|
||||
- exported accessors for:
|
||||
- `name`
|
||||
- `kind`
|
||||
- `url`
|
||||
- `path`
|
||||
- `ref`
|
||||
- `commit`
|
||||
- `sha256`
|
||||
- new `%default-freebsd-source`
|
||||
- extended `freebsd-base` so it now records both:
|
||||
- transitional `source-root`
|
||||
- declarative `source`
|
||||
- added/exported:
|
||||
- `freebsd-base-source`
|
||||
- threaded declared source fields into native package plans so native build outputs can record them
|
||||
- in `modules/fruix/system/freebsd.scm`:
|
||||
- added source validation for:
|
||||
- `local-tree`
|
||||
- `git`
|
||||
- `src-txz`
|
||||
- added `freebsd-source-spec`
|
||||
- `freebsd-base-spec` now nests the declared source
|
||||
- native manifests and `.freebsd-native-build-info.scm` now include:
|
||||
- `declared-source`
|
||||
- closures now generate:
|
||||
- `metadata/freebsd-source.scm`
|
||||
- `metadata/store-layout.scm` now records:
|
||||
- `freebsd-source`
|
||||
- in `scripts/fruix.scm`, `build` and `image` metadata now emit:
|
||||
- `freebsd_source_name`
|
||||
- `freebsd_source_kind`
|
||||
- `freebsd_source_url`
|
||||
- `freebsd_source_path`
|
||||
- `freebsd_source_ref`
|
||||
- `freebsd_source_commit`
|
||||
- `freebsd_source_sha256`
|
||||
- `freebsd_source_file`
|
||||
- added validation artifacts:
|
||||
- `tests/system/phase16-declarative-source-operating-system.scm.in`
|
||||
- `tests/system/run-phase16-declarative-source-build.sh`
|
||||
- `tests/system/validate-phase16-freebsd-source.scm`
|
||||
- compared Fruix's new source model with Guix's source modeling via:
|
||||
- `~/repos/guix/guix/packages.scm`
|
||||
- `~/repos/guix/guix/git-download.scm`
|
||||
- wrote:
|
||||
- `docs/reports/phase16-declarative-source-model-freebsd.md`
|
||||
|
||||
Validation:
|
||||
|
||||
- `PASS phase16-declarative-source-build`
|
||||
- source model probe confirmed support for:
|
||||
- local-tree `/usr/src`
|
||||
- Git refs such as `stable/15` at `https://git.FreeBSD.org/src.git`
|
||||
- canonical `src.txz` URLs such as:
|
||||
- `https://download.freebsd.org/releases/amd64/15.0-RELEASE/src.txz`
|
||||
- `https://download.freebsd.org/snapshots/amd64/15.0-STABLE/src.txz`
|
||||
- closure/native metadata now records the declared source explicitly while preserving the current validated `/usr/src` build path
|
||||
|
||||
Current assessment:
|
||||
|
||||
- Phase 16.1 is complete
|
||||
- Fruix can now describe FreeBSD source inputs explicitly, but it does not fetch/materialize them yet
|
||||
- the next step is Phase 16.2:
|
||||
- fetch or materialize declared FreeBSD source inputs under Fruix control and use their stable identity as the next reproducibility boundary
|
||||
|
||||
## 2026-04-01 — Phase 1.1 started: Guile verified on FreeBSD amd64
|
||||
|
||||
Completed work:
|
||||
|
||||
202
docs/reports/phase16-declarative-source-model-freebsd.md
Normal file
202
docs/reports/phase16-declarative-source-model-freebsd.md
Normal file
@@ -0,0 +1,202 @@
|
||||
# Phase 16.1: model FreeBSD source inputs explicitly
|
||||
|
||||
Date: 2026-04-03
|
||||
|
||||
## Goal
|
||||
|
||||
Phase 16.1 introduces a first-class Fruix model for FreeBSD source inputs so the native base path is no longer described only as "whatever `/usr/src` is on the host".
|
||||
|
||||
This step does **not** yet fetch or materialize remote source trees. It makes the source declaration explicit and records it through the package, system, and CLI metadata layers so later phases can replace ambient `/usr/src` with fetched or materialized inputs cleanly.
|
||||
|
||||
## Implementation
|
||||
|
||||
### New declarative FreeBSD source record
|
||||
|
||||
Added in `modules/fruix/packages/freebsd.scm`:
|
||||
|
||||
- `freebsd-source`
|
||||
- `freebsd-source?`
|
||||
- accessors for:
|
||||
- `name`
|
||||
- `kind`
|
||||
- `url`
|
||||
- `path`
|
||||
- `ref`
|
||||
- `commit`
|
||||
- `sha256`
|
||||
- `%default-freebsd-source`
|
||||
|
||||
Supported source kinds are now modeled explicitly as:
|
||||
|
||||
- `local-tree`
|
||||
- `git`
|
||||
- `src-txz`
|
||||
|
||||
The default source remains a local-tree declaration for:
|
||||
|
||||
- `/usr/src`
|
||||
|
||||
### FreeBSD bases now carry a declared source object
|
||||
|
||||
Extended `freebsd-base` so it now records:
|
||||
|
||||
- the transitional `source-root` still used by the current native build path
|
||||
- a new `source` record describing the declared FreeBSD source input
|
||||
|
||||
Added/exported:
|
||||
|
||||
- `freebsd-base-source`
|
||||
|
||||
This keeps the validated `/usr/src` path working while giving the base a source object that can later point at fetched Git or `src.txz` materializations.
|
||||
|
||||
### Native package plans and metadata now record the declared source
|
||||
|
||||
`modules/fruix/packages/freebsd.scm` now threads source fields into native package install plans.
|
||||
|
||||
`modules/fruix/system/freebsd.scm` now records a `declared-source` block in:
|
||||
|
||||
- native package manifests
|
||||
- `.freebsd-native-build-info.scm`
|
||||
|
||||
This means native kernel, bootloader, and runtime outputs now remember both:
|
||||
|
||||
- the declared base
|
||||
- the declared source input
|
||||
|
||||
### Operating-system validation now checks source declarations
|
||||
|
||||
Added source validation in `modules/fruix/system/freebsd.scm`.
|
||||
|
||||
Current accepted source declarations are:
|
||||
|
||||
- `local-tree`
|
||||
- requires a path
|
||||
- `git`
|
||||
- requires a URL and at least a ref or commit
|
||||
- `src-txz`
|
||||
- requires a URL
|
||||
|
||||
This is intentionally enough for Phase 16.1 modeling without yet enforcing the later fetch/materialization policy.
|
||||
|
||||
### Closure metadata now includes a dedicated source file
|
||||
|
||||
System closures now generate:
|
||||
|
||||
- `metadata/freebsd-source.scm`
|
||||
|
||||
and embed source information in:
|
||||
|
||||
- `metadata/freebsd-base.scm`
|
||||
- `metadata/store-layout.scm`
|
||||
- `parameters.scm`
|
||||
|
||||
### CLI metadata now exposes the declared FreeBSD source
|
||||
|
||||
`scripts/fruix.scm` now emits the following for `fruix system build` and `image`:
|
||||
|
||||
- `freebsd_source_name`
|
||||
- `freebsd_source_kind`
|
||||
- `freebsd_source_url`
|
||||
- `freebsd_source_path`
|
||||
- `freebsd_source_ref`
|
||||
- `freebsd_source_commit`
|
||||
- `freebsd_source_sha256`
|
||||
- `freebsd_source_file`
|
||||
|
||||
## Guix comparison
|
||||
|
||||
This follows the same broad idea as Guix source modeling:
|
||||
|
||||
- Guix uses `origin` in `guix/packages.scm`
|
||||
- Git-backed sources are modeled with `git-reference` in `guix/git-download.scm`
|
||||
|
||||
Phase 16.1 does not copy Guix mechanically, but it adopts the same useful architectural boundary:
|
||||
|
||||
- source identity should be a declarative object
|
||||
- builds should record that source object explicitly
|
||||
|
||||
For Fruix, the source kinds are FreeBSD-oriented:
|
||||
|
||||
- local source tree snapshots for development
|
||||
- FreeBSD Git refs/commits
|
||||
- official FreeBSD `src.txz` archives
|
||||
|
||||
## Upstream source forms verified during this step
|
||||
|
||||
Verified usable upstream source forms include:
|
||||
|
||||
- Git:
|
||||
- `https://git.FreeBSD.org/src.git`
|
||||
- release archive:
|
||||
- `https://download.freebsd.org/releases/amd64/15.0-RELEASE/src.txz`
|
||||
- snapshot archive:
|
||||
- `https://download.freebsd.org/snapshots/amd64/15.0-STABLE/src.txz`
|
||||
|
||||
The shorter release URL form above is treated as the canonical example in this phase.
|
||||
|
||||
## New files
|
||||
|
||||
Added:
|
||||
|
||||
- `docs/PLAN_4.md`
|
||||
- `tests/system/phase16-declarative-source-operating-system.scm.in`
|
||||
- `tests/system/run-phase16-declarative-source-build.sh`
|
||||
- `tests/system/validate-phase16-freebsd-source.scm`
|
||||
|
||||
## Validation
|
||||
|
||||
Passing run:
|
||||
|
||||
- `PASS phase16-declarative-source-build`
|
||||
- workdir:
|
||||
- `/tmp/fruix-phase16-declarative-source.0LRvaC`
|
||||
|
||||
The source model probe confirmed:
|
||||
|
||||
```text
|
||||
local_kind=local-tree
|
||||
local_path=/usr/src
|
||||
git_kind=git
|
||||
git_url=https://git.FreeBSD.org/src.git
|
||||
git_ref=stable/15
|
||||
txz_kind=src-txz
|
||||
txz_url=https://download.freebsd.org/releases/amd64/15.0-RELEASE/src.txz
|
||||
txz_sha256=example-sha256
|
||||
base_source_accessor=ok
|
||||
```
|
||||
|
||||
The closure build confirmed:
|
||||
|
||||
```text
|
||||
closure_path=/frx/store/ac73a2a89c3c3f794462ccde0d9f0952362dc2ae32e631a7e99e07e7363e6118-fruix-system-fruix-freebsd
|
||||
kernel_store=/frx/store/c2f771a794f94cf168ae26a421ffab33e0ae4765f23882257d5bb7b2947d493d-freebsd-native-kernel-15.0-STABLE-source-model
|
||||
bootloader_store=/frx/store/a146c9c2fcacdc02454fe3bfd3afb5c5dbea54b6514242d53df0783ef4ee34fd-freebsd-native-bootloader-15.0-STABLE-source-model
|
||||
runtime_store=/frx/store/530e96440a518821a701db03f9437d7646c0447f8ea55c5df08417e9274dead1-freebsd-native-runtime-15.0-STABLE-source-model
|
||||
native_base_store_count=3
|
||||
host_base_store_count=0
|
||||
freebsd_source_name=host-usr-src
|
||||
freebsd_source_kind=local-tree
|
||||
freebsd_source_path=/usr/src
|
||||
freebsd_source_file=/frx/store/ac73a2a89c3c3f794462ccde0d9f0952362dc2ae32e631a7e99e07e7363e6118-fruix-system-fruix-freebsd/metadata/freebsd-source.scm
|
||||
declarative_source_model=ok
|
||||
```
|
||||
|
||||
The harness also verified that:
|
||||
|
||||
- `metadata/freebsd-source.scm` exists
|
||||
- `metadata/freebsd-base.scm` contains a nested source block
|
||||
- `metadata/store-layout.scm` records the declared source explicitly
|
||||
- native build info files contain a `declared-source` block with:
|
||||
- `kind . local-tree`
|
||||
- `path . "/usr/src"`
|
||||
|
||||
## Result
|
||||
|
||||
Phase 16.1 is complete.
|
||||
|
||||
Fruix now has an explicit source declaration layer for FreeBSD bases while preserving the current validated `/usr/src`-driven native build path.
|
||||
|
||||
That means Phase 16.2 can focus narrowly on the next real boundary:
|
||||
|
||||
- fetching or materializing declared FreeBSD source inputs under Fruix control
|
||||
- instead of just describing them
|
||||
@@ -3,6 +3,16 @@
|
||||
#:use-module (srfi srfi-9)
|
||||
#:use-module (srfi srfi-13)
|
||||
#:export (freebsd-release
|
||||
freebsd-source
|
||||
freebsd-source?
|
||||
freebsd-source-name
|
||||
freebsd-source-kind
|
||||
freebsd-source-url
|
||||
freebsd-source-path
|
||||
freebsd-source-ref
|
||||
freebsd-source-commit
|
||||
freebsd-source-sha256
|
||||
%default-freebsd-source
|
||||
freebsd-base
|
||||
freebsd-base?
|
||||
freebsd-base-name
|
||||
@@ -10,6 +20,7 @@
|
||||
freebsd-base-release
|
||||
freebsd-base-branch
|
||||
freebsd-base-source-root
|
||||
freebsd-base-source
|
||||
freebsd-base-target
|
||||
freebsd-base-target-arch
|
||||
freebsd-base-kernconf
|
||||
@@ -87,8 +98,32 @@
|
||||
|
||||
(define freebsd-release "15.0-STABLE")
|
||||
|
||||
(define-record-type <freebsd-source>
|
||||
(make-freebsd-source name kind url path ref commit sha256)
|
||||
freebsd-source?
|
||||
(name freebsd-source-name)
|
||||
(kind freebsd-source-kind)
|
||||
(url freebsd-source-url)
|
||||
(path freebsd-source-path)
|
||||
(ref freebsd-source-ref)
|
||||
(commit freebsd-source-commit)
|
||||
(sha256 freebsd-source-sha256))
|
||||
|
||||
(define* (freebsd-source #:key
|
||||
(name "default")
|
||||
(kind 'local-tree)
|
||||
(url (and (eq? kind 'git) "https://git.FreeBSD.org/src.git"))
|
||||
(path (and (eq? kind 'local-tree) "/usr/src"))
|
||||
(ref #f)
|
||||
(commit #f)
|
||||
(sha256 #f))
|
||||
(make-freebsd-source name kind url path ref commit sha256))
|
||||
|
||||
(define %default-freebsd-source
|
||||
(freebsd-source))
|
||||
|
||||
(define-record-type <freebsd-base>
|
||||
(make-freebsd-base name version-label release branch source-root target
|
||||
(make-freebsd-base name version-label release branch source-root source target
|
||||
target-arch kernconf make-flags)
|
||||
freebsd-base?
|
||||
(name freebsd-base-name)
|
||||
@@ -96,6 +131,7 @@
|
||||
(release freebsd-base-release)
|
||||
(branch freebsd-base-branch)
|
||||
(source-root freebsd-base-source-root)
|
||||
(source freebsd-base-source)
|
||||
(target freebsd-base-target)
|
||||
(target-arch freebsd-base-target-arch)
|
||||
(kernconf freebsd-base-kernconf)
|
||||
@@ -123,13 +159,18 @@
|
||||
(version-label freebsd-release)
|
||||
(release freebsd-release)
|
||||
(branch (default-freebsd-branch release))
|
||||
(source-root "/usr/src")
|
||||
(source #f)
|
||||
(source-root #f)
|
||||
(target "amd64")
|
||||
(target-arch "amd64")
|
||||
(kernconf "GENERIC")
|
||||
(make-flags default-native-make-flags))
|
||||
(make-freebsd-base name version-label release branch source-root target
|
||||
target-arch kernconf make-flags))
|
||||
(let* ((source (or source %default-freebsd-source))
|
||||
(source-root (or source-root
|
||||
(freebsd-source-path source)
|
||||
"/usr/src")))
|
||||
(make-freebsd-base name version-label release branch source-root source target
|
||||
target-arch kernconf make-flags)))
|
||||
|
||||
(define %default-freebsd-base
|
||||
(freebsd-base))
|
||||
@@ -574,6 +615,13 @@ library for profile experiments."
|
||||
(base-version-label . ,(freebsd-base-version-label base))
|
||||
(base-release . ,(freebsd-base-release base))
|
||||
(base-branch . ,(freebsd-base-branch base))
|
||||
(base-source-name . ,(freebsd-source-name (freebsd-base-source base)))
|
||||
(base-source-kind . ,(freebsd-source-kind (freebsd-base-source base)))
|
||||
(base-source-url . ,(freebsd-source-url (freebsd-base-source base)))
|
||||
(base-source-path . ,(freebsd-source-path (freebsd-base-source base)))
|
||||
(base-source-ref . ,(freebsd-source-ref (freebsd-base-source base)))
|
||||
(base-source-commit . ,(freebsd-source-commit (freebsd-base-source base)))
|
||||
(base-source-sha256 . ,(freebsd-source-sha256 (freebsd-base-source base)))
|
||||
(source-root . ,(freebsd-base-source-root base))
|
||||
(target . ,(freebsd-base-target base))
|
||||
(target-arch . ,(freebsd-base-target-arch base))
|
||||
|
||||
@@ -313,10 +313,20 @@
|
||||
(release . ,(build-plan-ref plan 'base-release freebsd-release))
|
||||
(branch . ,(build-plan-ref plan 'base-branch "unknown"))))
|
||||
|
||||
(define (native-build-declared-source plan)
|
||||
`((name . ,(build-plan-ref plan 'base-source-name "default"))
|
||||
(kind . ,(build-plan-ref plan 'base-source-kind 'local-tree))
|
||||
(url . ,(build-plan-ref plan 'base-source-url #f))
|
||||
(path . ,(build-plan-ref plan 'base-source-path #f))
|
||||
(ref . ,(build-plan-ref plan 'base-source-ref #f))
|
||||
(commit . ,(build-plan-ref plan 'base-source-commit #f))
|
||||
(sha256 . ,(build-plan-ref plan 'base-source-sha256 #f))))
|
||||
|
||||
(define (native-build-manifest-string package input-paths)
|
||||
(let* ((plan (freebsd-package-install-plan package))
|
||||
(common (native-build-common-manifest plan))
|
||||
(declared-base (native-build-declared-base plan))
|
||||
(declared-source (native-build-declared-source plan))
|
||||
(keep-paths (build-plan-ref plan 'keep-paths '()))
|
||||
(prune-paths (build-plan-ref plan 'prune-paths '())))
|
||||
(string-append
|
||||
@@ -326,6 +336,8 @@
|
||||
"inputs=" (string-join input-paths ",") "\n"
|
||||
"declared-base=\n"
|
||||
(object->string declared-base)
|
||||
"\ndeclared-source=\n"
|
||||
(object->string declared-source)
|
||||
"\nnative-build-common=\n"
|
||||
(object->string common)
|
||||
"\nkeep-paths=\n"
|
||||
@@ -479,6 +491,7 @@
|
||||
`((package . ,(freebsd-package-name package))
|
||||
(version . ,(freebsd-package-version package))
|
||||
(declared-base . ,(native-build-declared-base plan))
|
||||
(declared-source . ,(native-build-declared-source plan))
|
||||
(build-system . ,(freebsd-package-build-system package))
|
||||
(source-root . ,(assoc-ref common 'source-root))
|
||||
(source-tree-sha256 . ,(assoc-ref common 'source-tree-sha256))
|
||||
@@ -682,12 +695,22 @@
|
||||
(define (package-names packages)
|
||||
(map freebsd-package-name packages))
|
||||
|
||||
(define (freebsd-source-spec source)
|
||||
`((name . ,(freebsd-source-name source))
|
||||
(kind . ,(freebsd-source-kind source))
|
||||
(url . ,(freebsd-source-url source))
|
||||
(path . ,(freebsd-source-path source))
|
||||
(ref . ,(freebsd-source-ref source))
|
||||
(commit . ,(freebsd-source-commit source))
|
||||
(sha256 . ,(freebsd-source-sha256 source))))
|
||||
|
||||
(define (freebsd-base-spec base)
|
||||
`((name . ,(freebsd-base-name base))
|
||||
(version-label . ,(freebsd-base-version-label base))
|
||||
(release . ,(freebsd-base-release base))
|
||||
(branch . ,(freebsd-base-branch base))
|
||||
(source-root . ,(freebsd-base-source-root base))
|
||||
(source . ,(freebsd-source-spec (freebsd-base-source base)))
|
||||
(target . ,(freebsd-base-target base))
|
||||
(target-arch . ,(freebsd-base-target-arch base))
|
||||
(kernconf . ,(freebsd-base-kernconf base))
|
||||
@@ -702,6 +725,31 @@
|
||||
(loop tail seen (if (member head duplicates) duplicates (cons head duplicates)))
|
||||
(loop tail (cons head seen) duplicates))))))
|
||||
|
||||
(define (non-empty-string? value)
|
||||
(and (string? value)
|
||||
(not (string-null? value))))
|
||||
|
||||
(define (validate-freebsd-source source)
|
||||
(unless (freebsd-source? source)
|
||||
(error "freebsd base source must be a <freebsd-source> record"))
|
||||
(let ((kind (freebsd-source-kind source)))
|
||||
(unless (member kind '(local-tree git src-txz))
|
||||
(error "unsupported freebsd source kind" kind))
|
||||
(case kind
|
||||
((local-tree)
|
||||
(unless (non-empty-string? (freebsd-source-path source))
|
||||
(error "local-tree freebsd source must declare a path" source)))
|
||||
((git)
|
||||
(unless (non-empty-string? (freebsd-source-url source))
|
||||
(error "git freebsd source must declare a URL" source))
|
||||
(unless (or (non-empty-string? (freebsd-source-ref source))
|
||||
(non-empty-string? (freebsd-source-commit source)))
|
||||
(error "git freebsd source must declare a ref or commit" source)))
|
||||
((src-txz)
|
||||
(unless (non-empty-string? (freebsd-source-url source))
|
||||
(error "src-txz freebsd source must declare a URL" source)))))
|
||||
#t)
|
||||
|
||||
(define (validate-operating-system os)
|
||||
(let* ((host-name (operating-system-host-name os))
|
||||
(base (operating-system-freebsd-base os))
|
||||
@@ -716,6 +764,7 @@
|
||||
(error "operating-system host-name must not be empty"))
|
||||
(unless (freebsd-base? base)
|
||||
(error "operating-system freebsd-base must be a <freebsd-base> record"))
|
||||
(validate-freebsd-source (freebsd-base-source base))
|
||||
(let ((dups (duplicate-elements user-names)))
|
||||
(unless (null? dups)
|
||||
(error "duplicate user names in operating-system" dups)))
|
||||
@@ -1386,11 +1435,14 @@
|
||||
(metadata-files
|
||||
`(("metadata/freebsd-base.scm"
|
||||
. ,(object->string (freebsd-base-spec (operating-system-freebsd-base os))))
|
||||
("metadata/freebsd-source.scm"
|
||||
. ,(object->string (freebsd-source-spec (freebsd-base-source (operating-system-freebsd-base os)))))
|
||||
("metadata/host-base-provenance.scm"
|
||||
. ,(object->string (host-freebsd-provenance)))
|
||||
("metadata/store-layout.scm"
|
||||
. ,(object->string
|
||||
`((freebsd-base . ,(freebsd-base-spec (operating-system-freebsd-base os)))
|
||||
(freebsd-source . ,(freebsd-source-spec (freebsd-base-source (operating-system-freebsd-base os))))
|
||||
(host-base-store-count . ,(length host-base-stores))
|
||||
(host-base-stores . ,host-base-stores)
|
||||
(native-base-store-count . ,(length native-base-stores))
|
||||
@@ -1466,6 +1518,7 @@
|
||||
(native-base-stores . ,native-base-stores)
|
||||
(fruix-runtime-stores . ,fruix-runtime-stores)
|
||||
(freebsd-base-file . ,(string-append closure-path "/metadata/freebsd-base.scm"))
|
||||
(freebsd-source-file . ,(string-append closure-path "/metadata/freebsd-source.scm"))
|
||||
(host-base-provenance-file . ,(string-append closure-path "/metadata/host-base-provenance.scm"))
|
||||
(store-layout-file . ,(string-append closure-path "/metadata/store-layout.scm"))
|
||||
(generated-files . ,(map car generated-files))
|
||||
|
||||
@@ -176,6 +176,7 @@ Options:\n\
|
||||
(native-base-stores (assoc-ref result 'native-base-stores))
|
||||
(fruix-runtime-stores (assoc-ref result 'fruix-runtime-stores))
|
||||
(base (operating-system-freebsd-base os))
|
||||
(source (freebsd-base-source base))
|
||||
(host-provenance (call-with-input-file (assoc-ref result 'host-base-provenance-file) read)))
|
||||
(emit-metadata
|
||||
`((action . "build")
|
||||
@@ -192,6 +193,14 @@ Options:\n\
|
||||
(freebsd_base_target_arch . ,(freebsd-base-target-arch base))
|
||||
(freebsd_base_kernconf . ,(freebsd-base-kernconf base))
|
||||
(freebsd_base_file . ,(assoc-ref result 'freebsd-base-file))
|
||||
(freebsd_source_name . ,(freebsd-source-name source))
|
||||
(freebsd_source_kind . ,(freebsd-source-kind source))
|
||||
(freebsd_source_url . ,(or (freebsd-source-url source) ""))
|
||||
(freebsd_source_path . ,(or (freebsd-source-path source) ""))
|
||||
(freebsd_source_ref . ,(or (freebsd-source-ref source) ""))
|
||||
(freebsd_source_commit . ,(or (freebsd-source-commit source) ""))
|
||||
(freebsd_source_sha256 . ,(or (freebsd-source-sha256 source) ""))
|
||||
(freebsd_source_file . ,(assoc-ref result 'freebsd-source-file))
|
||||
(ready_marker . ,(operating-system-ready-marker os))
|
||||
(kernel_store . ,(assoc-ref result 'kernel-store))
|
||||
(bootloader_store . ,(assoc-ref result 'bootloader-store))
|
||||
@@ -246,6 +255,7 @@ Options:\n\
|
||||
(native-base-stores (assoc-ref result 'native-base-stores))
|
||||
(fruix-runtime-stores (assoc-ref result 'fruix-runtime-stores))
|
||||
(base (operating-system-freebsd-base os))
|
||||
(source (freebsd-base-source base))
|
||||
(host-provenance (call-with-input-file (assoc-ref result 'host-base-provenance-file) read)))
|
||||
(emit-metadata
|
||||
`((action . "image")
|
||||
@@ -261,6 +271,14 @@ Options:\n\
|
||||
(freebsd_base_target_arch . ,(freebsd-base-target-arch base))
|
||||
(freebsd_base_kernconf . ,(freebsd-base-kernconf base))
|
||||
(freebsd_base_file . ,(assoc-ref result 'freebsd-base-file))
|
||||
(freebsd_source_name . ,(freebsd-source-name source))
|
||||
(freebsd_source_kind . ,(freebsd-source-kind source))
|
||||
(freebsd_source_url . ,(or (freebsd-source-url source) ""))
|
||||
(freebsd_source_path . ,(or (freebsd-source-path source) ""))
|
||||
(freebsd_source_ref . ,(or (freebsd-source-ref source) ""))
|
||||
(freebsd_source_commit . ,(or (freebsd-source-commit source) ""))
|
||||
(freebsd_source_sha256 . ,(or (freebsd-source-sha256 source) ""))
|
||||
(freebsd_source_file . ,(assoc-ref result 'freebsd-source-file))
|
||||
(disk_capacity . ,(assoc-ref image-spec 'disk-capacity))
|
||||
(root_size . ,(assoc-ref image-spec 'root-size))
|
||||
(image_store_path . ,(assoc-ref result 'image-store-path))
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
(use-modules (fruix system freebsd)
|
||||
(fruix packages freebsd))
|
||||
|
||||
(define phase16-source
|
||||
(freebsd-source
|
||||
#:name "__SOURCE_NAME__"
|
||||
#:kind 'local-tree
|
||||
#:path "/usr/src"))
|
||||
|
||||
(define phase16-base
|
||||
(freebsd-base
|
||||
#:name "__BASE_NAME__"
|
||||
#:version-label "__BASE_VERSION_LABEL__"
|
||||
#:release "__BASE_RELEASE__"
|
||||
#:branch "__BASE_BRANCH__"
|
||||
#:source phase16-source
|
||||
#:source-root "/usr/src"
|
||||
#:target "amd64"
|
||||
#:target-arch "amd64"
|
||||
#:kernconf "GENERIC"))
|
||||
|
||||
(define phase16-operating-system
|
||||
(operating-system
|
||||
#:host-name "fruix-freebsd"
|
||||
#:freebsd-base phase16-base
|
||||
#:kernel (freebsd-native-kernel-for phase16-base)
|
||||
#:bootloader (freebsd-native-bootloader-for phase16-base)
|
||||
#:base-packages (freebsd-native-system-packages-for phase16-base)
|
||||
#:groups (list (user-group #:name "wheel" #:gid 0 #:system? #t)
|
||||
(user-group #:name "sshd" #:gid 22 #:system? #t)
|
||||
(user-group #:name "_dhcp" #:gid 65 #:system? #t)
|
||||
(user-group #:name "operator" #:gid 1000 #:system? #f))
|
||||
#:users (list (user-account #:name "root"
|
||||
#:uid 0
|
||||
#:group "wheel"
|
||||
#:comment "Charlie &"
|
||||
#:home "/root"
|
||||
#:shell "/bin/sh"
|
||||
#:system? #t)
|
||||
(user-account #:name "sshd"
|
||||
#:uid 22
|
||||
#:group "sshd"
|
||||
#:comment "Secure Shell Daemon"
|
||||
#:home "/var/empty"
|
||||
#:shell "/usr/sbin/nologin"
|
||||
#:system? #t)
|
||||
(user-account #:name "_dhcp"
|
||||
#:uid 65
|
||||
#:group "_dhcp"
|
||||
#:comment "dhcp programs"
|
||||
#:home "/var/empty"
|
||||
#:shell "/usr/sbin/nologin"
|
||||
#:system? #t)
|
||||
(user-account #:name "operator"
|
||||
#:uid 1000
|
||||
#:group "operator"
|
||||
#:supplementary-groups '("wheel")
|
||||
#:comment "Fruix Operator"
|
||||
#:home "/home/operator"
|
||||
#:shell "/bin/sh"
|
||||
#:system? #f))
|
||||
#:file-systems (list (file-system #:device "/dev/gpt/fruix-root"
|
||||
#:mount-point "/"
|
||||
#:type "ufs"
|
||||
#:options "rw"
|
||||
#:needed-for-boot? #t)
|
||||
(file-system #:device "devfs"
|
||||
#:mount-point "/dev"
|
||||
#:type "devfs"
|
||||
#:options "rw"
|
||||
#:needed-for-boot? #t)
|
||||
(file-system #:device "tmpfs"
|
||||
#:mount-point "/tmp"
|
||||
#:type "tmpfs"
|
||||
#:options "rw,size=64m"))
|
||||
#:services '(shepherd ready-marker sshd)
|
||||
#:loader-entries '(("autoboot_delay" . "1")
|
||||
("boot_multicons" . "YES")
|
||||
("boot_serial" . "YES")
|
||||
("console" . "comconsole,vidconsole"))
|
||||
#:rc-conf-entries '(("clear_tmp_enable" . "NO")
|
||||
("hostid_enable" . "NO")
|
||||
("sendmail_enable" . "NONE")
|
||||
("sshd_enable" . "YES")
|
||||
("ifconfig_xn0" . "SYNCDHCP")
|
||||
("ifconfig_em0" . "SYNCDHCP")
|
||||
("ifconfig_vtnet0" . "SYNCDHCP"))
|
||||
#:init-mode 'shepherd-pid1
|
||||
#:ready-marker "/var/lib/fruix/ready"
|
||||
#:root-authorized-keys '("__ROOT_AUTHORIZED_KEY__")))
|
||||
245
tests/system/run-phase16-declarative-source-build.sh
Executable file
245
tests/system/run-phase16-declarative-source-build.sh
Executable file
@@ -0,0 +1,245 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
project_root=${PROJECT_ROOT:-$(pwd)}
|
||||
script_dir=$(CDPATH= cd -- "$(dirname "$0")" && pwd)
|
||||
fruix_cmd=$project_root/bin/fruix
|
||||
os_template=${OS_TEMPLATE:-$script_dir/phase16-declarative-source-operating-system.scm.in}
|
||||
source_probe=${SOURCE_PROBE:-$script_dir/validate-phase16-freebsd-source.scm}
|
||||
system_name=${SYSTEM_NAME:-phase16-operating-system}
|
||||
store_dir=${STORE_DIR:-/frx/store}
|
||||
base_name=${BASE_NAME:-source-model}
|
||||
base_version_label=${BASE_VERSION_LABEL:-15.0-STABLE-source-model}
|
||||
base_release=${BASE_RELEASE:-15.0-STABLE}
|
||||
base_branch=${BASE_BRANCH:-stable/15}
|
||||
source_name=${SOURCE_NAME:-host-usr-src}
|
||||
metadata_target=${METADATA_OUT:-}
|
||||
root_authorized_key_file=${ROOT_AUTHORIZED_KEY_FILE:-$HOME/.ssh/id_ed25519.pub}
|
||||
|
||||
[ -x "$fruix_cmd" ] || {
|
||||
echo "fruix command is not executable: $fruix_cmd" >&2
|
||||
exit 1
|
||||
}
|
||||
[ -f "$os_template" ] || {
|
||||
echo "missing operating-system template: $os_template" >&2
|
||||
exit 1
|
||||
}
|
||||
[ -f "$source_probe" ] || {
|
||||
echo "missing source probe script: $source_probe" >&2
|
||||
exit 1
|
||||
}
|
||||
[ -f "$root_authorized_key_file" ] || {
|
||||
echo "missing root authorized key file: $root_authorized_key_file" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
cleanup=0
|
||||
if [ -n "${WORKDIR:-}" ]; then
|
||||
workdir=$WORKDIR
|
||||
mkdir -p "$workdir"
|
||||
else
|
||||
workdir=$(mktemp -d /tmp/fruix-phase16-declarative-source.XXXXXX)
|
||||
cleanup=1
|
||||
fi
|
||||
if [ "${KEEP_WORKDIR:-0}" -eq 1 ]; then
|
||||
cleanup=0
|
||||
fi
|
||||
|
||||
cleanup_workdir() {
|
||||
if [ "$cleanup" -eq 1 ]; then
|
||||
rm -rf "$workdir" 2>/dev/null || sudo rm -rf "$workdir"
|
||||
fi
|
||||
}
|
||||
trap cleanup_workdir EXIT INT TERM
|
||||
|
||||
phase16_os_file=$workdir/phase16-declarative-source-operating-system.scm
|
||||
source_probe_out=$workdir/source-probe.txt
|
||||
build_out=$workdir/build.txt
|
||||
metadata_file=$workdir/phase16-declarative-source-build-metadata.txt
|
||||
root_authorized_key=$(tr -d '\n' < "$root_authorized_key_file")
|
||||
sed \
|
||||
-e "s|__BASE_NAME__|$base_name|g" \
|
||||
-e "s|__BASE_VERSION_LABEL__|$base_version_label|g" \
|
||||
-e "s|__BASE_RELEASE__|$base_release|g" \
|
||||
-e "s|__BASE_BRANCH__|$base_branch|g" \
|
||||
-e "s|__SOURCE_NAME__|$source_name|g" \
|
||||
-e "s|__ROOT_AUTHORIZED_KEY__|$root_authorized_key|g" \
|
||||
"$os_template" > "$phase16_os_file"
|
||||
|
||||
action_env() {
|
||||
sudo env \
|
||||
HOME="$HOME" \
|
||||
GUILE_AUTO_COMPILE=0 \
|
||||
FRUIX_FREEBSD_BUILD_JOBS="${FRUIX_FREEBSD_BUILD_JOBS:-8}" \
|
||||
GUIX_SOURCE_DIR="${GUIX_SOURCE_DIR:-$HOME/repos/guix}" \
|
||||
GUILE_BIN="${GUILE_BIN:-/tmp/guile-freebsd-validate-install/bin/guile}" \
|
||||
GUILE_EXTRA_PREFIX="${GUILE_EXTRA_PREFIX:-/tmp/guile-gnutls-freebsd-validate-install}" \
|
||||
SHEPHERD_PREFIX="${SHEPHERD_PREFIX:-/tmp/shepherd-freebsd-validate-install}" \
|
||||
"$@"
|
||||
}
|
||||
|
||||
action_env "${GUILE_BIN:-/tmp/guile-freebsd-validate-install/bin/guile}" \
|
||||
-L "$project_root/modules" \
|
||||
-c "(primitive-load \"$source_probe\")" >"$source_probe_out"
|
||||
|
||||
for expected in \
|
||||
'local_kind=local-tree' \
|
||||
'local_path=/usr/src' \
|
||||
'git_kind=git' \
|
||||
'git_url=https://git.FreeBSD.org/src.git' \
|
||||
'git_ref=stable/15' \
|
||||
'txz_kind=src-txz' \
|
||||
'txz_url=https://download.freebsd.org/releases/amd64/15.0-RELEASE/src.txz' \
|
||||
'txz_sha256=example-sha256' \
|
||||
'base_source_accessor=ok'
|
||||
do
|
||||
grep -F "$expected" "$source_probe_out" >/dev/null || {
|
||||
echo "source probe missing expected line: $expected" >&2
|
||||
exit 1
|
||||
}
|
||||
done
|
||||
|
||||
action_env "$fruix_cmd" system build "$phase16_os_file" --system "$system_name" --store "$store_dir" >"$build_out"
|
||||
|
||||
closure_path=$(sed -n 's/^closure_path=//p' "$build_out")
|
||||
kernel_store=$(sed -n 's/^kernel_store=//p' "$build_out")
|
||||
bootloader_store=$(sed -n 's/^bootloader_store=//p' "$build_out")
|
||||
native_base_store_count=$(sed -n 's/^native_base_store_count=//p' "$build_out")
|
||||
native_base_stores=$(sed -n 's/^native_base_stores=//p' "$build_out")
|
||||
host_base_store_count=$(sed -n 's/^host_base_store_count=//p' "$build_out")
|
||||
freebsd_base_name_out=$(sed -n 's/^freebsd_base_name=//p' "$build_out")
|
||||
freebsd_base_version_label_out=$(sed -n 's/^freebsd_base_version_label=//p' "$build_out")
|
||||
freebsd_base_release_out=$(sed -n 's/^freebsd_base_release=//p' "$build_out")
|
||||
freebsd_base_branch_out=$(sed -n 's/^freebsd_base_branch=//p' "$build_out")
|
||||
freebsd_base_source_root_out=$(sed -n 's/^freebsd_base_source_root=//p' "$build_out")
|
||||
freebsd_base_file=$(sed -n 's/^freebsd_base_file=//p' "$build_out")
|
||||
freebsd_source_name_out=$(sed -n 's/^freebsd_source_name=//p' "$build_out")
|
||||
freebsd_source_kind_out=$(sed -n 's/^freebsd_source_kind=//p' "$build_out")
|
||||
freebsd_source_url_out=$(sed -n 's/^freebsd_source_url=//p' "$build_out")
|
||||
freebsd_source_path_out=$(sed -n 's/^freebsd_source_path=//p' "$build_out")
|
||||
freebsd_source_ref_out=$(sed -n 's/^freebsd_source_ref=//p' "$build_out")
|
||||
freebsd_source_commit_out=$(sed -n 's/^freebsd_source_commit=//p' "$build_out")
|
||||
freebsd_source_sha256_out=$(sed -n 's/^freebsd_source_sha256=//p' "$build_out")
|
||||
freebsd_source_file=$(sed -n 's/^freebsd_source_file=//p' "$build_out")
|
||||
store_layout_file=$(sed -n 's/^store_layout_file=//p' "$build_out")
|
||||
|
||||
[ -n "$closure_path" ] || { echo "missing closure path" >&2; exit 1; }
|
||||
[ "$host_base_store_count" = 0 ] || { echo "expected zero host base stores, got: $host_base_store_count" >&2; exit 1; }
|
||||
[ "$native_base_store_count" = 3 ] || { echo "expected three native base stores, got: $native_base_store_count" >&2; exit 1; }
|
||||
[ "$freebsd_base_name_out" = "$base_name" ] || { echo "unexpected freebsd base name: $freebsd_base_name_out" >&2; exit 1; }
|
||||
[ "$freebsd_base_version_label_out" = "$base_version_label" ] || { echo "unexpected freebsd base version label: $freebsd_base_version_label_out" >&2; exit 1; }
|
||||
[ "$freebsd_base_release_out" = "$base_release" ] || { echo "unexpected freebsd base release: $freebsd_base_release_out" >&2; exit 1; }
|
||||
[ "$freebsd_base_branch_out" = "$base_branch" ] || { echo "unexpected freebsd base branch: $freebsd_base_branch_out" >&2; exit 1; }
|
||||
[ "$freebsd_base_source_root_out" = /usr/src ] || { echo "unexpected freebsd base source root: $freebsd_base_source_root_out" >&2; exit 1; }
|
||||
[ "$freebsd_source_name_out" = "$source_name" ] || { echo "unexpected freebsd source name: $freebsd_source_name_out" >&2; exit 1; }
|
||||
[ "$freebsd_source_kind_out" = local-tree ] || { echo "unexpected freebsd source kind: $freebsd_source_kind_out" >&2; exit 1; }
|
||||
[ "$freebsd_source_url_out" = "" ] || { echo "unexpected freebsd source URL: $freebsd_source_url_out" >&2; exit 1; }
|
||||
[ "$freebsd_source_path_out" = /usr/src ] || { echo "unexpected freebsd source path: $freebsd_source_path_out" >&2; exit 1; }
|
||||
[ "$freebsd_source_ref_out" = "" ] || { echo "unexpected freebsd source ref: $freebsd_source_ref_out" >&2; exit 1; }
|
||||
[ "$freebsd_source_commit_out" = "" ] || { echo "unexpected freebsd source commit: $freebsd_source_commit_out" >&2; exit 1; }
|
||||
[ "$freebsd_source_sha256_out" = "" ] || { echo "unexpected freebsd source sha256: $freebsd_source_sha256_out" >&2; exit 1; }
|
||||
[ -f "$freebsd_base_file" ] || { echo "missing freebsd base file: $freebsd_base_file" >&2; exit 1; }
|
||||
[ -f "$freebsd_source_file" ] || { echo "missing freebsd source file: $freebsd_source_file" >&2; exit 1; }
|
||||
[ -f "$store_layout_file" ] || { echo "missing store layout file: $store_layout_file" >&2; exit 1; }
|
||||
|
||||
case "$kernel_store" in
|
||||
/frx/store/*-freebsd-native-kernel-$base_version_label) : ;;
|
||||
*) echo "unexpected kernel store path: $kernel_store" >&2; exit 1 ;;
|
||||
esac
|
||||
case "$bootloader_store" in
|
||||
/frx/store/*-freebsd-native-bootloader-$base_version_label) : ;;
|
||||
*) echo "unexpected bootloader store path: $bootloader_store" >&2; exit 1 ;;
|
||||
esac
|
||||
runtime_store=$(printf '%s\n' "$native_base_stores" | tr ',' '\n' | grep "freebsd-native-runtime-$base_version_label$" | head -n 1)
|
||||
[ -n "$runtime_store" ] || { echo "failed to recover runtime store" >&2; exit 1; }
|
||||
|
||||
for path in "$kernel_store/.freebsd-native-build-info.scm" "$bootloader_store/.freebsd-native-build-info.scm" "$runtime_store/.freebsd-native-build-info.scm"; do
|
||||
[ -f "$path" ] || {
|
||||
echo "missing native build info file: $path" >&2
|
||||
exit 1
|
||||
}
|
||||
grep -F "(declared-source" "$path" >/dev/null || {
|
||||
echo "native build info missing declared source block in $path" >&2
|
||||
exit 1
|
||||
}
|
||||
grep -F "(kind . local-tree)" "$path" >/dev/null || {
|
||||
echo "native build info missing declared source kind in $path" >&2
|
||||
exit 1
|
||||
}
|
||||
grep -F "(path . \"/usr/src\")" "$path" >/dev/null || {
|
||||
echo "native build info missing declared source path in $path" >&2
|
||||
exit 1
|
||||
}
|
||||
done
|
||||
|
||||
grep -F "(name . \"$source_name\")" "$freebsd_source_file" >/dev/null || {
|
||||
echo "freebsd source file missing name" >&2
|
||||
exit 1
|
||||
}
|
||||
grep -F "(kind . local-tree)" "$freebsd_source_file" >/dev/null || {
|
||||
echo "freebsd source file missing kind" >&2
|
||||
exit 1
|
||||
}
|
||||
grep -F "(path . \"/usr/src\")" "$freebsd_source_file" >/dev/null || {
|
||||
echo "freebsd source file missing path" >&2
|
||||
exit 1
|
||||
}
|
||||
grep -F "(source" "$freebsd_base_file" >/dev/null || {
|
||||
echo "freebsd base file missing nested source block" >&2
|
||||
exit 1
|
||||
}
|
||||
if ! grep -F "(source" "$closure_path/parameters.scm" >/dev/null; then
|
||||
echo "closure parameters do not record the declared source" >&2
|
||||
exit 1
|
||||
fi
|
||||
grep -F "(freebsd-source" "$store_layout_file" >/dev/null || {
|
||||
echo "store layout file missing declared source block" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
closure_base=$(basename "$closure_path")
|
||||
cat >"$metadata_file" <<EOF
|
||||
workdir=$workdir
|
||||
phase16_os_file=$phase16_os_file
|
||||
source_probe_out=$source_probe_out
|
||||
closure_path=$closure_path
|
||||
closure_base=$closure_base
|
||||
kernel_store=$kernel_store
|
||||
bootloader_store=$bootloader_store
|
||||
runtime_store=$runtime_store
|
||||
native_base_store_count=$native_base_store_count
|
||||
native_base_stores=$native_base_stores
|
||||
host_base_store_count=$host_base_store_count
|
||||
freebsd_base_name=$freebsd_base_name_out
|
||||
freebsd_base_version_label=$freebsd_base_version_label_out
|
||||
freebsd_base_release=$freebsd_base_release_out
|
||||
freebsd_base_branch=$freebsd_base_branch_out
|
||||
freebsd_base_source_root=$freebsd_base_source_root_out
|
||||
freebsd_base_file=$freebsd_base_file
|
||||
freebsd_source_name=$freebsd_source_name_out
|
||||
freebsd_source_kind=$freebsd_source_kind_out
|
||||
freebsd_source_url=$freebsd_source_url_out
|
||||
freebsd_source_path=$freebsd_source_path_out
|
||||
freebsd_source_ref=$freebsd_source_ref_out
|
||||
freebsd_source_commit=$freebsd_source_commit_out
|
||||
freebsd_source_sha256=$freebsd_source_sha256_out
|
||||
freebsd_source_file=$freebsd_source_file
|
||||
store_layout_file=$store_layout_file
|
||||
declarative_source_model=ok
|
||||
EOF
|
||||
|
||||
if [ -n "$metadata_target" ]; then
|
||||
mkdir -p "$(dirname "$metadata_target")"
|
||||
cp "$metadata_file" "$metadata_target"
|
||||
fi
|
||||
|
||||
printf 'PASS phase16-declarative-source-build\n'
|
||||
printf 'Work directory: %s\n' "$workdir"
|
||||
printf 'Metadata file: %s\n' "$metadata_file"
|
||||
if [ -n "$metadata_target" ]; then
|
||||
printf 'Copied metadata to: %s\n' "$metadata_target"
|
||||
fi
|
||||
printf '%s\n' '--- source probe ---'
|
||||
cat "$source_probe_out"
|
||||
printf '%s\n' '--- metadata ---'
|
||||
cat "$metadata_file"
|
||||
69
tests/system/validate-phase16-freebsd-source.scm
Normal file
69
tests/system/validate-phase16-freebsd-source.scm
Normal file
@@ -0,0 +1,69 @@
|
||||
(use-modules (fruix packages freebsd)
|
||||
(ice-9 format))
|
||||
|
||||
(define (assert condition message . rest)
|
||||
(unless condition
|
||||
(apply error message rest)))
|
||||
|
||||
(define local-source
|
||||
(freebsd-source
|
||||
#:name "host-usr-src"
|
||||
#:kind 'local-tree
|
||||
#:path "/usr/src"))
|
||||
|
||||
(define git-source
|
||||
(freebsd-source
|
||||
#:name "stable15-git"
|
||||
#:kind 'git
|
||||
#:ref "stable/15"))
|
||||
|
||||
(define txz-source
|
||||
(freebsd-source
|
||||
#:name "release-15.0-txz"
|
||||
#:kind 'src-txz
|
||||
#:url "https://download.freebsd.org/releases/amd64/15.0-RELEASE/src.txz"
|
||||
#:sha256 "example-sha256"))
|
||||
|
||||
(define git-base
|
||||
(freebsd-base
|
||||
#:name "git-base"
|
||||
#:source git-source
|
||||
#:source-root "/usr/src"))
|
||||
|
||||
(define txz-base
|
||||
(freebsd-base
|
||||
#:name "txz-base"
|
||||
#:source txz-source
|
||||
#:source-root "/usr/src"))
|
||||
|
||||
(assert (eq? (freebsd-source-kind local-source) 'local-tree)
|
||||
"unexpected local source kind")
|
||||
(assert (string=? (freebsd-source-path local-source) "/usr/src")
|
||||
"unexpected local source path")
|
||||
(assert (eq? (freebsd-source-kind git-source) 'git)
|
||||
"unexpected git source kind")
|
||||
(assert (string=? (freebsd-source-url git-source) "https://git.FreeBSD.org/src.git")
|
||||
"unexpected default git source URL")
|
||||
(assert (string=? (freebsd-source-ref git-source) "stable/15")
|
||||
"unexpected git source ref")
|
||||
(assert (eq? (freebsd-source-kind txz-source) 'src-txz)
|
||||
"unexpected txz source kind")
|
||||
(assert (string=? (freebsd-source-url txz-source)
|
||||
"https://download.freebsd.org/releases/amd64/15.0-RELEASE/src.txz")
|
||||
"unexpected txz source URL")
|
||||
(assert (string=? (freebsd-source-sha256 txz-source) "example-sha256")
|
||||
"unexpected txz source sha256")
|
||||
(assert (freebsd-source? (freebsd-base-source git-base))
|
||||
"git base did not preserve source record")
|
||||
(assert (freebsd-source? (freebsd-base-source txz-base))
|
||||
"txz base did not preserve source record")
|
||||
|
||||
(format #t "local_kind=~a~%" (freebsd-source-kind local-source))
|
||||
(format #t "local_path=~a~%" (freebsd-source-path local-source))
|
||||
(format #t "git_kind=~a~%" (freebsd-source-kind git-source))
|
||||
(format #t "git_url=~a~%" (freebsd-source-url git-source))
|
||||
(format #t "git_ref=~a~%" (freebsd-source-ref git-source))
|
||||
(format #t "txz_kind=~a~%" (freebsd-source-kind txz-source))
|
||||
(format #t "txz_url=~a~%" (freebsd-source-url txz-source))
|
||||
(format #t "txz_sha256=~a~%" (freebsd-source-sha256 txz-source))
|
||||
(format #t "base_source_accessor=ok~%")
|
||||
Reference in New Issue
Block a user