Documentation
¶
Overview ¶
Package realign proves a proposed realignment of an overlay ebuild towards its ::gentoo baseline, and proving is the whole of what it does: the staged-bump ladder in internal/autoupdate/validate decides whether the realignment builds, and this package is only the composition that hands the proposal to it.
Why there is a package here at all ¶
internal/overlay, where the compare that produces a proposal lives, must not import internal/autoupdate (prune.go's RegistryKeys comment states the rule), so the proving step cannot live there. The validate -> internal/overlay import cycle that once also blocked it no longer exists, since the overlay scanner moved to internal/gentoo/repo; the import rule is the reason that still holds. cmd/bentoo could join the two, as it does for buildDivergenceMap, but at the price of putting orchestration in the layer that is hardest to test. So the composition gets a package of its own: it imports internal/autoupdate/validate for the ladder and internal/overlay for the proposal, and neither of those gains an import of the other.
Three authorities, and this package is the caller of exactly one of them ¶
A realignment has three steps that are never collapsed: the model may say a divergence is no longer justified, the GATES say whether the realignment still builds, and only the maintainer's approval publishes it. Prove is the middle step and nothing else. It adds no gate of its own — in particular no "it matches ::gentoo now" check, which is exactly how the party that PROPOSES a change would acquire the authority to DECIDE it.
Promote is the step after, and it is not a fourth authority: the maintainer's answer reaches it as a bare bool, and its whole job is to refuse to publish unless both of the other two already said yes. Enforcing an answer is not making one.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrNotPromoted = errors.New("the realignment stays unpublished")
ErrNotPromoted is the sentinel every refusal below wraps. It carries one step further the split Prove already draws between a FAILED gate and a staging failure, into the step where the consequence is a publish.
A refusal is the system WORKING: an authority said no, nothing was written, and the published overlay is byte-identical. A write that broke is not — it happened after every authority had said yes, and it may have left the package directory holding something nobody decided on. A caller that reported the two the same way would teach its operator to skim past the one that needs a human, so the difference is offered as a sentinel rather than as wording a command would have to pattern-match.
Functions ¶
func Promote ¶
Promote writes a proved realignment into the published overlay, and only when the two authorities that are NOT this function have both already said yes: every gate reported PASS or SKIPPED, and the maintainer approved. It writes the exact bytes that were proved. Every refusal returns before the overlay is touched, so a realignment that is not approved or does not pass leaves the published tree byte-identical.
approved is a bare bool: asking belongs to the command layer, where the terminal is, and a function that asked itself could not be tested for refusing without an answer. The maintainer adds what no gate can: the overlay's nodejs carries a 492-line divergence that passes every rung and would still be wrong to revert.
The gates are re-read through validate.PromotionDecision rather than taken from Passed, so a refusal names the gate that said no; Passed is checked as well, and a disagreement between the two records refuses. What is published is the proposal's own bytes, the slice the gates ran against, never re-read from the staged tree: nothing writes there after Stage, and an approval that arrives after a cleanup or reboot removed the tree must not expire for it.
Types ¶
type Options ¶
type Options struct {
// Overlay is the published overlay the staged tree copies its eclasses and
// profiles out of. It is READ here and never written:
// every write this package causes lands under StagingRoot.
Overlay, StagingRoot string
// Depth is how far up the ladder the operator asked to go, passed through
// unchanged. Prove never substitutes a depth of its own — a
// realignment proved shallower than requested is a proof of something nobody
// asked about, and one proved deeper spends machine time nobody agreed to.
//
// DepthNone is the zero value, and it covers no build gate at all: the ladder
// then returns an empty list, nothing has FAILED, and this package reports a
// proof of nothing as Passed. That vacuity is not resolved here, because the
// depth is the operator's to choose and validate already answers a
// depth nobody chose where it is chosen — ParseDepth refuses the empty string
// rather than answering DepthNone, "so a mistyped config key cannot switch
// validation off in silence". The command that registers --depth is therefore
// the place that owes a realign run a depth worth having.
Depth validate.Depth
// StagedManifest answers, for the PUBLISHED package directory, the Manifest
// content the staged tree must carry before a build gate can run in it.
//
// It is the seam `overlay validate --depth` already goes through, and this
// package neither produces the bytes nor knows where they come from:
// Manifest GENERATION lives in autoupdate, and validate accepts only what a
// caller supplies. Nil means NOTHING TRAVELS — nothing is staged
// and nothing is built — which is validate's rule verbatim rather than a
// second one stated here.
StagedManifest func(pkgDir string) ([]byte, error)
// RequireIsolation is the operator's policy, carried and never asserted. The
// refusal it governs lives inside RunBuildGates and fires only when the
// request carries it; hardcoding a true here would refuse every build on a
// host that cannot create the namespace, which is the ordinary case.
RequireIsolation bool
// LogDir is where the build's whole transcript is kept for whoever has to go
// past the summary. Empty is still accepted — the gate's own reason then
// says the log was not retained — but a FAILED gate with no log is the one
// case where the summary is not enough.
LogDir string
// Distdir is the directory the build reads its archives from, carried into
// the prepared build and set on the child as DISTDIR.
//
// Carried, never resolved: this package adds no rule of its own about where
// archives come from, exactly as it adds none about depth or isolation. A
// realignment is a SAME-VERSION edit, so no fetch of its own has produced an
// archive — whatever directory already holds the release's tarball is the
// command layer's answer to give.
//
// Empty sets nothing and invents nothing: the build then reads
// the host's own configured DISTDIR, which is what every realign proof did
// before this field existed.
Distdir string
// Deps are the process- and host-level seams the build gates run through,
// passed to RunBuildGates untouched. Its zero value means "use the real
// thing" — every field is normalised by validate itself — so a caller with
// nothing to substitute passes nothing.
Deps validate.BuildDeps
}
Options is what Prove cannot work out for itself: which overlay the staged tree is built from, where the staged tree goes, how deep to gate, and the seams the build runs through.
The Manifest source and the two POLICY fields of validate.BuildRequest (RequireIsolation, LogDir) are carried through from the caller's effective configuration. Leaving them at their zero value made isolation a policy only one of the two building commands applied, and discarded the log of exactly the run that FAILED, the one somebody needs. Neither is decided here: this package adds no rule of its own, it carries the decision the command layer already resolved.
type Proof ¶
type Proof struct {
// StagedRoot is the staged repository the gates read, outside the published
// overlay. It is named on the proof rather than discarded because it is
// the evidence: a maintainer asked to approve a realignment can read the exact
// tree that was judged, and a failure nobody can inspect is a failure nobody
// can act on.
StagedRoot string
// Gates are the ladder's results, in the order and the number it returned
// them. Not filtered, not re-worded, not appended to: this package adds no
// gate, so a Proof that carried a different list from the one the ladder
// produced would be reporting an authority that does not exist.
Gates []validate.GateResult
// Passed is validate.PromotionDecision's answer over those gates — "every gate
// reported PASS or SKIPPED" — and it is only ONE of the two conditions
// publishing requires. The other is the maintainer's approval, which this package does
// not ask for and this field must never be read as. Passing gates are a
// permission to ask; they are not the answer.
Passed bool
}
Proof is what proving produced: where it was proved, what the gates said, and whether that is enough to be ALLOWED to publish — never that it was published.
func Prove ¶
Prove materialises a realigned ebuild in a staged tree outside the published overlay and runs the ladder's build gates against it, up to the depth the caller asked for. It returns what the gates said and whether that is enough to be allowed to publish; it publishes nothing.
Outside the overlay is a security property: the overlay auto-commits and pushes, so anything staged inside it would be released by the clock, and `overlay autoupdate --clean` would delete it. Stage enforces that itself (ensureOutsideOverlay); it is not re-checked here.
A FAILED gate comes back as (Proof, nil) with Passed false and the gate's reason intact: the realignment was examined. A staging failure comes back as an error, because nothing was examined, and "we could not look" must not read as "it does not build"; the gates are not consulted after it.
Only the BUILD gates run. validate.Run's options-vs-archive comparison needs the upstream archive on disk, and a same-version edit fetched none, so a change to the option list is judged by the configure and compile rungs instead, and not at all at a depth below them.
type Proposal ¶
Proposal is one realigned ebuild: the package it belongs to, the version it is a realignment of, and the body to be proved.
The version is the version ALREADY PUBLISHED. A realignment is not a bump — it rewrites how the same version is built, which is why nothing here carries an "old" and a "new" version and why the archive the ebuild points at has not moved.
Ebuild is proved verbatim. Nothing in this package reformats, regenerates or normalises it, for the same reason StageRequest's own EbuildBytes are written unchanged: a gate result has to describe a file that exists somewhere, and the file it must describe is the one an approval would publish. The moment proving and publishing could disagree about a single byte, every gate outcome becomes a statement about a file nobody will ever install.