Skip to content

Commit 3938124

Browse files
authored
Version portable snapshot content identity (#8195)
1 parent 09be4a6 commit 3938124

9 files changed

Lines changed: 608 additions & 76 deletions

File tree

src/core/agent_task_scheduler/mod.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1510,11 +1510,17 @@ mod committed_harvest_tests {
15101510
let content_hash =
15111511
crate::core::runner::workspace_content_hash(workspace.path(), &snapshot.sync_excludes)
15121512
.expect("content hash");
1513+
let content_hash_algorithm = crate::core::runner::workspace_content_hash_algorithm(
1514+
crate::core::runner::WORKSPACE_CONTENT_DEFAULT_PERMISSION_POLICY,
1515+
)
1516+
.expect("default content hash algorithm");
15131517
let lab = serde_json::json!({
15141518
"runner_id": "lab", "remote_workspace": path, "sync_mode": "snapshot", "status": "offloaded",
15151519
"source_snapshot": snapshot,
15161520
"workspace_verification": {
1517-
"schema": "homeboy/lab-workspace-verification/v1", "identity": "snapshot:provider-ready",
1521+
"schema": "homeboy/lab-workspace-verification/v2", "identity": "snapshot:provider-ready",
1522+
"content_hash_algorithm": content_hash_algorithm,
1523+
"permission_policy": crate::core::runner::WORKSPACE_CONTENT_DEFAULT_PERMISSION_POLICY,
15181524
"content_hash": content_hash, "sync_excludes": snapshot.sync_excludes,
15191525
"source_snapshot": snapshot,
15201526
"primary_workspace": { "identity": "snapshot:provider-ready", "remote_path": workspace.path().display().to_string() }

src/core/extension/trace/canonicality.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1265,6 +1265,10 @@ mod tests {
12651265
let workspace_content_hash =
12661266
crate::core::runner::workspace_content_hash(source.path(), &snapshot.sync_excludes)
12671267
.unwrap();
1268+
let content_hash_algorithm = crate::core::runner::workspace_content_hash_algorithm(
1269+
crate::core::runner::WORKSPACE_CONTENT_DEFAULT_PERMISSION_POLICY,
1270+
)
1271+
.unwrap();
12681272
let lab = serde_json::json!({
12691273
"runner_id": "homeboy-lab",
12701274
"remote_workspace": remote.path().display().to_string(),
@@ -1274,8 +1278,10 @@ mod tests {
12741278
"workspace_content_hash": workspace_content_hash,
12751279
"workspace_materialization_plan": { "identity": "workspace:verified" },
12761280
"workspace_verification": {
1277-
"schema": "homeboy/lab-workspace-verification/v1",
1281+
"schema": "homeboy/lab-workspace-verification/v2",
12781282
"identity": "workspace:verified",
1283+
"content_hash_algorithm": content_hash_algorithm,
1284+
"permission_policy": crate::core::runner::WORKSPACE_CONTENT_DEFAULT_PERMISSION_POLICY,
12791285
"content_hash": workspace_content_hash,
12801286
"sync_excludes": [".git", ".git/**"],
12811287
"source_snapshot": snapshot,

src/core/runner/lab/offload/metadata.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -588,19 +588,25 @@ pub(crate) fn attach_lab_workspace_metadata(
588588
) -> Result<()> {
589589
let source_snapshot = inputs.source_snapshot;
590590
let primary_workspace_plan = &inputs.primary_synced_workspace.materialization_plan;
591+
let permission_policy = crate::core::runner::WORKSPACE_CONTENT_DEFAULT_PERMISSION_POLICY;
591592
let content_hash = crate::core::runner::workspace_content_hash(
592593
Path::new(&source_snapshot.local_path.clone().unwrap_or_default()),
593594
&source_snapshot.sync_excludes,
594595
)?;
596+
let content_hash_algorithm =
597+
crate::core::runner::workspace_content_hash_algorithm(permission_policy)
598+
.expect("default workspace content permission policy is supported");
595599
lab_metadata["source_snapshot"] =
596600
serde_json::to_value(source_snapshot).unwrap_or(serde_json::json!(null));
597601
lab_metadata["workspace_content_hash"] = serde_json::json!(content_hash);
598602
lab_metadata["workspace_materialization_plan"] =
599603
serde_json::to_value(inputs.legacy_path_materialization_plan)
600604
.unwrap_or(serde_json::json!(null));
601605
lab_metadata["workspace_verification"] = serde_json::json!({
602-
"schema": "homeboy/lab-workspace-verification/v1",
606+
"schema": "homeboy/lab-workspace-verification/v2",
603607
"identity": primary_workspace_plan.identity,
608+
"content_hash_algorithm": content_hash_algorithm,
609+
"permission_policy": permission_policy,
604610
"content_hash": content_hash,
605611
"sync_excludes": source_snapshot.sync_excludes,
606612
"source_snapshot": source_snapshot,

src/core/runner/lab/offload/tests/capability_metadata.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,37 @@ fn lab_offload_workspace_verification_metadata_survives_process_env_hydration()
288288
serde_json::to_value(&synced_workspace.materialization_plan)
289289
.expect("primary sync plan JSON")
290290
);
291+
assert_eq!(
292+
metadata["workspace_verification"]["schema"],
293+
"homeboy/lab-workspace-verification/v2"
294+
);
295+
assert_eq!(
296+
metadata["workspace_verification"]["content_hash_algorithm"],
297+
crate::core::runner::workspace_content_hash_algorithm(
298+
crate::core::runner::WORKSPACE_CONTENT_DEFAULT_PERMISSION_POLICY,
299+
)
300+
.expect("default content hash algorithm")
301+
);
302+
assert_eq!(
303+
metadata["workspace_verification"]["permission_policy"],
304+
crate::core::runner::WORKSPACE_CONTENT_DEFAULT_PERMISSION_POLICY
305+
);
306+
assert!(metadata["workspace_verification"]
307+
.get("content_manifest")
308+
.is_none());
309+
assert!(metadata["workspace_verification"].get("entries").is_none());
310+
let serialized_metadata = serde_json::to_string(&metadata).expect("metadata JSON");
311+
assert!(!serialized_metadata.contains("README.md"));
312+
assert!(!serialized_metadata.contains("verified contents"));
313+
314+
std::fs::write(remote.path().join("README.md"), "changed contents\n")
315+
.expect("change remote file");
316+
let error = verify_lab_workspace_from_env(&remote_path.display().to_string(), remote.path())
317+
.expect_err("changed remote content must fail verification");
318+
assert!(error.contains("homeboy-workspace-content-v2+"));
319+
assert!(error.contains("expected sha256:"));
320+
assert!(error.contains("got sha256:"));
321+
assert!(error.contains("homeboy runner workspace sync --mode snapshot"));
291322

292323
match prior_lab {
293324
Some(value) => std::env::set_var(LAB_OFFLOAD_METADATA_ENV, value),

src/core/runner/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,8 @@ pub use workspace::{
171171
};
172172
pub(crate) use workspace::{
173173
verify_lab_workspace_from_env, verify_lab_workspace_git_root, workspace_content_hash,
174-
VerifiedLabWorkspaceProvenance,
174+
workspace_content_hash_algorithm, VerifiedLabWorkspaceProvenance,
175+
WORKSPACE_CONTENT_DEFAULT_PERMISSION_POLICY,
175176
};
176177

177178
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]

src/core/runner/workspace/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ pub(crate) use provenance::{
4646
pub(crate) use snapshot::{
4747
copy_snapshot_to_directory, effective_snapshot_excludes, local_snapshot_stats,
4848
materialize_snapshot, materialize_snapshot_git, snapshot_identity, workspace_content_hash,
49+
workspace_content_hash_algorithm, WORKSPACE_CONTENT_DEFAULT_PERMISSION_POLICY,
4950
};
5051
pub(crate) use types::{canonical_workspace_path, DEFAULT_EXCLUDES};
5152
pub(crate) use util::{

0 commit comments

Comments
 (0)