From 8b13b75256a7d274feeb05fcc2945fe1943cdabd Mon Sep 17 00:00:00 2001 From: Mahmoud Abdelwahab Date: Tue, 21 Apr 2026 15:52:26 +0200 Subject: [PATCH] fix: dedupe workspaces in list output (#852) Workspaces returned by `me.workspaces` and `externalWorkspaces` can overlap when a user has both workspace membership and project-level access to the same workspace, causing duplicates in `railway list`, `railway project list`, and `railway whoami --json`. Dedupe by id while merging, preferring the Member variant (richer data). Closes #844, #831. --- src/workspace.rs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/workspace.rs b/src/workspace.rs index 50a4fa5..12cc9ce 100644 --- a/src/workspace.rs +++ b/src/workspace.rs @@ -1,5 +1,6 @@ use chrono::{DateTime, Utc}; use serde::Serialize; +use std::collections::HashSet; use std::fmt::Display; use super::{ @@ -17,18 +18,22 @@ pub async fn workspaces() -> Result> { let response = post_graphql::(&client, configs.get_backboard(), vars).await?; + // Member variants are yielded first so that a workspace the user both owns + // and is an external member of keeps the richer Member representation. + let mut seen: HashSet = HashSet::new(); let mut workspaces: Vec = response .me .workspaces .into_iter() .map(Workspace::Member) + .chain( + response + .external_workspaces + .into_iter() + .map(Workspace::External), + ) + .filter(|w| seen.insert(w.id().to_string())) .collect(); - workspaces.extend( - response - .external_workspaces - .into_iter() - .map(Workspace::External), - ); workspaces.sort_by(|a, b| b.id().cmp(a.id())); Ok(workspaces) }