Skip to content

Commit d7798c3

Browse files
committed
Auto merge of #42128 - kennytm:travis-folder, r=alexcrichton
Improve Travis CI log (travis_fold, colors) Result looks like (https://travis-ci.org/rust-lang/rust/jobs/234614611): <details><summary>Full page screenshot</summary> ![1-fullpage](https://cloud.githubusercontent.com/assets/103023/26302841/2627c354-3f18-11e7-9299-52a2088639af.jpg) </details> --- * Bring back colors on Travis, which was disabled since #39036. Append `--color=always` to cargo when running in CI environment. * Removed `set -x` from the shell scripts. The `retry` function already prints which command it is running, adding `-x` just adds noise to the output. Interesting information can be manually `echo`ed. * Support `travis_fold`/`travis_time`. Matching pairs of these allow Travis CI to collapse the output in between. This greatly cut down the unnecessary "successful" output one need to scroll through before finding the failed statement. * Passed `--quiet` to all tests, so tests not failing will not occupy a line of log, reducing bloat in the report. Also include some minor changes, like changing the `script` of `.travis.yml` to execute a single-line command, so the log won't write the extremely long multi-line `The command "if [ "$ALLOW_PR" = "" ] && [ "$TRAVIS_BRANCH" != "auto" ]; then … " exited with 0` at the end.
2 parents 558cd1e + 6ac0787 commit d7798c3

File tree

15 files changed

+259
-26
lines changed

15 files changed

+259
-26
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -101,3 +101,4 @@ version.ml
101101
version.texi
102102
.cargo
103103
!src/vendor/**
104+
/src/target/

.travis.yml

+8-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
language: minimal
1+
language: generic
22
sudo: required
33
dist: trusty
44
services:
@@ -152,20 +152,21 @@ before_script:
152152
echo "#### Disk usage before running script:";
153153
df -h;
154154
du . | sort -nr | head -n100
155-
156-
script:
157155
- >
158156
if [ "$ALLOW_PR" = "" ] && [ "$TRAVIS_BRANCH" != "auto" ]; then
159-
echo skipping, not a full build
157+
export RUN_SCRIPT="echo 'skipping, not a full build'";
160158
else
161-
stamp src/ci/init_repo.sh . "$HOME/rustsrc" &&
159+
RUN_SCRIPT="stamp src/ci/init_repo.sh . $HOME/rustsrc";
162160
if [ "$TRAVIS_OS_NAME" = "osx" ]; then
163-
stamp src/ci/run.sh;
161+
export RUN_SCRIPT="$RUN_SCRIPT && stamp src/ci/run.sh";
164162
else
165-
stamp src/ci/docker/run.sh $IMAGE;
163+
export RUN_SCRIPT="$RUN_SCRIPT && stamp src/ci/docker/run.sh $IMAGE";
166164
fi
167165
fi
168166
167+
script:
168+
- sh -x -c "$RUN_SCRIPT"
169+
169170
after_success:
170171
- >
171172
echo "#### Build successful; Disk usage after running script:";

src/bootstrap/check.rs

+18-5
Original file line numberDiff line numberDiff line change
@@ -124,13 +124,17 @@ pub fn cargo(build: &Build, stage: u32, host: &str) {
124124
/// otherwise just implements a few lint-like checks that are specific to the
125125
/// compiler itself.
126126
pub fn tidy(build: &Build, host: &str) {
127+
let _folder = build.fold_output(|| "tidy");
127128
println!("tidy check ({})", host);
128129
let compiler = Compiler::new(0, host);
129130
let mut cmd = build.tool_cmd(&compiler, "tidy");
130131
cmd.arg(build.src.join("src"));
131132
if !build.config.vendor {
132133
cmd.arg("--no-vendor");
133134
}
135+
if build.config.quiet_tests {
136+
cmd.arg("--quiet");
137+
}
134138
build.run(&mut cmd);
135139
}
136140

@@ -148,6 +152,7 @@ pub fn compiletest(build: &Build,
148152
target: &str,
149153
mode: &str,
150154
suite: &str) {
155+
let _folder = build.fold_output(|| format!("test_{}", suite));
151156
println!("Check compiletest suite={} mode={} ({} -> {})",
152157
suite, mode, compiler.host, target);
153158
let mut cmd = Command::new(build.tool(&Compiler::new(0, compiler.host),
@@ -278,6 +283,8 @@ pub fn compiletest(build: &Build,
278283
cmd.arg("--android-cross-path").arg("");
279284
}
280285

286+
build.ci_env.force_coloring_in_ci(&mut cmd);
287+
281288
let _time = util::timeit();
282289
build.run(&mut cmd);
283290
}
@@ -292,6 +299,7 @@ pub fn docs(build: &Build, compiler: &Compiler) {
292299
// tests for all files that end in `*.md`
293300
let mut stack = vec![build.src.join("src/doc")];
294301
let _time = util::timeit();
302+
let _folder = build.fold_output(|| "test_docs");
295303

296304
while let Some(p) = stack.pop() {
297305
if p.is_dir() {
@@ -325,6 +333,7 @@ pub fn docs(build: &Build, compiler: &Compiler) {
325333
/// generate a markdown file from the error indexes of the code base which is
326334
/// then passed to `rustdoc --test`.
327335
pub fn error_index(build: &Build, compiler: &Compiler) {
336+
let _folder = build.fold_output(|| "test_error_index");
328337
println!("Testing error-index stage{}", compiler.stage);
329338

330339
let dir = testdir(build, compiler.host);
@@ -349,13 +358,14 @@ fn markdown_test(build: &Build, compiler: &Compiler, markdown: &Path) {
349358
cmd.arg(markdown);
350359
cmd.env("RUSTC_BOOTSTRAP", "1");
351360

352-
let mut test_args = build.flags.cmd.test_args().join(" ");
353-
if build.config.quiet_tests {
354-
test_args.push_str(" --quiet");
355-
}
361+
let test_args = build.flags.cmd.test_args().join(" ");
356362
cmd.arg("--test-args").arg(test_args);
357363

358-
build.run(&mut cmd);
364+
if build.config.quiet_tests {
365+
build.run_quiet(&mut cmd);
366+
} else {
367+
build.run(&mut cmd);
368+
}
359369
}
360370

361371
/// Run all unit tests plus documentation tests for an entire crate DAG defined
@@ -384,6 +394,9 @@ pub fn krate(build: &Build,
384394
}
385395
_ => panic!("can only test libraries"),
386396
};
397+
let _folder = build.fold_output(|| {
398+
format!("{}_stage{}-{}", test_kind.subcommand(), compiler.stage, name)
399+
});
387400
println!("{} {} stage{} ({} -> {})", test_kind, name, compiler.stage,
388401
compiler.host, target);
389402

src/bootstrap/compile.rs

+4
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ pub fn std(build: &Build, target: &str, compiler: &Compiler) {
4141
let libdir = build.sysroot_libdir(compiler, target);
4242
t!(fs::create_dir_all(&libdir));
4343

44+
let _folder = build.fold_output(|| format!("stage{}-std", compiler.stage));
4445
println!("Building stage{} std artifacts ({} -> {})", compiler.stage,
4546
compiler.host, target);
4647

@@ -192,6 +193,7 @@ pub fn build_startup_objects(build: &Build, for_compiler: &Compiler, target: &st
192193
/// the build using the `compiler` targeting the `target` architecture. The
193194
/// artifacts created will also be linked into the sysroot directory.
194195
pub fn test(build: &Build, target: &str, compiler: &Compiler) {
196+
let _folder = build.fold_output(|| format!("stage{}-test", compiler.stage));
195197
println!("Building stage{} test artifacts ({} -> {})", compiler.stage,
196198
compiler.host, target);
197199
let out_dir = build.cargo_out(compiler, Mode::Libtest, target);
@@ -228,6 +230,7 @@ pub fn test_link(build: &Build,
228230
/// the `compiler` targeting the `target` architecture. The artifacts
229231
/// created will also be linked into the sysroot directory.
230232
pub fn rustc(build: &Build, target: &str, compiler: &Compiler) {
233+
let _folder = build.fold_output(|| format!("stage{}-rustc", compiler.stage));
231234
println!("Building stage{} compiler artifacts ({} -> {})",
232235
compiler.stage, compiler.host, target);
233236

@@ -435,6 +438,7 @@ pub fn maybe_clean_tools(build: &Build, stage: u32, target: &str, mode: Mode) {
435438
/// This will build the specified tool with the specified `host` compiler in
436439
/// `stage` into the normal cargo output directory.
437440
pub fn tool(build: &Build, stage: u32, target: &str, tool: &str) {
441+
let _folder = build.fold_output(|| format!("stage{}-{}", stage, tool));
438442
println!("Building stage{} tool {} ({})", stage, tool, target);
439443

440444
let compiler = Compiler::new(stage, &build.config.build);

src/bootstrap/lib.rs

+19-1
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ use std::process::Command;
9090

9191
use build_helper::{run_silent, run_suppressed, output, mtime};
9292

93-
use util::{exe, libdir, add_lib_path};
93+
use util::{exe, libdir, add_lib_path, OutputFolder, CiEnv};
9494

9595
mod cc;
9696
mod channel;
@@ -179,6 +179,7 @@ pub struct Build {
179179
crates: HashMap<String, Crate>,
180180
is_sudo: bool,
181181
src_is_git: bool,
182+
ci_env: CiEnv,
182183
}
183184

184185
#[derive(Debug)]
@@ -272,6 +273,7 @@ impl Build {
272273
lldb_python_dir: None,
273274
is_sudo: is_sudo,
274275
src_is_git: src_is_git,
276+
ci_env: CiEnv::current(),
275277
}
276278
}
277279

@@ -507,6 +509,9 @@ impl Build {
507509
if self.config.vendor || self.is_sudo {
508510
cargo.arg("--frozen");
509511
}
512+
513+
self.ci_env.force_coloring_in_ci(&mut cargo);
514+
510515
return cargo
511516
}
512517

@@ -1011,6 +1016,19 @@ impl Build {
10111016
"nightly" | _ => true,
10121017
}
10131018
}
1019+
1020+
/// Fold the output of the commands after this method into a group. The fold
1021+
/// ends when the returned object is dropped. Folding can only be used in
1022+
/// the Travis CI environment.
1023+
pub fn fold_output<D, F>(&self, name: F) -> Option<OutputFolder>
1024+
where D: Into<String>, F: FnOnce() -> D
1025+
{
1026+
if self.ci_env == CiEnv::Travis {
1027+
Some(OutputFolder::new(name().into()))
1028+
} else {
1029+
None
1030+
}
1031+
}
10141032
}
10151033

10161034
impl<'a> Compiler<'a> {

src/bootstrap/native.rs

+2
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ pub fn llvm(build: &Build, target: &str) {
6363
drop(fs::remove_dir_all(&out_dir));
6464
}
6565

66+
let _folder = build.fold_output(|| "llvm");
6667
println!("Building LLVM for {}", target);
6768
let _time = util::timeit();
6869
t!(fs::create_dir_all(&out_dir));
@@ -218,6 +219,7 @@ pub fn test_helpers(build: &Build, target: &str) {
218219
return
219220
}
220221

222+
let _folder = build.fold_output(|| "build_test_helpers");
221223
println!("Building test helpers");
222224
t!(fs::create_dir_all(&dst));
223225
let mut cfg = gcc::Config::new();

src/bootstrap/util.rs

+101-2
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@
1616
use std::env;
1717
use std::ffi::OsString;
1818
use std::fs;
19-
use std::io;
19+
use std::io::{self, Write};
2020
use std::path::{Path, PathBuf};
2121
use std::process::Command;
22-
use std::time::Instant;
22+
use std::time::{SystemTime, Instant};
2323

2424
use filetime::{self, FileTime};
2525

@@ -324,3 +324,102 @@ pub fn symlink_dir(src: &Path, dest: &Path) -> io::Result<()> {
324324
}
325325
}
326326
}
327+
328+
/// An RAII structure that indicates all output until this instance is dropped
329+
/// is part of the same group.
330+
///
331+
/// On Travis CI, these output will be folded by default, together with the
332+
/// elapsed time in this block. This reduces noise from unnecessary logs,
333+
/// allowing developers to quickly identify the error.
334+
///
335+
/// Travis CI supports folding by printing `travis_fold:start:<name>` and
336+
/// `travis_fold:end:<name>` around the block. Time elapsed is recognized
337+
/// similarly with `travis_time:[start|end]:<name>`. These are undocumented, but
338+
/// can easily be deduced from source code of the [Travis build commands].
339+
///
340+
/// [Travis build commands]:
341+
/// https://github.com/travis-ci/travis-build/blob/f603c0089/lib/travis/build/templates/header.sh
342+
pub struct OutputFolder {
343+
name: String,
344+
start_time: SystemTime, // we need SystemTime to get the UNIX timestamp.
345+
}
346+
347+
impl OutputFolder {
348+
/// Creates a new output folder with the given group name.
349+
pub fn new(name: String) -> OutputFolder {
350+
// "\r" moves the cursor to the beginning of the line, and "\x1b[0K" is
351+
// the ANSI escape code to clear from the cursor to end of line.
352+
// Travis seems to have trouble when _not_ using "\r\x1b[0K", that will
353+
// randomly put lines to the top of the webpage.
354+
print!("travis_fold:start:{0}\r\x1b[0Ktravis_time:start:{0}\r\x1b[0K", name);
355+
OutputFolder {
356+
name,
357+
start_time: SystemTime::now(),
358+
}
359+
}
360+
}
361+
362+
impl Drop for OutputFolder {
363+
fn drop(&mut self) {
364+
use std::time::*;
365+
use std::u64;
366+
367+
fn to_nanos(duration: Result<Duration, SystemTimeError>) -> u64 {
368+
match duration {
369+
Ok(d) => d.as_secs() * 1_000_000_000 + d.subsec_nanos() as u64,
370+
Err(_) => u64::MAX,
371+
}
372+
}
373+
374+
let end_time = SystemTime::now();
375+
let duration = end_time.duration_since(self.start_time);
376+
let start = self.start_time.duration_since(UNIX_EPOCH);
377+
let finish = end_time.duration_since(UNIX_EPOCH);
378+
println!(
379+
"travis_fold:end:{0}\r\x1b[0K\n\
380+
travis_time:end:{0}:start={1},finish={2},duration={3}\r\x1b[0K",
381+
self.name,
382+
to_nanos(start),
383+
to_nanos(finish),
384+
to_nanos(duration)
385+
);
386+
io::stdout().flush().unwrap();
387+
}
388+
}
389+
390+
/// The CI environment rustbuild is running in. This mainly affects how the logs
391+
/// are printed.
392+
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
393+
pub enum CiEnv {
394+
/// Not a CI environment.
395+
None,
396+
/// The Travis CI environment, for Linux (including Docker) and macOS builds.
397+
Travis,
398+
/// The AppVeyor environment, for Windows builds.
399+
AppVeyor,
400+
}
401+
402+
impl CiEnv {
403+
/// Obtains the current CI environment.
404+
pub fn current() -> CiEnv {
405+
if env::var("TRAVIS").ok().map_or(false, |e| &*e == "true") {
406+
CiEnv::Travis
407+
} else if env::var("APPVEYOR").ok().map_or(false, |e| &*e == "True") {
408+
CiEnv::AppVeyor
409+
} else {
410+
CiEnv::None
411+
}
412+
}
413+
414+
/// If in a CI environment, forces the command to run with colors.
415+
pub fn force_coloring_in_ci(self, cmd: &mut Command) {
416+
if self != CiEnv::None {
417+
// Due to use of stamp/docker, the output stream of rustbuild is not
418+
// a TTY in CI, so coloring is by-default turned off.
419+
// The explicit `TERM=xterm` environment is needed for
420+
// `--color always` to actually work. This env var was lost when
421+
// compiling through the Makefile. Very strange.
422+
cmd.env("TERM", "xterm").args(&["--color", "always"]);
423+
}
424+
}
425+
}

src/ci/docker/run.sh

+7
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ root_dir="`dirname $src_dir`"
2121

2222
source "$ci_dir/shared.sh"
2323

24+
travis_fold start build_docker
25+
travis_time_start
26+
2427
if [ -f "$docker_dir/$image/Dockerfile" ]; then
2528
retry docker \
2629
build \
@@ -44,6 +47,9 @@ else
4447
exit 1
4548
fi
4649

50+
travis_fold end build_docker
51+
travis_time_finish
52+
4753
objdir=$root_dir/obj
4854

4955
mkdir -p $HOME/.cargo
@@ -72,6 +78,7 @@ exec docker \
7278
--env DEPLOY=$DEPLOY \
7379
--env DEPLOY_ALT=$DEPLOY_ALT \
7480
--env LOCAL_USER_ID=`id -u` \
81+
--env TRAVIS=${TRAVIS-false} \
7582
--volume "$HOME/.cargo:/cargo" \
7683
--volume "$HOME/rustsrc:$HOME/rustsrc" \
7784
--privileged \

0 commit comments

Comments
 (0)