Update informer for CLI applications written in Rust 🦀
It checks for a new version on Crates.io, GitHub and PyPI 🚀
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
:
toml
[dependencies]
update-informer = "0.5.0"
By default, update-informer
can only check on Crates.io.
To enable support for other registries, use features
:
toml
[dependencies]
update-informer = { version = "0.5.0", default_features = false, features = ["github"] }
Available features:
| Name | Default? | | ------ | -------- | | cargo | Yes | | github | No | | pypi | No |
To check for a new version on Crates.io, use the UpdateInformer::check_version
function.
This function takes the project name and current version as well as check interval:
```rust use update_informer::{registry, Check};
let informer = updateinformer::new(registry::Crates, "cratename", "0.1.0"); if let Some(version) = informer.check_version().ok().flatten() { println!("New version is available: {}", version); } ```
Also, you can take the name and version of the project from Cargo
using environment variables:
```rust use update_informer::{registry, Check};
let name = env!("CARGOPKGNAME"); let version = env!("CARGOPKGVERSION"); updateinformer::new(registry::Crates, name, version).checkversion(); ```
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:
```rust use std::time::Duration; use update_informer::{registry, Check};
const EVERYHOUR: Duration = Duration::fromsecs(60 * 60);
let informer = updateinformer::new(registry::Crates, "cratename", "0.1.0").interval(EVERYHOUR); informer.checkversion(); // 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:
```rust use std::time::Duration; use update_informer::{registry, Check};
let informer = updateinformer::new(registry::Crates, "cratename", "0.1.0").interval(Duration::ZERO); informer.check_version(); ```
You can also change the request timeout. By default, it is 5 seconds:
```rust use std::time::Duration; use update_informer::{registry, Check};
const THIRTYSECONDS: Duration = Duration::fromsecs(30);
let informer = updateinformer::new(registry::Crates, "cratename", "0.1.0").timeout(THIRTYSECONDS); informer.checkversion(); ```
To check for a new version on GitHub (note that the project name must contain the owner):
```rust use update_informer::{registry, Check};
let informer = updateinformer::new(registry::GitHub, "owner/repo", "0.1.0"); informer.checkversion(); ```
To check for a new version on PyPI:
```rust use update_informer::{registry, Check};
let informer = updateinformer::new(registry::PyPI, "packagename", "0.1.0"); informer.check_version(); ```
You can implement your own registry to check updates. For example:
```rust use std::time::Duration; use update_informer::{registry, Check, Package, Registry, Result, Version};
struct YourOwnRegistry;
impl Registry for YourOwnRegistry { const NAME: &'static str = "yourownregistry";
fn get_latest_version(pkg: &Package, _current_version: &Version, _timeout: Duration) -> Result<Option<String>> {
let url = format!("https://your_own_registry.com/{}/latest-version", pkg);
let result = ureq::get(&url).call()?.into_string()?;
let version = result.trim().to_string();
Ok(Some(version))
}
}
let informer = updateinformer::new(YourOwnRegistry, "packagename", "0.1.0"); informer.check_version(); ```
A real example of using
update_informer
with colored crate.
```rust use colored::*; use update_informer::{registry, Check};
fn main() { let pkgname = env!("CARGOPKGNAME"); let currentversion = env!("CARGOPKGVERSION");
let informer = update_informer::new(registry::Crates, pkg_name, current_version);
if let Some(version) = informer.check_version().ok().flatten() {
let msg = format!(
"A new release of {pkg_name} is available: v{current_version} -> {new_version}",
pkg_name = pkg_name.italic().cyan(),
current_version = current_version,
new_version = version.to_string().green()
);
let release_url = format!("https://github.com/{pkg_name}/{pkg_name}/releases/tag/{version}").yellow();
println!("\n{msg}\n{url}", msg = msg, url = release_url);
}
} ```
The result will look like:
In order not to check for updates in tests, you can use the FakeUpdateInformer::check_version
function, which returns the desired version.
Example of usage in unit tests:
```rust use update_informer::{registry, Check};
let name = "crate_name"; let version = "0.1.0";
let informer = update_informer::new(registry::Crates, name, version);
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
:
toml
[features]
stub_check_version = []
Then use this feature flag in your code and integration tests:
```rust use update_informer::{registry, Check};
let name = "crate_name"; let version = "0.1.0";
let informer = update_informer::new(registry::Crates, name, 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]
[MIT]