mod campaign

module campaign

Persisted build-evaluation campaigns with typed failure findings.

Variables

const CAMPAIGN_SCHEMA_VERSION: u32

Schema version of a campaign state document.

Functions

fn claim_finding(state_path: &Path, finding_id: &str, owner: &str) -> Result<CampaignState, CampaignError>

Take ownership of an open finding.

Fails when another owner already holds it, so two people cannot both believe they are fixing the same failure.

fn classify_build_failure(stage: &str, stdout: &str, stderr: &str, exit_code: Option<i32>) -> BuildFindingClass

Classify a failed build stage from its output.

Routing depends on this: the class decides whether a failure is worth retrying, needs a recipe change, or means the target itself is broken.

fn resolve_finding(state_path: &Path, finding_id: &str, owner: &str, resolution: FindingResolution) -> Result<CampaignState, CampaignError>

Close a finding with an action and its evidence.

Only the owner may close it, and only while it is in progress.

fn run_campaign(request: &CampaignRequest) -> Result<CampaignState, CampaignError>

Run a campaign to completion or to its first unresolved failure.

Takes the state file lock for the duration, so a second campaign against the same state fails with CampaignError::Busy rather than interleaving writes with the first.

Enums

enum BuildFindingClass

What kind of failure a build hit.

The class drives routing, so it distinguishes causes that need different responses: a transport failure is worth a retry, a checksum failure never is.

Transport

The target could not be reached or files could not be moved.

Executor

The scheduler or container runtime refused the job.

Runtime

The build process died without a usable diagnostic.

Interrupted

The attempt was cancelled or the connection dropped.

Source

A source artifact could not be fetched.

Checksum

A downloaded artifact did not match its declared hash.

Patch

A patch failed to apply.

DependencyMissing

A required dependency is absent from the target.

Configure

The configure step failed.

Compile

Compilation failed.

Linking failed.

Test

The package test suite failed.

Install

The install step failed.

Sanity

EasyBuild’s sanity check failed: it built but is not usable.

Resource

The job ran out of memory, disk, or another quota.

Timeout

The job exceeded its time limit.

Unknown
The output did not match any known signature. Left unclassified

/// rather than guessed at, so it reaches a human.

enum CampaignError

Why a campaign could not run or be updated.

InvalidBundle(String)

The bundle is missing or does not describe a buildable package.

UnsupportedSchema(u32)

The state file declares a schema this build does not read.

StateIdentity

The state file describes a different package or bundle.

Busy(PathBuf)

Another process holds the campaign lock.

FindingNotFound(String)

No finding with that identifier.

FindingOwned

The finding is claimed by another owner.

id: String

Finding that another owner holds.

owner: String

Who holds it.

FindingState

The finding is not in a state that allows this.

id: String

Finding whose state forbids the operation.

status: FindingStatus

State it is actually in.

Target(TargetError)

The build target could not be reached or prepared.

Io(PathBuf, std::io::Error)

A campaign file could not be read or written.

Json(PathBuf, serde_json::Error)

A campaign file could not be parsed or serialized.

enum CampaignStatus

Where a campaign has got to.

Planned

Created, nothing attempted yet.

Running

An attempt is in flight.

Failed

An attempt failed and left findings to work through.

Completed

Every recipe built and its claims were verified.

enum FindingDisposition

What kind of intervention a finding needs.

Mechanical

A tool can fix it without a decision.

Retryable

Worth retrying unchanged; the cause was transient.

RequiresJudgment

Needs a human to decide what correct means.

TargetRepair

The build target is at fault, not the recipe.

enum FindingStatus

How far a finding has been taken.

Open

Nobody has taken it.

InProgress

Claimed by an owner who is working on it.

Resolved

Closed with an action and evidence.

Superseded

Overtaken by events, e.g. a later attempt stopped hitting it.

Structs and Unions

struct BuildFinding

One thing that went wrong, classified so it can be routed.

id: String

Stable identifier, used to claim and resolve it.

class: BuildFindingClass

What kind of failure it is.

disposition: FindingDisposition

What kind of intervention it needs.

stage: String

Build stage that failed.

recipe: String

Recipe being built.

target: String

Target it was building on.

summary: String

One line a reviewer can triage from.

evidence: String

Captured output supporting the classification.

command: CommandPlan

The command that failed, so it can be rerun by hand.

exit_code: Option<i32>
Exit status, when the process produced one. Absent when it was

/// killed or never started.

attempt: u32

Attempt number this arose on.

status: FindingStatus

How far it has been taken.

owner: Option<String>

Who claimed it, while it is in progress.

resolution: Option<FindingResolution>

What closed it, once it is resolved.

struct CampaignEvent

One entry in the campaign history.

attempt: u32

Attempt this belongs to.

status: CampaignStatus

Status after the event.

recipe: Option<String>

Recipe in play, when the event concerned one.

detail: String

What happened.

struct CampaignRequest

What to build, where, and where to keep the state.

bundle: PathBuf

Package bundle produced by the planning stage.

target: BuildTarget

Where the build runs: local, SSH, scheduler, or container.

state_path: PathBuf

State file. Also the lock: one campaign owns it at a time.

struct CampaignState

The durable record of a campaign, rewritten under a lock.

schema_version: u32

Must equal CAMPAIGN_SCHEMA_VERSION.

package: String

Package being built.

version: String

Package version.

bundle: String

Bundle the recipes came from.

target: String

Target the build runs on.

status: CampaignStatus

Where the campaign has got to.

attempts: u32

How many attempts have been made.

claims: ClaimLadder

What has been demonstrated so far.

current_recipe: Option<String>

Recipe in flight, while one is.

findings: Vec<BuildFinding>

Everything that went wrong, open and closed alike.

history: Vec<CampaignEvent>

Ordered record of what happened.

struct ClaimLadder

What has actually been demonstrated, in increasing strength.

Each rung is a separate claim: solving is not building, and building is not evidence that the installed binaries run.

resolves: bool

Dependencies were selected successfully.

builds: bool

The recipes built.

binary_verified: bool

The declared binaries were run and behaved.

struct FindingResolution

What was done about a finding, and the proof.

action: String

What was changed or decided.

evidence: String

Why that is believed to have worked, in reviewable terms.

changes: Vec<String>

Files or recipes touched.