Point your tool at its releases¶
Everything self-update needs lives on ToolMetadata. The download, verification and
swap are rtb-update's job; this page covers the declaration.
Declare where the releases are¶
use rtb_app::metadata::{ReleaseSource, ToolMetadata, UpdatePolicy};
let metadata = ToolMetadata::builder()
.name("mytool")
.summary("does the thing")
.release_source(ReleaseSource::Gitlab {
project: "acme/tools/mytool".into(),
host: "gitlab.com".into(),
})
.update_public_keys(vec![
"RWRWR1qnVGNHTAOhB7/zzhC+HXDdGOdLwJln5NYwm6UNXx3chmQSVTG4".to_string(),
])
.build();
Six hosting shapes are available — Github, Gitlab, Bitbucket, Gitea,
Codeberg and Direct. Their required fields and host defaults are tabulated in
Tool metadata. Two to watch:
Giteahas no host default. Omittinghostfails withmissing field "host".Codeberghas nohostfield at all — use it instead ofGiteawithhost: codeberg.org.
Pin the signing keys¶
update_public_keys holds minisign public keys in the encoded form a minisign.pub
file carries — the RWR… string, not raw key bytes. Use the same string you pin as
pubkey in [package.metadata.binstall.signing] and that sigillum keys minisign
prints, so cargo-binstall and rtb-update cannot end up trusting different things
and an operator can compare the two by eye.
An empty list means rtb-update refuses to run. It is empty by default, so this
is the field most likely to be the reason self-update does nothing.
List more than one to rotate keys without breaking already-deployed binaries — any
one verifying is accepted, so a binary shipped trusting {old, new} spans the
rotation:
Name the assets, if yours are named differently¶
update_asset_pattern is None by default, and rtb-update then falls back to
{name}-{version}-{target}{ext}:
| Placeholder | Resolves to |
|---|---|
{name} |
ToolMetadata::name |
{version} |
the release tag with any leading v stripped |
{target} |
the Rust host triple |
{ext} |
.tar.gz on Unix, .zip on Windows |
Set it explicitly when your release job names assets some other way.
update_checksums_asset names an asset listing SHA-256 checksums. When set,
rtb-update downloads it alongside the binary and cross-checks the hash before the
swap. When None, signature verification is the only integrity gate — which is
a real gate, but it is one gate rather than two.
Turn automatic checking on¶
| Policy | Behaviour |
|---|---|
Disabled (default) |
No automatic check. The update subcommand still works. |
Prompt |
Checks, throttled; prompts when a newer version exists. |
Enabled |
Checks, throttled; updates before running. |
The default is Disabled so a tool makes no unsolicited network call and pays no
pre-run cost unless its author asked for it. The update subcommand is available
regardless — the policy governs only the automatic pre-run check.
Four things that silently disable self-update¶
Work down this list when nothing happens:
Feature::Updateis runtime-disabled. It is on by default, but a tool that built itsFeatureswithFeaturesBuilder::none()— or withFeaturesBuilder::default(), which is also empty — has turned it off.release_sourceisNone. Every update field is inert without it.update_public_keysis empty.rtb-updaterefuses rather than trusting an unsigned asset.- The tool still uses
VersionInfo::from_env(). It reports rtb-app's version instead of the tool's, and the post-download self-check compares the staged binary's reported version against the release tag. See Report your tool's own version.
Setting these from a config file¶
Only some of these fields can come from a config file. update_public_keys,
update_checksums_asset and update_asset_pattern all carry #[serde(skip)] and are
compile-time-only — and because ToolMetadata is also deny_unknown_fields, putting
one of them in a YAML document fails the whole parse rather than being ignored.
release_source, update_policy and update_check_interval do deserialise.
update_check_interval needs serde's Duration shape: