Skip to content

Commit 3d251d6

Browse files
Add --should-fail flag to the bisect script (#16864)
2 parents 5693900 + 36926c8 commit 3d251d6

File tree

1 file changed

+17
-9
lines changed

1 file changed

+17
-9
lines changed

project/scripts/bisect.scala

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,20 @@ val usageMessage = """
3131
|The optional <bisect-options> may be any combination of:
3232
|* --dry-run
3333
| Don't try to bisect - just make sure the validation command works correctly
34+
|
3435
|* --releases <releases-range>
3536
| Bisect only releases from the given range (defaults to all releases).
3637
| The range format is <first>...<last>, where both <first> and <last> are optional, e.g.
3738
| * 3.1.0-RC1-bin-20210827-427d313-NIGHTLY..3.2.1-RC1-bin-20220716-bb9c8ff-NIGHTLY
3839
| * 3.2.1-RC1-bin-20220620-de3a82c-NIGHTLY..
3940
| * ..3.3.0-RC1-bin-20221124-e25362d-NIGHTLY
4041
| The ranges are treated as inclusive.
42+
|
4143
|* --bootstrapped
42-
| Publish locally and test a bootstrapped compiler rather than a nonboostrapped one
44+
| Publish locally and test a bootstrapped compiler rather than a nonboostrapped one.
45+
|
46+
|* --should-fail
47+
| Expect the validation command to fail rather that succeed. This can be used e.g. to find out when some illegal code started to compile.
4348
|
4449
|Warning: The bisect script should not be run multiple times in parallel because of a potential race condition while publishing artifacts locally.
4550
@@ -54,7 +59,7 @@ val usageMessage = """
5459

5560
val validationScript = scriptOptions.validationCommand.validationScript
5661
val releases = Releases.fromRange(scriptOptions.releasesRange)
57-
val releaseBisect = ReleaseBisect(validationScript, releases)
62+
val releaseBisect = ReleaseBisect(validationScript, shouldFail = scriptOptions.shouldFail, releases)
5863

5964
releaseBisect.verifyEdgeReleases()
6065

@@ -64,18 +69,19 @@ val usageMessage = """
6469
println(s"First bad release: ${firstBadRelease.version}")
6570
println("\nFinished bisecting releases\n")
6671

67-
val commitBisect = CommitBisect(validationScript, bootstrapped = scriptOptions.bootstrapped, lastGoodRelease.hash, firstBadRelease.hash)
72+
val commitBisect = CommitBisect(validationScript, shouldFail = scriptOptions.shouldFail, bootstrapped = scriptOptions.bootstrapped, lastGoodRelease.hash, firstBadRelease.hash)
6873
commitBisect.bisect()
6974

7075

71-
case class ScriptOptions(validationCommand: ValidationCommand, dryRun: Boolean, bootstrapped: Boolean, releasesRange: ReleasesRange)
76+
case class ScriptOptions(validationCommand: ValidationCommand, dryRun: Boolean, bootstrapped: Boolean, releasesRange: ReleasesRange, shouldFail: Boolean)
7277
object ScriptOptions:
7378
def fromArgs(args: Seq[String]) =
7479
val defaultOptions = ScriptOptions(
7580
validationCommand = null,
7681
dryRun = false,
7782
bootstrapped = false,
78-
ReleasesRange(first = None, last = None)
83+
ReleasesRange(first = None, last = None),
84+
shouldFail = false
7985
)
8086
parseArgs(args, defaultOptions)
8187

@@ -86,6 +92,7 @@ object ScriptOptions:
8692
case "--releases" :: argsRest =>
8793
val range = ReleasesRange.tryParse(argsRest.head).get
8894
parseArgs(argsRest.tail, options.copy(releasesRange = range))
95+
case "--should-fail" :: argsRest => parseArgs(argsRest, options.copy(shouldFail = true))
8996
case _ =>
9097
val command = ValidationCommand.fromArgs(args)
9198
options.copy(validationCommand = command)
@@ -182,7 +189,7 @@ case class Release(version: String):
182189
override def toString: String = version
183190

184191

185-
class ReleaseBisect(validationScript: File, allReleases: Vector[Release]):
192+
class ReleaseBisect(validationScript: File, shouldFail: Boolean, allReleases: Vector[Release]):
186193
assert(allReleases.length > 1, "Need at least 2 releases to bisect")
187194

188195
private val isGoodReleaseCache = collection.mutable.Map.empty[Release, Boolean]
@@ -217,21 +224,22 @@ class ReleaseBisect(validationScript: File, allReleases: Vector[Release]):
217224
isGoodReleaseCache.getOrElseUpdate(release, {
218225
println(s"Testing ${release.version}")
219226
val result = Seq(validationScript.getAbsolutePath, release.version).!
220-
val isGood = result == 0
227+
val isGood = if(shouldFail) result != 0 else result == 0 // invert the process status if failure was expected
221228
println(s"Test result: ${release.version} is a ${if isGood then "good" else "bad"} release\n")
222229
isGood
223230
})
224231

225-
class CommitBisect(validationScript: File, bootstrapped: Boolean, lastGoodHash: String, fistBadHash: String):
232+
class CommitBisect(validationScript: File, shouldFail: Boolean, bootstrapped: Boolean, lastGoodHash: String, fistBadHash: String):
226233
def bisect(): Unit =
227234
println(s"Starting bisecting commits $lastGoodHash..$fistBadHash\n")
228235
val scala3CompilerProject = if bootstrapped then "scala3-compiler-bootstrapped" else "scala3-compiler"
229236
val scala3Project = if bootstrapped then "scala3-bootstrapped" else "scala3"
237+
val validationCommandStatusModifier = if shouldFail then "! " else "" // invert the process status if failure was expected
230238
val bisectRunScript = s"""
231239
|scalaVersion=$$(sbt "print ${scala3CompilerProject}/version" | tail -n1)
232240
|rm -r out
233241
|sbt "clean; ${scala3Project}/publishLocal"
234-
|${validationScript.getAbsolutePath} "$$scalaVersion"
242+
|${validationCommandStatusModifier}${validationScript.getAbsolutePath} "$$scalaVersion"
235243
""".stripMargin
236244
"git bisect start".!
237245
s"git bisect bad $fistBadHash".!

0 commit comments

Comments
 (0)