Point a tool at a release source¶
Embed the config type¶
ReleaseSourceConfig is Deserialize and Serialize, so drop it into your
own config struct:
A user's YAML then looks like this:
The source_type key selects the variant, and the rest of the keys belong to
that variant's parameter struct. A typo in a required key name fails at
deserialise time with a serde error naming the field
(missing field `owner`). A typo in an optional key does not — unknown keys
are accepted and ignored, so a mistyped timeout_seconds silently leaves the
default in place. Every key, default and validation rule is in
Release source configuration.
Resolve it to a provider¶
Two steps: find the factory, then call it.
use rtb_forge::{lookup, registered_types, ReleaseProvider};
use secrecy::SecretString;
use std::sync::Arc;
fn build_provider(
cfg: &rtb_forge::ReleaseSourceConfig,
token: Option<SecretString>,
) -> anyhow::Result<Arc<dyn ReleaseProvider>> {
let factory = lookup(cfg.source_type()).ok_or_else(|| {
anyhow::anyhow!(
"no release backend for `{}`; this build supports: {}",
cfg.source_type(),
registered_types().join(", ")
)
})?;
Ok(factory(cfg, token)?)
}
Always render registered_types() in that error. The set of available backends
depends on the Cargo features this binary was built with, so a hard-coded list
in the message will be wrong on a trimmed build.
cfg.source_type() returns the right discriminator for every variant,
including Custom — where it returns the nested type value rather than the
literal string custom.
Supply a token¶
The second argument is Option<SecretString>. Pass None for public
repositories. For private ones, resolve the secret however your tool already
does — rtb-credentials if you use the toolkit:
use rtb_credentials::{CredentialRef, Resolver};
let cref = CredentialRef {
env: Some("GITHUB_TOKEN".into()),
..Default::default()
};
let token = Resolver::with_platform_default().resolve(&cref).await?;
let provider = build_provider(&cfg.release, Some(token))?;
Note that the private: true key in config does not do this for you, and
does not do anything else either — see
What rtb-forge does not do.
Reach a self-hosted instance¶
GitLab and Gitea take a bare host; the API path is appended for you.
release:
source_type: gitea
host: git.example.com # required — Gitea has no default host
owner: platform
repo: deploy-tool
GitHub Enterprise takes the instance host and gets /api/v3 appended:
release:
source_type: github
host: github.example.com # becomes github.example.com/api/v3
owner: platform
repo: deploy-tool
If your instance serves its API somewhere else, write the full path — a host
containing /api/ is passed through untouched.
All hosts must be HTTPS. An http:// prefix is a configuration error, and
there is no config-file switch to relax it.
Reach Codeberg, or another Gitea instance¶
Codeberg has its own source_type and takes no host:
The host is fixed at codeberg.org. For any other Gitea instance use
source_type: gitea and set host — it is the same backend underneath.
Serve releases from a bucket or mirror¶
When there is no forge API at all, use the direct backend. It needs a URL that returns the current version, and a template for the asset URL:
release:
source_type: direct
version_url: https://downloads.example.com/deploy-tool/stable.txt
asset_url_template: https://downloads.example.com/deploy-tool/{version}/deploy-tool-{target}{ext}
version_url may return the version as plain text, or as JSON with a
version string at the root. The template must contain {version};
{target}, {os}, {arch} and {ext} are also substituted.
{target} only resolves for x86_64 and aarch64 on Linux, macOS and Windows. On
any other host it becomes the empty string, producing a URL that looks fine
and 404s. If you ship for musl, 32-bit ARM or a BSD, build the filename from
{os} and {arch} instead:
asset_url_template: https://downloads.example.com/deploy-tool/{version}/deploy-tool-{os}-{arch}{ext}
Pin to a known version¶
Set pinned_version on a direct source and the version URL is never fetched:
release:
source_type: direct
version_url: https://downloads.example.com/deploy-tool/stable.txt
asset_url_template: https://downloads.example.com/deploy-tool/{version}/tool{ext}
pinned_version: "1.4.2"
latest_release() then returns 1.4.2 without any network call, and
release_by_tag() returns NotFound for anything else. This is the only
backend with a pinning mechanism.
Set a timeout¶
Every backend accepts timeout_seconds, defaulting to 30:
0 does not mean "immediate" — it removes the timeout entirely, so a request
to an unresponsive host can hang indefinitely. If you want a short timeout,
write a short timeout.