Radish alpha
r
rad:zwTxygwuz5LDGBq255RA2CbNGrz8
Radicle CI broker
Radicle
Git
feat: make CI events versioned
Merged liw opened 1 year ago

This will help us avoid breaking changes in the future, when CI events need to be modified, and CI broker instances need to cope with the event queues in their databases.

Previously we had

enum CiEvent {
    BranchCreated { ... },
    BranchUpdatee { ... },
    ....
}

Change that to:

enum CiEvent {
    V1(CiEventV1),
}

enum CiEventV1 {
    BranchCreated { ... },
    BranchUpdatee { ... },
    ....
}

This will allow us to add new version variants to CiEvent, without losing access to the already enqueued V1 events.

Signed-off-by: Lars Wirzenius liw@liw.fi

refactor: make BrokerError::NotTrigger not be so large

It’s awkward if enum variants have wildly different sizes. Change BrokerError::NotTrigger to store the Request value in a Box, so that it’s not in the enum directly. This makes all variants about the same size, and thus the decorators that allow the clippy::large_enum_variant can be dropped.

Signed-off-by: Lars Wirzenius liw@liw.fi

11 files changed +109 -102 5e813f73 320c4269
modified src/bin/cib.rs
@@ -273,7 +273,6 @@ impl ProcessEventsCmd {
}

