Coverage Report

Created: 2026-06-16 01:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}