Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add selective.resolveChanged to further help debugging selective test execution #4358

Merged
merged 2 commits into from
Jan 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading