Add public local bundle writer

This commit is contained in:
2026-06-01 20:56:58 +00:00
parent bb68cb6602
commit 04557f610d
11 changed files with 522 additions and 16 deletions

View File

@@ -2,7 +2,7 @@
## Purpose
`internal/bundle` discovers and validates source bundles through the storage interface. The source manifest model, manifest parsing, manifest validation, path rules, and digest calculation come from `pkg/bundle` so producer-facing APIs and distributor validation share one manifest contract.
`internal/bundle` discovers and validates source bundles through the storage interface. The source manifest model, manifest parsing, manifest validation, path rules, digest calculation, and producer-side local writer come from `pkg/bundle` so producer-facing APIs and distributor validation share one manifest contract.
## Inputs and outputs
@@ -38,7 +38,7 @@ Manifest parsing and validation fail before destination planning. Storage-backed
## Boundaries
Internal bundle discovery uses `internal/storage` and does not import concrete adapters. Producer-side local filesystem manifest building and validation belong to `pkg/bundle`. CLI local path support is wired in `internal/app`.
Internal bundle discovery uses `internal/storage` and does not import concrete adapters. Producer-side local filesystem manifest building, complete bundle writing, and validation belong to `pkg/bundle`. CLI local path support is wired in `internal/app`.
## Tests

View File

@@ -76,27 +76,29 @@ Each published destination bundle contains `.distributor.json`. This file is the
Do not edit `.distributor.json` by hand during normal operation. If it is missing or invalid while destination files remain, `distributor` treats the destination as unmanaged or conflicted.
## Go Producer Manifests
## Go Producer Bundles
Go producer applications can import `gitea.maximumdirect.net/eric/distributor/pkg/bundle` to create source manifests with the same path, digest, timestamp, and validation rules used by `distributor`.
Go producer applications can import `gitea.maximumdirect.net/eric/distributor/pkg/bundle` to create complete local source bundles with the same path, digest, timestamp, and validation rules used by `distributor`.
Minimal producer-side manifest creation:
Minimal producer-side bundle creation:
```go
manifest, err := bundle.BuildManifest(bundle.BuildOptions{
manifest, err := bundle.WriteBundle(bundle.WriteBundleOptions{
Root: outputDir,
ID: "reports.example.2026-05-30",
Files: []string{"report.md", "summary.txt"},
Files: []bundle.BundleFile{
{SourcePath: reportPath, Path: "report.md"},
{SourcePath: summaryPath, Path: "summary.txt"},
},
})
if err != nil {
return err
}
if err := bundle.WriteManifest(outputDir, manifest, bundle.WriteManifestOptions{}); err != nil {
return err
}
```
Use explicit `Files` to preserve caller order, or `Scan: true` to recursively include regular files under `Root` in deterministic slash-path order. Scan mode includes dotfiles, excludes files named `manifest.json` or `.distributor.json`, and rejects symlinks.
`WriteBundle` copies local producer files into a sibling temporary directory, writes `manifest.json`, validates the result, and promotes the completed bundle into place. It fails if `Root` already exists unless `Overwrite` is true. With overwrite enabled, it builds and validates the replacement before moving the existing root aside.
Use `BuildManifest` and `WriteManifest` when a producer already wrote all bundle files into the final root. `BuildManifest` can preserve an explicit file order, or `Scan: true` can recursively include regular files under `Root` in deterministic slash-path order. Scan mode includes dotfiles, excludes files named `manifest.json` or `.distributor.json`, and rejects symlinks.
## Dry Runs

View File

@@ -187,7 +187,7 @@ Avoid dependencies for small conveniences. Do not let external dependency types
Use this current layout unless the project has a documented reason to differ:
- `cmd/distributor`: application entrypoint only.
- `pkg/bundle`: public producer-facing source manifest model, digest logic, parsing, building, manifest writing, and local validation helpers.
- `pkg/bundle`: public producer-facing source manifest model, digest logic, parsing, manifest building, complete local bundle writing, and local validation helpers.
- `internal/app`: application orchestration and top-level use cases.
- `internal/cli`: CLI command definitions, flags, argument parsing, and command wiring.
- `internal/config`: configuration structs, defaults, loading, precedence, and validation.

View File

@@ -6,7 +6,7 @@ Use it with `docs/policy/architecture.md` and `docs/policy/documentation.md`.
## Repository Layout
- `cmd/distributor`: executable entrypoint only.
- `pkg/bundle`: public producer-facing source manifest helpers.
- `pkg/bundle`: public producer-facing source manifest and local bundle writer helpers.
- `internal/app`: top-level use cases for `run`, `validate`, and `inspect`.
- `internal/cli`: standard-library command parsing, flags, help text, and command wiring.
- `internal/config`: YAML configuration structs, loading, defaults, and validation.