feat: distribute latest workspace config to runtimes

This commit is contained in:
2026-09-07 02:40:03 +09:00
parent 31f7d39647
commit f1baea1705
11 changed files with 656 additions and 403 deletions
+32 -102
View File
@@ -1,5 +1,7 @@
use crate::Error;
use crate::resource_broker::{BackendResourceBroker, BackendResourceTarget};
use crate::resource_broker::BackendResourceBroker;
#[cfg(test)]
use crate::resource_broker::BackendResourceTarget;
use chrono::Utc;
use protocol::Segment;
use reqwest::blocking::{Client as BlockingHttpClient, RequestBuilder};
@@ -24,8 +26,8 @@ use workdir::{
use worker_runtime::RuntimeWorkspaceScope;
use worker_runtime::auth::{CapabilityTokenSigner, capability_claims};
use worker_runtime::catalog::{
ConfigBundleRef, CreateWorkerRequest, ProfileSelector, ProfileSourceArchiveHttpRef,
ProfileSourceArchiveSource, RepositoryRefObservation, RepositoryRefObservationRequest,
ConfigBundleRef, CreateWorkerRequest, ProfileSelector, ProfileSourceArchiveSource,
RepositoryRefObservation, RepositoryRefObservationRequest,
WorkerDetail as EmbeddedWorkerDetail, WorkerStatus as EmbeddedWorkerStatus,
WorkingDirectoryClaim, WorkingDirectoryRepositoryAccessRequest, WorkingDirectoryRequest,
WorkingDirectoryStatus, WorkingDirectorySummary, WorkspaceApiRef,
@@ -57,7 +59,7 @@ use worker_runtime::interaction::{
WorkerInput as EmbeddedWorkerInput, WorkerInputKind as EmbeddedWorkerInputKind,
};
use worker_runtime::management::{RuntimeOptions as EmbeddedRuntimeOptions, RuntimeStatus};
use worker_runtime::profile_archive::{ProfileSourceArchive, ProfileSourceArchiveInput};
use worker_runtime::profile_archive::ProfileSourceArchive;
use worker_runtime::retention::{
WorkerRetentionExecutionRequest, WorkerRetentionExecutionResult, WorkerRetentionInventory,
};
@@ -1481,7 +1483,9 @@ impl RuntimeRegistry {
_ => {}
}
let runtime = self.runtime(runtime_id)?;
if let Some(bundle) = request.resolved_config_bundle.clone() {
if runtime_id == EMBEDDED_RUNTIME_ID
&& let Some(bundle) = request.resolved_config_bundle.clone()
{
let sync = runtime.sync_config_bundle(bundle);
if sync.state != WorkerOperationState::Accepted {
let message = sync
@@ -2972,7 +2976,6 @@ pub struct RemoteWorkerRuntime {
runtime_id: String,
display_name: String,
base_url: String,
backend_base_url: String,
workspace_id: String,
bearer_token: Option<String>,
auth: Option<RemoteRuntimeAuthConfig>,
@@ -3049,7 +3052,7 @@ impl RemoteWorkerRuntime {
pub fn new(
config: RemoteRuntimeConfig,
workspace_id: String,
backend_base_url: String,
_backend_base_url: String,
) -> Result<Self, RuntimeRegistryError> {
validate_backend_identifier("runtime_id", &config.runtime_id)?;
let base_url = config.base_url.trim_end_matches('/').to_string();
@@ -3077,7 +3080,6 @@ impl RemoteWorkerRuntime {
runtime_id: config.runtime_id,
display_name: config.display_name,
base_url,
backend_base_url: backend_base_url.trim_end_matches('/').to_string(),
workspace_id,
bearer_token: config.bearer_token,
auth: config.auth,
@@ -3722,28 +3724,24 @@ impl WorkspaceWorkerRuntime for RemoteWorkerRuntime {
};
}
let profile = request.profile.clone();
let profile_source = match profile_source_archive_http_source(
&request,
&profile,
&self.workspace_id,
Some(self.runtime_id.as_str()),
&self.resource_broker,
&self.backend_base_url,
) {
Ok(source) => source,
let profile_source_archive = match profile_source_archive_for_request(&request, &profile) {
Ok(archive) => archive,
Err(error) => {
return WorkerSpawnResult {
state: WorkerOperationState::Rejected,
worker: None,
acceptance_evidence: Vec::new(),
diagnostics: vec![diagnostic(
"remote_profile_source_archive_invalid",
"remote_workspace_config_invalid",
DiagnosticSeverity::Error,
error,
)],
};
}
};
let profile_source = ProfileSourceArchiveSource::WorkspaceConfig {
archive: profile_source_archive.reference,
};
let workspace_api = match required_worker_workspace_api(&request) {
Ok(workspace_api) => workspace_api,
Err(diagnostic) => {
@@ -4088,7 +4086,7 @@ fn profile_source_archive_for_request(
{
return Ok(archive);
}
builtin_profile_source_archive(profile)
crate::profile_settings::builtin_profile_source_archive(profile)
}
fn profile_source_archive_source(
@@ -4100,36 +4098,14 @@ fn profile_source_archive_source(
})
}
fn profile_source_archive_http_source(
#[cfg(test)]
fn profile_source_archive_workspace_config_source(
request: &WorkerSpawnRequest,
profile: &ProfileSelector,
workspace_id: &str,
runtime_id: Option<&str>,
resource_broker: &BackendResourceBroker,
backend_base_url: &str,
) -> Result<ProfileSourceArchiveSource, String> {
let archive = profile_source_archive_for_request(request, profile)?;
let target = runtime_id
.map(BackendResourceTarget::Runtime)
.unwrap_or(BackendResourceTarget::Workspace);
let _handle = resource_broker.issue_profile_source_archive_handle(
workspace_id.to_string(),
target,
archive.clone(),
);
let etag = format!("\"profile-source:{}\"", archive.reference.digest);
let url = format!(
"{}/api/w/{}/profile-source-archives/{}",
backend_base_url.trim_end_matches('/'),
workspace_id,
archive.reference.digest
);
Ok(ProfileSourceArchiveSource::Http {
location: ProfileSourceArchiveHttpRef {
url,
etag: Some(etag),
archive: archive.reference.clone(),
},
Ok(ProfileSourceArchiveSource::WorkspaceConfig {
archive: archive.reference,
})
}
@@ -4154,7 +4130,7 @@ fn builtin_profile_config_bundle(
.unwrap_or_else(|| "default".to_string())
.replace([':', '/', ' '], "-")
);
let archive = builtin_profile_source_archive(profile)?;
let archive = crate::profile_settings::builtin_profile_source_archive(profile)?;
let (profile_source_archive, profile_source_archive_handle) = match archive_transport {
ProfileSourceArchiveTransport::Inline => (Some(archive), None),
ProfileSourceArchiveTransport::BackendResourceHandle => {
@@ -4208,39 +4184,6 @@ fn embedded_profile_label(profile: &ProfileSelector) -> Option<String> {
})
}
fn builtin_profile_source_archive(
profile: &ProfileSelector,
) -> Result<ProfileSourceArchive, String> {
let selected_profile = match profile {
ProfileSelector::Builtin(name) => {
if name.starts_with("builtin:") {
name.clone()
} else {
format!("builtin:{name}")
}
}
ProfileSelector::Named(name) => {
return Err(format!(
"embedded runtime does not provide named Profile `{name}`"
));
}
};
let catalog = manifest::builtin_profile_catalog_snapshot();
if !catalog.entrypoints.contains_key(&selected_profile) {
return Err(format!(
"embedded runtime does not provide Profile `{selected_profile}`"
));
}
ProfileSourceArchive::build(ProfileSourceArchiveInput {
id: catalog.id.to_owned(),
sources: catalog.sources,
entrypoints: catalog.entrypoints,
imports: catalog.imports,
})
.map_err(|error| format!("failed to build built-in Profile source archive: {error}"))
}
const MEMORY_CONSOLIDATION_PROFILE: &str = "memory-consolidation";
const MEMORY_CONSOLIDATION_SINGLETON_KEY: &str = "workspace-memory-consolidation";
const WORKSPACE_ORCHESTRATOR_PROFILE: &str = "orchestrator";
@@ -4940,7 +4883,7 @@ mod tests {
fn resolved_project_profile_archive_is_used_for_runtime_delivery() {
let broker = BackendResourceBroker::default();
let builtin_selector = ProfileSelector::Builtin("builtin:coder".to_string());
let archive = builtin_profile_source_archive(&builtin_selector)
let archive = crate::profile_settings::builtin_profile_source_archive(&builtin_selector)
.expect("build stand-in project profile archive");
let mut bundle = builtin_profile_config_bundle(
&builtin_selector,
@@ -4962,30 +4905,17 @@ mod tests {
}
#[test]
fn remote_profile_source_archive_url_uses_workspace_id_not_host_id() {
let broker = BackendResourceBroker::default();
let runtime_id = "remote:test";
fn remote_profile_source_uses_workspace_config_archive_reference() {
let request = embedded_spawn_request();
let source = profile_source_archive_http_source(
&request,
&ProfileSelector::Builtin("builtin:coder".to_string()),
"workspace-actual",
Some(runtime_id),
&broker,
"http://127.0.0.1:8787/",
)
.unwrap();
let ProfileSourceArchiveSource::Http { location } = source else {
panic!("remote profile source should be HTTP fetched");
};
assert!(
location.url.starts_with(
"http://127.0.0.1:8787/api/w/workspace-actual/profile-source-archives/"
),
"{}",
location.url
let profile = ProfileSelector::Builtin("builtin:coder".to_string());
let expected = profile_source_archive_for_request(&request, &profile)
.unwrap()
.reference;
let source = profile_source_archive_workspace_config_source(&request, &profile).unwrap();
assert_eq!(
source,
ProfileSourceArchiveSource::WorkspaceConfig { archive: expected }
);
assert!(!location.url.contains("remote-runtime"), "{}", location.url);
}
#[test]
@@ -4,7 +4,7 @@ use std::path::{Component, Path, PathBuf};
use std::time::UNIX_EPOCH;
use config_source::{ConfigContentType, ConfigSchemaContribution, VirtualPath};
use manifest::{ProfileSource, resolve_profile_artifact_value};
use manifest::{ProfileSource, builtin_profile_catalog_snapshot, resolve_profile_artifact_value};
use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256};
use worker::EffectivePromptCatalog;
@@ -361,6 +361,38 @@ pub fn build_virtual_profile_config_bundle(
)
}
pub(crate) fn builtin_profile_source_archive(
profile: &worker_runtime::catalog::ProfileSelector,
) -> std::result::Result<ProfileSourceArchive, String> {
let selected_profile = match profile {
worker_runtime::catalog::ProfileSelector::Builtin(value) => {
if value.starts_with("builtin:") {
value.clone()
} else {
format!("builtin:{value}")
}
}
worker_runtime::catalog::ProfileSelector::Named(value) => {
return Err(format!(
"builtin profile source catalog has no named entrypoint for '{value}'"
));
}
};
let catalog = builtin_profile_catalog_snapshot();
if !catalog.entrypoints.contains_key(&selected_profile) {
return Err(format!(
"builtin profile source catalog has no entrypoint for '{selected_profile}'"
));
}
ProfileSourceArchive::build(ProfileSourceArchiveInput {
id: catalog.id.to_owned(),
entrypoints: catalog.entrypoints,
imports: catalog.imports,
sources: catalog.sources,
})
.map_err(|error| format!("failed to build builtin profile source archive: {error}"))
}
pub fn build_virtual_profile_config_bundle_with_prompt_projection(
projection: &ProfileConfigProjection,
state: &WorkspaceConfigState,
@@ -371,13 +403,17 @@ pub fn build_virtual_profile_config_bundle_with_prompt_projection(
) -> Result<Option<ConfigBundle>> {
validate_prompt_projection_matches_state(workspace_id, state, prompt_projection)?;
let prompt_catalog = prompt_projection.catalog().clone();
let archive = projection
.entries
.get(selector)
.map(|entry| build_virtual_profile_archive(selector, entry, &projection.sources, state))
.transpose()?;
let profile_selector = selector_for_builtin_candidate(selector)
.unwrap_or_else(|| worker_runtime::catalog::ProfileSelector::Named(selector.to_string()));
let archive = match projection.entries.get(selector) {
Some(entry) => Some(build_virtual_profile_archive(
selector,
entry,
&projection.sources,
state,
)?),
None => Some(builtin_profile_source_archive(&profile_selector).map_err(Error::Store)?),
};
let bundle_id = virtual_profile_bundle_id(
state,
workspace_id,
@@ -1,15 +1,12 @@
use super::*;
use protocol::subscription::{SubscriptionWorkerIds, SubscriptionWorkerState};
use worker_runtime::Runtime;
use worker_runtime::catalog::{
CreateWorkerRequest, ProfileSelector, ProfileSourceArchiveHttpRef, ProfileSourceArchiveSource,
};
use worker_runtime::catalog::{CreateWorkerRequest, ProfileSelector, ProfileSourceArchiveSource};
use worker_runtime::execution::{
WorkerExecutionBackend, WorkerExecutionHandle, WorkerExecutionOperation, WorkerExecutionResult,
WorkerExecutionSpawnRequest, WorkerExecutionSpawnResult,
};
use worker_runtime::identity::WorkerId;
use worker_runtime::profile_archive::{ProfileSourceArchiveRef, ProfileSourceGraphSummary};
#[derive(Debug)]
struct TestExecutionBackend;
@@ -57,22 +54,11 @@ fn create_request(name: &str) -> CreateWorkerRequest {
profile: ProfileSelector::Builtin("builtin:companion".to_string()),
display_name: Some(name.to_string()),
config_bundle: None,
profile_source: ProfileSourceArchiveSource::Http {
location: ProfileSourceArchiveHttpRef {
url: "http://127.0.0.1/profiles/test".to_string(),
etag: None,
archive: ProfileSourceArchiveRef {
id: "test-profile-source".to_string(),
digest: "test-digest".to_string(),
size_bytes: 0,
source_graph: ProfileSourceGraphSummary {
source_count: 0,
total_source_bytes: 0,
entrypoints: std::collections::BTreeMap::new(),
import_count: 0,
},
},
},
profile_source: ProfileSourceArchiveSource::Embedded {
archive: crate::profile_settings::builtin_profile_source_archive(
&ProfileSelector::Builtin("builtin:default".to_string()),
)
.unwrap(),
},
initial_input: None,
working_directory_request: None,
+153 -72
View File
@@ -6,7 +6,9 @@ use std::sync::{Arc, Mutex, RwLock, Weak};
use axum::body::Bytes;
use axum::extract::ws::{Message as WsMessage, WebSocket, WebSocketUpgrade};
use axum::extract::{DefaultBodyLimit, Extension, Path as AxumPath, Query, Request, State};
use axum::http::header::{CONTENT_TYPE, ETAG, IF_NONE_MATCH, LOCATION, ORIGIN, SET_COOKIE};
use axum::http::header::{
CACHE_CONTROL, CONTENT_TYPE, ETAG, IF_NONE_MATCH, LOCATION, ORIGIN, SET_COOKIE,
};
use axum::http::{HeaderMap, Method, StatusCode, Uri};
use axum::middleware::{self, Next};
use axum::response::{IntoResponse, Response};
@@ -1596,7 +1598,10 @@ async fn authorize_scoped_workspace_request(
{
worker_runtime::auth::WORKSPACE_WORKER_DISCOVERY_PERMISSION
} else if path.starts_with("/api/runtime/v1/workspaces/")
|| path.contains("/profile-source-archives/")
|| path
.split('?')
.next()
.is_some_and(|path| path.ends_with("/runtime-config"))
{
worker_runtime::auth::BACKEND_RESOURCE_FETCH_PERMISSION
} else {
@@ -1705,7 +1710,10 @@ async fn authorize_workspace_api_request(
{
worker_runtime::auth::WORKSPACE_WORKER_DISCOVERY_PERMISSION
} else if path.starts_with("/api/runtime/v1/workspaces/")
|| path.contains("/profile-source-archives/")
|| path
.split('?')
.next()
.is_some_and(|path| path.ends_with("/runtime-config"))
{
worker_runtime::auth::BACKEND_RESOURCE_FETCH_PERMISSION
} else {
@@ -3112,8 +3120,8 @@ fn build_inner_router(api: WorkspaceApi) -> Router {
.route("/api/hosts", get(list_hosts))
.route("/api/w/{workspace_id}/hosts", get(scoped_list_hosts))
.route(
"/api/w/{workspace_id}/profile-source-archives/{digest}",
get(scoped_get_profile_source_archive),
"/api/w/{workspace_id}/runtime-config",
get(get_latest_workspace_runtime_config),
)
.route(
"/api/w/{workspace_id}/runtimes/{runtime_id}/working-directories",
@@ -3752,12 +3760,6 @@ struct ScopedRepositoryHostTrustPath {
host_trust_id: String,
}
#[derive(Debug, Deserialize)]
struct ScopedProfileArchivePath {
workspace_id: String,
digest: String,
}
#[derive(Debug, Deserialize)]
struct ScopedHostPath {
workspace_id: String,
@@ -8940,30 +8942,99 @@ async fn scoped_list_hosts(
list_hosts(State(api)).await
}
async fn scoped_get_profile_source_archive(
#[derive(Debug, Deserialize)]
struct LatestWorkspaceRuntimeConfigQuery {
profile: String,
}
async fn get_latest_workspace_runtime_config(
State(api): State<WorkspaceApi>,
AxumPath(path): AxumPath<ScopedProfileArchivePath>,
AxumPath(path): AxumPath<ScopedWorkspacePath>,
Query(query): Query<LatestWorkspaceRuntimeConfigQuery>,
headers: HeaderMap,
) -> ApiResult<(StatusCode, HeaderMap, Vec<u8>)> {
validate_workspace_scope(&api, &path.workspace_id)?;
let archive = api
.resource_broker
.profile_source_archive(&path.digest)
.ok_or_else(|| Error::Store("profile source archive not found".to_string()))?;
let etag = format!("\"profile-source:{}\"", archive.reference.digest);
source: Option<Extension<crate::worker_source::VerifiedRuntimeRequestSource>>,
) -> Response {
let Some(Extension(_source)) = source else {
return (
StatusCode::FORBIDDEN,
Json(serde_json::json!({ "error": "runtime_config_source_required" })),
)
.into_response();
};
if let Err(error) = validate_workspace_scope(&api, &path.workspace_id) {
return error.into_response();
}
let config_state = match api.config_store.load_workspace_config(&path.workspace_id) {
Ok(Some(config)) => config,
Ok(None) => {
return (
StatusCode::NOT_FOUND,
Json(serde_json::json!({ "error": "workspace_config_not_found" })),
)
.into_response();
}
Err(error) => return ApiError::from(error).into_response(),
};
let profile_projection = match crate::profile_settings::project_profiles_from_workspace_config(
&path.workspace_id,
&config_state,
) {
Ok(projection) => projection,
Err(error) => return ApiError::from(error).into_response(),
};
if crate::profile_settings::selector_for_workspace_candidate(
&profile_projection,
&query.profile,
)
.is_none()
{
return (
StatusCode::NOT_FOUND,
Json(serde_json::json!({ "error": "runtime_config_profile_not_found" })),
)
.into_response();
};
let prompt_catalog = match api
.prompt_projection_cache
.resolve(&path.workspace_id, &config_state)
{
Ok(catalog) => catalog,
Err(error) => return ApiError::from(error).into_response(),
};
let Some(bundle) =
(match crate::profile_settings::build_virtual_profile_config_bundle_with_prompt_projection(
&profile_projection,
&config_state,
&path.workspace_id,
&api.config.workspace_created_at,
&query.profile,
prompt_catalog.as_ref(),
) {
Ok(bundle) => bundle,
Err(error) => return ApiError::from(error).into_response(),
})
else {
return (
StatusCode::NOT_FOUND,
Json(serde_json::json!({ "error": "runtime_config_profile_not_found" })),
)
.into_response();
};
let etag = worker_runtime::config_bundle::workspace_config_etag(&bundle.metadata.digest);
let mut response_headers = HeaderMap::new();
response_headers.insert(ETAG, etag.parse().expect("Workspace Config ETag is valid"));
response_headers.insert(
CACHE_CONTROL,
"no-cache".parse().expect("valid cache policy"),
);
if headers
.get(IF_NONE_MATCH)
.and_then(|value| value.to_str().ok())
.is_some_and(|value| value.split(',').any(|candidate| candidate.trim() == etag))
{
let mut response_headers = HeaderMap::new();
response_headers.insert(ETAG, etag.parse().unwrap());
return Ok((StatusCode::NOT_MODIFIED, response_headers, Vec::new()));
return (StatusCode::NOT_MODIFIED, response_headers).into_response();
}
let mut response_headers = HeaderMap::new();
response_headers.insert(ETAG, etag.parse().unwrap());
response_headers.insert(CONTENT_TYPE, "application/x-tar".parse().unwrap());
Ok((StatusCode::OK, response_headers, archive.content))
(StatusCode::OK, response_headers, Json(bundle)).into_response()
}
async fn scoped_list_runtimes(
@@ -25846,42 +25917,39 @@ mod tests {
}
#[tokio::test]
async fn runtime_signed_profile_source_archive_fetch_uses_resource_permission() {
async fn runtime_fetches_latest_workspace_config_with_etag_revalidation() {
let workspace = tempfile::tempdir().unwrap();
init_clean_git_workspace(workspace.path());
let mut api = test_api(workspace.path()).await;
let identity =
worker_runtime::auth::RuntimeIdentityMaterial::generate("runtime-test").unwrap();
configure_runtime_request_auth(&mut api, &identity, "runtime-test");
let handle = api.resource_broker.issue_profile_source_archive_handle(
TEST_WORKSPACE_ID,
crate::resource_broker::BackendResourceTarget::Runtime("runtime-test"),
test_profile_archive(),
);
let path = format!(
"/api/w/{TEST_WORKSPACE_ID}/profile-source-archives/{}",
handle.digest
);
let proof = worker_runtime::auth::RuntimeRequestSourceSigner::from_identity(&identity)
.issue(
"server-test",
TEST_WORKSPACE_ID,
None,
worker_runtime::auth::BACKEND_RESOURCE_FETCH_PERMISSION,
"GET",
&path,
b"",
i64::try_from(worker_runtime::auth::unix_now_seconds()).unwrap_or(i64::MAX),
30,
)
.unwrap();
let response = build_router(api)
let target =
format!("/api/w/{TEST_WORKSPACE_ID}/runtime-config?profile=builtin%3Acompanion");
let issue = || {
worker_runtime::auth::RuntimeRequestSourceSigner::from_identity(&identity)
.issue(
"server-test",
TEST_WORKSPACE_ID,
None,
worker_runtime::auth::BACKEND_RESOURCE_FETCH_PERMISSION,
"GET",
&target,
b"",
i64::try_from(worker_runtime::auth::unix_now_seconds()).unwrap_or(i64::MAX),
30,
)
.unwrap()
};
let app = build_router(api);
let response = app
.clone()
.oneshot(
Request::builder()
.uri(path)
.uri(&target)
.header(
worker_runtime::auth::RUNTIME_REQUEST_SOURCE_PROOF_HEADER,
proof,
issue(),
)
.body(Body::empty())
.unwrap(),
@@ -25889,12 +25957,34 @@ mod tests {
.await
.unwrap();
assert_eq!(response.status(), StatusCode::OK);
let etag = response.headers().get(ETAG).unwrap().clone();
assert_eq!(response.headers().get(CACHE_CONTROL).unwrap(), "no-cache");
let bundle: worker_runtime::config_bundle::ConfigBundle =
serde_json::from_slice(&to_bytes(response.into_body(), usize::MAX).await.unwrap())
.unwrap();
assert!(bundle.profile_source_archive.is_some());
assert_eq!(
response.headers().get(ETAG).unwrap().to_str().unwrap(),
format!("\"profile-source:{}\"", handle.digest)
etag.to_str().unwrap(),
worker_runtime::config_bundle::workspace_config_etag(&bundle.metadata.digest)
);
let response = app
.oneshot(
Request::builder()
.uri(&target)
.header(
worker_runtime::auth::RUNTIME_REQUEST_SOURCE_PROOF_HEADER,
issue(),
)
.header(IF_NONE_MATCH, etag)
.body(Body::empty())
.unwrap(),
)
.await
.unwrap();
assert_eq!(response.status(), StatusCode::NOT_MODIFIED);
assert!(
!to_bytes(response.into_body(), usize::MAX)
to_bytes(response.into_body(), usize::MAX)
.await
.unwrap()
.is_empty()
@@ -25994,22 +26084,13 @@ mod tests {
"builtin:companion".to_string(),
),
display_name: None,
profile_source: worker_runtime::catalog::ProfileSourceArchiveSource::Http {
location: worker_runtime::catalog::ProfileSourceArchiveHttpRef {
url: "http://127.0.0.1/profile-source.tar".to_string(),
etag: None,
archive: worker_runtime::profile_archive::ProfileSourceArchiveRef {
id: "test-profile-source".to_string(),
digest: "test-digest".to_string(),
size_bytes: 0,
source_graph: worker_runtime::profile_archive::ProfileSourceGraphSummary {
source_count: 0,
total_source_bytes: 0,
entrypoints: std::collections::BTreeMap::new(),
import_count: 0,
},
},
},
profile_source: worker_runtime::catalog::ProfileSourceArchiveSource::Embedded {
archive: crate::profile_settings::builtin_profile_source_archive(
&worker_runtime::catalog::ProfileSelector::Builtin(
"builtin:default".to_string(),
),
)
.unwrap(),
},
config_bundle: Some(worker_runtime::catalog::ConfigBundleRef {
id: bundle.metadata.id,