feat: support typed remote repository sources

This commit is contained in:
2026-08-24 13:35:19 +09:00
parent d69c367285
commit 163a403636
17 changed files with 1041 additions and 199 deletions
+2
View File
@@ -41,9 +41,11 @@ tar.workspace = true
thiserror = { workspace = true }
tokio = { workspace = true, features = ["net", "rt", "sync", "time"] }
toml.workspace = true
url.workspace = true
uuid = { workspace = true, features = ["v7"] }
tower = { workspace = true, features = ["util"], optional = true }
worker.workspace = true
workspace-api = { path = "../workspace-api" }
workdir.workspace = true
[dev-dependencies]
+3 -4
View File
@@ -2,7 +2,6 @@ use crate::identity::{RuntimeWorkerRef, WorkerId, WorkerRef};
use crate::interaction::WorkerInput;
use crate::profile_archive::{ProfileSourceArchive, ProfileSourceArchiveRef};
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
fn is_false(value: &bool) -> bool {
!*value
@@ -85,9 +84,9 @@ impl std::ops::Deref for RepositorySelector {
pub struct WorkingDirectoryRepository {
pub id: String,
pub provider: String,
pub uri: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub local_path: Option<PathBuf>,
pub source: workspace_api::RepositorySource,
pub source_revision: u64,
pub source_fingerprint: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub selector: Option<RepositorySelector>,
}
+6 -2
View File
@@ -2631,8 +2631,12 @@ mod tests {
repository: WorkingDirectoryRepository {
id: "repo-main".to_string(),
provider: "git".to_string(),
uri: ".".to_string(),
local_path: Some(repo.to_path_buf()),
source: workspace_api::RepositorySource {
kind: workspace_api::RepositorySourceKind::LocalPath,
uri: repo.display().to_string(),
},
source_revision: 1,
source_fingerprint: "sha256:test".to_string(),
selector: Some(RepositorySelector::from("HEAD")),
},
materializer: MaterializerKind::LocalGitWorktree,
+42 -22
View File
@@ -318,18 +318,36 @@ impl LocalGitWorktreeMaterializer {
),
));
}
if is_remote_uri(&request.repository.uri) {
return Err(WorkingDirectoryDiagnostic::new(
"working_directory_remote_repository_unsupported",
"remote repository URI materialization is not implemented in v0",
));
}
let source_path = request
.repository
.local_path
.clone()
.unwrap_or_else(|| PathBuf::from(&request.repository.uri));
let source_path = match request.repository.source.kind {
workspace_api::RepositorySourceKind::LocalPath => {
PathBuf::from(&request.repository.source.uri)
}
workspace_api::RepositorySourceKind::File => {
url::Url::parse(&request.repository.source.uri)
.ok()
.and_then(|uri| uri.to_file_path().ok())
.ok_or_else(|| {
WorkingDirectoryDiagnostic::new(
"working_directory_repository_source_invalid",
"configured file Repository source is invalid",
)
})?
}
workspace_api::RepositorySourceKind::Ssh
| workspace_api::RepositorySourceKind::Http
| workspace_api::RepositorySourceKind::Https => {
return Err(WorkingDirectoryDiagnostic::new(
"working_directory_remote_repository_access_required",
"remote Repository materialization requires an explicit authenticated access and trust handle",
));
}
workspace_api::RepositorySourceKind::Invalid => {
return Err(WorkingDirectoryDiagnostic::new(
"working_directory_repository_source_invalid",
"configured Repository source is invalid and cannot be materialized",
));
}
};
let source_root = git_stdout(&source_path, ["rev-parse", "--show-toplevel"])
.map(|value| PathBuf::from(value.trim()))
.map_err(|_| {
@@ -661,10 +679,6 @@ fn path_str(path: &Path) -> Result<String, WorkingDirectoryDiagnostic> {
})
}
fn is_remote_uri(uri: &str) -> bool {
uri.contains("://") || uri.starts_with("git@") || uri.starts_with("ssh:")
}
fn sanitize_path_component(value: &str) -> String {
let sanitized = value
.chars()
@@ -793,8 +807,12 @@ mod tests {
repository: WorkingDirectoryRepository {
id: "repo-main".to_string(),
provider: "git".to_string(),
uri: ".".to_string(),
local_path: Some(repo.to_path_buf()),
source: workspace_api::RepositorySource {
kind: workspace_api::RepositorySourceKind::LocalPath,
uri: repo.display().to_string(),
},
source_revision: 1,
source_fingerprint: "sha256:test".to_string(),
selector: Some(RepositorySelector::from("HEAD")),
},
materializer: MaterializerKind::LocalGitWorktree,
@@ -908,19 +926,21 @@ mod tests {
let runtime_root = tempfile::tempdir().unwrap();
let materializer = LocalGitWorktreeMaterializer::new(runtime_root.path());
let mut remote = request(Path::new("."));
remote.repository.local_path = None;
remote.repository.uri = "https://example.invalid/repo.git".to_string();
remote.repository.source = workspace_api::RepositorySource {
kind: workspace_api::RepositorySourceKind::Https,
uri: "https://example.invalid/repo.git".to_string(),
};
let error = materializer
.materialize(&worker_ref(1), &remote)
.unwrap_err();
assert_eq!(
error.code,
"working_directory_remote_repository_unsupported"
"working_directory_remote_repository_access_required"
);
let mut non_git = remote;
non_git.repository.provider = "archive".to_string();
non_git.repository.uri = ".".to_string();
non_git.repository.source.uri = ".".to_string();
let error = materializer
.materialize(&worker_ref(2), &non_git)
.unwrap_err();