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