Radish alpha
r
rad:zwTxygwuz5LDGBq255RA2CbNGrz8
Radicle CI broker
Radicle
Git
feat: add the AnyDelegate filter
Lars Wirzenius committed 5 months ago
commit 94fbd9f72fc4db779422fa97786c99bb9b3b14d4
parent 31543ca
2 files changed +63 -1
modified ci-broker.md
@@ -1234,6 +1234,43 @@ sed -i "s/NODEID/$rid/g" "$yaml"
~~~


+
## Filter predicate `AnyDelegate`
+

+
_Want:_ We can allow an event that originates in a node for any delegate.
+

+
_Why:_ We want to constrain CI to privileged developers for a repository.
+

+
~~~scenario
+
given a Radicle node, with CI configured with broker.yaml and adapter dummy.sh
+
given a Git repository xyzzy in the Radicle node
+
given a Git repository other in the Radicle node
+

+
given file config.yaml from filter-anydelegate.yaml
+
given file update-nodeid.sh
+
when I run bash update-nodeid.sh xyzzy config.yaml
+

+
when I run cibtool --db ci-broker.db trigger --repo xyzzy --commit HEAD
+
when I run cibtool --db ci-broker.db trigger --repo other --commit HEAD --node z6MkgEMYod7Hxfy9qCvDv5hYHkZ4ciWmLFgfvm3Wn1b2w2FV
+

+
when I run ./env.sh cib --config config.yaml queued
+

+
when I run cibtool --db ci-broker.db run list --json
+
then stdout contains ""repo_name": "xyzzy""
+
then stdout doesn't contain ""repo_name": "other""
+
~~~
+

+
~~~{#filter-anydelegate.yaml .file .json}
+
db: ci-broker.db
+
adapters:
+
  default:
+
    command: ./adapter.sh
+
triggers:
+
  - adapter: default
+
    filters:
+
      - !AnyDelegate
+
~~~
+

+

## Filter predicate `Tag`

_Want:_ We can allow an event that is about a specific tag.
modified src/filter.rs
@@ -1,5 +1,6 @@
use std::path::{Path, PathBuf};

+
use radicle_crypto::PublicKey;
use regex::Regex;
use serde::{Deserialize, Serialize};

@@ -8,7 +9,7 @@ use radicle::{
    git::{BranchName, Oid, raw::ObjectType},
    node::NodeId,
    prelude::{Profile, RepoId},
-
    storage::git::Repository,
+
    storage::{ReadRepository, git::Repository},
};

use crate::{
@@ -92,6 +93,11 @@ pub enum EventFilter {
    /// Change originated from specific node.
    Node(NodeId),

+
    /// Change originated from any delegate node. Note that will change to
+
    /// "from delegate" once Radicle separates the "user" and "node"
+
    /// concepts.
+
    AnyDelegate,
+

    /// Commit in change contains a file or directory with this name.
    HasFile(PathBuf),

@@ -147,6 +153,25 @@ impl EventFilter {
                    format!("wanted={wanted} actual={actual:?}"),
                )
            }
+
            #[allow(clippy::unwrap_used)]
+
            Self::AnyDelegate => {
+
                let repo_id = event.repository().unwrap();
+
                let radicle = crate::ergo::Radicle::new().unwrap();
+
                let repo = radicle.repository(repo_id).unwrap();
+
                let origin = event.from_node().unwrap();
+
                let delegates: Vec<PublicKey> = repo
+
                    .delegates()
+
                    .iter()
+
                    .flatten()
+
                    .map(|d| *d.as_key())
+
                    .collect();
+
                let allowed = delegates.contains(origin);
+
                Decision::string(
+
                    "AnyDelegate",
+
                    allowed,
+
                    format!("wanted={origin} delegates={delegates:?}",),
+
                )
+
            }
            Self::Repository(wanted) => {
                let actual = event.repository();
                let allowed = Some(wanted) == actual;