Publishing your own catalog
nem catalog publish turns a directory of package manifests into an OCI
index that other machines can add. It pushes manifests, not archives; those
come from build --push and fill.
What publish does
nem catalog publish takes a bare repository reference and a local
catalog, a directory or a single pkg.yaml:
nem catalog publish registry.example/nem/catalog . --dry-run # the plan, nothing pushed
nem catalog publish registry.example/nem/catalog . # publish under tag v4It lints the catalog first and refuses on findings. Both runs start by
comparing the catalog with the index the tags currently point at. The
dry run prints the packages that would change, as new, updated or
removed, and the tags it would write:
PACKAGE VERSION STATUS
jq 1.8.2 new
OK Would publish registry.example/nem/catalog: 1 to push, tags v4, v4.20260930T092433ZThe real run pushes each changed package manifest, assembles the index, and tags it:
OK Compared with registry.example/nem/catalog:v4: 1 to push
OK Pushed jq 1.8.2
OK Published registry.example/nem/catalog: 1 pushed, 0 unchanged, tags v4, v4.20260930T092433ZTwo things to notice. The reference carries no tag: --tag says which
tags to move, v4 by default, and the reference with a tag is refused
with must be a bare repository ref. And every run also writes a release
tag, v4. followed by the UTC time, so each published state keeps a name
you can pin or roll back to. A second run with nothing changed pushes
nothing and moves the tags to the same index:
OK Compared with registry.example/nem/catalog:v4: 1 unchanged
OK Published registry.example/nem/catalog: 0 pushed, 1 unchanged, tags v4, v4.20260930T092512ZA package that the published index lists but the catalog no longer has
is dropped from the new index; the dry run shows it as removed and the
summary counts it.
--force pushes every manifest again regardless.
--output json prints the result on stdout for scripts: the reference,
the tags, the digest of the published index, and the changed packages.
The dry run prints the same document, with the digest the publish would
produce, so a pipeline can tag that exact index later.
{
"ref": "registry.example/nem/catalog",
"tags": ["v4", "v4.20260930T092433Z"],
"index": "sha256:…",
"packages": [{"name": "jq", "version": "1.8.2", "status": "new"}]
}Archives
Publishing pushes manifests, not archives. Packages built from source get
their archives from nem catalog build --push against the published
reference with its tag;
see Building from source.
Packages that download from upstream work without archives, and
nem catalog fill against the published
reference adds them when you want consumers to stop reaching upstream.
A safe pipeline
The official catalog publishes to a staging tag, proves it, then promotes, and the same shape works for any catalog:
nem catalog publish registry.example/nem/catalog . --tag v4-staging # 1. stage
nem catalog build registry.example/nem/catalog:v4-staging --missing --push # 2. archives against staging
nem catalog test registry.example/nem/catalog:v4-staging --package jq # 3. prove it, on each platform's runner
oras tag registry.example/nem/catalog:v4-staging v4 # 4. promote by retaggingPromotion retags the same index, so what was tested is what ships. The release tag written in step 1 is the permanent name for that state.
Telling consumers
nem catalog add corp registry.example/nem/catalog:v4 # follow the moving tag
nem catalog add corp registry.example/nem/catalog@sha256:… # or freeze one stateAccess and rollout covers credentials and getting the entry onto every machine.