worker: add workspace workdir management feature
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user