Skip to content

Latest commit

 

History

History
160 lines (125 loc) · 7.22 KB

File metadata and controls

160 lines (125 loc) · 7.22 KB

Deciding what a repository publishes

A repository publishes what its lock says is placed on the configured track. Promoting, yanking and pruning edit those placements; collecting and rolling back act on what has already been published.

Promotions and yanks

Promotions and yanks edit only placement records. Package versions, blob bindings, and publication history remain available for later re-promotion:

go run ./cmd/snailmail promote --track testing python snail-demo 1.2.3
go run ./cmd/snailmail yank --track stable python snail-demo 1.2.3
# Or remove every placement for the exact version:
go run ./cmd/snailmail yank --all python snail-demo 1.2.3

git diff -- repos/python.lock.toml
git add repos/python.lock.toml
git commit -m "update Python package placements"
go run ./cmd/snailmail plan
go run ./cmd/snailmail apply

The repository and package version are exact; promotion does not copy package versions between repositories. Each repository renders only its configured --track (default stable), and Debian additionally renders only placements for its configured suite. Other placements remain recorded but are not exposed in that view. Removing the final visible placement publishes a valid empty index while retaining immutable package and blob records in Git. Debian defaults a new placement's distro to the configured suite; --distro DISTRO selects another distro coordinate explicitly.

Retention pruning removes only older placements, independently per package, track, and distro, using native PEP 440, Debian, or SemVer precedence:

go run ./cmd/snailmail prune python --keep 5
git add repos/python.lock.toml
git commit -m "prune old Python placements"
go run ./cmd/snailmail plan
go run ./cmd/snailmail apply

Versions tied at the retention boundary are kept together. Prune does not remove package-version records, CAS objects, remote blobs, or publication history; physical blob GC remains a separate future operation with tombstones and a grace period.

Raw repositories

raw repositories publish artifacts that carry no ecosystem metadata: release tarballs, static binaries, installers. Every other format reads a package name and version out of the bytes; raw cannot, so identity comes from the filename by convention, or from you when the convention does not apply.

go run ./cmd/snailmail setup raw --name tools --output public/tools

# <name>_<version>[_<os>][_<arch>].<ext> is read without flags.
go run ./cmd/snailmail add tools ./dist/ttysvg_0.1.2_linux_amd64.tar.gz

# Anything else needs identity supplied, including a name with an underscore,
# which cannot be told apart from an extra field.
go run ./cmd/snailmail add --name ttysvg --version 0.2.0 tools ./dist/build-final.bin

go run ./cmd/snailmail plan && go run ./cmd/snailmail apply
go run ./cmd/snailmail verify raw --repo public/tools

Artifacts are published at <name>/<version>/<filename> beside a generated SHA256SUMS and index.html. Identity lives in the path on purpose: because it may have come from a flag rather than from the bytes, the published tree has to record it somewhere a later reader can check without knowing what was typed. SHA256SUMS is the interchange format — sha256sum -c verifies a raw repository with no snailmail present. Raw has no signing: it is not an ecosystem, so no client knows to check a signature.

Collecting superseded releases

An object store keeps every revision it has ever published: a publication writes a whole tree under .snailmail/releases/<tree>/, and nothing removes the previous one. A project publishing daily accumulates a copy a day.

snailmail collect                 # report what would be removed
snailmail collect --keep 3 --yes  # remove it, retaining three recent revisions

Reporting is the default; --yes deletes. Three things always survive whatever --keep says: the live revision, whatever its rollback depends on, and any revision the ledger records within --keep. The first two are established by reading the host rather than the workspace, so a checkout whose ledger is behind cannot delete what is being served.

Note that with only two publications nothing is collectable — both are protected, the live one and the one it rolls back to. Local directories and GitHub Pages have nothing to collect and say so: the first leaves nothing behind, and the second leaves unreachable objects to git.

Collection is the one operation that needs s3:ListBucket, so it may run under a different credential from publishing.

Two things accumulate, and they are collected together. Release directories are one; the other only exists for helm and unsigned rpm, which write their artifacts at the paths clients fetch them from rather than inside a release directory — because index.yaml and repomd.xml name those paths, and rewriting a signed rpm would invalidate it. A chart dropped from the workspace a year ago is still a billable object that no release collection has ever touched. collect now removes those too, keeping every file that any surviving revision publishes.

Two revisions are always protected: the live one and the one its restore rolls back to. So the first collectable revision is the live one's grandparent, which is worth knowing before reading a --dry-run and concluding it reclaims less than expected. If a surviving revision's release descriptor cannot be read, the whole collection is refused rather than run against an unknown reference set — deleting too little costs storage, deleting too much costs the repository.

How much a repository keeps is part of its configuration, not a flag someone remembers:

snailmail setup deb --name apt --keep 20 ...

collect uses that, and --keep N overrides it for one run. The order matters: collection is the only operation here that deletes published bytes, so the policy belongs in the reviewed manifest where changing it is a diff, exactly like changing a gate or a signing key. A repository that declares nothing keeps the default of 10, so nothing configured before this behaves differently.

Undoing a publication

When a publication succeeded and turned out to be wrong:

snailmail rollback apt            # report what would be restored
snailmail rollback apt --yes      # restore the previous publication

One step, deliberately. A published revision carries a reference to the root it replaced, and collection protects that target for exactly this reason — so going back one publication is something the host can still verify. Going back further is not offered: nothing keeps a chain of restore references, and the older releases may have been collected. A rollback whose target cannot be checked is not a rollback.

Not every host can do it. A local directory and an ssh host both decline, because neither can establish that the release it would point back at is intact. There the answer is to revert the lock in git and publish forward, and rollback says so rather than failing obscurely.

Your lock still describes what you rolled back from. That is deliberate — the rollback changed what is served, not what your workspace wants — but it means the next apply will republish what you just undid unless you revert or amend the lock first. The command says this every time it runs.


Back to snailmail.