runtime: remove workspace cwd options

This commit is contained in:
Keisuke Hirata 2026-07-13 18:31:54 +09:00
parent f54ba6950c
commit b82407816e
No known key found for this signature in database
4 changed files with 43 additions and 66 deletions

View File

@ -1,8 +1,8 @@
--- ---
title: 'Remove workspace and cwd from worker runtime server' title: 'Remove workspace and cwd from worker runtime server'
state: 'inprogress' state: 'done'
created_at: '2026-07-13T09:21:46Z' created_at: '2026-07-13T09:21:46Z'
updated_at: '2026-07-13T09:22:30Z' updated_at: '2026-07-13T09:31:37Z'
assignee: null assignee: null
queued_by: 'yoi ticket' queued_by: 'yoi ticket'
queued_at: '2026-07-13T09:22:30Z' queued_at: '2026-07-13T09:22:30Z'

View File

@ -39,4 +39,40 @@ Ticket を `yoi ticket` が queued にしました。
State changed to `inprogress`. State changed to `inprogress`.
---
<!-- event: implementation_report author: hare at: 2026-07-13T09:31:37Z -->
## Implementation report
Removed `worker-runtime-rest-server` `--workspace` and `--cwd` options.
- Removed process config fields and CLI parsing for workspace/cwd.
- Runtime Worker factory now uses a Runtime-local `worker-root` under the Runtime root instead of a workspace root for workdirless Workers.
- Workdir bindings still provide their materialized root/cwd when a Worker has a Workdir.
- Help no longer lists `--workspace` / `--cwd`; specifying either now fails as an unknown argument.
Validation:
- `cargo fmt --check`
- `git diff --check`
- `cargo check -q`
- `cargo check -q -p worker-runtime --features fs-store,ws-server`
- `cargo test -q -p worker-runtime --features fs-store,ws-server`
- `cargo test -q -p yoi-workspace-server`
- `cargo run -q -p worker-runtime --features ws-server,fs-store --bin worker-runtime-rest-server -- --help`
- `cargo run -q -p worker-runtime --features ws-server,fs-store --bin worker-runtime-rest-server -- --workspace /tmp` rejects the removed option
- `cargo run -q -p worker-runtime --features ws-server,fs-store --bin worker-runtime-rest-server -- --cwd /tmp` rejects the removed option
- Started `worker-runtime-rest-server` with only `--bind` and `--fs-root` and verified `/v1/runtime` responds with `backend: fs_store`
- `nix build .#yoi --no-link`
---
<!-- event: state_changed author: "yoi ticket" at: 2026-07-13T09:31:37Z from: inprogress to: done reason: cli_state field: state -->
## State changed
State changed to `done`.
--- ---

View File