#[derive(Debug, thiserror::Error)]
-
#[allow(clippy::large_enum_variant)]
enum CibError {
    #[error("failed to read configuration file {0}")]
    ReadConfig(PathBuf, #[source] ConfigError),
modified src/bin/cibtool.rs
@@ -30,7 +30,7 @@ use radicle_git_ext::Oid;

use radicle_ci_broker::{
    broker::BrokerError,
-
    ci_event::{CiEvent, CiEventError},
+
    ci_event::{CiEvent, CiEventError, CiEventV1},
    db::{Db, DbError, QueueId, QueuedCiEvent},
    logger,
    msg::{RunId, RunResult},
@@ -240,7 +240,6 @@ enum RunSubCmd {
}

#[derive(Debug, thiserror::Error)]
-
#[allow(clippy::large_enum_variant)]
enum CibToolError {
    #[error("failed to look up node profile")]
    Profile(#[source] radicle::profile::Error),
modified src/bin/cibtoolcmd/event.rs
@@ -291,7 +291,7 @@ pub struct Shutdown {
impl Leaf for Shutdown {
    fn run(&self, args: &Args) -> Result<(), CibToolError> {
        let db = args.open_db()?;
-
        let id = db.push_queued_ci_event(CiEvent::Shutdown)?;
+
        let id = db.push_queued_ci_event(CiEvent::V1(CiEventV1::Shutdown))?;

        if let Some(filename) = &self.id_file {
            write(filename, id.to_string().as_bytes())
modified src/broker.rs
@@ -127,7 +127,6 @@ fn now() -> Result<String, time::error::Format> {

/// All possible errors from this module.
#[derive(Debug, thiserror::Error)]
-
#[allow(clippy::large_enum_variant)]
pub enum BrokerError {
    /// Error formatting a time as a string.
    #[error(transparent)]
@@ -151,7 +150,7 @@ pub enum BrokerError {

    /// Request is not a trigger message.
    #[error("tried to execute CI based on a message that is not a trigger one: {0:#?}")]
-
    NotTrigger(Request),
+
    NotTrigger(Box<Request>),

    /// Could not convert repository ID from string.
    #[error("failed to understand repository id {0:?}")]
modified src/ci_event.rs
@@ -15,6 +15,11 @@ use radicle::{

#[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)]
pub enum CiEvent {
+
    V1(CiEventV1),
+
}
+

+
#[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)]
+
pub enum CiEventV1 {
    Shutdown,
    BranchCreated {
        from_node: NodeId,
@@ -55,13 +60,13 @@ impl CiEvent {
        branch: &str,
        tip: Oid,
    ) -> Result<Self, CiEventError> {
-
        Ok(Self::BranchCreated {
+
        Ok(Self::V1(CiEventV1::BranchCreated {
            from_node: node,
            repo,
            branch: RefString::try_from(branch)
                .map_err(|e| CiEventError::RefString(branch.into(), e))?,
            tip,
-
        })
+
        }))
    }

    pub fn branch_updated(
@@ -73,14 +78,14 @@ impl CiEvent {
    ) -> Result<Self, CiEventError> {
        let branch =
            namespaced_branch(branch).map_err(|_| CiEventError::without_namespace2(branch))?;
-
        Ok(Self::BranchUpdated {
+
        Ok(Self::V1(CiEventV1::BranchUpdated {
            from_node: node,
            repo,
            branch: RefString::try_from(branch.clone())
                .map_err(|e| CiEventError::RefString(branch.clone(), e))?,
            tip,
            old_tip,
-
        })
+
        }))
    }

    pub fn from_node_event(event: &Event) -> Result<Vec<Self>, CiEventError> {
@@ -107,14 +112,14 @@ impl CiEvent {
                        RefUpdate::Created { name, oid } => {
                            eprintln!("created: {name:?}");
                            if let Ok(patch_id) = patch_id(name) {
-
                                CiEvent::PatchCreated {
+
                                CiEventV1::PatchCreated {
                                    from_node: *remote,
                                    repo: *rid,
                                    patch: patch_id,
                                    new_tip: *oid,
                                }
                            } else if let Ok(branch) = namespaced_branch(name) {
-
                                CiEvent::BranchCreated {
+
                                CiEventV1::BranchCreated {
                                    from_node: *remote,
                                    repo: *rid,
                                    branch: ref_string(branch)?,
@@ -129,7 +134,7 @@ impl CiEvent {
                            eprintln!("updated: {name:?}");
                            if let Ok(patch_id) = patch_id(name) {
                                eprintln!("it's a patch");
-
                                CiEvent::PatchUpdated {
+
                                CiEventV1::PatchUpdated {
                                    from_node: *remote,
                                    repo: *rid,
                                    patch: patch_id,
@@ -137,7 +142,7 @@ impl CiEvent {
                                }
                            } else if let Ok(branch) = namespaced_branch(name) {
                                eprintln!("it's a branch update");
-
                                CiEvent::BranchUpdated {
+
                                CiEventV1::BranchUpdated {
                                    from_node: *remote,
                                    repo: *rid,
                                    branch: ref_string(branch)?,
@@ -149,14 +154,14 @@ impl CiEvent {
                                continue;
                            }
                        }
-
                        RefUpdate::Deleted { name, oid } => CiEvent::BranchDeleted {
+
                        RefUpdate::Deleted { name, oid } => CiEventV1::BranchDeleted {
                            repo: *rid,
                            branch: branch(name, update)?,
                            tip: *oid,
                        },
                        RefUpdate::Skipped { .. } => continue,
                    };
-
                    events.push(e);
+
                    events.push(CiEvent::V1(e));
                }
                Ok(events)
            }
@@ -325,12 +330,12 @@ mod test {
            Ok(events) if !events.is_empty() => {
                for e in events {
                    match e {
-
                        CiEvent::BranchCreated {
+
                        CiEvent::V1(CiEventV1::BranchCreated {
                            from_node: _,
                            repo,
                            branch,
                            tip,
-
                        } if repo == rid && branch == main && tip == oid => {}
+
                        }) if repo == rid && branch == main && tip == oid => {}
                        _ => panic!("should not succeed that way"),
                    }
                }
@@ -360,13 +365,13 @@ mod test {
            Ok(events) if !events.is_empty() => {
                for e in events {
                    match e {
-
                        CiEvent::BranchUpdated {
+
                        CiEvent::V1(CiEventV1::BranchUpdated {
                            from_node: _,
                            repo,
                            branch,
                            tip,
                            old_tip,
-
                        } if repo == rid && branch == main && tip == oid && old_tip == oid => {}
+
                        }) if repo == rid && branch == main && tip == oid && old_tip == oid => {}
                        _ => panic!("should not succeed that way"),
                    }
                }
@@ -395,7 +400,7 @@ mod test {
            Ok(events) if !events.is_empty() => {
                for e in events {
                    match e {
-
                        CiEvent::BranchDeleted { repo, branch, tip }
+
                        CiEvent::V1(CiEventV1::BranchDeleted { repo, branch, tip })
                            if repo == rid && branch == main && tip == oid => {}
                        _ => panic!("should not succeed that way"),
                    }
@@ -425,12 +430,12 @@ mod test {
            Ok(events) if !events.is_empty() => {
                for e in events {
                    match e {
-
                        CiEvent::PatchCreated {
+
                        CiEvent::V1(CiEventV1::PatchCreated {
                            from_node: _,
                            repo,
                            patch,
                            new_tip,
-
                        } if repo == rid && patch == patch_id && new_tip == oid => {}
+
                        }) if repo == rid && patch == patch_id && new_tip == oid => {}
                        _ => panic!("should not succeed that way"),
                    }
                }
@@ -460,12 +465,12 @@ mod test {
            Ok(events) if !events.is_empty() => {
                for e in events {
                    match e {
-
                        CiEvent::PatchUpdated {
+
                        CiEvent::V1(CiEventV1::PatchUpdated {
                            from_node: _,
                            repo,
                            patch,
                            new_tip,
-
                        } if repo == rid && patch == patch_id && new_tip == oid => {}
+
                        }) if repo == rid && patch == patch_id && new_tip == oid => {}
                        _ => panic!("should not succeed that way"),
                    }
                }
modified src/filter.rs
@@ -5,7 +5,10 @@ use serde::{Deserialize, Serialize};
use radicle::{cob::patch::PatchId, git::RefString, prelude::RepoId};
use radicle_git_ext::Oid;

-
use crate::{ci_event::CiEvent, logger};
+
use crate::{
+
    ci_event::{CiEvent, CiEventV1},
+
    logger,
+
};

/// A Boolean expression for filtering broker events.
#[derive(Debug, Clone, Deserialize, Serialize)]
@@ -64,32 +67,32 @@ impl EventFilter {
        }

        match event {
-
            CiEvent::Shutdown => true,
-
            CiEvent::BranchCreated { repo, branch, .. } => match self {
+
            CiEvent::V1(CiEventV1::Shutdown) => true,
+
            CiEvent::V1(CiEventV1::BranchCreated { repo, branch, .. }) => match self {
                Self::Repository(wanted) => repo == wanted,
                Self::Branch(wanted) => branch == wanted,
                Self::BranchCreated => true,
                _ => false,
            },
-
            CiEvent::BranchUpdated { repo, branch, .. } => match self {
+
            CiEvent::V1(CiEventV1::BranchUpdated { repo, branch, .. }) => match self {
                Self::Repository(wanted) => repo == wanted,
                Self::Branch(wanted) => branch == wanted,
                Self::BranchUpdated => true,
                _ => false,
            },
-
            CiEvent::BranchDeleted { repo, branch, .. } => match self {
+
            CiEvent::V1(CiEventV1::BranchDeleted { repo, branch, .. }) => match self {
                Self::Repository(wanted) => repo == wanted,
                Self::Branch(wanted) => branch == wanted,
                Self::BranchDeleted => true,
                _ => false,
            },
-
            CiEvent::PatchCreated { repo, patch, .. } => match self {
+
            CiEvent::V1(CiEventV1::PatchCreated { repo, patch, .. }) => match self {
                Self::Repository(wanted) => repo == wanted,
                Self::Patch(wanted) => *patch == PatchId::from(wanted),
                Self::PatchCreated => true,
                _ => false,
            },
-
            CiEvent::PatchUpdated { repo, patch, .. } => match self {
+
            CiEvent::V1(CiEventV1::PatchUpdated { repo, patch, .. }) => match self {
                Self::Repository(wanted) => repo == wanted,
                Self::Patch(wanted) => *patch == PatchId::from(wanted),
                Self::PatchUpdated => true,
@@ -166,7 +169,7 @@ mod test {
    }

    fn shutdown() -> CiEvent {
-
        CiEvent::Shutdown
+
        CiEvent::V1(CiEventV1::Shutdown)
    }

    fn all_events(
@@ -178,32 +181,32 @@ mod test {
        old_tip: Oid,
    ) -> Vec<CiEvent> {
        vec![
-
            CiEvent::BranchCreated {
+
            CiEvent::V1(CiEventV1::BranchCreated {
                from_node: did.into(),
                repo,
                branch: branch.clone(),
                tip,
-
            },
-
            CiEvent::BranchUpdated {
+
            }),
+
            CiEvent::V1(CiEventV1::BranchUpdated {
                from_node: did.into(),
                repo,
                branch: branch.clone(),
                tip,
                old_tip,
-
            },
-
            CiEvent::BranchDeleted { repo, branch, tip },
-
            CiEvent::PatchCreated {
+
            }),
+
            CiEvent::V1(CiEventV1::BranchDeleted { repo, branch, tip }),
+
            CiEvent::V1(CiEventV1::PatchCreated {
                from_node: did.into(),
                repo,
                patch,
                new_tip: tip,
-
            },
-
            CiEvent::PatchUpdated {
+
            }),
+
            CiEvent::V1(CiEventV1::PatchUpdated {
                from_node: did.into(),
                repo,
                patch,
                new_tip: tip,
-
            },
+
            }),
        ]
    }

@@ -248,9 +251,9 @@ mod test {
        for e in events.iter().filter(|e| {
            matches!(
                e,
-
                CiEvent::BranchCreated { .. }
-
                    | CiEvent::BranchUpdated { .. }
-
                    | CiEvent::BranchDeleted { .. }
+
                CiEvent::V1(CiEventV1::BranchCreated { .. })
+
                    | CiEvent::V1(CiEventV1::BranchUpdated { .. })
+
                    | CiEvent::V1(CiEventV1::BranchDeleted { .. })
            )
        }) {
            eprintln!("{:#?} → {}", e, filter.allows(e));
@@ -283,7 +286,7 @@ mod test {
        eprintln!("filter: {filter:#?}");
        for e in all_events(did(), rid(), refstring("main"), patch_id(), oid(), oid())
            .iter()
-
            .filter(|e| matches!(e, CiEvent::BranchCreated { .. }))
+
            .filter(|e| matches!(e, CiEvent::V1(CiEventV1::BranchCreated { .. })))
        {
            eprintln!("{:#?} → {}", e, filter.allows(e));
            assert!(filter.allows(e));
@@ -297,7 +300,7 @@ mod test {
        eprintln!("filter: {filter:#?}");
        for e in all_events(did(), rid(), refstring("main"), patch_id(), oid(), oid())
            .iter()
-
            .filter(|e| !matches!(e, CiEvent::BranchCreated { .. }))
+
            .filter(|e| !matches!(e, CiEvent::V1(CiEventV1::BranchCreated { .. })))
        {
            eprintln!("{:#?} → {}", e, filter.allows(e));
            assert!(!filter.allows(e));
@@ -311,7 +314,7 @@ mod test {
        eprintln!("filter: {filter:#?}");
        for e in all_events(did(), rid(), refstring("main"), patch_id(), oid(), oid())
            .iter()
-
            .filter(|e| matches!(e, CiEvent::BranchUpdated { .. }))
+
            .filter(|e| matches!(e, CiEvent::V1(CiEventV1::BranchUpdated { .. })))
        {
            eprintln!("{:#?} → {}", e, filter.allows(e));
            assert!(filter.allows(e));
@@ -325,7 +328,7 @@ mod test {
        eprintln!("filter: {filter:#?}");
        for e in all_events(did(), rid(), refstring("main"), patch_id(), oid(), oid())
            .iter()
-
            .filter(|e| !matches!(e, CiEvent::BranchUpdated { .. }))
+
            .filter(|e| !matches!(e, CiEvent::V1(CiEventV1::BranchUpdated { .. })))
        {
            eprintln!("{:#?} → {}", e, filter.allows(e));
            assert!(!filter.allows(e));
@@ -339,7 +342,7 @@ mod test {
        eprintln!("filter: {filter:#?}");
        for e in all_events(did(), rid(), refstring("main"), patch_id(), oid(), oid())
            .iter()
-
            .filter(|e| matches!(e, CiEvent::BranchDeleted { .. }))
+
            .filter(|e| matches!(e, CiEvent::V1(CiEventV1::BranchDeleted { .. })))
        {
            eprintln!("{:#?} → {}", e, filter.allows(e));
            assert!(filter.allows(e));
@@ -353,7 +356,7 @@ mod test {
        eprintln!("filter: {filter:#?}");
        for e in all_events(did(), rid(), refstring("main"), patch_id(), oid(), oid())
            .iter()
-
            .filter(|e| !matches!(e, CiEvent::BranchDeleted { .. }))
+
            .filter(|e| !matches!(e, CiEvent::V1(CiEventV1::BranchDeleted { .. })))
        {
            eprintln!("{:#?} → {}", e, filter.allows(e));
            assert!(!filter.allows(e));
@@ -368,7 +371,8 @@ mod test {
        for e in events.iter().filter(|e| {
            matches!(
                e,
-
                CiEvent::PatchCreated { .. } | CiEvent::PatchUpdated { .. }
+
                CiEvent::V1(CiEventV1::PatchCreated { .. })
+
                    | CiEvent::V1(CiEventV1::PatchUpdated { .. })
            )
        }) {
            eprintln!("{:#?} → {}", e, filter.allows(e));
@@ -391,7 +395,8 @@ mod test {
        for e in events.iter().filter(|e| {
            matches!(
                e,
-
                CiEvent::PatchCreated { .. } | CiEvent::PatchUpdated { .. }
+
                CiEvent::V1(CiEventV1::PatchCreated { .. })
+
                    | CiEvent::V1(CiEventV1::PatchUpdated { .. })
            )
        }) {
            eprintln!("{:#?} → {}", e, filter.allows(e));
@@ -406,7 +411,7 @@ mod test {
        eprintln!("filter: {filter:#?}");
        for e in all_events(did(), rid(), refstring("main"), patch_id(), oid(), oid())
            .iter()
-
            .filter(|e| matches!(e, CiEvent::PatchCreated { .. }))
+
            .filter(|e| matches!(e, CiEvent::V1(CiEventV1::PatchCreated { .. })))
        {
            eprintln!("{:#?} → {}", e, filter.allows(e));
            assert!(filter.allows(e));
@@ -420,7 +425,7 @@ mod test {
        eprintln!("filter: {filter:#?}");
        for e in all_events(did(), rid(), refstring("main"), patch_id(), oid(), oid())
            .iter()
-
            .filter(|e| !matches!(e, CiEvent::PatchCreated { .. }))
+
            .filter(|e| !matches!(e, CiEvent::V1(CiEventV1::PatchCreated { .. })))
        {
            eprintln!("{:#?} → {}", e, filter.allows(e));
            assert!(!filter.allows(e));
@@ -434,7 +439,7 @@ mod test {
        eprintln!("filter: {filter:#?}");
        for e in all_events(did(), rid(), refstring("main"), patch_id(), oid(), oid())
            .iter()
-
            .filter(|e| matches!(e, CiEvent::PatchUpdated { .. }))
+
            .filter(|e| matches!(e, CiEvent::V1(CiEventV1::PatchUpdated { .. })))
        {
            eprintln!("{:#?} → {}", e, filter.allows(e));
            assert!(filter.allows(e));
@@ -448,7 +453,7 @@ mod test {
        eprintln!("filter: {filter:#?}");
        for e in all_events(did(), rid(), refstring("main"), patch_id(), oid(), oid())
            .iter()
-
            .filter(|e| !matches!(e, CiEvent::PatchUpdated { .. }))
+
            .filter(|e| !matches!(e, CiEvent::V1(CiEventV1::PatchUpdated { .. })))
        {
            eprintln!("{:#?} → {}", e, filter.allows(e));
            assert!(!filter.allows(e));
modified src/msg.rs
@@ -31,7 +31,7 @@ use radicle::{
    Profile,
};

-
use crate::ci_event::CiEvent;
+
use crate::ci_event::{CiEvent, CiEventV1};

// This gets put into every [`Request`] message so the adapter can
// detect its getting a message it knows how to handle.
@@ -132,12 +132,12 @@ impl<'a> RequestBuilder<'a> {

        match self.ci_event {
            None => Err(MessageError::CiEventNotSet),
-
            Some(CiEvent::BranchCreated {
+
            Some(CiEvent::V1(CiEventV1::BranchCreated {
                from_node,
                repo,
                branch,
                tip,
-
            }) => {
+
            })) => {
                let rad_repo = profile.storage.repository(*repo)?;
                let project_info = rad_repo.project()?;

@@ -170,13 +170,13 @@ impl<'a> RequestBuilder<'a> {
                    patch: None,
                })
            }
-
            Some(CiEvent::BranchUpdated {
+
            Some(CiEvent::V1(CiEventV1::BranchUpdated {
                from_node,
                repo,
                branch,
                tip,
                old_tip,
-
            }) => {
+
            })) => {
                let rad_repo = profile.storage.repository(*repo)?;
                let git_repo =
                    radicle_surf::Repository::open(paths::repository(&profile.storage, repo))?;
@@ -227,12 +227,12 @@ impl<'a> RequestBuilder<'a> {
                    patch: None,
                })
            }
-
            Some(CiEvent::PatchCreated {
+
            Some(CiEvent::V1(CiEventV1::PatchCreated {
                from_node,
                repo,
                patch: patch_id,
                new_tip,
-
            }) => {
+
            })) => {
                let rad_repo = profile.storage.repository(*repo)?;
                let git_repo =
                    radicle_surf::Repository::open(paths::repository(&profile.storage, repo))?;
@@ -317,12 +317,12 @@ impl<'a> RequestBuilder<'a> {
                    }),
                })
            }
-
            Some(CiEvent::PatchUpdated {
+
            Some(CiEvent::V1(CiEventV1::PatchUpdated {
                from_node,
                repo,
                patch: patch_id,
                new_tip,
-
            }) => {
+
            })) => {
                let rad_repo = profile.storage.repository(*repo)?;
                let git_repo =
                    radicle_surf::Repository::open(paths::repository(&profile.storage, repo))?;
@@ -908,7 +908,7 @@ pub enum MessageError {
#[cfg(test)]
#[allow(clippy::unwrap_used)] // OK in tests: panic is fine
pub mod trigger_from_ci_event_tests {
-
    use crate::ci_event::CiEvent;
+
    use crate::ci_event::{CiEvent, CiEventV1};
    use crate::msg::{EventType, Request, RequestBuilder};
    use radicle::git::RefString;
    use radicle::patch::{MergeTarget, Patches};
@@ -930,14 +930,14 @@ pub mod trigger_from_ci_event_tests {
            &project.backend,
        );

-
        let ci_event = CiEvent::BranchCreated {
+
        let ci_event = CiEvent::V1(CiEventV1::BranchCreated {
            from_node: *profile.id(),
            repo: project.id,
            branch: RefString::try_from(
                "refs/namespaces/$nid/refs/heads/master".replace("$nid", &profile.id().to_string()),
            )?,
            tip: cmt,
-
        };
+
        });

        let req = RequestBuilder::default()
            .profile(&profile)
@@ -981,7 +981,7 @@ pub mod trigger_from_ci_event_tests {
            &project.backend,
        );

-
        let ci_event = CiEvent::BranchUpdated {
+
        let ci_event = CiEvent::V1(CiEventV1::BranchUpdated {
            from_node: *profile.id(),
            repo: project.id,
            branch: RefString::try_from(
@@ -989,7 +989,7 @@ pub mod trigger_from_ci_event_tests {
            )?,
            old_tip: repo_head,
            tip: cmt,
-
        };
+
        });

        let req = RequestBuilder::default()
            .profile(&profile)
@@ -1048,12 +1048,12 @@ pub mod trigger_from_ci_event_tests {
            &node.signer,
        )?;

-
        let ci_event = CiEvent::PatchCreated {
+
        let ci_event = CiEvent::V1(CiEventV1::PatchCreated {
            from_node: *profile.id(),
            repo: project.id,
            patch: *patch_cob.id(),
            new_tip: cmt,
-
        };
+
        });

        let req = RequestBuilder::default()
            .profile(&profile)
@@ -1120,12 +1120,12 @@ pub mod trigger_from_ci_event_tests {
            &node.signer,
        )?;

-
        let ci_event = CiEvent::PatchUpdated {
+
        let ci_event = CiEvent::V1(CiEventV1::PatchUpdated {
            from_node: *profile.id(),
            repo: project.id,
            patch: *patch_cob.id(),
            new_tip: cmt,
-
        };
+
        });

        let req = RequestBuilder::default()
            .profile(&profile)
modified src/pages.rs
@@ -28,7 +28,7 @@ use radicle::{
};

use crate::{
-
    ci_event::CiEvent,
+
    ci_event::{CiEvent, CiEventV1},
    db::{Db, DbError, QueuedCiEvent},
    logger,
    msg::RunId,
@@ -179,33 +179,35 @@ impl PageData {
            }

            let event_element = match event.event() {
-
                CiEvent::Shutdown => Element::new(Tag::Span).with_text("shutdown"),
-
                CiEvent::BranchCreated {
+
                CiEvent::V1(CiEventV1::Shutdown) => Element::new(Tag::Span).with_text("shutdown"),
+
                CiEvent::V1(CiEventV1::BranchCreated {
                    from_node: _,
                    repo,
                    branch,
                    tip,
-
                } => render_event(repo, branch, tip),
-
                CiEvent::BranchUpdated {
+
                }) => render_event(repo, branch, tip),
+
                CiEvent::V1(CiEventV1::BranchUpdated {
                    from_node: _,
                    repo,
                    branch,
                    tip,
                    old_tip: _,
-
                } => render_event(repo, branch, tip),
-
                CiEvent::BranchDeleted { repo, branch, tip } => render_event(repo, branch, tip),
-
                CiEvent::PatchCreated {
+
                }) => render_event(repo, branch, tip),
+
                CiEvent::V1(CiEventV1::BranchDeleted { repo, branch, tip }) => {
+
                    render_event(repo, branch, tip)
+
                }
+
                CiEvent::V1(CiEventV1::PatchCreated {
                    from_node: _,
                    repo,
                    patch,
                    new_tip,
-
                } => render_event(repo, &patch.to_string(), new_tip),
-
                CiEvent::PatchUpdated {
+
                }) => render_event(repo, &patch.to_string(), new_tip),
+
                CiEvent::V1(CiEventV1::PatchUpdated {
                    from_node: _,
                    repo,
                    patch,
                    new_tip,
-
                } => render_event(repo, &patch.to_string(), new_tip),
+
                }) => render_event(repo, &patch.to_string(), new_tip),
            };

            table.push_child(
@@ -546,11 +548,11 @@ impl StatusPage {
                .iter()
                .filter_map(|id| match db.get_queued_ci_event(id) {
                    Ok(Some(event)) => match event.event() {
-
                        CiEvent::Shutdown => Some(Ok(event)),
-
                        CiEvent::BranchCreated { repo, .. }
-
                        | CiEvent::BranchUpdated { repo, .. }
-
                        | CiEvent::PatchCreated { repo, .. }
-
                        | CiEvent::PatchUpdated { repo, .. } => {
+
                        CiEvent::V1(CiEventV1::Shutdown) => Some(Ok(event)),
+
                        CiEvent::V1(CiEventV1::BranchCreated { repo, .. })
+
                        | CiEvent::V1(CiEventV1::BranchUpdated { repo, .. })
+
                        | CiEvent::V1(CiEventV1::PatchCreated { repo, .. })
+
                        | CiEvent::V1(CiEventV1::PatchUpdated { repo, .. }) => {
                            if Self::is_public_repo(profile, repo) {
                                Some(Ok(event))
                            } else {
modified src/queueproc.rs
@@ -12,7 +12,7 @@ use radicle::Profile;

use crate::{
    broker::{Broker, BrokerError},
-
    ci_event::CiEvent,
+
    ci_event::{CiEvent, CiEventV1},
    db::{Db, DbError, QueueId, QueuedCiEvent},
    logger,
    msg::{MessageError, RequestBuilder},
@@ -119,16 +119,16 @@ impl QueueProcessor {

    fn process_event(&mut self, event: &CiEvent) -> Result<bool, QueueError> {
        match event {
-
            CiEvent::Shutdown => {
+
            CiEvent::V1(CiEventV1::Shutdown) => {
                logger::queueproc_action_shutdown();
                Ok(true)
            }
-
            CiEvent::BranchCreated {
+
            CiEvent::V1(CiEventV1::BranchCreated {
                from_node: _,
                repo,
                branch: _,
                tip,
-
            } => {
+
            }) => {
                logger::queueproc_action_run(repo, tip);
                let trigger = RequestBuilder::default()
                    .profile(&self.profile)
@@ -140,13 +140,13 @@ impl QueueProcessor {
                    .map_err(QueueError::execute_ci)?;
                Ok(false)
            }
-
            CiEvent::BranchUpdated {
+
            CiEvent::V1(CiEventV1::BranchUpdated {
                from_node: _,
                repo,
                branch: _,
                tip,
                old_tip: _,
-
            } => {
+
            }) => {
                logger::queueproc_action_run(repo, tip);
                let trigger = RequestBuilder::default()
                    .profile(&self.profile)
@@ -170,7 +170,6 @@ impl QueueProcessor {
}

#[derive(Debug, thiserror::Error)]
-
#[allow(clippy::large_enum_variant)]
pub enum QueueError {
    #[error("failed to load node profile")]
    Profile(#[source] radicle::profile::Error),
modified src/test.rs
@@ -5,7 +5,7 @@ use std::{
};

use crate::adapter::Adapter;
-
use crate::ci_event::CiEvent;
+
use crate::ci_event::{CiEvent, CiEventV1};
use crate::msg::{Request, RequestBuilder};
use radicle::crypto::ssh::Keystore;
use radicle::crypto::test::signer::MockSigner;
@@ -64,14 +64,14 @@ pub fn trigger_request() -> TestResult<Request> {
    let cmt =
        radicle::test::fixtures::commit("my test commit", &[repo_head.into()], &project.backend);

-
    let ci_event = CiEvent::BranchCreated {
+
    let ci_event = CiEvent::V1(CiEventV1::BranchCreated {
        from_node: *profile.id(),
        repo: project.id,
        branch: RefString::try_from(
            "refs/namespaces/$nid/refs/heads/master".replace("$nid", &profile.id().to_string()),
        )?,
        tip: cmt,
-
    };
+
    });

    Ok(RequestBuilder::default()
        .profile(&profile)
modified src/util.rs
@@ -89,7 +89,6 @@ pub fn now() -> Result<String, UtilError> {
}

#[derive(Debug, thiserror::Error)]
-
#[allow(clippy::large_enum_variant)]
pub enum UtilError {
    #[error("failed to look up node profile")]
    Profile(#[source] radicle::profile::Error),