Radish alpha
r
Radicle CI broker
Radicle
Git (anonymous pull)
Log in to clone via SSH
feat: add a RequestBuilder to create Request messages
Lars Wirzenius committed 2 years ago
commit fee8700dc8d1845c7c8c55e0fd2dd99b29d3efe6
parent 65c2cbfd92534a1de6907feae1b9aaa6072700dc
4 files changed +110 -60
modified src/bin/broker-messages.rs
@@ -2,7 +2,7 @@ use radicle::git::RefString;
use radicle::Profile;
use radicle_ci_broker::{
    event::BrokerEvent,
-
    msg::{Oid, RepoId, Request, Response, RunId, RunResult},
+
    msg::{Oid, RepoId, RequestBuilder, Response, RunId, RunResult},
};

fn main() {
@@ -17,7 +17,11 @@ fn main() {
        old: None,
    };
    let profile = Profile::load().expect("create profile");
-
    let trigger = Request::trigger(&profile, &be).expect("create trigger");
+
    let trigger = RequestBuilder::default()
+
        .profile(&profile)
+
        .broker_event(&be)
+
        .build_trigger()
+
        .expect("create trigger");
    println!("Trigger request:\n{}\n", trigger);

    let triggered = Response::triggered(RunId::from("any-string-works-as-run-id"));
modified src/bin/ci-broker.rs
@@ -14,7 +14,7 @@ use radicle_ci_broker::{
    config::Config,
    error::BrokerError,
    event::NodeEventSource,
-
    msg::Request,
+
    msg::RequestBuilder,
    pages::{PageBuilder, StatusPage},
};

@@ -101,7 +101,10 @@ fn fallible_main() -> Result<(), BrokerError> {
        for e in source.event()? {
            page.broker_event(&e);
            debug!("broker event {e:#?}");
-
            let req = Request::trigger(&profile, &e)?;
+
            let req = RequestBuilder::default()
+
                .profile(&profile)
+
                .broker_event(&e)
+
                .build_trigger()?;
            broker.execute_ci(&req, &mut page)?;
        }
    }
modified src/msg.rs
@@ -95,62 +95,31 @@ impl fmt::Display for RunResult {
    }
}

-
/// A request message sent by the broker to its adapter child process.
-
#[derive(Debug, Clone, Serialize, Deserialize)]
-
#[serde(tag = "request")]
-
#[serde(rename_all = "snake_case")]
-
#[non_exhaustive]
-
pub enum Request {
-
    /// Trigger a run.
-
    Trigger {
-
        /// Common fields for all message variants.
-
        #[serde(flatten)]
-
        common: EventCommonFields,
-

-
        /// The push event, if any.
-
        #[serde(flatten)]
-
        push: Option<PushEvent>,
-

-
        /// The patch event, if any.
-
        #[serde(flatten)]
-
        patch: Option<PatchEvent>,
-
    },
+
/// Build a [`Request`].
+
#[derive(Debug, Default)]
+
pub struct RequestBuilder<'a> {
+
    profile: Option<&'a Profile>,
+
    event: Option<&'a BrokerEvent>,
}

