Skip to main content

hm_plugin_protocol/
executor.rs

1//! Wire types passed to and returned by step-executor plugins.
2
3use std::collections::BTreeMap;
4
5use schemars::JsonSchema as DeriveJsonSchema;
6use serde::{Deserialize, Serialize};
7use uuid::Uuid;
8
9use crate::ir::CommandStep;
10
11/// Opaque archive handle. The plugin streams bytes via
12/// `hm_archive_read(id, offset, max)`.
13#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, DeriveJsonSchema)]
14#[serde(transparent)]
15pub struct ArchiveId(pub Uuid);
16
17/// Opaque snapshot reference. For the docker plugin this is an image
18/// tag; other plugins are free to encode their own format. The host
19/// never inspects the contents.
20#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, DeriveJsonSchema)]
21#[serde(transparent)]
22pub struct SnapshotRef(pub String);
23
24#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, DeriveJsonSchema)]
25pub struct ArtifactRef {
26    pub key: String,
27    pub mime: String,
28    pub size_bytes: u64,
29}
30
31/// Host-decided cache outcome. The executor honours this; it does
32/// not re-decide.
33#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, DeriveJsonSchema)]
34#[serde(tag = "kind", rename_all = "snake_case")]
35pub enum CacheDecision {
36    /// Boot from `tag`; skip running `cmd`.
37    Hit { tag: SnapshotRef },
38    /// Run `cmd`; on success, commit to `tag` and report it back in
39    /// `StepResult::committed_snapshot`.
40    MissBuildAs { tag: SnapshotRef },
41    /// Run `cmd`; do not commit.
42    MissNoCommit,
43}
44
45#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, DeriveJsonSchema)]
46#[serde(deny_unknown_fields)]
47pub struct ExecutorInput {
48    pub step: CommandStep,
49    pub workspace_archive_id: ArchiveId,
50    pub env: BTreeMap<String, String>,
51    pub workdir: String,
52    pub run_id: Uuid,
53    pub step_id: Uuid,
54    /// Host-decided; see [`CacheDecision`]. Every step has one.
55    pub cache_lookup: CacheDecision,
56
57    /// Snapshot tag of the upstream step in this chain (if any),
58    /// or of the chain-fork parent. When `Some`, the executor must
59    /// boot from this tag rather than `step.image` — that's how
60    /// chain-stepwise filesystem inheritance works: the orchestrator
61    /// commits a snapshot between steps and the next step boots from
62    /// it.
63    #[serde(default)]
64    pub parent_snapshot: Option<SnapshotRef>,
65}
66
67#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, DeriveJsonSchema)]
68pub struct StepResult {
69    pub exit_code: i32,
70    /// `Some(tag)` when the executor wrote a snapshot for this step
71    /// (typically only on `CacheDecision::MissBuildAs`).
72    pub committed_snapshot: Option<SnapshotRef>,
73    pub artifacts: Vec<ArtifactRef>,
74}