Skip to content

Commit 72d52f5

Browse files
committed
Garbage in, rainbows out
This commit includes a lot of changes to how problematic cases are handled. The basic idea is that first the code snippet is tested on good and bad revisions (git is not doing that by default), and further behavior is adapted according to that. Also, 2015.12 is now used instead of v6.c.
1 parent 68ba961 commit 72d52f5

File tree

3 files changed

+114
-18
lines changed

3 files changed

+114
-18
lines changed

bot.pl

Lines changed: 84 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,29 +26,50 @@ package Bisectable;
2626
use File::Temp qw( tempfile tempdir );
2727
use Cwd qw(cwd abs_path);
2828
use IO::Handle;
29+
use IPC::Open3;
2930

3031
my $link = 'https://github.com/rakudo/rakudo/commit';
3132
my $rakudo = './rakudo';
3233
my $builds = abs_path './builds';
3334
my $commit_tester = abs_path './test-commit';
35+
my $build_lock = abs_path './lock';
36+
37+
38+
sub get_output {
39+
# TODO flag if stderr is needed
40+
my $pid = open3(undef, \*RESULT, \*RESULT, @_);
41+
waitpid($pid, 0);
42+
my $exit_status = $? >> 8;
43+
my $out = do { local $/; <RESULT> };
44+
chomp $out;
45+
return ($out, $exit_status)
46+
}
47+
48+
sub to_commit {
49+
my ($str) = @_;
50+
return if system('git', 'rev-parse', '--verify', $str) != 0;
51+
my ($result, $exit_status) = get_output('git', 'rev-list', '-1', $str);
52+
return if $exit_status != 0;
53+
return $result;
54+
}
3455