@ -66,8 +66,8 @@ fn run() -> Result<(), ProcessError> {
} }
fn build_runtime(config: &ProcessConfig) -> Result<Runtime, ProcessError> { fn build_runtime(config: &ProcessConfig) -> Result<Runtime, ProcessError> {
let mut factory = ProfileRuntimeWorkerFactory::new(config.workspace_root.clone()) let runtime_root = working_directory_runtime_root(config);
.with_cwd(config.cwd.clone()); let mut factory = ProfileRuntimeWorkerFactory::new(runtime_root.join("worker-root"));
if let Some(store_dir) = config.worker_store_dir.clone() { if let Some(store_dir) = config.worker_store_dir.clone() {
factory = factory.with_store_dir(store_dir); factory = factory.with_store_dir(store_dir);
} }
@ -168,12 +168,6 @@ where
"--display-name" => { "--display-name" => {
config.http.display_name = Some(take_value(&flag, inline_value, &mut args)?); config.http.display_name = Some(take_value(&flag, inline_value, &mut args)?);
} }
"--workspace" => {
config.workspace_root = PathBuf::from(take_value(&flag, inline_value, &mut args)?);
}
"--cwd" => {
config.cwd = PathBuf::from(take_value(&flag, inline_value, &mut args)?);
}
"--worker-store-dir" => { "--worker-store-dir" => {
config.worker_store_dir = config.worker_store_dir =
Some(PathBuf::from(take_value(&flag, inline_value, &mut args)?)); Some(PathBuf::from(take_value(&flag, inline_value, &mut args)?));
@ -250,33 +244,9 @@ where
} }
apply_store_selection(&mut config.http, store)?; apply_store_selection(&mut config.http, store)?;
config.workspace_root = normalize_workspace_path(config.workspace_root)?;
if config.cwd.as_os_str().is_empty() {
config.cwd = config.workspace_root.clone();
} else {
config.cwd = normalize_child_path(&config.workspace_root, config.cwd);
}
Ok(Some(config)) Ok(Some(config))
} }
fn normalize_workspace_path(path: PathBuf) -> Result<PathBuf, ProcessError> {
let absolute = if path.is_absolute() {
path
} else {
env::current_dir()?.join(path)
};
Ok(absolute.canonicalize().unwrap_or(absolute))
}
fn normalize_child_path(base: &std::path::Path, path: PathBuf) -> PathBuf {
if path.is_absolute() {
path.canonicalize().unwrap_or(path)
} else {
let absolute = base.join(path);
absolute.canonicalize().unwrap_or(absolute)
}
}
fn split_flag_value(arg: String) -> Result<(String, Option<String>), ProcessError> { fn split_flag_value(arg: String) -> Result<(String, Option<String>), ProcessError> {
if !arg.starts_with('-') { if !arg.starts_with('-') {
return Err(ProcessError::usage(format!( return Err(ProcessError::usage(format!(
@ -328,8 +298,6 @@ fn apply_store_selection(
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq)]
struct ProcessConfig { struct ProcessConfig {
http: RuntimeHttpServerConfig, http: RuntimeHttpServerConfig,
workspace_root: PathBuf,
cwd: PathBuf,
worker_store_dir: Option<PathBuf>, worker_store_dir: Option<PathBuf>,
worker_metadata_dir: Option<PathBuf>, worker_metadata_dir: Option<PathBuf>,
worker_runtime_base_dir: Option<PathBuf>, worker_runtime_base_dir: Option<PathBuf>,
@ -340,11 +308,8 @@ struct ProcessConfig {
impl ProcessConfig { impl ProcessConfig {
fn default() -> Result<Self, ProcessError> { fn default() -> Result<Self, ProcessError> {
let workspace_root = env::current_dir()?;
Ok(Self { Ok(Self {
http: RuntimeHttpServerConfig::default(), http: RuntimeHttpServerConfig::default(),
cwd: workspace_root.clone(),
workspace_root,
worker_store_dir: None, worker_store_dir: None,
worker_metadata_dir: None, worker_metadata_dir: None,
worker_runtime_base_dir: None, worker_runtime_base_dir: None,
@ -418,8 +383,6 @@ Browsers must not connect to this Runtime process directly.\n\n\
Options:\n\ Options:\n\
--bind <ADDR> Bind socket address (default: 127.0.0.1:38800)\n\ --bind <ADDR> Bind socket address (default: 127.0.0.1:38800)\n\
--display-name <NAME> Runtime display name\n\ --display-name <NAME> Runtime display name\n\
--workspace <PATH> Workspace root used for spawned Workers (default: cwd)\n\
--cwd <PATH> Process cwd used for spawned Workers (default: workspace)\n\
--profile <SELECTOR> Force spawned Workers to use a Profile selector\n\ --profile <SELECTOR> Force spawned Workers to use a Profile selector\n\
--worker-store-dir <PATH> Worker session store directory\n\ --worker-store-dir <PATH> Worker session store directory\n\
--worker-metadata-dir <PATH> Worker metadata directory\n\ --worker-metadata-dir <PATH> Worker metadata directory\n\
@ -454,14 +417,9 @@ mod tests {
} }
#[test] #[test]
fn normalizes_relative_workspace_for_worker_spawn() { fn rejects_removed_workspace_and_cwd_options() {
let current_dir = env::current_dir().unwrap().canonicalize().unwrap(); assert!(parse_args(["--workspace", "/tmp/workspace"]).is_err());
let config = parse_args(["--workspace", ".", "--cwd", "."]) assert!(parse_args(["--cwd", "/tmp/workspace"]).is_err());
.unwrap()
.unwrap();
assert_eq!(config.workspace_root, current_dir);
assert_eq!(config.cwd, current_dir);
} }
#[test] #[test]
@ -471,10 +429,6 @@ mod tests {
"127.0.0.1:0", "127.0.0.1:0",
"--display-name", "--display-name",
"Runtime Alpha", "Runtime Alpha",
"--workspace",
"/tmp/workspace",
"--cwd",
"/tmp/workspace/subdir",
"--profile", "--profile",
"builtin:coder", "builtin:coder",
"--local-token-env", "--local-token-env",
@ -490,10 +444,6 @@ mod tests {
"127.0.0.1:0", "127.0.0.1:0",
"--display-name", "--display-name",
"Runtime Alpha", "Runtime Alpha",
"--workspace",
"/tmp/workspace",
"--cwd",
"/tmp/workspace/subdir",
"--profile", "--profile",
"builtin:coder", "builtin:coder",
"--local-token-env", "--local-token-env",
@ -507,8 +457,6 @@ mod tests {
assert_eq!(config.http.bind_addr, "127.0.0.1:0".parse().unwrap()); assert_eq!(config.http.bind_addr, "127.0.0.1:0".parse().unwrap());
assert_eq!(config.http.display_name.as_deref(), Some("Runtime Alpha")); assert_eq!(config.http.display_name.as_deref(), Some("Runtime Alpha"));
assert_eq!(config.workspace_root, PathBuf::from("/tmp/workspace"));
assert_eq!(config.cwd, PathBuf::from("/tmp/workspace/subdir"));
assert_eq!(config.profile.as_deref(), Some("builtin:coder")); assert_eq!(config.profile.as_deref(), Some("builtin:coder"));
assert_eq!(config.http.local_token.as_deref(), Some("secret-token")); assert_eq!(config.http.local_token.as_deref(), Some("secret-token"));
} }

View File

@ -65,7 +65,6 @@ pub trait RuntimeWorkerFactory: Send + Sync + 'static {
#[derive(Clone)] #[derive(Clone)]
pub struct ProfileRuntimeWorkerFactory { pub struct ProfileRuntimeWorkerFactory {
profile_base_dir: PathBuf, profile_base_dir: PathBuf,
cwd: PathBuf,
store_dir: Option<PathBuf>, store_dir: Option<PathBuf>,
worker_metadata_dir: Option<PathBuf>, worker_metadata_dir: Option<PathBuf>,
profile: Option<String>, profile: Option<String>,
@ -78,7 +77,6 @@ impl ProfileRuntimeWorkerFactory {
pub fn new(profile_base_dir: impl Into<PathBuf>) -> Self { pub fn new(profile_base_dir: impl Into<PathBuf>) -> Self {
let profile_base_dir = profile_base_dir.into(); let profile_base_dir = profile_base_dir.into();
Self { Self {
cwd: profile_base_dir.clone(),
profile_base_dir, profile_base_dir,
store_dir: None, store_dir: None,
worker_metadata_dir: None, worker_metadata_dir: None,
@ -89,11 +87,6 @@ impl ProfileRuntimeWorkerFactory {
} }
} }
pub fn with_cwd(mut self, cwd: impl Into<PathBuf>) -> Self {
self.cwd = cwd.into();
self
}
pub fn with_store_dir(mut self, store_dir: impl Into<PathBuf>) -> Self { pub fn with_store_dir(mut self, store_dir: impl Into<PathBuf>) -> Self {
self.store_dir = Some(store_dir.into()); self.store_dir = Some(store_dir.into());
self self