This is a sub-PRD of the [Semantic Layer and Deployment Refactor](semantic_layer_refactor_overview.md) project. Please refer to the parent PRD for the overall project context, goals, and implementation plan.
## Problem Statement
The current CLI (`deploy` command) has a limited way of discovering model files and managing configurations. The `buster.yml` is typically expected in the current directory or a specified path, and its structure is flat. This doesn't cater well to monorepos or projects where models might be organized into sub-directories, each potentially with slightly different default configurations (like schema or database).
Behavior of `deploy` command pathing:
- The `deploy` command, when invoked, should look for `buster.yml` only in the effective target directory (either the one provided as an argument or the current working directory if no argument is given).
- It should *not* search in parent directories for `buster.yml`.
- Once `buster.yml` is found (or defaults are used if it's not found), model file discovery (e.g., `*.yml`) will proceed based on the paths specified in `buster.yml` (new `projects` field) or the directory containing `buster.yml` itself (for backward compatibility or simple cases). Model search should be recursive *within* these specified model paths.
Current behavior:
-`BusterConfig` in `cli/cli/src/utils/config.rs` is flat, primarily supporting global `data_source_name`, `schema`, `database`, `exclude_tags`, and `exclude_files`.
- Model discovery is generally from the current path or a specified path, without a structured way to define multiple distinct "project" sources of models within one `buster.yml`.
- The `deploy` command might have ambiguous behavior regarding `buster.yml` lookup upwards in the directory tree.
Expected behavior:
- The `deploy` command will strictly look for `buster.yml` in the target directory (current or specified) and *not* traverse upwards.
-`BusterConfig` will be extended to include an optional `projects: Vec<ProjectConfig>` field.
- Each `ProjectConfig` will define a `path` (relative to the `buster.yml` location) where its models are located, and can optionally specify its own `data_source_name`, `schema`, and `database` that override the global settings in `buster.yml` for models within that project path.
- The CLI's model discovery logic will iterate through these `projects` (if defined) or use the `buster.yml` directory / `model_paths` (if defined and `projects` is not) to find model files (`.yml` excluding `buster.yml`).
- Configuration (database, schema, data_source_name) for a deployed model will be resolved with the following precedence: Model File -> ProjectConfig -> Global BusterConfig.
## Goals
1. Modify the `deploy` command to search for `buster.yml` only in the current/specified directory and its subdirectories (when looking for models), not parent directories.
2. Extend `BusterConfig` in `cli/cli/src/utils/config.rs` to include `projects: Option<Vec<ProjectConfig>>`.
3. Define a `ProjectConfig` struct with `path: String` and optional `data_source_name`, `schema`, `database` fields.
4. Update the model file discovery logic in `cli/cli/src/commands/deploy.rs` to:
a. Honor the `projects` structure in `buster.yml` if present.
b. If `projects` is not present, fall back to existing `model_paths` logic or searching the directory of `buster.yml` (or current/specified path if no `buster.yml`).
c. Recursively search for `.yml` model files within the determined project/model paths.
5. Implement the configuration inheritance logic (Model File > ProjectConfig > Global BusterConfig) when preparing models for deployment.
## Non-Goals
1. Changing the YAML parsing for individual model files (covered in `prd_semantic_model_definition.md` and `prd_cli_deployment_logic.md`).
2. Altering the `exclude_tags` or `exclude_files` functionality at the global level (though they would apply to all discovered models).
## Implementation Plan
### Phase 1: Update BusterConfig and Discovery Logic
#### Technical Design
**1. `BusterConfig` and `ProjectConfig` structs (`cli/cli/src/utils/config.rs`):**
a. Modify `deploy` to determine `base_dir` (current or specified path).
b. Load `BusterConfig` strictly from `base_dir`.
c. Use `resolve_effective_model_paths` to get search locations.
d. Implement recursive search for `.yml` files (excluding `buster.yml`) in these locations, associating found files with their `Option<ProjectConfig>`.
- Relies on `prd_semantic_model_definition.md` for the structure of model files being discovered, but primarily focuses on *finding* them and their *configuration context*.
## Security Considerations
- Path resolution from `buster.yml` (for `projects.path` or `model_paths`) must be handled carefully to ensure paths are treated as relative to `buster.yml` and do not allow traversal to unintended locations (e.g., `../../../../../etc/passwd`). Standard library functions like `Path::join` are generally safe but input validation or sanitization might be considered if paths can be arbitrary strings.
## References
- Existing `cli/cli/src/utils/config.rs`
- Existing `cli/cli/src/commands/deploy.rs` model discovery logic.