3556
sub said {
3657
my ($self, $message) = @_;
3758
if ($message->{body} =~ /^bisect:
3859
(?:
39-
(?: \s+ good (?: \s+ | \s*=\s*) ([\w\d.-]+) )
40-
(?: \s+ bad (?: \s+ | \s*=\s*) ([\w\d.-]+) )?
60+
(?: \s+ good (?: \s*=\s* | \s+) ([^\s]+) )
61+
(?: \s+ bad (?: \s*=\s* | \s+) ([^\s]+) )?
4162
|
42-
(?: \s+ bad (?: \s+ | \s*=\s*) ([\w\d.-]+) )?
43-
(?: \s+ good (?: \s+ | \s*=\s*) ([\w\d.-]+) )?
63+
(?: \s+ bad (?: \s*=\s* | \s+) ([^\s]+) )?
64+
(?: \s+ good (?: \s*=\s* | \s+) ([^\s]+) )?
4465
)
4566
(*PRUNE)
4667
\s+ (.+)
4768
/xu) {
4869
if (defined $message->{address}) {
4970
return 'Sorry, it is too private here';
5071
}
51-
my $good = $1 // $4 // 'v6.c';
72+
my $good = $1 // $4 // '2015.12';
5273
my $bad = $2 // $3 // 'HEAD';
5374
my $code = $5;
5475

@@ -57,18 +78,70 @@ sub said {
5778
print $fh $code;
5879
close $fh;
5980

60-
my $dir = tempdir(CLEANUP => 1);
6181
# TODO use --no-checkout ?
62-
system('git', 'clone', $rakudo, $dir);
6382
my $oldDir = cwd;
83+
84+
# convert to real ids so we can look up the builds
85+
chdir($rakudo);
86+
$good = to_commit($good);
87+
chdir($oldDir);
88+
return "$message->{who}: cannot find such “good” revision" unless defined $good;
89+
return "$message->{who}: no build for such “good” revision" if ! -e "$builds/$good/bin/perl6";
90+
chdir($rakudo);
91+
$bad = to_commit($bad);
92+
chdir($oldDir);
93+
return "$message->{who}: cannot find such “bad” revision" unless defined $bad;
94+
if (! -e "$builds/$bad/bin/perl6" and -e $build_lock) {
95+
# TODO fix the problem when it is building new commits
96+
return "$message->{who}: no build for such “bad” revision. Right now the build process is in action, please try again later or specify some older “bad” commit (e.g. bad=HEAD~40)";
97+
}
98+
return "$message->{who}: no build for such “bad” revision" if ! -e "$builds/$bad/bin/perl6";
99+
100+
my ($out_good, $exit_good) = get_output("$builds/$good/bin/perl6", $filename);
101+
my ($out_bad, $exit_bad) = get_output("$builds/$bad/bin/perl6", $filename);
102+
if ($exit_good == $exit_bad and $out_good eq $out_bad) {
103+
return "$message->{who}: on both starting points the exit code is $exit_bad and the output is identical as well";
104+
}
105+
my $output_file = '';
106+
if ($exit_good == $exit_bad) {
107+
$self->say(
108+
channel => $message->{channel},
109+
body => "$message->{who}: exit code is $exit_bad on both starting points, bisecting by using the output",
110+
);
111+
(my $fh, $output_file) = tempfile(UNLINK => 1);
112+
print $fh $out_good;
113+
close $fh;
114+
}
115+
if ($exit_good != $exit_bad and $exit_good != 0) {
116+
$self->say(
117+
channel => $message->{channel},
118+
body => "$message->{who}: exit code on a “good” revision is $exit_good (which is bad), bisecting with inverted logic",
119+
);
120+
}
121+
122+
my $dir = tempdir(CLEANUP => 1);
123+
system('git', 'clone', $rakudo, $dir);
64124
chdir($dir);
125+
65126
system('git', 'bisect', 'start');
66127
system('git', 'bisect', 'good', $good);
67128
system('git', 'bisect', 'bad', $bad);
68-
system('git', 'bisect', 'run', $commit_tester, $builds, $filename);
69-
my $result = `git show --quiet --date=short --pretty='(%cd) $link/%h' bisect/bad`;
129+
my $bisect_status;
130+
if ($output_file) {
131+
$bisect_status = system('git', 'bisect', 'run', $commit_tester, $builds, $filename, $output_file);
132+
} else {
133+
if ($exit_good == 0) {
134+
$bisect_status = system('git', 'bisect', 'run', $commit_tester, $builds, $filename);
135+
} else {
136+
$bisect_status = system('git', 'bisect', 'run', $commit_tester, $builds, $filename, $exit_good);
137+
}
138+
}
139+
if ($bisect_status != 0) {
140+
chdir($oldDir);
141+
return "$message->{who}: “bisect run” failure";
142+
}
143+
my ($result) = get_output('git', 'show', '--quiet', '--date=short', "--pretty=(%cd) $link/%h", 'bisect/bad');
70144
chdir($oldDir);
71-
72145
return "$message->{who}: $result";
73146
}
74147
if ($message->{body} eq 'source') {
@@ -77,7 +150,7 @@ sub said {
77150
}
78151

79152
sub help {
80-
'Like this: bisect: good=v6.c bad=HEAD exit 1 if (^∞).grep({ last })[5] // 0 == 4 # RT 128181'
153+
'Like this: bisect: good=2015.12 bad=HEAD exit 1 if (^∞).grep({ last })[5] // 0 == 4 # RT 128181'
81154
}
82155

83156
Bisectable->new(

new-commits

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@
55
export WORKING_DIRECTORY='.' # TODO not supported yet
66
export RAKUDO_LOCATION="$WORKING_DIRECTORY/rakudo"
77
RAKUDO_ORIGIN='https://github.com/rakudo/rakudo.git'
8-
TEST_LOCK="$WORKING_DIRECTORY/lock"
8+
BUILD_LOCK="$WORKING_DIRECTORY/lock"
99
PARALLEL_COUNT=7
1010

1111
clean() {
1212
while popd &> /dev/null; do :; done # change directory back
13-
rmdir -- "$TEST_LOCK"
13+
rmdir -- "$BUILD_LOCK"
1414
}
1515

16-
if mkdir -p -- "$TEST_LOCK"; then # only one instance running
16+
if mkdir -p -- "$BUILD_LOCK"; then # only one instance running
1717
trap clean EXIT
1818
else
1919
exit 0
@@ -29,6 +29,6 @@ fi
2929

3030
git_orig=('git' '--git-dir' "$RAKUDO_LOCATION/.git" '--work-tree' "$RAKUDO_LOCATION")
3131

32-
# you can change v6.c...HEAD to something else
33-
"${git_orig[@]}" log -z --pretty='%H' v6.c...HEAD \
32+
# you can change 2015.12^..HEAD to something else
33+
"${git_orig[@]}" log -z --pretty='%H' 2015.12^..HEAD \
3434
| xargs -0 -n 1 -P "$PARALLEL_COUNT" ./process-sha

test-commit

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,28 @@ perl6="$builds/$current_commit/bin/perl6"
66

77
[[ -e $perl6 ]] || exit 125 # skip failed builds
88

9-
"$perl6" --setting=RESTRICTED -- "$code_file"
10-
exit $?
9+
# plain bisect
10+
if (( $# < 3 )); then
11+
"$perl6" --setting=RESTRICTED -- "$code_file"
12+
exit $?
13+
fi
14+
15+
# inverted exit code
16+
if [[ $3 =~ ^[0-9]+$ ]]; then # invert exit code
17+
"$perl6" --setting=RESTRICTED -- "$code_file"
18+
exit_code=$?
19+
if (( $exit_code == $3 )); then
20+
exit 0
21+
else
22+
exit $(( $exit_code == 0 ? 1 : $exit_code ))
23+
fi
24+
fi
25+
26+
# compare the output
27+
output=$("$perl6" --setting=RESTRICTED -- "$code_file" 2>&1)
28+
output_good=$(<"$3")
29+
if [[ $output == "$output_good" ]]; then
30+
exit 0
31+
else
32+
exit 1
33+
fi

0 commit comments

Comments
 (0)