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

Clean workers too from the clean command #3579

Merged
merged 6 commits into from
Sep 26, 2024
Merged
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Show workers in resolve / show / inspect too
  • Loading branch information
alexarchambault committed Sep 25, 2024
commit cfcd3a245cb070149529724f2b3a9ea2b05fe0ef
16 changes: 15 additions & 1 deletion integration/feature/docannotations/resources/build.mill
Original file line number Diff line number Diff line change
@@ -11,13 +11,27 @@ trait JUnitTests extends TestModule.Junit4 {
def task = Task {
"???"
}

/**
* *The worker*
*/
def theWorker = Task.Worker {
()
}
}

/**
* The Core Module Docz!
*/
object core extends JavaModule {
object test extends JavaTests with JUnitTests
object test extends JavaTests with JUnitTests {
/**
* -> The worker <-
*/
def theWorker = Task.Worker {
()
}
}

/**
* Core Target Docz!
16 changes: 16 additions & 0 deletions integration/feature/docannotations/src/DocAnnotationsTests.scala
Original file line number Diff line number Diff line change
@@ -113,6 +113,22 @@ object DocAnnotationsTests extends UtestIntegrationTestSuite {
)
)

assert(eval(("inspect", "core.test.theWorker")).isSuccess)
val theWorkerInspect = out("inspect").json.str

assert(
globMatches(
"""core.test.theWorker(build.mill:...)
| -> The worker <-
|
| *The worker*
|
|Inputs:
|""".stripMargin,
theWorkerInspect
)
)

// Make sure both kebab-case and camelCase flags work, even though the
// docs from `inspect` only show the kebab-case version
assert(eval(("core.ivyDepsTree", "--withCompile", "--withRuntime")).isSuccess)
9 changes: 9 additions & 0 deletions main/eval/src/mill/eval/GroupEvaluator.scala
Original file line number Diff line number Diff line change
@@ -375,6 +375,15 @@ private[mill] trait GroupEvaluator {
.map { w =>
upickle.default.writeJs(v.value)(w.asInstanceOf[upickle.default.Writer[Any]])
}
.orElse {
labelled.task.asWorker.map { w =>
ujson.Obj(
"worker" -> ujson.Str(labelled.segments.render),
"toString" -> ujson.Str(v.value.toString),
"inputsHash" -> ujson.Num(inputsHash)
)
}
}

for (json <- terminalResult) {
os.write.over(
15 changes: 9 additions & 6 deletions main/resolve/src/mill/resolve/Resolve.scala
Original file line number Diff line number Diff line change
@@ -41,10 +41,10 @@ object Resolve {
allowPositionalCommandArgs: Boolean
) = {
val taskList = resolved.map {
case r: Resolved.Target =>
case r: Resolved.NamedTask =>
val instantiated = ResolveCore
.instantiateModule(rootModule, r.segments.init)
.flatMap(instantiateTarget(r, _))
.flatMap(instantiateNamedTask(r, _))

instantiated.map(Some(_))

@@ -76,7 +76,7 @@ object Resolve {

directChildrenOrErr.flatMap(directChildren =>
directChildren.head match {
case r: Resolved.Target => instantiateTarget(r, value).map(Some(_))
case r: Resolved.NamedTask => instantiateNamedTask(r, value).map(Some(_))
case r: Resolved.Command =>
instantiateCommand(
rootModule,
@@ -104,13 +104,16 @@ object Resolve {
items.distinctBy(_.ctx.segments)
}

private def instantiateTarget(r: Resolved.Target, p: Module): Either[String, Target[_]] = {
private def instantiateNamedTask(
r: Resolved.NamedTask,
p: Module
): Either[String, NamedTask[_]] = {
val definition = Reflect
.reflect(p.getClass, classOf[Target[_]], _ == r.segments.parts.last, true)
.reflect(p.getClass, classOf[NamedTask[_]], _ == r.segments.parts.last, true)
.head

ResolveCore.catchWrapException(
definition.invoke(p).asInstanceOf[Target[_]]
definition.invoke(p).asInstanceOf[NamedTask[_]]
)
}

12 changes: 6 additions & 6 deletions main/resolve/src/mill/resolve/ResolveCore.scala
Original file line number Diff line number Diff line change
@@ -29,7 +29,7 @@ private object ResolveCore {

object Resolved {
case class Module(segments: Segments, cls: Class[_]) extends Resolved
case class Target(segments: Segments) extends Resolved
case class NamedTask(segments: Segments) extends Resolved
case class Command(segments: Segments) extends Resolved
}

@@ -327,7 +327,7 @@ private object ResolveCore {
.map(
_.map {
case (Resolved.Module(s, cls), _) => Resolved.Module(segments ++ s, cls)
case (Resolved.Target(s), _) => Resolved.Target(segments ++ s)
case (Resolved.NamedTask(s), _) => Resolved.NamedTask(segments ++ s)
case (Resolved.Command(s), _) => Resolved.Command(segments ++ s)
}
.toSet
@@ -376,10 +376,10 @@ private object ResolveCore {
}
}

val targets = Reflect
.reflect(cls, classOf[Target[_]], namePred, noParams = true)
val namedTasks = Reflect
.reflect(cls, classOf[NamedTask[_]], namePred, noParams = true)
.map { m =>
Resolved.Target(Segments.labels(decode(m.getName))) ->
Resolved.NamedTask(Segments.labels(decode(m.getName))) ->
None
}

@@ -388,7 +388,7 @@ private object ResolveCore {
.map(m => decode(m.getName))
.map { name => Resolved.Command(Segments.labels(name)) -> None }

modulesOrErr.map(_ ++ targets ++ commands)
modulesOrErr.map(_ ++ namedTasks ++ commands)
}

def notFoundResult(
2 changes: 1 addition & 1 deletion main/src/mill/main/RunScript.scala
Original file line number Diff line number Diff line change
@@ -62,7 +62,7 @@ object RunScript {
case 0 =>
val nameAndJson = for (t <- targets.toSeq) yield {
t match {
case t: mill.define.NamedTask[_] =>
case t: mill.define.NamedTask[_] if t.writerOpt.isDefined || t.asWorker.isDefined =>
val jsonFile = EvaluatorPaths.resolveDestPaths(evaluator.outPath, t).meta
val metadata = upickle.default.read[Evaluator.Cached](ujson.read(jsonFile.toIO))
Some((t.toString, metadata.value))
43 changes: 43 additions & 0 deletions main/test/src/mill/main/MainModuleTests.scala
Original file line number Diff line number Diff line change
@@ -27,6 +27,18 @@ object MainModuleTests extends TestSuite {
Map("1" -> "hello", "2" -> "world")
}
def helloCommand(x: Int, y: Task[String]) = Task.Command { (x, y(), hello()) }

/**
* The hello worker
*/
def helloWorker = Task.Worker {
// non-JSON-serializable, but everything should work fine nonetheless
new AutoCloseable {
def close() = ()
override def toString =
"theHelloWorker"
}
}
override lazy val millDiscover: Discover = Discover[this.type]
}

