OXYGENHUB
# a72abeeedd78 oxygenflow / crates / flow-core / src / api.rs
4.0 KiB · Rust · last changed Guest /dev/fd links; jobs are told what they build 1 month ago source blame history raw
e0918b88 Andy McCall 1
//! The runner API between OxygenHub and `flow runner` (docs/m0.md §5).
2
//! Both sides use these types, so they cannot drift.
3
4
use crate::pipeline::{Job, Sandbox};
5
use crate::receipt::Receipt;
6
use serde::{Deserialize, Serialize};
7
8
/// `POST /api/v1/flow/claim`.
9
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
10
pub struct ClaimRequest {
11
    /// The runner's name, shown on job pages.
12
    pub runner: String,
13
    /// Tiers this runner can run (`microvm`, `syscall`).
14
    pub runtimes: Vec<String>,
15
}
16
c23d5191 Andy McCall ↶ 17
/// A pinned subrepo to put in the workspace: `repo`'s state `heads`, at `path`.
18
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
19
pub struct SubrepoInput {
20
    pub path: String,
21
    /// `owner/name` on the hub.
22
    pub repo: String,
23
    pub clone_url: String,
24
    pub heads: Vec<String>,
25
}
26
e0918b88 Andy McCall 27
/// A claimed job: everything the runner needs, nothing more.
28
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
29
pub struct Claim {
30
    pub job_id: i64,
31
    pub run_id: i64,
32
    /// `owner/name`.
33
    pub repo: String,
34
    /// Where to fetch the repository from (`oxy` wire protocol).
35
    pub clone_url: String,
36
    /// Read access to this repository only, until the job finishes.
37
    pub token: String,
38
    /// The state to build, as full change hashes.
39
    pub heads: Vec<String>,
40
    /// Hex BLAKE3 of the canonical pipeline.
41
    pub pipeline_hash: String,
42
    pub job: Job,
43
    pub sandbox: Sandbox,
44
    /// The hub's limit for this job.
45
    pub timeout_s: u64,
c23d5191 Andy McCall ↶ 46
    /// Subrepos the state pins (Oxygen spec §7.8) that the job may read,
47
    /// fetched with the same token and written at their paths.
48
    #[serde(default, skip_serializing_if = "Vec::is_empty")]
49
    pub subrepos: Vec<SubrepoInput>,
c4285535 Andy McCall ↶ 50
    /// The state's hash on the hub (what checks are keyed by).
51
    #[serde(default, skip_serializing_if = "String::is_empty")]
52
    pub state: String,
53
    /// The bookmark the run is for.
54
    #[serde(default, skip_serializing_if = "String::is_empty")]
55
    pub bookmark: String,
56
    /// The run's number within its repository.
57
    #[serde(default)]
58
    pub run_number: i64,
59
}
60
61
impl Claim {
62
    /// What a job is told about what it builds (docs/m0.md §4):
63
    /// `FLOW_REPO`, `FLOW_STATE`, `FLOW_HEADS` (full hashes joined with
64
    /// `+`), `FLOW_BOOKMARK`, `FLOW_RUN` and `FLOW_JOB`. Unknown values are
65
    /// left out.
66
    pub fn flow_env(&self) -> Vec<(String, String)> {
67
        let mut v = vec![
68
            ("FLOW_REPO".to_string(), self.repo.clone()),
69
            ("FLOW_HEADS".to_string(), self.heads.join("+")),
70
            ("FLOW_JOB".to_string(), self.job.name.clone()),
71
        ];
72
        if !self.state.is_empty() {
73
            v.push(("FLOW_STATE".into(), self.state.clone()));
74
        }
75
        if !self.bookmark.is_empty() {
76
            v.push(("FLOW_BOOKMARK".into(), self.bookmark.clone()));
77
        }
78
        if self.run_number > 0 {
79
            v.push(("FLOW_RUN".into(), self.run_number.to_string()));
80
        }
81
        v
82
    }
e0918b88 Andy McCall 83
}
84
85
/// One line of output (docs/m0.md §2).
86
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
87
pub struct Record {
88
    /// Milliseconds since the job started.
89
    pub t: u64,
90
    /// `out`, `err`, `console` (the VM outside the job) or `flow` (the runner).
91
    pub stream: String,
92
    pub text: String,
93
}
94
95
/// `POST /api/v1/flow/jobs/{id}/log`.
96
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
97
pub struct LogBatch {
98
    pub records: Vec<Record>,
99
}
100
101
/// `POST /api/v1/flow/jobs/{id}/finish`.
102
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
103
pub struct Finish {
104
    /// The job's exit code; absent when the runner could not run it.
105
    pub exit_code: Option<i32>,
106
    pub duration_ms: u64,
107
    pub receipt: Option<Receipt>,
108
    /// Why the runner could not run the job (rootfs missing, VM failed).
109
    pub error: Option<String>,
110
}
111
112
/// Longest text of one record the hub keeps; longer lines are cut.
113
pub const MAX_RECORD_TEXT: usize = 16 * 1024;
114
/// Most records the hub keeps per job; later ones are dropped with a note.
115
pub const MAX_RECORDS: usize = 50_000;