sbt / sbt-projectmatrix

MIT License
124 stars 14 forks source link

Clarify (fix?) aggregation #65

Open keynmol opened 3 years ago

keynmol commented 3 years ago

At the moment the aggregation works differently for project matrices.

// cat build.sbt
lazy val root = projectMatrix.in(file(".")).aggregate(core, api).settings(commons)

lazy val core = projectMatrix.in(file("core")).jvmPlatform(scalaVersions = Seq("2.13.6")).settings(commons)
lazy val api = projectMatrix.in(file("api")).jvmPlatform(scalaVersions = Seq("2.13.6")).settings(commons)

val commons = Seq(
  publishTo := Some("Nexus" at "http://big-scary-corp.com")
)

// project/plugins.sbt
addSbtPlugin("com.eed3si9n" % "sbt-projectmatrix" % "0.8.0")

// $ sbt 'show publishTo'
[info] welcome to sbt 1.5.5 (AdoptOpenJDK Java 11.0.11)
[info] loading global plugins from /.../.sbt/1.0/plugins
[info] loading settings for project tmp-tdxyj8ux-build from plugins.sbt ...
[info] loading project definition from /private/var/folders/m1/3py6pkgs3l1dvt3jpdht11nc0000gn/T/tmp.TDXYj8Ux/project
[info] loading settings for project tmp-tdxyj8ux from build.sbt ...
[info] set current project to tmp-tdxyj8ux (in build file:/private/var/folders/m1/3py6pkgs3l1dvt3jpdht11nc0000gn/T/tmp.TDXYj8Ux/)
[info] core / publishTo
[info]  Some(Nexus: http://big-scary-corp.com)
[info] api / publishTo
[info]  Some(Nexus: http://big-scary-corp.com)
[info] publishTo
[info]  None
[success] Total time: 0 s, completed 13 Oct 2021, 13:28:54

The most common situation I've seen this become a problem is running sbt publish and aggregated project failing with Repository for publishing is not specified.

workaround

To circumvent it, one must go a different route:

diff --git a/build.sbt.old b/build.sbt
index 29f0ee1..564b84a 100644
--- a/build.sbt.old
+++ b/build.sbt
@@ -1,4 +1,4 @@
-lazy val root = projectMatrix.in(file(".")).aggregate(core, api).settings(commons)
+lazy val root = project.in(file(".")).aggregate((core.projectRefs ++ api.projectRefs):_*).settings(commons)

 lazy val core = projectMatrix.in(file("core")).jvmPlatform(scalaVersions = Seq("2.13.6")).settings(commons)

Which behaves as you expect:

// $ sbt 'show publishTo'
[info] welcome to sbt 1.5.5 (AdoptOpenJDK Java 11.0.11)
[info] loading global plugins from /.../.sbt/1.0/plugins
[info] loading settings for project tmp-tdxyj8ux-build from plugins.sbt ...
[info] loading project definition from /private/var/folders/m1/3py6pkgs3l1dvt3jpdht11nc0000gn/T/tmp.TDXYj8Ux/project
[info] loading settings for project root from build.sbt ...
[info] set current project to root (in build file:/private/var/folders/m1/3py6pkgs3l1dvt3jpdht11nc0000gn/T/tmp.TDXYj8Ux/)
[info] core / publishTo
[info]  Some(Nexus: http://big-scary-corp.com)
[info] api / publishTo
[info]  Some(Nexus: http://big-scary-corp.com)
[info] publishTo
[info]  Some(Nexus: http://big-scary-corp.com)
[success] Total time: 0 s, completed 13 Oct 2021, 13:33:12

With the downside of not being more verbose, of course

solution

TBD, I haven't looked at the code in detail yet to understand why this happens.

Suspect that this:

https://github.com/sbt/sbt-projectmatrix/blob/e46c2e3c3a4eba186a204303834e5d01893455b7/src/main/scala/sbt/internal/ProjectMatrix.scala#L249-L250

is to blame.

Not sure what's the best way to solve this?

eed3si9n commented 3 years ago

Maybe you need to add publish / skip := true?

keynmol commented 3 years ago

Doesn't have effect, same with publish := {}.

In fact, if you look at the projects created:

[info]     api
[info]     core
[info]   * tmp-jrfolkaw

tmp-jrfolkaw - is the temp folder I run this in. Which means root was not created at all.

Which makes sense, because just calling aggregate doesn't create any rows, so the project is not registered at all (because it iterates over rows here).

At the same time, you can't really synthesise project rows for root project from aggregatees, right?

I think this needs to have 4 scenarios during projects generation:

  1. if rows is empty and aggregates is empty -> generate no projects
  2. if rows is non-empty and aggregates is non-empty -> generate project according to rows and each one aggregates other projects
  3. if rows is empty and aggregates is non-empty -> generate 1 project which just does aggregation, don't mangle the name of that project
  4. if rows is non-empty and aggregates is empty -> same as 2, without adding .aggregate to generated project

WDYT?

eed3si9n commented 3 years ago
  1. if rows is empty and aggregates is non-empty -> generate 1 project which just does aggregation, don't mangle the name of that project

I am not 100% sure, but I have a feeling that adding this inconsistency would end up making the design weaker. Maybe we could add some method that adds a dummy row?