Skip to content
This repository was archived by the owner on Apr 11, 2026. It is now read-only.

Commit 9dd2d3d

Browse files
z23ccclaude
andcommitted
fix(flowctl): detect Rust stack in subdirectories
detect_stack() only checked for Cargo.toml at repo root. Now also checks immediate subdirectories (e.g., flowctl/Cargo.toml). When found in a subdirectory, guard commands include a `cd <subdir> &&` prefix. This ensures `flowctl guard` and `flowctl stack detect` work for monorepo layouts where the Rust workspace is in a subdirectory. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent d8cabda commit 9dd2d3d

1 file changed

Lines changed: 30 additions & 6 deletions

File tree

  • flowctl/crates/flowctl-cli/src/commands

flowctl/crates/flowctl-cli/src/commands/stack.rs

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -134,15 +134,39 @@ fn detect_stack() -> serde_json::Value {
134134
// --- Backend detection ---
135135
let mut backend = json!({});
136136

137-
// Rust detection
137+
// Rust detection — check repo root and one level of subdirectories
138138
let cargo_toml = repo.join("Cargo.toml");
139-
if cargo_toml.exists() {
139+
let rust_dir = if cargo_toml.exists() {
140+
Some((repo.clone(), cargo_toml.clone()))
141+
} else {
142+
// Check immediate subdirectories for Cargo.toml (e.g., flowctl/Cargo.toml)
143+
fs::read_dir(&repo).ok().and_then(|entries| {
144+
entries
145+
.filter_map(Result::ok)
146+
.filter(|e| e.file_type().is_ok_and(|ft| ft.is_dir()))
147+
.find_map(|e| {
148+
let candidate = e.path().join("Cargo.toml");
149+
if candidate.exists() {
150+
Some((e.path(), candidate))
151+
} else {
152+
None
153+
}
154+
})
155+
})
156+
};
157+
if let Some((rust_root, cargo_path)) = rust_dir {
140158
backend["language"] = json!("rust");
141-
backend["test"] = json!("cargo test");
142-
backend["lint"] = json!("cargo clippy -- -D warnings");
143-
backend["typecheck"] = json!("cargo check");
159+
// Use relative path prefix for subdirectory workspaces
160+
let prefix = if rust_root == repo {
161+
String::new()
162+
} else {
163+
format!("cd {} && ", rust_root.file_name().unwrap_or_default().to_string_lossy())
164+
};
165+
backend["test"] = json!(format!("{prefix}cargo test --all"));
166+
backend["lint"] = json!(format!("{prefix}cargo clippy --all-targets -- -D warnings"));
167+
backend["typecheck"] = json!(format!("{prefix}cargo check"));
144168

145-
if let Ok(content) = fs::read_to_string(&cargo_toml) {
169+
if let Ok(content) = fs::read_to_string(&cargo_path) {
146170
if content.contains("actix") {
147171
backend["framework"] = json!("actix");
148172
} else if content.contains("axum") {

0 commit comments

Comments
 (0)