Radish alpha
r
Radicle CI broker
Radicle
Git (anonymous pull)
Log in to clone via SSH
feat: add cibtool subcommand to show broker events from node ones
Lars Wirzenius committed 1 year ago
commit 6981c483c6cc81b7a3a9f842db4292fdba5e8eaf
parent 795dc1c97aa39e91f906a33d4ccb26449ea8248a
3 files changed +110 -1
modified ci-broker.md
@@ -1150,6 +1150,35 @@ when I run bash radenv.sh cibtool event record --output events.json
then file events.json contains ""type":"refsFetched""
~~~

+
## Convert recorded node events into broker events
+

+
_What:_ Node operator can see what broke events are created from node
+
events.
+

+
_Why:_ This is helpful so that node operators can see what broker
+
events are created from node events, which may have been previously
+
recorded. It's also helpful for CI broker developers as a development
+
tool.
+

+
_Who:_ `cib-dev`, `node-ops`
+

+
~~~scenario
+
given file radenv.sh
+
given file setup-node.sh
+
when I run bash radenv.sh bash setup-node.sh
+

+
given an installed synthetic-events
+
given file refsfetched.json
+
given file set-rid
+
when I run bash radenv.sh env HOME=../homedir python3 set-rid refsfetched.json testy
+
when I run synthetic-events synt.sock refsfetched.json --log log.txt
+

+
given an installed cibtool
+
when I run bash radenv.sh cibtool event record --output node-events.json
+
when I run bash radenv.sh cibtool event broker --output broker-events.json node-events.json
+
then file broker-events.json contains "RefChanged""
+
~~~
+

# Acceptance criteria for logging

The CI broker writes log messages to its standard error output
modified src/bin/cibtool.rs
@@ -182,6 +182,7 @@ impl Subcommand for EventCmd {
            EventSubCmd::Show(x) => x.run(args)?,
            EventSubCmd::Remove(x) => x.run(args)?,
            EventSubCmd::Record(x) => x.run(args)?,
+
            EventSubCmd::Broker(x) => x.run(args)?,
        }
        Ok(())
    }
@@ -198,6 +199,7 @@ enum EventSubCmd {
    Show(cibtoolcmd::ShowEvent),
    Remove(cibtoolcmd::RemoveEvent),
    Record(cibtoolcmd::RecordEvents),
+
    Broker(cibtoolcmd::BrokerEvents),
}

#[derive(Parser)]
@@ -320,4 +322,16 @@ enum CibToolError {

    #[error("failed to write node event to file {0}")]
    WriteEvent(PathBuf, #[source] std::io::Error),
+

+
    #[error("failed to read node events from file {0}")]
+
    ReadEvents(PathBuf, #[source] std::io::Error),
+

+
    #[error("failed to read node events as UTF8 from file {0}")]
+
    NodeEventNotUtf8(PathBuf, #[source] std::string::FromUtf8Error),
+

+
    #[error("failed to read node events as JSON from file {0}")]
+
    JsonToNodeEvent(PathBuf, #[source] serde_json::Error),
+

+
    #[error("failed to create file for broker events: {0}")]
+
    CreateBrokerEventsFile(PathBuf, #[source] std::io::Error),
}
modified src/bin/cibtoolcmd/event.rs
@@ -328,9 +328,10 @@ impl Leaf for RecordEvents {
                Ok(None) => break,
                Ok(Some(event)) => {
                    println!("got event {event:?}");
-
                    let json = serde_json::to_string(&event)
+
                    let mut json = serde_json::to_string(&event)
                        .map_err(|e| CibToolError::NodeEevnetToJson(event.clone(), e))?;
                    if let Some(file) = &mut file {
+
                        json.push('\n');
                        file.write_all(json.as_bytes()).map_err(|e| {
                            CibToolError::WriteEvent(self.output.as_ref().unwrap().clone(), e)
                        })?;
@@ -344,3 +345,68 @@ impl Leaf for RecordEvents {
        Ok(())
    }
}
+

+
/// Convert node events into broker events.
+
///
+
/// Node events are read from the specified file. Note that one node
+
/// event can result in any number of broker events.
+
///
+
/// The events are written to the standard output or to the specified
+
/// file, as one JSON object per line.
+
#[derive(Parser)]
+
pub struct BrokerEvents {
+
    /// Write broker events to this file.
+
    #[clap(long)]
+
    output: Option<PathBuf>,
+

+
    /// Read node events from this file.
+
    input: PathBuf,
+
}
+

+
impl Leaf for BrokerEvents {
+
    fn run(&self, _args: &Args) -> Result<(), CibToolError> {
+
        let bytes = std::fs::read(&self.input)
+
            .map_err(|e| CibToolError::ReadEvents(self.input.clone(), e))?;
+
        let text = String::from_utf8(bytes)
+
            .map_err(|e| CibToolError::NodeEventNotUtf8(self.input.clone(), e))?;
+

+
        let mut node_events = vec![];
+
        for line in text.lines() {
+
            let event: radicle::node::Event = serde_json::from_str(line)
+
                .map_err(|e| CibToolError::JsonToNodeEvent(self.input.clone(), e))?;
+
            node_events.push(event);
+
        }
+

+
        let mut broker_events = vec![];
+
        for node_event in node_events.iter() {
+
            if let Some(mut bes) = BrokerEvent::from_event(node_event) {
+
                broker_events.append(&mut bes);
+
            }
+
        }
+

+
        let mut jsons = vec![];
+
        for be in broker_events.iter() {
+
            jsons.push(
+
                serde_json::to_string(be)
+
                    .map_err(|err| CibToolError::EventToJson(be.clone(), err))?,
+
            );
+
        }
+

+
        if let Some(filename) = &self.output {
+
            let mut file = std::fs::File::create(filename)
+
                .map_err(|e| CibToolError::CreateBrokerEventsFile(filename.into(), e))?;
+
            for json in jsons {
+
                let json = format!("{json}\n");
+
                file.write_all(json.as_bytes()).map_err(|e| {
+
                    CibToolError::WriteEvent(self.output.as_ref().unwrap().clone(), e)
+
                })?;
+
            }
+
        } else {
+
            for json in jsons {
+
                println!("{json}");
+
            }
+
        }
+

+
        Ok(())
+
    }
+
}