contrib/triage: add bisect-num
Add a helper script used by the ChromeOS Release Triage team to help
with first-build bisects.
BUG=b:400792464
TEST=bisect-num 15474 15506
Change-Id: I36c35ea73642c4b57eebbfb8e1cf2e73b31351ce
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/dev-util/+/6336256
Reviewed-by: Luis Menezes <lmenezes@google.com>
Reviewed-by: Matt Davis <mattedavis@google.com>
Tested-by: Ross Zwisler <zwisler@google.com>
Reviewed-by: Aaron Massey <aaronmassey@google.com>
Auto-Submit: Ross Zwisler <zwisler@google.com>
Commit-Queue: Ross Zwisler <zwisler@google.com>
diff --git a/contrib/triage/bisect-num b/contrib/triage/bisect-num
new file mode 100755
index 0000000..79e2db8
--- /dev/null
+++ b/contrib/triage/bisect-num
@@ -0,0 +1,71 @@
+#!/usr/bin/perl
+#
+# Copyright 2025 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# Maintainer: Ross Zwisler <zwisler@google.com>
+#
+# bisect-num: Help automate a first-build bisect for a given issue.
+# See http://go/cros-imt-first-build-codelab
+# Given an <old_revision> and <new_revision>, this script will give you a
+# middle revision to test at each step until we find two adjacent builds, one
+# which is good and one which is bad. This script also allows us to update the
+# build we are actually testing, in the case that some images are unavailable
+# because of build issues.
+#
+# Usage: bisect-num <old_revision> <new_revision>
+# $ bisect-num 15474 15506
+# range (15474 (good) - 15506 (bad), in 5 steps) Next revision to test: 15490
+# Good? (y/n) or enter revision actually tested:
+use strict;
+use warnings;
+
+if ($#ARGV != 1) {
+ print "Usage: $0 <old_revision> <new_revision>\n";
+ exit 0;
+}
+
+my $min = shift(@ARGV);
+my $max = shift(@ARGV);
+
+# Function for log2 calculator
+sub log2
+{
+ my $n = shift;
+ # using pre-defined log function
+ return log($n) / log(2);
+}
+
+while (1) {
+ my $mid = int(($min + $max) / 2);
+
+ $mid++ if ($mid == $min);
+
+ if ($mid == $max) {
+ print "First bad number: $mid\n";
+ exit 0;
+ }
+
+ while (1) {
+ my $steps = int(log2($max - $min));
+ print "range ($min (good) - $max (bad), in $steps steps) Next revision to test: $mid\n";
+ print "Good? (y/n) or enter revision actually tested: ";
+
+ my $answer = <STDIN>;
+ exit if (!$answer);
+ chomp($answer);
+
+ if ($answer eq 'y') {
+ print "YES\n";
+ $min = $mid;
+ last;
+ } elsif ($answer eq "n") {
+ print "NO\n";
+ $max = $mid;
+ last;
+ } elsif ($answer =~ /^(\d)+$/) {
+ $mid = $answer;
+ }
+ }
+}