Skip to main content

snix_build/buildservice/
mod.rs

1use auto_impl::auto_impl;
2use futures::stream::BoxStream;
3
4pub mod build_request;
5pub use crate::buildservice::build_request::*;
6mod dummy;
7mod from_addr;
8mod grpc;
9
10#[cfg(target_os = "linux")]
11mod oci;
12
13#[cfg(target_os = "linux")]
14mod bwrap;
15
16pub mod streaming;
17
18pub use dummy::DummyBuildService;
19pub use from_addr::from_addr;
20
21pub enum BuildUpdate {
22    ProducedOutput {
23        /// The contents of this output
24        node: snix_castore::Node,
25
26        /// Specifies which output is being sent, indexing into [BuildRequest::outputs].
27        idx: u64,
28
29        /// Indexes into the found [BuildRequest::refscan_needles] in this output.
30        refscan_needles: std::collections::BTreeSet<u64>,
31    },
32
33    // The build produced output on stdout.
34    ProducedStdout(Vec<u8>),
35
36    // The build produced output on stderr.
37    ProducedStderr(Vec<u8>),
38
39    // The build failed.
40    BuildFailure(BuildFailure),
41}
42
43impl From<BuildFailure> for BuildUpdate {
44    fn from(value: BuildFailure) -> Self {
45        Self::BuildFailure(value)
46    }
47}
48
49#[derive(thiserror::Error, Debug)]
50pub enum BuildFailure {
51    #[error("nonzero exit code")]
52    NonzeroExitCode,
53    #[error("not all outputs produced, missing: {}", .output)]
54    MissingOutput { output: String },
55    #[error("other error: {}", .message)]
56    Other { message: String },
57}
58
59impl From<std::io::Error> for BuildFailure {
60    fn from(err: std::io::Error) -> Self {
61        Self::Other {
62            message: err.to_string(),
63        }
64    }
65}
66
67impl From<anyhow::Error> for BuildFailure {
68    fn from(err: anyhow::Error) -> Self {
69        Self::Other {
70            message: err.to_string(),
71        }
72    }
73}
74
75impl From<tonic::Status> for BuildFailure {
76    fn from(value: tonic::Status) -> Self {
77        Self::Other {
78            message: format!("Tonic status: {value}"),
79        }
80    }
81}
82
83impl From<tokio::sync::AcquireError> for BuildFailure {
84    fn from(err: tokio::sync::AcquireError) -> Self {
85        Self::Other {
86            message: format!("failed to acquire semaphore: {err}"),
87        }
88    }
89}
90
91impl<E: std::fmt::Display> From<snix_castore::import::IngestionError<E>> for BuildFailure {
92    fn from(err: snix_castore::import::IngestionError<E>) -> Self {
93        Self::Other {
94            message: format!("Unable to ingest output: {err}"),
95        }
96    }
97}
98
99#[auto_impl(&, &mut, Arc, Box)]
100pub trait BuildService: Send + Sync {
101    // TODO: document
102    fn do_build(&self, request: BuildRequest) -> BoxStream<'_, BuildUpdate>;
103}