-
impl Request {
-
    /// Repository that the event concerns.
-
    pub fn repo(&self) -> RepoId {
-
        match self {
-
            Self::Trigger {
-
                common,
-
                push: _,
-
                patch: _,
-
            } => common.repository.id,
-
        }
+
impl<'a> RequestBuilder<'a> {
+
    /// Set the node profile to use.
+
    pub fn profile(mut self, profile: &'a Profile) -> Self {
+
        self.profile = Some(profile);
+
        self
    }

-
    /// Return the commit the event concerns. In other words, the
-
    /// commit that CI should run against.
-
    pub fn commit(&self) -> Oid {
-
        match self {
-
            Self::Trigger {
-
                common: _,
-
                push,
-
                patch,
-
            } => {
-
                if let Some(push) = push {
-
                    *push.commits.last().unwrap()
-
                } else if let Some(patch) = patch {
-
                    *patch.patch.commits.last().unwrap()
-
                } else {
-
                    panic!("neither push not panic: {self:#?}");
-
                }
-
            }
-
        }
+
    /// Set the broker event to use.
+
    pub fn broker_event(mut self, event: &'a BrokerEvent) -> Self {
+
        self.event = Some(event);
+
        self
    }

-
    /// Create a request event to trigger a run.
-
    pub fn trigger(profile: &Profile, event: &BrokerEvent) -> Result<Self, MessageError> {
+
    /// Create a [`Request::Trigger`] message.
+
    pub fn build_trigger(self) -> Result<Request, MessageError> {
+
        let profile = self.profile.ok_or(MessageError::NoProfile)?;
+
        let event = self.event.ok_or(MessageError::NoEvent)?;
+

        let BrokerEvent::RefChanged {
            rid,
            name,
@@ -268,12 +237,67 @@ impl Request {
            },
        };

-
        Ok(Self::Trigger {
+
        Ok(Request::Trigger {
            common,
            push: push_info,
            patch: patch_info,
        })
    }
+
}
+

+
/// A request message sent by the broker to its adapter child process.
+
#[derive(Debug, Clone, Serialize, Deserialize)]
+
#[serde(tag = "request")]
+
#[serde(rename_all = "snake_case")]
+
#[non_exhaustive]
+
pub enum Request {
+
    /// Trigger a run.
+
    Trigger {
+
        /// Common fields for all message variants.
+
        #[serde(flatten)]
+
        common: EventCommonFields,
+

+
        /// The push event, if any.
+
        #[serde(flatten)]
+
        push: Option<PushEvent>,
+

+
        /// The patch event, if any.
+
        #[serde(flatten)]
+
        patch: Option<PatchEvent>,
+
    },
+
}
+

+
impl Request {
+
    /// Repository that the event concerns.
+
    pub fn repo(&self) -> RepoId {
+
        match self {
+
            Self::Trigger {
+
                common,
+
                push: _,
+
                patch: _,
+
            } => common.repository.id,
+
        }
+
    }
+

+
    /// Return the commit the event concerns. In other words, the
+
    /// commit that CI should run against.
+
    pub fn commit(&self) -> Oid {
+
        match self {
+
            Self::Trigger {
+
                common: _,
+
                push,
+
                patch,
+
            } => {
+
                if let Some(push) = push {
+
                    *push.commits.last().unwrap()
+
                } else if let Some(patch) = patch {
+
                    *patch.patch.commits.last().unwrap()
+
                } else {
+
                    panic!("neither push not panic: {self:#?}");
+
                }
+
            }
+
        }
+
    }

    /// Serialize the request as a single-line JSON, including the
    /// newline. This is meant for the broker to use.
@@ -547,6 +571,14 @@ impl Response {
/// All possible errors from the CI broker messages.
#[derive(Debug, thiserror::Error)]
pub enum MessageError {
+
    /// [`RequestBuilder`] does not have profile set.
+
    #[error("RequestBuilder must have profile set")]
+
    NoProfile,
+

+
    /// [`RequestBuilder`] does not have event set.
+
    #[error("RequestBuilder must have broker event set")]
+
    NoEvent,
+

    /// Failed to serialize a request message as JSON. This should
    /// never happen and likely indicates a programming failure.
    #[error("failed to serialize a request into JSON to a file handle")]
@@ -606,7 +638,7 @@ pub enum MessageError {
#[cfg(test)]
pub mod tests {
    use crate::event::BrokerEvent;
-
    use crate::msg::Request;
+
    use crate::msg::{Request, RequestBuilder};
    use radicle::git::raw::Oid;
    use radicle::git::RefString;
    use radicle::patch::{MergeTarget, Patches};
@@ -637,7 +669,11 @@ pub mod tests {
            old: Some(repo_head),
        };

-
        let req = Request::trigger(&profile, &be).expect("expect request trigger");
+
        let req = RequestBuilder::default()
+
            .profile(&profile)
+
            .broker_event(&be)
+
            .build_trigger()
+
            .unwrap();
        let Request::Trigger {
            common,
            push,
@@ -702,7 +738,11 @@ pub mod tests {
            old: None,
        };

-
        let req = Request::trigger(&profile, &be)?;
+
        let req = RequestBuilder::default()
+
            .profile(&profile)
+
            .broker_event(&be)
+
            .build_trigger()
+
            .unwrap();
        let Request::Trigger {
            common,
            push,
modified src/test.rs
@@ -6,7 +6,7 @@ use std::{

use crate::adapter::Adapter;
use crate::event::BrokerEvent;
-
use crate::msg::Request;
+
use crate::msg::{Request, RequestBuilder};
use radicle::crypto::ssh::Keystore;
use radicle::crypto::test::signer::MockSigner;
use radicle::crypto::Signer;
@@ -77,7 +77,10 @@ pub fn trigger_request() -> TestResult<Request> {
        old: Some(repo_head),
    };

-
    Ok(Request::trigger(&profile, &be)?)
+
    Ok(RequestBuilder::default()
+
        .profile(&profile)
+
        .broker_event(&be)
+
        .build_trigger()?)
}

pub fn mock_adapter(filename: &Path, script: &str) -> TestResult<Adapter> {