mirror of
https://seed.radicle.dev/rad:zwTxygwuz5LDGBq255RA2CbNGrz8.git
synced 2026-10-18 19:30:29 +08:00
doc: document how to add a new event filter
This commit is contained in:
+4
-1
@@ -14,7 +14,7 @@
|
||||
pikchr-cli $< > $@.tmp
|
||||
mv $@.tmp $@
|
||||
|
||||
all: architecture.html userguide.html overview.html
|
||||
all: architecture.html userguide.html overview.html filter-impl.html
|
||||
|
||||
architecture.html: architecture.subplot architecture.md Makefile messages.md
|
||||
|
||||
@@ -26,3 +26,6 @@ userguide.html: userguide.subplot userguide.md Makefile
|
||||
|
||||
overview.html: overview.md Makefile
|
||||
pandoc --standalone --metadata title="Radicle CI overview" "$<" --output "$@"
|
||||
|
||||
filter-impl.html: filter-impl.md Makefile
|
||||
pandoc --standalone --metadata title="Radicle CI overview" "$<" --output "$@"
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
# Implementing a new event filter
|
||||
|
||||
Overview:
|
||||
|
||||
* in `src/filter.rs`, add a new variant to `enum EventFilter`, with whatever
|
||||
fields are needed for that filter
|
||||
* in `sr/filter.rs`, in the `EventFilter::decide` method, add a new `match` arm
|
||||
for the new filter variant
|
||||
* in `ci-broker.md` add a new section `## Filter predicte XXX`, like the existing
|
||||
ones, to verify the new filter works
|
||||
* run `make` at the root of the source tree to make sure everything works
|
||||
|
||||
## Example
|
||||
|
||||
The patch to add a `AnyDelegate` filter looks like below.
|
||||
|
||||
~~~~~~diff
|
||||
commit 94fbd9f72fc4db779422fa97786c99bb9b3b14d4
|
||||
Author: Lars Wirzenius <liw@liw.fi>
|
||||
Date: Mon Nov 10 14:00:53 2025 +0200
|
||||
|
||||
feat: add the AnyDelegate filter
|
||||
|
||||
diff --git a/ci-broker.md b/ci-broker.md
|
||||
index f86748e..ac217d0 100644
|
||||
--- a/ci-broker.md
|
||||
+++ b/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.
|
||||
diff --git a/src/filter.rs b/src/filter.rs
|
||||
index 188c8bd..86ea648 100644
|
||||
--- a/src/filter.rs
|
||||
+++ b/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;
|
||||
~~~~~~
|
||||
Reference in New Issue
Block a user