@@ -93,6 +105,17 @@ object MainModuleTests extends TestSuite {
res.contains("hello")
)
}
test("worker") - UnitTester(mainModule, null).scoped { eval =>
val Right(result) = eval.apply("inspect", "helloWorker")

val Seq(res: String) = result.value
assert(
res.startsWith("helloWorker("),
res.contains("MainModuleTests.scala:"),
res.contains("The hello worker"),
res.contains("hello")
)
}
}

test("show") {
@@ -173,6 +196,14 @@ object MainModuleTests extends TestSuite {
val Seq(res) = result.value
assert(res == ujson.Arr(1337, "lol", ujson.Arr("hello", "world")))
}

test("worker") {
val Right(result) = evaluator.apply("show", "helloWorker")
val Seq(res: ujson.Obj) = result.value
assert(res("toString").str == "theHelloWorker")
assert(res("worker").str == "helloWorker")
assert(res("inputsHash").numOpt.isDefined)
}
}

test("showNamed") {
@@ -209,6 +240,18 @@ object MainModuleTests extends TestSuite {
}
}

test("resolve") {
UnitTester(mainModule, null).scoped { eval =>
val Right(result) = eval.apply("resolve", "_")

val Seq(res: Seq[String]) = result.value
assert(res.contains("hello"))
assert(res.contains("hello2"))
assert(res.contains("helloCommand"))
assert(res.contains("helloWorker"))
}
}

test("clean") {
val ev = UnitTester(cleanModule, null)
val out = ev.evaluator.outPath