89 lines
3.3 KiB
Markdown
89 lines
3.3 KiB
Markdown
# `pkg/bundle`
|
|
|
|
Audience: upstream Go producer developers and LLM coding agents using `distributor` source bundle helpers.
|
|
|
|
Import path:
|
|
|
|
```go
|
|
import "gitea.maximumdirect.net/eric/distributor/pkg/bundle"
|
|
```
|
|
|
|
`pkg/bundle` builds, writes, parses, and validates local source bundles. Use it directly when a producer writes bundles for `distributor` to discover, or when a producer wants to assemble and validate a bundle before using another transport.
|
|
|
|
The canonical source bundle file-format contract is [Source Bundle Contract](../integrations/source-bundle.md).
|
|
|
|
## Preferred Complete-Bundle Workflow
|
|
|
|
Use `WriteBundle` when producer-generated files live outside the final bundle root.
|
|
|
|
```go
|
|
manifest, err := bundle.WriteBundle(bundle.WriteBundleOptions{
|
|
Root: "/var/spool/distributor/weather/hourly-2026-06-07T15",
|
|
ID: "weather.hourly.brentwood.2026-06-07T15",
|
|
Files: []bundle.BundleFile{
|
|
{SourcePath: "/tmp/weather/report.md", Path: "report.md"},
|
|
{SourcePath: "/tmp/weather/summary.txt", Path: "summary.txt"},
|
|
},
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_ = manifest
|
|
```
|
|
|
|
`WriteBundle` copies each source file into a staged bundle root, writes `manifest.json`, validates the staged bundle, and promotes it into place. Set `Overwrite: true` only when the producer intentionally replaces an existing bundle root.
|
|
|
|
## Existing Bundle Root Workflow
|
|
|
|
Use `BuildManifest` and `WriteManifest` when files are already staged under the final bundle root.
|
|
|
|
```go
|
|
root := "/var/spool/distributor/weather/hourly-2026-06-07T15"
|
|
manifest, err := bundle.BuildManifest(bundle.BuildOptions{
|
|
Root: root,
|
|
ID: "weather.hourly.brentwood.2026-06-07T15",
|
|
Files: []string{"report.md", "summary.txt"},
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := bundle.WriteManifest(root, manifest, bundle.WriteManifestOptions{}); err != nil {
|
|
return err
|
|
}
|
|
if err := bundle.ValidateBundle(root, manifest); err != nil {
|
|
return err
|
|
}
|
|
```
|
|
|
|
Use `Scan: true` instead of `Files` only when every valid regular file under the root should be included. Scan mode includes dotfiles, skips reserved metadata files, rejects symlinks, and sorts paths lexically.
|
|
|
|
## Paths And Ordering
|
|
|
|
Bundle paths are slash-separated paths relative to the bundle root.
|
|
|
|
Invalid paths include:
|
|
|
|
- empty paths;
|
|
- absolute paths;
|
|
- paths containing backslashes;
|
|
- `.` or `..` path segments;
|
|
- empty path segments;
|
|
- any basename of `manifest.json` or `.distributor.json`.
|
|
|
|
Explicit file lists preserve caller order. File order is part of the bundle digest, so producers should choose it deliberately and keep it stable.
|
|
|
|
## Validation And Digest Helpers
|
|
|
|
Use `ValidateBundle` before handing an existing local bundle to another process. It verifies manifest semantics, file existence, regular-file type, file size, per-file SHA-256 digests, and bundle digest.
|
|
|
|
Useful helpers:
|
|
|
|
- `LoadManifest`: read `manifest.json` from a bundle root.
|
|
- `ParseManifest` and `MarshalManifest`: parse or write manifest bytes.
|
|
- `ValidateManifest`: validate manifest-only semantics.
|
|
- `FileDigest`, `BundleDigest`, and `ValidateDigest`: digest helpers for diagnostics and tests.
|
|
|
|
## Boundaries
|
|
|
|
`pkg/bundle` does not upload bundles, publish destinations, transform Markdown, select pipelines, configure credentials, or write destination state. Those concerns belong to `pkg/upload` or the `distributor` application.
|