Publishing a Program
A program is one file, so it travels as one OCI layer with no tarball around it.
# berm.toml, beside the program's Cargo.toml
name = "example"
image = "ghcr.io/org/example"
public = []
crab deploy
crab deploy builds the program and, against a host that pulls from a
registry, pushes the image to image tagged with the crate's version and
deploys that reference. Against bermd it sends the image itself, so bermd
never talks to a registry, holds no credentials, and still restores from
--root on start without a network.
The artifact
{
"schemaVersion": 2,
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"artifactType": "application/vnd.berm.program.v1",
"config": { "mediaType": "application/vnd.berm.manifest.v1+json", "digest": "sha256:…" },
"layers": [ { "mediaType": "application/vnd.berm.program.v1", "digest": "sha256:…" } ]
}
The config blob is the .berm.abi section carried out of the
image byte for byte, so what a registry serves cannot disagree with what the image
holds. The tools, their schemas and the README are one blob, and reading them
never means pulling the program.
Nothing about the program is repeated in annotations. Only
org.opencontainers.image.source and .revision are set, from
GITHUB_REPOSITORY and GITHUB_SHA when a build has them, which is what makes
GHCR show a package against its repository.
One digest
Because the layer is the image and nothing else, the layer's digest is sha256 of
the image — the same hash crab ls reports, carrying the registry's sha256:
prefix:
$ crab ls
NAME DIGEST TOOLS
fixture 222890c498ed echo
$ shasum -a256 target/wasm32-unknown-unknown/release/fixture.wasm
222890c498ed28f4bf60670a223141489d9879020bd1890111b8c11ac79fa31d
A pulled image is checked against the digest the registry advertised before it goes anywhere, so a registry that serves the wrong bytes is caught by the deploy rather than by the model.
What deploy refuses
crab deploy reads the manifest out of the image before it uploads anything,
which means a broken image is refused by whoever built it rather than at deploy
on someone else's machine. Reading it never runs the guest.
From a workflow
GITHUB_TOKEN is the registry credential, and the deploy is two lines — there
is no action to install.
permissions:
packages: write
steps:
- run: crab context add cloud https://api.crabtalk.ai --token "$KEY" --org acme
env:
KEY: ${{ secrets.CRABTALK_KEY }}
- run: crab deploy --context cloud
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Locally, GITHUB_TOKEN=$(gh auth token) does the same. ~/.docker/config.json
is not read.
BERM_REGISTRY_MIRRORS reaches a registry at another address, as
name=endpoint pairs separated by commas. A host in a container pulls what was
pushed to localhost:5001 from http://registry:5000 with
BERM_REGISTRY_MIRRORS=localhost:5001=http://registry:5000.