nimbus_cli/updater/
taskcluster.rs1use serde::de::DeserializeOwned;
6use std::time::Duration;
7use update_informer::{
8 http_client::{GenericHttpClient, HeaderMap, HttpClient},
9 Check, Package, Registry, Result,
10};
11
12#[derive(serde::Deserialize)]
13struct Response {
14 version: String,
15}
16
17struct TaskClusterRegistry;
18
19impl Registry for TaskClusterRegistry {
20 const NAME: &'static str = "taskcluster";
21
22 fn get_latest_version<T: HttpClient>(
23 http_client: GenericHttpClient<T>,
24 pkg: &Package,
25 ) -> Result<Option<String>> {
26 let name = pkg.to_string();
27 let url = format!("https://firefox-ci-tc.services.mozilla.com/api/index/v1/task/project.application-services.v2.{name}.latest/artifacts/public%2Fbuild%2F{name}.json");
28 let resp = http_client.get::<Response>(&url)?;
29 Ok(Some(resp.version))
30 }
31}
32
33#[allow(dead_code)]
34pub struct GunzippingHttpClient;
35
36impl HttpClient for GunzippingHttpClient {
37 fn get<T: DeserializeOwned>(url: &str, _timeout: Duration, headers: HeaderMap) -> Result<T> {
38 let mut req = viaduct::Request::get(viaduct::parse_url(url)?);
39
40 for (key, value) in headers {
41 req = req.header(key.to_string(), value.to_string())?;
42 }
43
44 let json = req.send()?.json()?;
45
46 Ok(json)
47 }
48}
49
50pub(crate) fn check_taskcluster_for_update() -> Option<(String, String)> {
53 let name = env!("CARGO_PKG_NAME");
54 let version = env!("CARGO_PKG_VERSION");
55 let interval = Duration::from_secs(60 * 60);
56
57 #[cfg(not(test))]
58 let informer = update_informer::new(TaskClusterRegistry, name, version)
59 .http_client(GunzippingHttpClient)
60 .interval(interval);
61
62 #[cfg(test)]
63 let informer =
64 update_informer::fake(TaskClusterRegistry, name, version, "1.0.0").interval(interval);
65
66 if let Ok(Some(new_version)) = informer.check_version() {
67 Some((format!("v{version}"), new_version.to_string()))
68 } else {
69 None
70 }
71}