Gunnar

nordisk/Skidbladnir

.nornir/pack-guide.md

# pack — guide

> **Class:** `guide` · audience: a product author assembling a bundle. The *what* is in
> [`pack-design.md`](pack-design.md).

## Build a staging tree

```rust
use skidbladnir::pack::{self, Staging};

let staging = Staging::new(&staging_root, "20260704")?;   // pack.rs:38
staging.add_artifact(&local_binary, "linux-x86_64/holger")?;   // copy in under a relative path
staging.add_component_spec(&spec)?;                            // → manifests/holger.json
let files = staging.artifacts()?;                              // sorted list of what you staged
```

Then seal it with an `Archive` engine and write the VERSION beside the bundle:

```rust
use skidbladnir::archive::{Archive, TarZstd};
let manifest = TarZstd::new().pack(&staging_root, "20260704", &bundle_path)?;
pack::write_version_file(&bundle_path, "20260704")?;   // VERSION sits NEXT TO the bundle
```

## Record provenance

```rust
let pm = pack::pack(&staging, "holger", /* built_in_container */ false)?;   // PackManifest
// pm.artifacts lists everything staged; pm.built_in_container records how it was built
```

## Capture target-identical dependencies (build host only)

To make a component byte-alike with the destination OS, build it in a container:

```rust
use skidbladnir::pack::{ContainerBuild, PodmanBuild};

let builder = PodmanBuild::new("registry/nordisk/build:ubuntu-24.04")
    .step("cargo build --release -p holger");
if builder.runtime_available() {
    let produced = builder.build_into("holger", "x86_64-unknown-linux-gnu", &staging_root)?;
    // `produced` = the relative paths copied out of the container's /out
}
```

If podman is not installed, `build_into` returns a clear error naming the missing runtime — it
never fabricates a capture. Run this on the **build host**, never on the airgapped target.

## Gotchas

- `add_artifact`'s `rel` is the path the entry will have *inside* the bundle — mirror the layout
  the installer expects (e.g. `linux-x86_64/<binary>`; the install lifecycle unfolds the whole
  tree, so keep the real relative path — see [`install-guide.md`](install-guide.md)).
- The `VERSION` file is deliberately outside the archive — bump it without repacking.