Radish alpha
r
Radicle CI broker
Radicle
Git (anonymous pull)
Log in to clone via SSH
fix: use node id from ref name as originating node id
Lars Wirzenius committed 1 year ago
commit 2e2236aea751a401b6a6f4e6e702e8a1bc5105ec
parent 10f52163ba7041d92b569222b4a57890cd0a2e3f
3 files changed +38 -23
modified Cargo.lock
@@ -2006,6 +2006,7 @@ dependencies = [
 "duration-str",
 "html-page",
 "radicle",
+
 "radicle-crypto",
 "radicle-git-ext",
 "radicle-surf",
 "regex",
modified Cargo.toml
@@ -15,6 +15,7 @@ anyhow = "1.0.86"
clap = { version = "4.5.11", features = ["derive", "wrap_help"] }
duration-str = "0.11.2"
html-page = "0.4.0"
+
radicle-crypto = "0.11.0"
radicle-git-ext = "0.8.0"
radicle-surf = { version = "0.22.0", default-features = false, features = ["serde"] }
regex = "1.10.5"
modified src/ci_event.rs
@@ -7,12 +7,15 @@ use radicle_git_ext::Oid;

use radicle::{
    cob::patch::PatchId,
+
    crypto::PublicKey,
    git::RefString,
    node::{Event, NodeId},
    prelude::RepoId,
    storage::RefUpdate,
};

+
use crate::logger;
+

#[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)]
#[non_exhaustive]
pub enum CiEvent {
@@ -129,17 +132,11 @@ impl CiEvent {
        }))
    }

+
    #[allow(clippy::unwrap_used)]
    pub fn from_node_event(event: &Event) -> Result<Vec<Self>, CiEventError> {
-
        fn branch(ref_name: &str, update: &RefUpdate) -> Result<RefString, CiEventError> {
-
            ref_string(
-
                &namespaced_branch(ref_name)
-
                    .map_err(|_| CiEventError::without_namespace(ref_name, update.clone()))?,
-
            )
-
        }
-

        match event {
            Event::RefsFetched {
-
                remote,
+
                remote: _,
                rid,
                updated,
            } => {
@@ -147,26 +144,28 @@ impl CiEvent {
                for update in updated {
                    let e = match update {
                        RefUpdate::Created { name, oid } => {
+
                            let origin = originator(name.to_ref_string())?;
                            if let Ok(patch_id) = patch_id(name) {
-
                                Self::patch_created(*remote, *rid, patch_id, *oid)?
+
                                Self::patch_created(origin, *rid, patch_id, *oid)?
                            } else if let Ok(branch) = namespaced_branch(name) {
-
                                Self::branch_created(*remote, *rid, &branch, *oid)?
+
                                Self::branch_created(origin, *rid, &branch, *oid)?
                            } else {
                                continue;
                            }
                        }
                        RefUpdate::Updated { name, old, new } => {
+
                            let origin = originator(name.to_ref_string())?;
                            if let Ok(patch_id) = patch_id(name) {
-
                                Self::patch_updated(*remote, *rid, patch_id, *new)?
+
                                Self::patch_updated(origin, *rid, patch_id, *new)?
                            } else if namespaced_branch(name).is_ok() {
-
                                Self::branch_updated(*remote, *rid, name, *new, *old)?
+
                                Self::branch_updated(origin, *rid, name, *new, *old)?
                            } else {
                                continue;
                            }
                        }
                        RefUpdate::Deleted { name, oid } => {
-
                            branch(name, update)?; // check that there is a name spaced branch name
-
                            Self::branch_deleted(*remote, *rid, name, *oid)?
+
                            let origin = originator(name.to_ref_string())?;
+
                            Self::branch_deleted(origin, *rid, name, *oid)?
                        }
                        RefUpdate::Skipped { .. } => continue,
                    };
@@ -188,6 +187,19 @@ impl CiEvent {
    }
}

+
fn originator(name: RefString) -> Result<PublicKey, CiEventError> {
+
    logger::trace2(format!("originator: name={name:?}"));
+
    if let Some(qualified) = name.clone().into_qualified() {
+
        logger::trace2(format!("originator: qualified={qualified:?}"));
+
        if let Some(namespaced) = qualified.to_namespaced() {
+
            logger::trace2(format!("originator: namespaced={namespaced:?}"));
+
            return PublicKey::from_namespaced(&namespaced)
+
                .map_err(|err| CiEventError::key_from_namespaced(&name, err));
+
        }
+
    }
+
    Err(CiEventError::without_namespace2(name.as_str()))
+
}
+

fn ref_string(s: &str) -> Result<RefString, CiEventError> {
    RefString::try_from(s).map_err(|e| CiEventError::ref_string(s, e))
}
@@ -217,9 +229,6 @@ impl CiEvents {

#[derive(Debug, thiserror::Error)]
pub enum CiEventError {
-
    #[error("updated ref name has no name space: {0:?}): from {1:#?}")]
-
    WithoutNamespace(String, RefUpdate),
-

    #[error("updated ref name has no name space: {0:?})")]
    WithoutNamespace2(String),

@@ -234,13 +243,12 @@ pub enum CiEventError {

    #[error("broker events file is not valid JSON: {0}")]
    NotJson(PathBuf, #[source] serde_json::Error),
+

+
    #[error("failed to convert name spaced Git ref into node public key: {0}")]
+
    KeyFromNamespaced(RefString, #[source] radicle_crypto::PublicKeyError),
}

impl CiEventError {
-
    fn without_namespace(refname: &str, update: RefUpdate) -> Self {
-
        Self::WithoutNamespace(refname.into(), update)
-
    }
-

    fn without_namespace2(refname: &str) -> Self {
        Self::WithoutNamespace2(refname.into())
    }
@@ -260,6 +268,10 @@ impl CiEventError {
    fn not_json(filename: &Path, err: serde_json::Error) -> Self {
        Self::NotJson(filename.into(), err)
    }
+

+
    fn key_from_namespaced(name: &RefString, err: radicle_crypto::PublicKeyError) -> Self {
+
        Self::KeyFromNamespaced(name.to_ref_string(), err)
+
    }
}

#[cfg(test)]
@@ -269,11 +281,12 @@ mod test {
    use radicle::{prelude::NodeId, storage::RefUpdate};
    use std::str::FromStr;

-
    const MAIN_BRANCH_REF_NAME: &str = "refs/namespaces/NID/refs/heads/main";
+
    const MAIN_BRANCH_REF_NAME: &str =
+
        "refs/namespaces/z6MkiB8T5cBEQHnrs2MgjMVqvpSVj42X81HjKfFi2XBoMbtr/refs/heads/main";
    const MAIN_BRANCH_NAME: &str = "main";

    const PATCH_REF_NAME: &str =
-
        "refs/namespaces/NID/refs/heads/patches/f9fa90725474de9002be503ae3cda4670c9a174";
+
        "refs/namespaces/z6MkiB8T5cBEQHnrs2MgjMVqvpSVj42X81HjKfFi2XBoMbtr/refs/heads/patches/f9fa90725474de9002be503ae3cda4670c9a174";
    const PATCH_ID: &str = "f9fa90725474de9002be503ae3cda4670c9a174";

    fn nid() -> NodeId {