Skip to content

Commit 18b5476

Browse files
committed
.
1 parent d3ea9c0 commit 18b5476

File tree

5 files changed

+46
-14
lines changed

5 files changed

+46
-14
lines changed

core/eval/src/mill/eval/EvaluatorImpl.scala

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ final class EvaluatorImpl(
271271
serialCommandExec = serialCommandExec
272272
)
273273

274-
val allResults = evaluated.transitiveResults.iterator ++ selectiveResults
274+
val allResults = evaluated.transitiveResults ++ selectiveResults
275275

276276
@scala.annotation.nowarn("msg=cannot be checked at runtime")
277277
val watched = allResults.collect {
@@ -301,18 +301,16 @@ final class EvaluatorImpl(
301301
result.map(_.value).hashCode(),
302302
pretty
303303
))
304-
}.flatten.toSeq
304+
}.flatten.toVector
305305

306-
for(newMetadata <- maybeNewMetadata) {
306+
for (newMetadata <- maybeNewMetadata) {
307307
val failingTaskNames = allResults
308-
.collect { case (t: Task.Named[_], r) if r.asSuccess.isEmpty => t.ctx.segments.render}
308+
.collect { case (t: Task.Named[_], r) if r.asSuccess.isEmpty => t.ctx.segments.render }
309309
.toSet
310310

311-
selective.saveMetadata(
312-
newMetadata.copy(forceRunTasks = failingTaskNames)
313-
)
311+
// For tasks that were not successful, force them to re-run next time even if not changed
312+
selective.saveMetadata(newMetadata.copy(forceRunTasks = failingTaskNames))
314313
}
315-
316314

317315
val errorStr = ExecutionResultsApi.formatFailing(evaluated)
318316
evaluated.transitiveFailing.size match {

integration/invalidation/selective-execution/src/SelectiveExecutionChangedCodeTests.scala

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ import scala.concurrent.duration._
55
import utest._
66
import utest.asserts.{RetryMax, RetryInterval}
77

8-
9-
108
object SelectiveExecutionChangedCodeTests extends UtestIntegrationTestSuite {
119
implicit val retryMax: RetryMax = RetryMax(120.seconds)
1210
implicit val retryInterval: RetryInterval = RetryInterval(1.seconds)

integration/invalidation/selective-execution/src/SelectiveExecutionChangedInputsTests.scala

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ import scala.concurrent.duration._
55
import utest._
66
import utest.asserts.{RetryMax, RetryInterval}
77

8-
9-
108
object SelectiveExecutionChangedInputsTests extends UtestIntegrationTestSuite {
119
implicit val retryMax: RetryMax = RetryMax(120.seconds)
1210
implicit val retryInterval: RetryInterval = RetryInterval(1.seconds)
@@ -82,4 +80,3 @@ object SelectiveExecutionChangedInputsTests extends UtestIntegrationTestSuite {
8280
}
8381
}
8482
}
85-

integration/invalidation/selective-execution/src/SelectiveExecutionTests.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,3 @@ object SelectiveExecutionTests extends UtestIntegrationTestSuite {
5656
}
5757
}
5858
}
59-

integration/invalidation/selective-execution/src/SelectiveExecutionWatchTests.scala

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,5 +104,45 @@ object SelectiveExecutionWatchTests extends UtestIntegrationTestSuite {
104104
}
105105
}
106106
}
107+
108+
// Make sure that if a task fail/skipped/aborted during `--watch`, next time we
109+
// run things selectively we run that task again to help ensure that the user
110+
// seeing no failures in the terminal really means there are no failures left
111+
test("rerun-failures") - retry(1) {
112+
integrationTest { tester =>
113+
import tester._
114+
115+
modifyFile(
116+
workspacePath / "build.mill",
117+
_.replace(
118+
"def fooCommand() = Task.Command {",
119+
"def fooCommand() = Task.Command { sys.error(\"boom foo\")"
120+
)
121+
.replace(
122+
"def barCommand() = Task.Command {",
123+
"def barCommand() = Task.Command { sys.error(\"boom bar\")"
124+
)
125+
)
126+
127+
val spawned = spawn(("-j1", "--watch", "{foo.fooCommand,bar.barCommand}"))
128+
129+
assertEventually { spawned.err.text().contains("boom") }
130+
131+
spawned.clear()
132+
modifyFile(workspacePath / "build.mill", _.replace("sys.error(\"boom foo\")", ""))
133+
134+
assertEventually {
135+
spawned.out.text().contains("Computing fooCommand") &&
136+
// Make sure `bar` re-runs here and blows up again, even though we didn't modify the
137+
// task, so the user is aware there is still a remaining failure after fixing foo
138+
spawned.err.text().contains("boom bar")
139+
}
140+
141+
spawned.clear()
142+
modifyFile(workspacePath / "build.mill", _.replace("sys.error(\"boom bar\")", ""))
143+
144+
assertEventually { spawned.out.text().contains("Computing barCommand") }
145+
}
146+
}
107147
}
108148
}

0 commit comments

Comments
 (0)