Update public bundle metadata contract
This commit is contained in:
parent
c4d8d94f49
commit
c4141e0dee
6 changed files with 204 additions and 5 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"kind": "disasmer-filtered-public-tree",
|
"kind": "disasmer-filtered-public-tree",
|
||||||
"source_commit": "3313653a3d00fcd3fa5613e12cde2f76ae9a8ad0",
|
"source_commit": "b2b2e4a1b7c94ccc39c4d8cdfca6e98928fe2185",
|
||||||
"release_name": "dryrun-3313653a3d00",
|
"release_name": "dryrun-b2b2e4a1b7c9",
|
||||||
"filtered_out": [
|
"filtered_out": [
|
||||||
"private/**",
|
"private/**",
|
||||||
"experiments/**",
|
"experiments/**",
|
||||||
|
|
|
||||||
|
|
@ -4316,8 +4316,11 @@ fn bundle_inspection(args: BundleInspectArgs, cwd: PathBuf) -> Result<BundleInsp
|
||||||
let identity_inputs = BundleIdentityInputs {
|
let identity_inputs = BundleIdentityInputs {
|
||||||
wasm_code: wasm_source_proxy_digest(&selected_inputs),
|
wasm_code: wasm_source_proxy_digest(&selected_inputs),
|
||||||
task_abi: task_abi_digest(&model),
|
task_abi: task_abi_digest(&model),
|
||||||
|
entrypoints: model.entrypoints.keys().cloned().collect(),
|
||||||
|
default_entrypoint: model.default_entrypoint.clone(),
|
||||||
environments: model.environments.clone(),
|
environments: model.environments.clone(),
|
||||||
source_provider_manifest: source_provider_manifest.digest.clone(),
|
source_provider_manifest: source_provider_manifest.digest.clone(),
|
||||||
|
source_transfer_policy: source_provider_manifest.transfer_policy.clone(),
|
||||||
selected_inputs,
|
selected_inputs,
|
||||||
};
|
};
|
||||||
let pre_schedule_diagnostics = pre_schedule_diagnostics(
|
let pre_schedule_diagnostics = pre_schedule_diagnostics(
|
||||||
|
|
@ -5951,12 +5954,18 @@ mod tests {
|
||||||
fn bundle_inspect_discovers_environments_selected_inputs_and_source_providers() {
|
fn bundle_inspect_discovers_environments_selected_inputs_and_source_providers() {
|
||||||
let temp = tempfile::tempdir().unwrap();
|
let temp = tempfile::tempdir().unwrap();
|
||||||
fs::create_dir_all(temp.path().join("envs/linux")).unwrap();
|
fs::create_dir_all(temp.path().join("envs/linux")).unwrap();
|
||||||
|
fs::create_dir_all(temp.path().join("envs/docker")).unwrap();
|
||||||
fs::create_dir_all(temp.path().join("src")).unwrap();
|
fs::create_dir_all(temp.path().join("src")).unwrap();
|
||||||
fs::write(
|
fs::write(
|
||||||
temp.path().join("envs/linux/Containerfile"),
|
temp.path().join("envs/linux/Containerfile"),
|
||||||
"FROM alpine\n",
|
"FROM alpine\n",
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
fs::write(
|
||||||
|
temp.path().join("envs/docker/Dockerfile"),
|
||||||
|
"FROM debian:stable-slim\n",
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
fs::write(temp.path().join("Cargo.toml"), "[package]\nname='demo'\n").unwrap();
|
fs::write(temp.path().join("Cargo.toml"), "[package]\nname='demo'\n").unwrap();
|
||||||
fs::write(temp.path().join("src/main.rs"), "fn main() {}\n").unwrap();
|
fs::write(temp.path().join("src/main.rs"), "fn main() {}\n").unwrap();
|
||||||
|
|
||||||
|
|
@ -6003,7 +6012,62 @@ mod tests {
|
||||||
.transfer_policy
|
.transfer_policy
|
||||||
.default_full_repo_tarball
|
.default_full_repo_tarball
|
||||||
);
|
);
|
||||||
assert_eq!(inspection.metadata.environments[0].name, "linux");
|
assert!(inspection
|
||||||
|
.metadata
|
||||||
|
.environments
|
||||||
|
.iter()
|
||||||
|
.any(|environment| environment.name == "linux"));
|
||||||
|
assert!(inspection
|
||||||
|
.metadata
|
||||||
|
.environments
|
||||||
|
.iter()
|
||||||
|
.any(|environment| environment.name == "docker"));
|
||||||
|
assert_eq!(
|
||||||
|
inspection.metadata.source_metadata.source_provider_manifest,
|
||||||
|
inspection.source_provider_manifest.digest
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
inspection
|
||||||
|
.metadata
|
||||||
|
.source_metadata
|
||||||
|
.transfer_policy
|
||||||
|
.local_source_bytes_remain_node_local
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
!inspection
|
||||||
|
.metadata
|
||||||
|
.source_metadata
|
||||||
|
.transfer_policy
|
||||||
|
.coordinator_receives_source_bytes_by_default
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
!inspection
|
||||||
|
.metadata
|
||||||
|
.source_metadata
|
||||||
|
.transfer_policy
|
||||||
|
.default_full_repo_tarball
|
||||||
|
);
|
||||||
|
assert!(inspection
|
||||||
|
.metadata
|
||||||
|
.task_metadata
|
||||||
|
.entrypoints
|
||||||
|
.contains(&"build".to_owned()));
|
||||||
|
assert_eq!(
|
||||||
|
inspection.metadata.task_metadata.default_entrypoint,
|
||||||
|
"build"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
inspection.metadata.task_metadata.task_abi,
|
||||||
|
task_abi_digest(&ProjectModel::discover_without_config(temp.path()).unwrap())
|
||||||
|
);
|
||||||
|
assert!(inspection
|
||||||
|
.metadata
|
||||||
|
.wasm_code
|
||||||
|
.as_str()
|
||||||
|
.starts_with("sha256:"));
|
||||||
|
assert!(inspection.metadata.debug_metadata.available);
|
||||||
|
assert!(inspection.metadata.debug_metadata.source_level_breakpoints);
|
||||||
|
assert!(inspection.metadata.debug_metadata.variables_pane_supported);
|
||||||
assert!(!inspection.metadata.embeds_full_container_images);
|
assert!(!inspection.metadata.embeds_full_container_images);
|
||||||
assert!(inspection
|
assert!(inspection
|
||||||
.metadata
|
.metadata
|
||||||
|
|
@ -7567,6 +7631,33 @@ mod tests {
|
||||||
.as_str()
|
.as_str()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.starts_with("sha256:"));
|
.starts_with("sha256:"));
|
||||||
|
assert!(report["bundle"]["metadata"]["wasm_code"]
|
||||||
|
.as_str()
|
||||||
|
.unwrap()
|
||||||
|
.starts_with("sha256:"));
|
||||||
|
assert_eq!(
|
||||||
|
report["bundle"]["metadata"]["task_metadata"]["default_entrypoint"],
|
||||||
|
"build"
|
||||||
|
);
|
||||||
|
assert!(report["bundle"]["metadata"]["task_metadata"]["entrypoints"]
|
||||||
|
.as_array()
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.any(|entrypoint| entrypoint == "release"));
|
||||||
|
assert_eq!(
|
||||||
|
report["bundle"]["metadata"]["source_metadata"]["transfer_policy"]
|
||||||
|
["coordinator_receives_source_bytes_by_default"],
|
||||||
|
false
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
report["bundle"]["metadata"]["source_metadata"]["transfer_policy"]
|
||||||
|
["default_full_repo_tarball"],
|
||||||
|
false
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
report["bundle"]["metadata"]["debug_metadata"]["dap_virtual_process"],
|
||||||
|
true
|
||||||
|
);
|
||||||
assert_eq!(report["status"], "built");
|
assert_eq!(report["status"], "built");
|
||||||
assert_eq!(report["scheduled_work"], false);
|
assert_eq!(report["scheduled_work"], false);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{Digest, EnvironmentResource};
|
use crate::{Digest, EnvironmentResource, SourceTransferPolicy};
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct SelectedInput {
|
pub struct SelectedInput {
|
||||||
|
|
@ -12,19 +12,49 @@ pub struct SelectedInput {
|
||||||
pub struct BundleIdentityInputs {
|
pub struct BundleIdentityInputs {
|
||||||
pub wasm_code: Digest,
|
pub wasm_code: Digest,
|
||||||
pub task_abi: Digest,
|
pub task_abi: Digest,
|
||||||
|
pub entrypoints: Vec<String>,
|
||||||
|
pub default_entrypoint: String,
|
||||||
pub environments: Vec<EnvironmentResource>,
|
pub environments: Vec<EnvironmentResource>,
|
||||||
pub source_provider_manifest: Digest,
|
pub source_provider_manifest: Digest,
|
||||||
|
pub source_transfer_policy: SourceTransferPolicy,
|
||||||
pub selected_inputs: Vec<SelectedInput>,
|
pub selected_inputs: Vec<SelectedInput>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct BundleMetadata {
|
pub struct BundleMetadata {
|
||||||
pub identity: Digest,
|
pub identity: Digest,
|
||||||
|
pub wasm_code: Digest,
|
||||||
|
pub task_metadata: BundleTaskMetadata,
|
||||||
|
pub source_metadata: BundleSourceMetadata,
|
||||||
|
pub debug_metadata: BundleDebugMetadata,
|
||||||
pub environments: Vec<EnvironmentResource>,
|
pub environments: Vec<EnvironmentResource>,
|
||||||
pub selected_inputs: Vec<SelectedInput>,
|
pub selected_inputs: Vec<SelectedInput>,
|
||||||
pub embeds_full_container_images: bool,
|
pub embeds_full_container_images: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub struct BundleTaskMetadata {
|
||||||
|
pub task_abi: Digest,
|
||||||
|
pub entrypoints: Vec<String>,
|
||||||
|
pub default_entrypoint: String,
|
||||||
|
pub boundary: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub struct BundleSourceMetadata {
|
||||||
|
pub source_provider_manifest: Digest,
|
||||||
|
pub transfer_policy: SourceTransferPolicy,
|
||||||
|
pub selected_inputs: Vec<SelectedInput>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub struct BundleDebugMetadata {
|
||||||
|
pub available: bool,
|
||||||
|
pub source_level_breakpoints: bool,
|
||||||
|
pub dap_virtual_process: bool,
|
||||||
|
pub variables_pane_supported: bool,
|
||||||
|
}
|
||||||
|
|
||||||
impl BundleIdentityInputs {
|
impl BundleIdentityInputs {
|
||||||
pub fn identity(&self) -> Digest {
|
pub fn identity(&self) -> Digest {
|
||||||
let mut parts = vec![
|
let mut parts = vec![
|
||||||
|
|
@ -32,8 +62,16 @@ impl BundleIdentityInputs {
|
||||||
self.wasm_code.as_str().as_bytes().to_vec(),
|
self.wasm_code.as_str().as_bytes().to_vec(),
|
||||||
self.task_abi.as_str().as_bytes().to_vec(),
|
self.task_abi.as_str().as_bytes().to_vec(),
|
||||||
self.source_provider_manifest.as_str().as_bytes().to_vec(),
|
self.source_provider_manifest.as_str().as_bytes().to_vec(),
|
||||||
|
self.default_entrypoint.as_bytes().to_vec(),
|
||||||
|
format!("{:?}", self.source_transfer_policy).into_bytes(),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
let mut entrypoints = self.entrypoints.clone();
|
||||||
|
entrypoints.sort();
|
||||||
|
for entrypoint in entrypoints {
|
||||||
|
parts.push(entrypoint.into_bytes());
|
||||||
|
}
|
||||||
|
|
||||||
let mut environments = self.environments.clone();
|
let mut environments = self.environments.clone();
|
||||||
environments.sort_by(|left, right| left.name.cmp(&right.name));
|
environments.sort_by(|left, right| left.name.cmp(&right.name));
|
||||||
for environment in environments {
|
for environment in environments {
|
||||||
|
|
@ -53,8 +91,29 @@ impl BundleIdentityInputs {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn inspectable_metadata(&self) -> BundleMetadata {
|
pub fn inspectable_metadata(&self) -> BundleMetadata {
|
||||||
|
let mut entrypoints = self.entrypoints.clone();
|
||||||
|
entrypoints.sort();
|
||||||
|
|
||||||
BundleMetadata {
|
BundleMetadata {
|
||||||
identity: self.identity(),
|
identity: self.identity(),
|
||||||
|
wasm_code: self.wasm_code.clone(),
|
||||||
|
task_metadata: BundleTaskMetadata {
|
||||||
|
task_abi: self.task_abi.clone(),
|
||||||
|
entrypoints,
|
||||||
|
default_entrypoint: self.default_entrypoint.clone(),
|
||||||
|
boundary: "disasmer_task_exports".to_owned(),
|
||||||
|
},
|
||||||
|
source_metadata: BundleSourceMetadata {
|
||||||
|
source_provider_manifest: self.source_provider_manifest.clone(),
|
||||||
|
transfer_policy: self.source_transfer_policy.clone(),
|
||||||
|
selected_inputs: self.selected_inputs.clone(),
|
||||||
|
},
|
||||||
|
debug_metadata: BundleDebugMetadata {
|
||||||
|
available: true,
|
||||||
|
source_level_breakpoints: true,
|
||||||
|
dap_virtual_process: true,
|
||||||
|
variables_pane_supported: true,
|
||||||
|
},
|
||||||
environments: self.environments.clone(),
|
environments: self.environments.clone(),
|
||||||
selected_inputs: self.selected_inputs.clone(),
|
selected_inputs: self.selected_inputs.clone(),
|
||||||
embeds_full_container_images: false,
|
embeds_full_container_images: false,
|
||||||
|
|
@ -86,8 +145,11 @@ mod tests {
|
||||||
let base = BundleIdentityInputs {
|
let base = BundleIdentityInputs {
|
||||||
wasm_code: Digest::sha256("wasm"),
|
wasm_code: Digest::sha256("wasm"),
|
||||||
task_abi: Digest::sha256("abi"),
|
task_abi: Digest::sha256("abi"),
|
||||||
|
entrypoints: vec!["build".to_owned()],
|
||||||
|
default_entrypoint: "build".to_owned(),
|
||||||
environments: vec![env("recipe-a")],
|
environments: vec![env("recipe-a")],
|
||||||
source_provider_manifest: Digest::sha256("source"),
|
source_provider_manifest: Digest::sha256("source"),
|
||||||
|
source_transfer_policy: SourceTransferPolicy::local_first_snapshot_chunks(),
|
||||||
selected_inputs: vec![],
|
selected_inputs: vec![],
|
||||||
};
|
};
|
||||||
let mut changed = base.clone();
|
let mut changed = base.clone();
|
||||||
|
|
@ -101,8 +163,11 @@ mod tests {
|
||||||
let inputs = BundleIdentityInputs {
|
let inputs = BundleIdentityInputs {
|
||||||
wasm_code: Digest::sha256("wasm"),
|
wasm_code: Digest::sha256("wasm"),
|
||||||
task_abi: Digest::sha256("abi"),
|
task_abi: Digest::sha256("abi"),
|
||||||
|
entrypoints: vec!["build".to_owned(), "test".to_owned()],
|
||||||
|
default_entrypoint: "build".to_owned(),
|
||||||
environments: vec![env("recipe")],
|
environments: vec![env("recipe")],
|
||||||
source_provider_manifest: Digest::sha256("source"),
|
source_provider_manifest: Digest::sha256("source"),
|
||||||
|
source_transfer_policy: SourceTransferPolicy::local_first_snapshot_chunks(),
|
||||||
selected_inputs: vec![SelectedInput {
|
selected_inputs: vec![SelectedInput {
|
||||||
path: "inputs/config.json".to_owned(),
|
path: "inputs/config.json".to_owned(),
|
||||||
digest: Digest::sha256("config"),
|
digest: Digest::sha256("config"),
|
||||||
|
|
@ -111,6 +176,19 @@ mod tests {
|
||||||
|
|
||||||
let metadata = inputs.inspectable_metadata();
|
let metadata = inputs.inspectable_metadata();
|
||||||
|
|
||||||
|
assert!(metadata.wasm_code.as_str().starts_with("sha256:"));
|
||||||
|
assert_eq!(metadata.task_metadata.default_entrypoint, "build");
|
||||||
|
assert!(metadata
|
||||||
|
.task_metadata
|
||||||
|
.entrypoints
|
||||||
|
.contains(&"test".to_owned()));
|
||||||
|
assert!(metadata.debug_metadata.dap_virtual_process);
|
||||||
|
assert!(
|
||||||
|
metadata
|
||||||
|
.source_metadata
|
||||||
|
.transfer_policy
|
||||||
|
.local_source_bytes_remain_node_local
|
||||||
|
);
|
||||||
assert_eq!(metadata.environments.len(), 1);
|
assert_eq!(metadata.environments.len(), 1);
|
||||||
assert!(!metadata.embeds_full_container_images);
|
assert!(!metadata.embeds_full_container_images);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,10 @@ pub use auth::{
|
||||||
CliLoginFlow, CredentialKind, EnrollmentError, EnrollmentGrant, IdentityKind, NodeCredential,
|
CliLoginFlow, CredentialKind, EnrollmentError, EnrollmentGrant, IdentityKind, NodeCredential,
|
||||||
PublicKeyIdentity, Scope,
|
PublicKeyIdentity, Scope,
|
||||||
};
|
};
|
||||||
pub use bundle::{BundleIdentityInputs, BundleMetadata, SelectedInput};
|
pub use bundle::{
|
||||||
|
BundleDebugMetadata, BundleIdentityInputs, BundleMetadata, BundleSourceMetadata,
|
||||||
|
BundleTaskMetadata, SelectedInput,
|
||||||
|
};
|
||||||
pub use capability::{Capability, CapabilityReportError, EnvironmentBackend, NodeCapabilities, Os};
|
pub use capability::{Capability, CapabilityReportError, EnvironmentBackend, NodeCapabilities, Os};
|
||||||
pub use checkpoint::{
|
pub use checkpoint::{
|
||||||
CheckpointBoundary, CompatibilityFailure, RestartDecision, RestartPolicy, RestartRequest,
|
CheckpointBoundary, CompatibilityFailure, RestartDecision, RestartPolicy, RestartRequest,
|
||||||
|
|
|
||||||
|
|
@ -376,6 +376,21 @@ expect(
|
||||||
"CLI exposes environment pre-schedule diagnostics",
|
"CLI exposes environment pre-schedule diagnostics",
|
||||||
/environment_diagnostics_for_inputs[\s\S]*diagnose_environment_references[\s\S]*missing_environment/
|
/environment_diagnostics_for_inputs[\s\S]*diagnose_environment_references[\s\S]*missing_environment/
|
||||||
);
|
);
|
||||||
|
expect(
|
||||||
|
cli,
|
||||||
|
"CLI bundle metadata exposes MVP build facets",
|
||||||
|
/BundleIdentityInputs[\s\S]*entrypoints[\s\S]*default_entrypoint[\s\S]*source_transfer_policy[\s\S]*wasm_source_proxy_digest[\s\S]*task_abi_digest/
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
cli,
|
||||||
|
"CLI bundle coverage verifies Dockerfile and debug metadata",
|
||||||
|
/fn bundle_inspect_discovers_environments_selected_inputs_and_source_providers\(\)[\s\S]*envs\/docker\/Dockerfile[\s\S]*task_metadata[\s\S]*source_metadata[\s\S]*debug_metadata/
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
cli,
|
||||||
|
"CLI build coverage verifies inspectable metadata",
|
||||||
|
/fn build_command_reuses_bundle_inspection_without_full_repo_upload\(\)[\s\S]*wasm_code[\s\S]*task_metadata[\s\S]*source_metadata[\s\S]*debug_metadata/
|
||||||
|
);
|
||||||
expect(
|
expect(
|
||||||
cli,
|
cli,
|
||||||
"CLI blocks build before scheduling unsafe inputs",
|
"CLI blocks build before scheduling unsafe inputs",
|
||||||
|
|
|
||||||
|
|
@ -89,5 +89,17 @@ assertHuman("bundle inspect", inspectHuman, [
|
||||||
const inspectJson = json(["bundle", "inspect", "--project", project, "--json"]);
|
const inspectJson = json(["bundle", "inspect", "--project", project, "--json"]);
|
||||||
assert.strictEqual(inspectJson.project, project);
|
assert.strictEqual(inspectJson.project, project);
|
||||||
assert.match(inspectJson.metadata.identity, /^sha256:/);
|
assert.match(inspectJson.metadata.identity, /^sha256:/);
|
||||||
|
assert.match(inspectJson.metadata.wasm_code, /^sha256:/);
|
||||||
|
assert.strictEqual(inspectJson.metadata.task_metadata.default_entrypoint, "build");
|
||||||
|
assert(inspectJson.metadata.task_metadata.entrypoints.includes("release"));
|
||||||
|
assert.strictEqual(
|
||||||
|
inspectJson.metadata.source_metadata.transfer_policy.coordinator_receives_source_bytes_by_default,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
assert.strictEqual(
|
||||||
|
inspectJson.metadata.source_metadata.transfer_policy.default_full_repo_tarball,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
assert.strictEqual(inspectJson.metadata.debug_metadata.dap_virtual_process, true);
|
||||||
|
|
||||||
console.log("CLI output mode smoke passed");
|
console.log("CLI output mode smoke passed");
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue