worker: add workspace workdir management feature

This commit is contained in:
2026-08-04 19:28:59 +09:00
parent e6a2da548f
commit da90ac74b4
9 changed files with 821 additions and 10 deletions
+35
View File
@@ -3924,6 +3924,41 @@ mod tests {
}
}
#[test]
fn embedded_orchestrator_profile_enables_manage_workdir() {
let root = tempfile::tempdir().unwrap();
let broker = BackendResourceBroker::default();
let runtime_id = "runtime-test";
let selector = ProfileSelector::Builtin("builtin:orchestrator".to_string());
let bundle = builtin_profile_config_bundle(
&selector,
"workspace-test",
Some(runtime_id),
&broker,
ProfileSourceArchiveTransport::BackendResourceHandle,
)
.unwrap();
let handle = bundle.profile_source_archive_handle.as_ref().unwrap();
let response = broker
.fetch_profile_source_archive(worker_runtime::resource::BackendResourceFetchRequest {
handle: handle.clone(),
runtime_id: runtime_id.to_string(),
worker_id: None,
audit_correlation_id: handle.audit_correlation_id.clone(),
})
.unwrap();
let archive =
worker_runtime::resource::profile_source_archive_from_response(handle, response)
.unwrap()
.verify()
.unwrap();
let manifest = archive
.resolve_profile("builtin:orchestrator", root.path(), "embedded-orchestrator")
.unwrap();
assert!(manifest.feature.manage_workdir.enabled);
}
#[test]
fn embedded_builtin_decodal_profiles_resolve_through_archive() {
let root = tempfile::tempdir().unwrap();
+64 -10
View File
@@ -3736,11 +3736,8 @@ async fn scoped_working_directory_detail(
AxumPath(path): AxumPath<ScopedWorkingDirectoryPath>,
) -> ApiResult<Json<BrowserWorkingDirectoryDetailResponse>> {
validate_workspace_scope(&api, &path.workspace_id)?;
working_directory_detail_for_runtime(
api,
EMBEDDED_WORKER_RUNTIME_ID,
&path.working_directory_id,
)
let runtime_id = registered_workdir_runtime_id(&api, &path.working_directory_id)?;
working_directory_detail_for_runtime(api, &runtime_id, &path.working_directory_id)
}
async fn scoped_cleanup_working_directory(
@@ -3748,11 +3745,27 @@ async fn scoped_cleanup_working_directory(
AxumPath(path): AxumPath<ScopedWorkingDirectoryPath>,
) -> ApiResult<Json<BrowserWorkingDirectoryDetailResponse>> {
validate_workspace_scope(&api, &path.workspace_id)?;
cleanup_working_directory_for_runtime(
api,
EMBEDDED_WORKER_RUNTIME_ID,
&path.working_directory_id,
)
let runtime_id = registered_workdir_runtime_id(&api, &path.working_directory_id)?;
cleanup_working_directory_for_runtime(api, &runtime_id, &path.working_directory_id)
}
fn registered_workdir_runtime_id(
api: &WorkspaceApi,
working_directory_id: &str,
) -> ApiResult<String> {
api.store
.get_workdir_registry(&api.config.workspace_id, working_directory_id)?
.map(|record| record.runtime_id)
.ok_or_else(|| {
ApiError::with_diagnostics(
Error::RuntimeOperationFailed {
runtime_id: "workspace-backend".to_string(),
code: "working_directory_not_found".to_string(),
message: format!("Unknown Workdir `{working_directory_id}`"),
},
Vec::new(),
)
})
}
fn create_working_directory_for_runtime(
@@ -10525,6 +10538,47 @@ mod tests {
.unwrap();
}
#[tokio::test]
async fn workspace_scoped_workdir_routes_resolve_runtime_owner_from_registry() {
let workspace = tempfile::tempdir().unwrap();
init_clean_git_workspace(workspace.path());
let api = test_api(workspace.path()).await;
seed_cleanup_workdir(&api, "remote-workdir", "present", "clean");
assert_eq!(
registered_workdir_runtime_id(&api, "remote-workdir").unwrap(),
"runtime-test"
);
}
#[tokio::test]
async fn simple_workdir_cleanup_rejects_dirty_and_blocked_candidates() {
let workspace = tempfile::tempdir().unwrap();
init_clean_git_workspace(workspace.path());
let api = test_api(workspace.path()).await;
seed_cleanup_workdir(&api, "dirty-workdir", "present", "dirty");
let dirty =
cleanup_working_directory_for_runtime(api.clone(), "runtime-test", "dirty-workdir")
.unwrap_err();
assert!(matches!(
dirty.error,
Error::RuntimeOperationFailed { ref code, .. }
if code == "workspace_cleanup_dirty_confirmation_required"
));
let pinned = seed_cleanup_worker(&api, 17, "pinned");
seed_cleanup_workdir(&api, "blocked-workdir", "present", "clean");
seed_cleanup_link(&api, pinned.as_str(), "blocked-workdir");
let blocked =
cleanup_working_directory_for_runtime(api.clone(), "runtime-test", "blocked-workdir")
.unwrap_err();
assert!(matches!(
blocked.error,
Error::RuntimeOperationFailed { ref code, .. }
if code == "workspace_cleanup_workdir_blocked"
));
}
#[tokio::test]
async fn synthetic_verified_clean_workdir_can_still_use_clean_cleanup_path() {
let workspace = tempfile::tempdir().unwrap();