The watch key encoded source, repo, and number but not the thread
kind, and on GitLab an issue and a merge request share one number
space: iid 7 twice produced one key, one snapshot, and comments on
the merge request landing in the issue (or a 404 fallback that
misrouted the other way). The key carries the kind now —
{source}:{kind}:{owner}/{name}#{number}, with GitLab spelling the
pull variant mr — comment and snapshot route outright by kind, and a
kind-less payload parses to the unparsable key instead of guessing
issue. The claw's callers thread the kind from the payload and strip
the segment where the bare repo is wanted; pre-kind stored keys parse
as None rather than misroute. Four route-pinning wiremock tests cover
the GitLab split, and the GitHub/Gitea clients take the kind without
using it (their issues and PRs share the same REST space).
77 lines
3.1 KiB
Rust
77 lines
3.1 KiB
Rust
//! `rhema-forge-integration` — the forge integration: one normalized
|
|
//! event vocabulary and one client contract for GitHub, Gitea, and
|
|
//! GitLab, and the ingest path that turns forge activity into RSD
|
|
//! dispatch.
|
|
//!
|
|
//! An integration, not an agent: no driver, no model, no loop lives
|
|
//! here. A consumer composes the crate with its own agent tier — the
|
|
//! [`crate::Watcher`] polls a [`crate::Forge`] for activity and feeds
|
|
//! the events to a [`rhema_rsd::Dispatcher`](rhema_rsd) (the forge's
|
|
//! stable dedup id becomes the event id, and the resource key is spec
|
|
//! §8's `host:kind:owner/repo#number` shape, so re-polling unchanged
|
|
//! history dedups away and a changed row re-dispatches), and a dispatched
|
|
//! thread is answered through the same [`crate::Forge`] capabilities,
|
|
//! with [`crate::decode`] recovering the event behind an inbox item.
|
|
//! Polling cadence, handler policy, and the loop itself are the
|
|
//! consumer's — the claw daemon today, any other agent consumer of the
|
|
//! framework tomorrow; the dispatch guarantees are the dispatcher's.
|
|
//!
|
|
//! ```
|
|
//! use rhema_forge_integration::{Forge, GitHubForge, RepoRef};
|
|
//!
|
|
//! # async fn demo() -> Result<(), rhema_forge_integration::ForgeError> {
|
|
//! let forge = GitHubForge::new(std::env::var("GITHUB_TOKEN").unwrap());
|
|
//! // First poll: everything. Later polls: pass `page.cursor` back in.
|
|
//! let page = forge.poll(&RepoRef::new("acme", "widgets"), None).await?;
|
|
//! for event in &page.events {
|
|
//! println!("{:?} on {}#{}", event.kind, event.repo.path(), event.number);
|
|
//! }
|
|
//! # Ok(())
|
|
//! # }
|
|
//! ```
|
|
//!
|
|
//! Layout:
|
|
//! - [`event`] — the normalized vocabulary: `ForgeEvent`, `EventKind`,
|
|
//! `RepoRef`, `Snapshot`, `Timestamp`
|
|
//! - [`error`] — the crate's single forge error type
|
|
//! - [`forge`] — the `Forge` client contract and `ForgePage`
|
|
//! - [`github`] — the GitHub adapter (api.github.com)
|
|
//! - [`gitea`] — the Gitea adapter (self-hosted, `/api/v1`)
|
|
//! - [`gitlab`] — the GitLab adapter (gitlab.com or self-hosted, `/api/v4`)
|
|
//! - [`watcher`] — the dispatcher seam: polls a forge into an RSD
|
|
//! `Dispatcher` (keys, dedup, cursors) and decodes delivered inbox
|
|
//! items back into forge events
|
|
//! - [`triage`] — what an account notification earns: the default
|
|
//! classification of the notification vocabulary into agent
|
|
//! dispatches, surfaces, and drops
|
|
|
|
#![forbid(unsafe_code)]
|
|
|
|
pub mod error;
|
|
pub mod event;
|
|
pub mod forge;
|
|
pub mod gitea;
|
|
pub mod kind;
|
|
pub use kind::{ForgeKind, resolve_token};
|
|
pub mod github;
|
|
pub mod gitlab;
|
|
pub mod triage;
|
|
pub mod watcher;
|
|
|
|
// Re-exported so implementors of the async seam can apply #[async_trait]
|
|
// without adding the crate themselves.
|
|
pub use async_trait::async_trait;
|
|
pub use error::ForgeError;
|
|
pub use event::{
|
|
EventKind, ForgeEvent, ForgeThreadKind, Notification, NotificationPage, NotificationReason,
|
|
RepoRef, Snapshot, ThreadState, Timestamp,
|
|
};
|
|
pub use forge::{Forge, ForgePage};
|
|
pub use gitea::GiteaForge;
|
|
pub use github::GitHubForge;
|
|
pub use gitlab::GitLabForge;
|
|
pub use triage::{Role, Triage};
|
|
pub use watcher::{
|
|
WatchError, Watcher, decode, forge_key_fn, parse_key, register_forge, resource_key,
|
|
};
|