[V2:04] Add Workspace Configuration Discovery - #18
Conversation
208ad72 to
16168f9
Compare
8d3c598 to
e60a9b0
Compare
e60a9b0 to
8c9b119
Compare
SamWilsn
left a comment
There was a problem hiding this comment.
Hm, so is the intended directory structure something like:
~/Workspace/.build-eips.toml~/Workspace/.local-build/...~/Workspace/ERCs/...~/Workspace/EIPs/...
?
| } | ||
|
|
||
| impl WorkspaceConfig { | ||
| fn starter() -> Self { |
There was a problem hiding this comment.
This seems like a good candidate for a Default::default impl instead, unless there's a reason to not have a default?
There was a problem hiding this comment.
There is a reason for keeping these separate. WorkspaceConfig already has Default: that is the omitted-user-config state, where site.base_url stays None so later code can distinguish “no override was configured” from “use this explicit base URL.” starter() is only for scaffolding a new .build-eips.toml, where it is useful to write an explicit local dev value like http://127.0.0.1:1111. Collapsing those would either make omitted config behave like an override, or make the generated starter file less useful.
| /// Workspace-local bind address defaults for local server commands. | ||
| #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] | ||
| #[serde(default, deny_unknown_fields)] | ||
| pub struct ServerSettings { | ||
| /// Host or interface address used by `serve` and `preview`. | ||
| pub host: String, | ||
|
|
||
| /// TCP port used by `serve` and `preview`. | ||
| pub port: u16, | ||
| } |
There was a problem hiding this comment.
I'd keep host and port separate. SocketAddr is an IP address plus a port, so it has nowhere to store a hostname. Making it accept localhost would mean resolving the name during config parsing, which turns reading a file into fallible name resolution and discards the original hostname. Keeping host: String stores what the user typed and lets the bind call resolve it when the server starts. Separate keys are also easier to read and edit in TOML.
There was a problem hiding this comment.
$ zola serve --interface example.com
error: invalid value 'example.com' for '--interface <INTERFACE>': invalid IP address syntax
For more information, try '--help'.
I haven't traced the whole path, but this seems like where host ends up.
There was a problem hiding this comment.
Good catch. Zola’s --interface argument only accepts an IP address, so I updated the server config and CLI from host: String to interface: IpAddr. Invalid values such as hostnames are now rejected during config or CLI parsing rather than being passed through to Zola.
I also updated the downstream consumers and added coverage for hostname rejection, IPv4, IPv6, and Zola argument construction. The full test suite passes locally.
Exactly. |
|
I need to rebase this to align with the repo manifest changes merged today and do some work adjusting the architecture downstream (which may cascade down to earlier branches, maybe here), especially regarding theme ownership. |
8c9b119 to
322e2f9
Compare
|
Okay I just finished a system-wide reworking to accommodate the foundational changes introduced from #43's new architecture. This PR is ready to review and everything else is good downstream for this series. |
SamWilsn
left a comment
There was a problem hiding this comment.
This PR, on its own, doesn't add any functionality. I understand that it's foundational to later PRs, but the way you've split this up makes it hard to review. I can't tell if, for example, WorkspaceCommandContext is the best approach to solving a problem if I can't see what that problem is.
I've reviewed this for Rust-isms and such, but I'll have to come back here when I get to the later PR that uses the stuff introduced here.
| if !find_root::is_root(path).whatever_context("invalid root directory")? { | ||
| snafu::whatever!("invalid root directory"); | ||
| } |
There was a problem hiding this comment.
This seems to have duplicated the is_root check, unless there's some reason to do it before and again after canonicalizing?
There was a problem hiding this comment.
Fair, I updated this to canonicalize an explicit path first and then perform a single is_root check on the canonical path.
I also added coverage for a nonexistent explicit path, which now reports the canonicalization failure directly.
| pub(crate) fn resolve_input_path(path: &Path) -> Result<PathBuf, Whatever> { | ||
| if path.is_absolute() { | ||
| Ok(path.to_path_buf()) | ||
| } else { | ||
| let cwd = std::env::current_dir().whatever_context("unable to get current directory")?; | ||
| Ok(cwd.join(path)) | ||
| } | ||
| } |
There was a problem hiding this comment.
If you're just going to canonicalize it later, there's no reason to do this step. canonicalize will resolve against the current working directory for you.
There was a problem hiding this comment.
You're right for this call site canonicalize() already resolves relative paths against the current working directory, so resolve_input_path() is redundant here.
The helper is used later in v2/06-workspace-init-baseline for destination paths that may not exist yet and therefore cannot be canonicalized first. I'll remove it from this canonicalization path and introduce or retain it where that behavior is actually needed.
|
|
||
| #[snafu(display( | ||
| "unable to parse repo manifest `{}`", | ||
| "unable to parse Build.toml `{}`", |
There was a problem hiding this comment.
| "unable to parse Build.toml `{}`", | |
| "unable to parse {MANIFEST_FILE} `{}`", |
|
|
||
| #[snafu(display( | ||
| "repo manifest `{}` is invalid: {}", | ||
| "Build.toml `{}` is invalid: {}", |
There was a problem hiding this comment.
| "Build.toml `{}` is invalid: {}", | |
| "{MANIFEST_FILE} `{}` is invalid: {}", |
|
|
||
| let error = ActiveRepo::load(tempdir.path()).unwrap_err().to_string(); | ||
|
|
||
| assert!(error.contains("Build.toml"), "{error}"); |
There was a problem hiding this comment.
| assert!(error.contains("Build.toml"), "{error}"); | |
| assert!(error.contains(BUILD_MANIFEST), "{error}"); |
There was a problem hiding this comment.
Applied using the existing constant name MANIFEST_FILE; BUILD_MANIFEST isn't defined in this codebase.
| } | ||
| } | ||
|
|
||
| pub(crate) fn load_workspace_command_context( |
There was a problem hiding this comment.
Should be something like:
impl WorkspaceCommandContext {
fn load(...) { ... }
}There was a problem hiding this comment.
Updated this to WorkspaceCommandContext::load(args).
I used pub(crate) rather than a private fn because the method is called from the sibling workspace module.
Add workspace-local `.build-eips.toml` loading and starter configuration. Introduce `config::ActiveRepo` to load the selected checkout’s `Build.toml`, validate explicit `-C` roots, and expose active repository context to later commands. Keep source materialization, initialization, and diagnostics in their owning later branches.
322e2f9 to
54fbb1b
Compare
Yes, as we know, downstream verification is the tradeoff of this decomposition. Allow me to help make this more reviewable by providing the missing problem and consumption context below. The underlying problem is that V2 moves from a single-repository build model to a multi-repository local workspace. Later commands therefore need to resolve two distinct kinds of context:
This PR introduces those loaders, upward workspace discovery, and explicit The most useful downstream branches to inspect are:
For a focused review of |
Summary
This PR adds the local workspace configuration layer that later init, doctor, runtime, and serve/preview PRs consume. It defines strict
.build-eips.tomlparsing, upward discovery, server/site defaults, and workspace path helpers; the[render].onlysurface is intentionally deferred to V2:15.LoadedWorkspaceConfig::discoveris not called frommain.rsyet, so review should focus on schema stability, discovery behavior, and derived path/default semantics rather than command integration..build-eips.tomlworkspace config parsing and upward discovery.Review Notes
This is the workspace configuration foundation for the preprocessor stack. It defines how local workspaces are discovered and how workspace-local server/site/path defaults are represented, but it does not yet add user-facing workspace commands.
LoadedWorkspaceConfig::discoveris defined here but not yet called frommain.rs; init, doctor, and the runtime PRs wire it in.Workspace init and doctor consume this in V2:06-V2:07. Execution policy consumes the loaded config in V2:08, and server binding is used by serve/preview in V2:11-V2:12.
[render].onlyis intentionally excluded here. Targeted rendering adds the render config surface in V2:15, when the build command can actually consume it.The strict parse tests verify that unsupported workspace-config fields fail clearly instead of being silently ignored.
Review
config.rsas a schema/discovery change: the important parts are strict parsing, stable starter output, upward discovery from active repo paths, and path helpers derived from the workspace root.Verification
WorkspaceConfig,LoadedWorkspaceConfig,ServerSettings,ServerBinding, andSiteSettingsinsrc/config.rs.default_workspace_config_text()and the roundtrip/default tests for stable starter config output.discover_path()andLoadedWorkspaceConfig::discover()for upward config discovery.