/home/runner/work/lyquor/lyquor/toolchain/shaker/src/publish.rs
Line | Count | Source |
1 | | use anyhow::Context; |
2 | | use lyquor_oci::pack::LyquidPack; |
3 | | use lyquor_oci::registry::{ClientProtocol, OCIReference, OCIRegistryClient, Reference as RegistryReference}; |
4 | | use lyquor_primitives::B256; |
5 | | use reqwest::Url; |
6 | | |
7 | | /// Pushes a Lyquid pack to an OCI registry reference and returns its digest. |
8 | 2 | pub async fn push_lyquid( |
9 | 2 | pack: LyquidPack, registry: &OCIRegistryClient, reference: &OCIReference, |
10 | 2 | ) -> anyhow::Result<B256> { |
11 | 2 | let digest = registry |
12 | 2 | .push_reference(pack, reference) |
13 | 2 | .await |
14 | 2 | .map_err(|e| anyhow::anyhow!0 (e.to_string()0 ))?0 ; |
15 | 2 | Ok(*digest.digest()) |
16 | 2 | } |
17 | | |
18 | | /// Pushes a Lyquid pack to the local registry derived from a node API endpoint. |
19 | 0 | pub async fn push_lyquid_to_endpoint(pack: LyquidPack, endpoint: &str) -> anyhow::Result<B256> { |
20 | 0 | let reference = local_oci_target_from_api_endpoint(endpoint)?; |
21 | 0 | let oci = crate::oci_registry_from_reference(&reference, None, None, None).await?; |
22 | 0 | push_lyquid(pack, &oci, reference.reference()).await |
23 | 0 | } |
24 | | |
25 | 4 | fn local_oci_target_from_api_endpoint(endpoint: &str) -> anyhow::Result<RegistryReference> { |
26 | 4 | let url = Url::parse(endpoint).with_context(|| format!0 ("Invalid node API endpoint `{endpoint}`"))?0 ; |
27 | 4 | let registry = registry_host_from_api_endpoint(&url)?0 ; |
28 | 4 | let reference = OCIReference::with_tag(registry, "lyquids/local".into(), "latest".into()); |
29 | 4 | let transport = match url.scheme() { |
30 | 4 | "http" | "ws"3 => ClientProtocol::Http3 , |
31 | 1 | "https" | "wss" => ClientProtocol::Https, |
32 | 0 | scheme => anyhow::bail!("Unsupported node API endpoint scheme `{scheme}`"), |
33 | | }; |
34 | 4 | Ok(RegistryReference::new(reference, transport)) |
35 | 4 | } |
36 | | |
37 | 4 | fn registry_host_from_api_endpoint(url: &Url) -> anyhow::Result<String> { |
38 | 4 | let host = url.host_str().context("Node API endpoint is missing a host")?0 ; |
39 | 4 | let host = if host.contains(':') { |
40 | 0 | format!("[{host}]") |
41 | | } else { |
42 | 4 | host.to_owned() |
43 | | }; |
44 | 4 | let port = url |
45 | 4 | .port_or_known_default() |
46 | 4 | .context("Node API endpoint is missing a port and has no known default")?0 ; |
47 | 4 | Ok(format!("{host}:{port}")) |
48 | 4 | } |
49 | | |
50 | | #[cfg(test)] |
51 | | mod tests { |
52 | | use super::*; |
53 | | use lyquor_test::test; |
54 | | |
55 | | #[test] |
56 | | fn local_reference_derives_target_from_supported_endpoint_forms() { |
57 | | let cases = [ |
58 | | ( |
59 | | "ws://127.0.0.1:10087/ws", |
60 | | "127.0.0.1:10087/lyquids/local:latest", |
61 | | ClientProtocol::Http, |
62 | | ), |
63 | | ( |
64 | | "http://localhost:10087/api", |
65 | | "localhost:10087/lyquids/local:latest", |
66 | | ClientProtocol::Http, |
67 | | ), |
68 | | ("ws://lyquor/ws", "lyquor:80/lyquids/local:latest", ClientProtocol::Http), |
69 | | ( |
70 | | "wss://lyquor/ws", |
71 | | "lyquor:443/lyquids/local:latest", |
72 | | ClientProtocol::Https, |
73 | | ), |
74 | | ]; |
75 | | |
76 | | for (endpoint, expected_reference, expected_transport) in cases { |
77 | | let reference = local_oci_target_from_api_endpoint(endpoint).unwrap(); |
78 | | assert_eq!(reference.reference().to_string(), expected_reference); |
79 | | assert_eq!(reference.protocol(), expected_transport); |
80 | | } |
81 | | } |
82 | | } |