Skip to content

Commit 534790f

Browse files
committed
Auto merge of #376 - pietroalbini:crates-build-env, r=pietroalbini
Switch build environment to rustops/crates-build-env This PR switches the build environment used by Crater to the Docker image built in the [rust-ops/crates-build-env](https://github.com/rust-ops/crates-build-env) repository. Instead of installing GTK and all the suggested stuff and hoping for the best, the new image installs a curated set of packages built over time by the docs.rs developers (thanks @onur!) which weights about 3GB (1GB compressed download). The image is also downloaded from Docker Hub instead of being built locally, and it's automatically updated every time a run is started. This also means `prepare-local` is no longer needed if you only want to execute a run (creating new ones still requires the command). This PR also removes the distinction between the mini and the full images, since the new image has a reasonable size for local development and it's prebuilt.
2 parents f739aa5 + 5f76a0e commit 534790f

File tree

13 files changed

+157
-136
lines changed

13 files changed

+157
-136
lines changed

ci/run/minicrater-linux.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
set -euo pipefail
33
IFS=$'\n\t'
44

5-
cargo run -- prepare-local --docker-env=mini
5+
cargo run -- create-lists
66
MINICRATER_SHOW_OUTPUT=1 cargo test -- --ignored --nocapture --test-threads 1

docker/Dockerfile.full

Lines changed: 0 additions & 29 deletions
This file was deleted.

docker/Dockerfile.mini

Lines changed: 0 additions & 27 deletions
This file was deleted.

docker/run2.sh

Lines changed: 0 additions & 9 deletions
This file was deleted.

docs/cli-usage.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ of its output is into the `./work` directory, where it maintains its
1010
own rustup installation, crate mirrors, etc.
1111

1212
```
13-
cargo run -- prepare-local --docker-env mini
13+
cargo run -- prepare-local
1414
cargo run -- define-ex --crate-select=demo --cap-lints=forbid stable beta
1515
cargo run -- run-graph --threads NUM_CPUS
1616
cargo run -- gen-report work/ex/default/

src/agent/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,15 @@ fn run_heartbeat(url: &str, token: &str) {
4747
});
4848
}
4949

50-
pub fn run(url: &str, token: &str, threads_count: usize) -> Fallible<()> {
50+
pub fn run(url: &str, token: &str, threads_count: usize, docker_env: &str) -> Fallible<()> {
5151
let agent = Agent::new(url, token)?;
5252
let db = results::ResultsUploader::new(&agent.api);
5353

5454
run_heartbeat(url, token);
5555

5656
loop {
5757
let ex = agent.experiment()?;
58-
::runner::run_ex(&ex, &db, threads_count, &agent.config)?;
58+
::runner::run_ex(&ex, &db, threads_count, &agent.config, docker_env)?;
5959
agent.api.complete_experiment()?;
6060
}
6161
}

src/cli.rs

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ use crater::agent;
1414
use crater::config::Config;
1515
use crater::crates::Crate;
1616
use crater::db::Database;
17-
use crater::docker;
1817
use crater::experiments::{Assignee, CapLints, CrateSelect, Experiment, Mode, Status};
1918
use crater::report;
2019
use crater::results::{DatabaseDB, DeleteResults};
@@ -27,6 +26,8 @@ use std::path::PathBuf;
2726
use std::str::FromStr;
2827
use structopt::clap::AppSettings;
2928

29+
static DEFAULT_DOCKER_ENV: &str = "rustops/crates-build-env";
30+
3031
// An experiment name
3132
#[derive(Debug, Clone)]
3233
pub struct Ex(String);
@@ -75,10 +76,7 @@ pub enum Crater {
7576
name = "prepare-local",
7677
about = "acquire toolchains, build containers, build crate lists"
7778
)]
78-
PrepareLocal {
79-
#[structopt(name = "docker env", long = "docker-env", default_value = "full")]
80-
env: DockerEnv,
81-
},
79+
PrepareLocal,
8280

8381
#[structopt(name = "create-lists", about = "create all the lists of crates")]
8482
CreateLists {
@@ -189,6 +187,8 @@ pub enum Crater {
189187
ex: Ex,
190188
#[structopt(name = "threads", short = "t", long = "threads", default_value = "1")]
191189
threads: usize,
190+
#[structopt(name = "docker-env", long = "docker-env")]
191+
docker_env: Option<String>,
192192
},
193193

194194
#[structopt(name = "gen-report", about = "generate the experiment report")]
@@ -227,6 +227,8 @@ pub enum Crater {
227227
token: String,
228228
#[structopt(name = "threads", short = "t", long = "threads", default_value = "1")]
229229
threads: usize,
230+
#[structopt(name = "docker-env", long = "docker-env")]
231+
docker_env: Option<String>,
230232
},
231233

232234
#[structopt(
@@ -275,12 +277,9 @@ impl Crater {
275277
action.apply(&db, &config)?;
276278
}
277279
}
278-
Crater::PrepareLocal { ref env } => {
280+
Crater::PrepareLocal => {
279281
let config = Config::load()?;
280282
let db = Database::open()?;
281-
282-
let docker_env = &env.0;
283-
docker::build_container(docker_env)?;
284283
actions::UpdateLists::default().apply(&db, &config)?;
285284
}
286285
Crater::DefineEx {
@@ -367,7 +366,15 @@ impl Crater {
367366
bail!("missing experiment {}", ex.0);
368367
}
369368
}
370-
Crater::RunGraph { ref ex, threads } => {
369+
Crater::RunGraph {
370+
ref ex,
371+
threads,
372+
ref docker_env,
373+
} => {
374+
let docker_env = docker_env
375+
.as_ref()
376+
.map(|e| e.as_str())
377+
.unwrap_or(DEFAULT_DOCKER_ENV);
371378
let config = Config::load()?;
372379
let db = Database::open()?;
373380

@@ -387,7 +394,7 @@ impl Crater {
387394
}
388395

389396
let result_db = DatabaseDB::new(&db);
390-
runner::run_ex(&experiment, &result_db, threads, &config)?;
397+
runner::run_ex(&experiment, &result_db, threads, &config, docker_env)?;
391398
experiment.set_status(&db, Status::NeedsReport)?;
392399
} else {
393400
bail!("missing experiment {}", ex.0);
@@ -481,8 +488,13 @@ impl Crater {
481488
ref url,
482489
ref token,
483490
threads,
491+
ref docker_env,
484492
} => {
485-
agent::run(url, token, threads)?;
493+
let docker_env = docker_env
494+
.as_ref()
495+
.map(|e| e.as_str())
496+
.unwrap_or(DEFAULT_DOCKER_ENV);
497+
agent::run(url, token, threads, docker_env)?;
486498
}
487499
Crater::DumpTasksGraph { ref dest, ref ex } => {
488500
let config = Config::load()?;

src/docker.rs

Lines changed: 70 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,51 @@ use std::fs;
66
use std::path::{Path, PathBuf};
77
use utils::size::Size;
88

9-
pub(crate) static IMAGE_NAME: &'static str = "crater";
10-
11-
/// Builds the docker container image, 'crater', what will be used
12-
/// to isolate builds from each other. This expects the Dockerfile
13-
/// to exist in the `docker` directory, at runtime.
14-
pub fn build_container(docker_env: &str) -> Fallible<()> {
15-
let dockerfile = format!("docker/Dockerfile.{}", docker_env);
9+
pub(crate) fn is_running() -> bool {
10+
info!("checking if the docker daemon is running");
1611
RunCommand::new("docker")
17-
.args(&["build", "-f", &dockerfile, "-t", IMAGE_NAME, "docker"])
18-
.enable_timeout(false)
12+
.args(&["info"])
13+
.hide_output(true)
1914
.run()
15+
.is_ok()
2016
}
2117

22-
pub(crate) fn is_running() -> bool {
23-
RunCommand::new("docker").args(&["info"]).run().is_ok()
18+
pub(crate) struct DockerEnv {
19+
image: String,
20+
local: bool,
21+
}
22+
23+
impl DockerEnv {
24+
pub(crate) fn new(image: &str) -> Self {
25+
DockerEnv {
26+
image: image.to_string(),
27+
local: !image.contains('/'),
28+
}
29+
}
30+
31+
pub(crate) fn ensure_exists_locally(&self) -> Fallible<()> {
32+
if !self.local {
33+
self.pull()?;
34+
} else {
35+
info!("docker environment is local, skipping pull");
36+
}
37+
38+
info!("checking the image {} is available locally", self.image);
39+
RunCommand::new("docker")
40+
.args(&["image", "inspect", &self.image])
41+
.hide_output(true)
42+
.run()?;
43+
44+
Ok(())
45+
}
46+
47+
fn pull(&self) -> Fallible<()> {
48+
info!("pulling image {} from Docker Hub", self.image);
49+
RunCommand::new("docker")
50+
.args(&["pull", &self.image])
51+
.enable_timeout(false)
52+
.run()
53+
}
2454
}
2555

2656
#[derive(Copy, Clone)]
@@ -50,21 +80,25 @@ impl MountConfig {
5080
}
5181
}
5282

53-
pub(crate) struct ContainerBuilder {
54-
image: String,
83+
pub(crate) struct ContainerBuilder<'a> {
84+
image: &'a DockerEnv,
5585
mounts: Vec<MountConfig>,
5686
env: Vec<(String, String)>,
5787
memory_limit: Option<Size>,
88+
workdir: Option<String>,
89+
cmd: Vec<String>,
5890
enable_networking: bool,
5991
}
6092

61-
impl ContainerBuilder {
62-
pub(crate) fn new<S: Into<String>>(image: S) -> Self {
93+
impl<'a> ContainerBuilder<'a> {
94+
pub(crate) fn new(image: &'a DockerEnv) -> Self {
6395
ContainerBuilder {
64-
image: image.into(),
96+
image,
6597
mounts: Vec::new(),
6698
env: Vec::new(),
99+
workdir: None,
67100
memory_limit: None,
101+
cmd: Vec::new(),
68102
enable_networking: true,
69103
}
70104
}
@@ -88,11 +122,21 @@ impl ContainerBuilder {
88122
self
89123
}
90124

125+
pub(crate) fn workdir<S: Into<String>>(mut self, workdir: S) -> Self {
126+
self.workdir = Some(workdir.into());
127+
self
128+
}
129+
91130
pub(crate) fn memory_limit(mut self, limit: Option<Size>) -> Self {
92131
self.memory_limit = limit;
93132
self
94133
}
95134

135+
pub(crate) fn cmd(mut self, cmd: Vec<String>) -> Self {
136+
self.cmd = cmd;
137+
self
138+
}
139+
96140
pub(crate) fn enable_networking(mut self, enable: bool) -> Self {
97141
self.enable_networking = enable;
98142
self
@@ -112,6 +156,11 @@ impl ContainerBuilder {
112156
args.push(format! {"{}={}", var, value})
113157
}
114158

159+
if let Some(workdir) = self.workdir {
160+
args.push("-w".into());
161+
args.push(workdir);
162+
}
163+
115164
if let Some(limit) = self.memory_limit {
116165
args.push("-m".into());
117166
args.push(limit.to_string());
@@ -122,7 +171,11 @@ impl ContainerBuilder {
122171
args.push("none".into());
123172
}
124173

125-
args.push(self.image);
174+
args.push(self.image.image.clone());
175+
176+
for arg in self.cmd {
177+
args.push(arg);
178+
}
126179

127180
let (out, _) = RunCommand::new("docker").args(&*args).run_capture()?;
128181
Ok(Container { id: out[0].clone() })

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ pub mod config;
7272
pub mod crates;
7373
pub mod db;
7474
pub mod dirs;
75-
pub mod docker;
75+
mod docker;
7676
pub mod experiments;
7777
mod native;
7878
mod prelude;

0 commit comments

Comments
 (0)