feat: add swimlanes

Signed-off-by: kjuulh <contact@kjuulh.io>
This commit is contained in:
2026-03-07 22:53:48 +01:00
parent 9fe1630986
commit 45353089c2
51 changed files with 3845 additions and 147 deletions

View File

@@ -4,7 +4,7 @@ use axum::Router;
use chrono::Utc;
use forage_core::auth::*;
use forage_core::platform::{
Artifact, ArtifactContext, ForestPlatform, Organisation, OrgMember, PlatformError,
Artifact, ArtifactContext, Destination, ForestPlatform, Organisation, OrgMember, PlatformError,
};
use forage_core::session::{
CachedOrg, CachedUser, InMemorySessionStore, SessionData, SessionStore,
@@ -23,6 +23,10 @@ pub(crate) struct MockBehavior {
pub list_tokens_result: Option<Result<Vec<PersonalAccessToken>, AuthError>>,
pub create_token_result: Option<Result<CreatedToken, AuthError>>,
pub delete_token_result: Option<Result<(), AuthError>>,
pub update_username_result: Option<Result<User, AuthError>>,
pub change_password_result: Option<Result<(), AuthError>>,
pub add_email_result: Option<Result<UserEmail, AuthError>>,
pub remove_email_result: Option<Result<(), AuthError>>,
}
/// Configurable mock behavior for platform (orgs, projects, artifacts).
@@ -36,6 +40,8 @@ pub(crate) struct MockPlatformBehavior {
pub add_member_result: Option<Result<OrgMember, PlatformError>>,
pub remove_member_result: Option<Result<(), PlatformError>>,
pub update_member_role_result: Option<Result<OrgMember, PlatformError>>,
pub get_artifact_by_slug_result: Option<Result<Artifact, PlatformError>>,
pub list_destinations_result: Option<Result<Vec<Destination>, PlatformError>>,
}
pub(crate) fn ok_tokens() -> AuthTokens {
@@ -166,6 +172,57 @@ impl ForestAuth for MockForestClient {
let b = self.behavior.lock().unwrap();
b.delete_token_result.clone().unwrap_or(Ok(()))
}
async fn update_username(
&self,
_access_token: &str,
_user_id: &str,
new_username: &str,
) -> Result<User, AuthError> {
let b = self.behavior.lock().unwrap();
b.update_username_result.clone().unwrap_or(Ok(User {
user_id: "user-123".into(),
username: new_username.into(),
emails: vec![UserEmail {
email: "test@example.com".into(),
verified: true,
}],
}))
}
async fn change_password(
&self,
_access_token: &str,
_user_id: &str,
_current_password: &str,
_new_password: &str,
) -> Result<(), AuthError> {
let b = self.behavior.lock().unwrap();
b.change_password_result.clone().unwrap_or(Ok(()))
}
async fn add_email(
&self,
_access_token: &str,
_user_id: &str,
email: &str,
) -> Result<UserEmail, AuthError> {
let b = self.behavior.lock().unwrap();
b.add_email_result.clone().unwrap_or(Ok(UserEmail {
email: email.into(),
verified: false,
}))
}
async fn remove_email(
&self,
_access_token: &str,
_user_id: &str,
_email: &str,
) -> Result<(), AuthError> {
let b = self.behavior.lock().unwrap();
b.remove_email_result.clone().unwrap_or(Ok(()))
}
}
pub(crate) struct MockPlatformClient {
@@ -228,6 +285,8 @@ impl ForestPlatform for MockPlatformClient {
context: ArtifactContext {
title: "Deploy v1.0".into(),
description: Some("Initial release".into()),
web: None,
pr: None,
},
source: None,
git_ref: None,
@@ -302,6 +361,39 @@ impl ForestPlatform for MockPlatformClient {
joined_at: Some("2026-01-01T00:00:00Z".into()),
}))
}
async fn get_artifact_by_slug(
&self,
_access_token: &str,
slug: &str,
) -> Result<Artifact, PlatformError> {
let b = self.behavior.lock().unwrap();
b.get_artifact_by_slug_result
.clone()
.unwrap_or(Ok(Artifact {
artifact_id: "art-1".into(),
slug: slug.into(),
context: ArtifactContext {
title: "Deploy v1.0".into(),
description: Some("Initial release".into()),
web: None,
pr: None,
},
source: None,
git_ref: None,
destinations: vec![],
created_at: "2026-03-07T12:00:00Z".into(),
}))
}
async fn list_destinations(
&self,
_access_token: &str,
_organisation: &str,
) -> Result<Vec<Destination>, PlatformError> {
let b = self.behavior.lock().unwrap();
b.list_destinations_result.clone().unwrap_or(Ok(vec![]))
}
}
pub(crate) fn make_templates() -> TemplateEngine {