Skip to main content

snix_build/buildservice/
build_request.rs

1use std::collections::{BTreeMap, HashSet};
2use std::path::PathBuf;
3
4use bytes::Bytes;
5use snix_castore::{Node, PathComponent};
6
7/// A BuildRequest describes the request of something to be run on the builder.
8/// It is distinct from an actual \[Build\] that has already happened, or might be
9/// currently ongoing.
10///
11/// A BuildRequest can be seen as a more normalized version of a Derivation
12/// (parsed from A-Term), "writing out" some of the Nix-internal details about
13/// how e.g. environment variables in the build are set.
14///
15/// Nix has some impurities when building a Derivation, for example the --cores option
16/// ends up as an environment variable in the build, that's not part of the ATerm.
17///
18/// As of now, we serialize this into the BuildRequest, so builders can stay dumb.
19/// This might change in the future.
20///
21/// There's also a big difference when it comes to how inputs are modelled:
22///
23/// * Nix only uses store path (strings) to describe the inputs.
24///   As store paths can be input-addressed, a certain store path can contain
25///   different contents (as not all store paths are binary reproducible).
26///   This requires that for every input-addressed input, the builder has access
27///   to either the input's deriver (and needs to build it) or else a trusted
28///   source for the built input.
29///   to upload input-addressed paths, requiring the trusted users concept.
30/// * snix-build records a list of snix.castore.v1.Node as inputs.
31///   These map from the store path base name to their contents, relieving the
32///   builder from having to "trust" any input-addressed paths, contrary to Nix.
33///
34/// While this approach gives a better hermeticity, it has one downside:
35/// A BuildRequest can only be sent once the contents of all its inputs are known.
36///
37/// As of now, we're okay to accept this, but it prevents uploading an
38/// entirely-non-IFD subgraph of BuildRequests eagerly.
39#[derive(Default, Debug, Clone, PartialEq)]
40pub struct BuildRequest {
41    /// The list of all root nodes that should be visible in `inputs_dir` at the
42    /// time of the build.
43    /// As all references are content-addressed, no additional signatures are
44    /// needed to substitute / make these available in the build environment.
45    pub inputs: BTreeMap<PathComponent, Node>,
46    /// The command (and its args) executed as the build script.
47    /// In the case of a Nix derivation, this is usually
48    /// \["/path/to/some-bash/bin/bash", "-e", "/path/to/some/builder.sh"\].
49    pub command_args: Vec<String>,
50    /// The working dir of the command, relative to the build root.
51    /// "build", in the case of Nix.
52    /// This MUST be a clean relative path, without any ".", "..", or superfluous
53    /// slashes.
54    pub working_dir: String,
55    /// A list of "scratch" paths, relative to the build root.
56    /// These will be write-able during the build.
57    /// \[build, nix/store\] in the case of Nix.
58    /// These MUST be clean relative paths, without any ".", "..", or superfluous
59    /// slashes, and sorted.
60    pub scratch_paths: Vec<String>,
61    /// The path where the castore input nodes will be located at,
62    /// "nix/store" in case of Nix.
63    /// Builds might also write into here (Nix builds do that).
64    /// This MUST be a clean relative path, without any ".", "..", or superfluous
65    /// slashes.
66    pub inputs_dir: String,
67    /// The list of output paths the build is expected to produce,
68    /// relative to the root.
69    /// If the path is not produced, the build is considered to have failed.
70    /// These MUST be clean relative paths, without any ".", "..", or superfluous
71    /// slashes, and sorted.
72    pub outputs: Vec<String>,
73    /// The list of environment variables and their values that should be set
74    /// inside the build environment.
75    /// This includes both environment vars set inside the derivation, as well as
76    /// more "ephemeral" ones like NIX_BUILD_CORES, controlled by the `--cores`
77    /// CLI option of `nix-build`.
78    /// For now, we consume this as an option when turning a Derivation into a BuildRequest,
79    /// similar to how Nix has a `--cores` option.
80    /// We don't want to bleed these very nix-specific sandbox impl details into
81    /// (dumber) builders if we don't have to.
82    /// Environment variables are sorted by their keys.
83    pub environment_vars: Vec<EnvVar>,
84    /// A set of constraints that need to be satisfied on a build host before a
85    /// Build can be started.
86    pub constraints: HashSet<BuildConstraints>,
87    /// Additional (small) files and their contents that should be placed into the
88    /// build environment, but outside inputs_dir.
89    /// Used for passAsFile and structuredAttrs in Nix.
90    pub additional_files: Vec<AdditionalFile>,
91    /// If this is an non-empty list, all paths in `outputs` are scanned for these.
92    /// For Nix, `refscan_needles` would be populated with the nixbase32 hash parts of
93    /// every input store path and output store path. The latter is necessary to scan
94    /// for references between multi-output derivations.
95    pub refscan_needles: Vec<String>,
96}
97
98#[derive(Debug, Clone, PartialEq)]
99pub struct EnvVar {
100    /// name of the environment variable. Must not contain =.
101    pub key: String,
102    pub value: Bytes,
103}
104/// BuildConstraints represents certain conditions that must be fulfilled
105/// inside the build environment to be able to build this.
106/// Constraints can be things like required architecture and minimum amount of memory.
107/// The required input paths are *not* represented in here, because it
108/// wouldn't be hermetic enough - see the comment around inputs too.
109#[derive(Debug, Clone, PartialEq, Eq, Hash)]
110pub enum BuildConstraints {
111    /// The system that's needed to execute the build.
112    /// Must not be empty.
113    System(String),
114    /// The amount of memory required to be available for the build, in bytes.
115    MinMemory(u64),
116    /// An absolute path that need to be available in the build
117    /// environment, like `/dev/kvm`.
118    /// This is distinct from the castore nodes in inputs.
119    /// These MUST be clean absolute paths, without any ".", "..", or superfluous
120    /// slashes, and sorted.
121    AvailableReadOnlyPath(String),
122    /// Whether the build should be able to access the network.
123    NetworkAccess,
124    /// Whether to provide a /bin/sh inside the build environment, usually a static bash.
125    ProvideBinSh,
126}
127
128#[derive(Debug, Clone, PartialEq)]
129pub struct AdditionalFile {
130    pub path: PathBuf,
131    pub contents: Bytes,
132}