Update informer for applications written in Rust 🦀
It checks for a new version on Crates.io, GitHub, Npm and PyPI. 🚀
- Support of Crates.io, GitHub, Npm and PyPI.
- Configurable check frequency and request timeout.
- Caching the results of checking updates.
- Ability to implement your own registry or http client.
- Minimum dependencies - only directories, semver, serde and an HTTP client (ureq or reqwest).
The idea is actually not new. This feature has long been present in the GitHub CLI application and npm.
There is also a popular JavaScript library.
Add update-informer
to Cargo.toml
:
[dependencies]
update-informer = "1.1"
By default, update-informer
can only check on Crates.io and uses ureq as a default HTTP client.
To enable support for other registries or change the HTTP client, use features
:
[dependencies]
update-informer = { version = "1.1", default-features = false, features = ["github", "reqwest", "native-tls"] }
Available features:
Name | Type | Default? |
---|---|---|
crates | Registry | Yes |
github | Registry | No |
npm | Registry | No |
pypi | Registry | No |
ureq | HTTP client | Yes |
reqwest | HTTP client | No |
rustls-tls | HTTP client feature | Yes |
native-tls | HTTP client feature | No |
To check for a new version, use the UpdateInformer::check_version
function.
This function takes the project name and current version as well as registry:
use update_informer::{registry, Check};
let name = env!("CARGO_PKG_NAME");
let version = env!("CARGO_PKG_VERSION");
let informer = update_informer::new(registry::Crates, name, version);
if let Some(version) = informer.check_version().ok().flatten() {
println!("New version is available: {}", version);
}
More examples you can find here.
Note that the first check will start only after the interval has expired. By default, the interval is 24 hours, but you can change it:
use std::time::Duration;
use update_informer::{registry, Check};
const EVERY_HOUR: Duration = Duration::from_secs(60 * 60);
let informer = update_informer::new(registry::Crates, "crate_name", "0.1.0").interval(EVERY_HOUR);
informer.check_version(); // The check will start only after an hour
By default, update-informer
creates a file in the cache directory to avoid spam requests to the registry API.
In order not to cache requests, use a zero interval:
use std::time::Duration;
use update_informer::{registry, Check};
let informer = update_informer::new(registry::Crates, "crate_name", "0.1.0").interval(Duration::ZERO);
informer.check_version();
You can also change the request timeout. By default, it is 5 seconds:
use std::time::Duration;
use update_informer::{registry, Check};
const THIRTY_SECONDS: Duration = Duration::from_secs(30);
let informer = update_informer::new(registry::Crates, "crate_name", "0.1.0").timeout(THIRTY_SECONDS);
informer.check_version();
You can implement your own registry to check updates. For example:
use update_informer::{http_client::{GenericHttpClient, HttpClient}, registry, Check, Package, Registry, Result};
#[derive(serde::Deserialize)]
struct Response {
version: String,
}
struct YourOwnRegistry;
impl Registry for YourOwnRegistry {
const NAME: &'static str = "your_own_registry";
fn get_latest_version<T: HttpClient>(http_client: GenericHttpClient<T>, pkg: &Package) -> Result<Option<String>> {
let url = "https://turbo.build/api/binaries/version";
let resp = http_client.get::<Response>(&url)?;
Ok(Some(resp.version))
}
}
let informer = update_informer::new(YourOwnRegistry, "turbo", "0.1.0");
informer.check_version();
You can use your own HTTP client to check updates. For example, isahc:
use isahc::ReadResponseExt;
use std::time::Duration;
use serde::de::DeserializeOwned;
use update_informer::{http_client::{HeaderMap, HttpClient}, registry, Check};
struct YourOwnHttpClient;
impl HttpClient for YourOwnHttpClient {
fn get<T: DeserializeOwned>(
url: &str,
_timeout: Duration,
_headers: HeaderMap,
) -> update_informer::Result<T> {
let json = isahc::get(url)?.json()?;
Ok(json)
}
}
let informer = update_informer::new(registry::Crates, "crate_name", "0.1.0").http_client(YourOwnHttpClient);
informer.check_version();
In order not to check for updates in tests, you can use the FakeUpdateInformer::check_version
function, which returns the desired version:
use update_informer::{registry, Check};
let name = "crate_name";
let version = "0.1.0";
#[cfg(not(test))]
let informer = update_informer::new(registry::Crates, name, version);
#[cfg(test)]
let informer = update_informer::fake(registry::Crates, name, version, "1.0.0");
if let Some(version) = informer.check_version().ok().flatten() {
println!("New version is available: {}", version);
}
To use the FakeUpdateInformer::check_version
function in integration tests, you must first add the feature flag to Cargo.toml
:
[features]
stub_check_version = []
Then use this feature flag in your code and integration tests:
use update_informer::{registry, Check};
let name = "crate_name";
let version = "0.1.0";
#[cfg(not(feature = "stub_check_version"))]
let informer = update_informer::new(registry::Crates, name, version);
#[cfg(feature = "stub_check_version")]
let informer = update_informer::fake(registry::Crates, name, version, "1.0.0");
informer.check_version();
Minimum Supported Rust Version: 1.56.1
update-informer is created & supported by Evrone