FerrFlow now publishes your packages to registries declaratively. Instead of wiring a postPublish shell hook that shells out to cargo publish, npm publish, or docker buildx, you describe the intent in ferrflow.json and FerrFlow runs it after the GitHub Release is created — per package, idempotently, and crash-resume safe.
Six publisher kinds are supported:
cargo publish to crates.io or a private registry, with allowDirty and noVerify.npm publish with a scoped, throwaway .npmrc so your project's .npmrc is never touched.docker buildx build --push with multi-arch ({version}/{major}/{minor}/latest tag templates), and optional sign: sigstore (cosign).helm package + helm push to an OCI registry.--clobber.{name}, {version}, {tag} and {env:NAME} interpolation.{
"workspace": {
"registries": {
"kellnr": { "tokenEnv": "CARGO_REGISTRIES_KELLNR_TOKEN" }
}
},
"package": [{
"name": "my-crate",
"path": "crates/my-crate",
"publishers": [
{ "kind": "cargo", "registry": "kellnr", "noVerify": true }
]
}]
}
Registry tokens are referenced by env-var name (tokenEnv) — the token value never lives in the config file, so ferrflow.json stays safe to commit. Every command publisher also takes an args array, a verbatim escape hatch for flags FerrFlow doesn't model natively (--locked, --provenance, --build-arg, …).
Publishers are idempotent: an already-published version is detected and skipped, so a re-run after a partial failure picks up exactly where it left off. The block is additive — your existing postPublish hooks keep working while you migrate. See the publishers documentation for the full reference.