Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/holger

.nornir/consolidation-jera-embed-guide.md

Using the job ledger + hosting the holger pane — guide

Class: guide. Architecture: consolidation-jera-embed-design.md.

Record promotions in the durable jera ledger

The server wires it automatically — every promotion becomes a tracked job at <data>/holger-jobs/jobs.redb. To attach a ledger yourself (a test, a tool):

use std::sync::Arc;
use holger_server_lib::promote::PromotionEngine;
use jera::jobs::{JobStore, JobSelector};

let store = Arc::new(JobStore::open(std::path::Path::new("/var/lib/holger/holger-jobs"))?);
let engine = PromotionEngine::new("/var/lib/holger/holger-prod-store")
    .with_job_ledger(store.clone());

// Every seal is now a `promote` job (running → done|failed) in the ledger:
engine.seal("rust-dev", "rust-prod", &id, &bytes, "alice@corp", now)?;

// List what the server promoted:
for job in store.list(&JobSelector::Kind("promote".into()))? {
    println!("{} {} -> {} [{}]", job.kind, job.target, job.workspace, job.status);
}

No ledger? Don't call with_job_ledger — seal behaves exactly as before and writes no job row. The ledger is purely additive.

Host holger's registry pane in another app

holger-embed returns the pane as a Box<dyn Facet> you drop into any egui host:

use holger_embed::{panel, Source};

// (a) fat / embedded: read an on-disk dev-pair registry in-process (no server).
let p = panel(Source::InProcess {
    data_dir: std::path::Path::new("/var/lib/holger/dev"),
    grpc: "127.0.0.1:50051", http: "127.0.0.1:8080", per_repo_limit: 1000,
})?;

// (b) thin gRPC: assemble a RegistryModel from a remote read, then feed it.
//     let model = my_grpc_read_into_registry_model();
//     let p = panel(Source::Model(model))?;

// (c) no backend (demo): the sample fixture.
let p = panel(Source::Fixture)?;

// The host drops `p` into a tab and calls p.ui(ui) each frame; p.state_json() is the
// observable state the test matrix + web state-hook consume.

Use the component directly (holger-demo does this)

use facett_holger::{RegistryBrowser, RegistryModel};

let mut browser = RegistryBrowser::from_fixture();      // or ::from_model(model)
browser.select_repo("npm-proxy");                       // or .update_json(r#"{"select_repo":"npm-proxy"}"#)
// browser.ui(ui) in your egui frame; browser.state_json() for assertions.