Skip to content

Commit

Permalink
Add selective.resolveChanged to further help debugging selective te…
Browse files Browse the repository at this point in the history
…st execution (#4358)
  • Loading branch information
lihaoyi authored Jan 17, 2025
1 parent 018a64e commit 31d41c0
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 7 deletions.
5 changes: 2 additions & 3 deletions example/fundamentals/out-dir/1-out-files/build.mill
Original file line number Diff line number Diff line change
Expand Up @@ -243,8 +243,7 @@ out/mill-server

> cat out/mill-build/methodCodeHashSignatures.dest/current/spanningInvalidationTree.json
{
"call scala.runtime.BoxesRunTime.boxToInteger(int)java.lang.Integer": {},
"call scala.Predef$#println(java.lang.Object)void": {
...
"def build_.package_$foo$#<init>(build_.package_)void": {
"call build_.package_$foo$!<init>(build_.package_)void": {
"def build_.package_#foo$lzycompute$1()void": {
Expand All @@ -254,7 +253,7 @@ out/mill-server
}
}
}
}
...
}

*/
Expand Down
9 changes: 8 additions & 1 deletion example/large/selective/9-selective-execution/build.mill
Original file line number Diff line number Diff line change
Expand Up @@ -135,13 +135,18 @@ Test run bar.BarTests finished: 0 failed, 0 ignored, 1 total, ...
// ```
//
// For a more detailed report of how the changed inputs resulted in the selected tasks
// being chosen, you can also use `selective.resolveTree` to print out the selected tasks
// being chosen, you can also use `selective.resolveChanged` to print out the upstream
// input tasks that Mill found had changed and will cause downstream tasks to be selected,
// or `selective.resolveTree` to print out the selected tasks
// as a JSON tree illustrating the relationships between the invalidated inputs (at the root
// of the tree) and the selected tasks (at the leaves of the tree)
//

/** Usage

> mill selective.resolveChanged __.test
bar.sources

> mill selective.resolveTree __.test
{
"bar.sources": {
Expand Down Expand Up @@ -176,6 +181,8 @@ Test run bar.BarTests finished: 0 failed, 0 ignored, 1 total, ...
}
}



*/

// Similarly, if we make a change `qux/`, using selective execution will only run tests
Expand Down
2 changes: 1 addition & 1 deletion example/package.mill
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ object `package` extends RootModule with Module {
trait ExampleCrossModule extends build.integration.IntegrationTestModule {
// disable scalafix because these example modules don't have sources causing it to misbehave
def testRepoSourceRoot: T[PathRef] = Task.Source(millSourcePath)
def testRepoRoot: T[PathRef] = Task{ testRepoSourceRoot() }
def testRepoRoot: T[PathRef] = Task { testRepoSourceRoot() }

def sources0 = Task.Sources(millSourcePath)
def sources = Task {
Expand Down
10 changes: 8 additions & 2 deletions main/src/mill/main/SelectiveExecution.scala
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ private[mill] object SelectiveExecution {

case class ChangedTasks(
resolved: Seq[NamedTask[_]],
changedRootTasks: Set[Task[_]],
changedRootTasks: Set[NamedTask[_]],
downstreamTasks: Seq[NamedTask[_]],
results: Map[Task[_], Evaluator.TaskResult[Val]]
)
Expand Down Expand Up @@ -142,7 +142,7 @@ private[mill] object SelectiveExecution {

ChangedTasks(
tasks,
changedRootTasks,
changedRootTasks.collect { case n: NamedTask[_] => n },
downstreamTasks.collect { case n: NamedTask[_] => n },
results
)
Expand All @@ -160,6 +160,12 @@ private[mill] object SelectiveExecution {
}
}

def resolveChanged(evaluator: Evaluator, tasks: Seq[String]): Either[String, Seq[String]] = {
for (changedTasks <- SelectiveExecution.computeChangedTasks(evaluator, tasks)) yield {
changedTasks.changedRootTasks.map(_.ctx.segments.render).toSeq.sorted
}
}

def resolveTree(evaluator: Evaluator, tasks: Seq[String]): Either[String, ujson.Value] = {
for (changedTasks <- SelectiveExecution.computeChangedTasks(evaluator, tasks)) yield {
val taskSet = changedTasks.downstreamTasks.toSet[Task[_]]
Expand Down
14 changes: 14 additions & 0 deletions main/src/mill/main/SelectiveExecutionModule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,20 @@ trait SelectiveExecutionModule extends mill.define.Module {
}
}

/**
* Similar to [[resolve]], but prints the _changed upstream tasks_ rather than
* the _selected downstream tasks_.
*/
def resolveChanged(evaluator: Evaluator, tasks: String*): Command[Seq[String]] =
Task.Command(exclusive = true) {
SelectiveExecution.resolveChanged(evaluator, tasks) match {
case Left(err) => Result.Failure(err)
case Right(success) =>
success.foreach(println)
Result.Success(success)
}
}

/**
* Run after [[prepare]], selectively executes the tasks in [[tasks]] that are
* affected by any changes to the task inputs or task implementations since [[prepare]]
Expand Down

0 comments on commit 31d41c0

Please sign in to comment.