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 BOM / dependency management support #3924

Merged
merged 43 commits into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
910e8a4
Remove trailing space
alexarchambault Nov 8, 2024
4f5f070
NIT Use allIvyDeps task
alexarchambault Nov 8, 2024
3e8643d
WIP Add BOM support
alexarchambault Nov 8, 2024
f796d0c
Merge branch 'main' into pr/bom-support
alexarchambault Nov 13, 2024
bc5e1b3
more
alexarchambault Nov 13, 2024
425b4aa
Merge branch 'main' into pr/bom-support
alexarchambault Nov 19, 2024
732c659
more
alexarchambault Nov 19, 2024
17259c0
fixup
alexarchambault Nov 19, 2024
a8b86e3
more
alexarchambault Nov 19, 2024
67ff17a
Merge branch 'main' into pr/bom-support
alexarchambault Nov 20, 2024
067d84d
more
alexarchambault Nov 20, 2024
17c3084
more
alexarchambault Nov 21, 2024
c143182
Merge branch 'main' into pr/bom-support
alexarchambault Nov 21, 2024
a45ddd6
fix
alexarchambault Nov 21, 2024
d601c44
Revert UnidocModule stuff
alexarchambault Nov 21, 2024
20f59c5
Merge branch 'main' into pr/bom-support
alexarchambault Nov 21, 2024
8c00ccb
Merge branch 'main' into pr/bom-support
alexarchambault Nov 21, 2024
f53fd8d
tweaking
alexarchambault Nov 21, 2024
c549b21
alexarchambault Nov 21, 2024
06b0c5b
more
alexarchambault Nov 21, 2024
1828975
fmt
alexarchambault Nov 21, 2024
c9054a3
more
alexarchambault Nov 21, 2024
3dbc225
Starting to look good 🤔
alexarchambault Nov 21, 2024
b260f6f
Merge branch 'main' into pr/bom-support
alexarchambault Nov 21, 2024
e13a102
Merge branch 'main' into pr/bom-support
alexarchambault Nov 22, 2024
9c75f73
Merge branch 'main' into pr/bom-support
alexarchambault Nov 22, 2024
97cb113
more
alexarchambault Nov 22, 2024
13fdbca
Merge branch 'main' into pr/bom-support
alexarchambault Nov 25, 2024
8e28493
more
alexarchambault Nov 25, 2024
7950d4f
fmt
alexarchambault Nov 25, 2024
4f78fe8
Merge branch 'main' into pr/bom-support
alexarchambault Nov 27, 2024
03857e0
Merge branch 'main' into pr/bom-support
alexarchambault Nov 27, 2024
745b500
more - needs clean-up, only checking if CI passes
alexarchambault Nov 27, 2024
26b5c54
Merge branch 'main' into pr/bom-support
alexarchambault Nov 28, 2024
f286477
Merge branch 'main' into pr/bom-support
alexarchambault Dec 2, 2024
8aa498a
more
alexarchambault Dec 2, 2024
61b6061
fmt
alexarchambault Dec 2, 2024
5bd61aa
Merge branch 'main' into pr/bom-support
alexarchambault Dec 3, 2024
73f5c10
rework / add doc, remove parentDep stuff
alexarchambault Dec 3, 2024
e5fe19f
Merge branch 'main' into pr/bom-support
alexarchambault Dec 4, 2024
169a747
Address review comments
alexarchambault Dec 4, 2024
2a5ca63
nit
alexarchambault Dec 4, 2024
26116a9
Minor refactoring
alexarchambault Dec 4, 2024
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
4 changes: 2 additions & 2 deletions build.mill
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ object Settings {
val docUrl = "https://mill-build.org"
// the exact branches containing a doc root
val docBranches = Seq()
// the exact tags containing a doc root. Publish docs for
// the exact tags containing a doc root. Publish docs for
// the last point version in each minor release series
val legacyDocTags: Seq[String] = Seq(
"0.9.12",
Expand Down Expand Up @@ -114,7 +114,7 @@ object Deps {
val asmTree = ivy"org.ow2.asm:asm-tree:9.7.1"
val bloopConfig = ivy"ch.epfl.scala::bloop-config:1.5.5"

val coursier = ivy"io.get-coursier::coursier:2.1.14"
val coursier = ivy"io.get-coursier::coursier:2.1.17"
val coursierInterface = ivy"io.get-coursier:interface:1.0.22"

val cask = ivy"com.lihaoyi::cask:0.9.4"
Expand Down
34 changes: 34 additions & 0 deletions integration/feature/bom/resources/build.mill
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package build
lefou marked this conversation as resolved.
Show resolved Hide resolved

import mill._
import mill.scalalib._

object `google-cloud-java` extends JavaModule {
def bomDeps = Agg(
ivy"com.google.cloud:libraries-bom:26.50.0"
)
def ivyDeps = Agg(
ivy"com.google.protobuf:protobuf-java:_"
)
}

object `google-cloud-java-no-bom` extends JavaModule {
def ivyDeps = Agg(
ivy"com.google.protobuf:protobuf-java:_"
)
}

object `google-cloud-scala` extends JavaModule {
def bomDeps = Agg(
ivy"com.google.cloud:libraries-bom:26.50.0"
)
def ivyDeps = Agg(
ivy"com.thesamet.scalapb:scalapbc_2.13:0.9.8"
)
}

object `google-cloud-scala-no-bom` extends JavaModule {
def ivyDeps = Agg(
ivy"com.thesamet.scalapb:scalapbc_2.13:0.9.8"
)
}
58 changes: 58 additions & 0 deletions integration/feature/bom/src/BomTests.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package mill.integration

import mill.testkit.{IntegrationTester, UtestIntegrationTestSuite}
import utest._

object BomTests extends UtestIntegrationTestSuite {

def tests: Tests = Tests {

def expectedProtobufJavaVersion = "4.28.3"

def compileClasspathFileNames(tester: IntegrationTester, moduleName: String): Seq[String] = {
import tester._
val res = eval(
("show", s"$moduleName.compileClasspath"),
stderr = os.Inherit,
check = true
)
ujson.read(res.out).arr.map(v => os.Path(v.str.split(":").last).last).toSeq
}

test("googleCloudJavaCheck") - integrationTest { tester =>
import tester._

val res = eval(
("show", "google-cloud-java-no-bom.compileClasspath"),
check = false
)
assert(
res.err.contains(
"not found: https://repo1.maven.org/maven2/com/google/protobuf/protobuf-java/_/protobuf-java-_.pom"
)
)
}

test("googleCloudJava") - integrationTest { tester =>
val compileClasspathFileNames0 = compileClasspathFileNames(tester, "google-cloud-java")
assert(compileClasspathFileNames0.contains(s"protobuf-java-$expectedProtobufJavaVersion.jar"))
}

test("googleCloudScalaCheck") - integrationTest { tester =>
val compileClasspathFileNames0 =
compileClasspathFileNames(tester, "google-cloud-scala-no-bom")
assert(
compileClasspathFileNames0.exists(v => v.startsWith("protobuf-java-") && v.endsWith(".jar"))
)
assert(
!compileClasspathFileNames0.contains(s"protobuf-java-$expectedProtobufJavaVersion.jar")
)
}

test("googleCloudScala") - integrationTest { tester =>
val compileClasspathFileNames0 = compileClasspathFileNames(tester, "google-cloud-scala")
assert(compileClasspathFileNames0.contains(s"protobuf-java-$expectedProtobufJavaVersion.jar"))
}

}
}
25 changes: 15 additions & 10 deletions main/util/src/mill/util/CoursierSupport.scala
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ trait CoursierSupport {
ctx: Option[mill.api.Ctx.Log] = None,
coursierCacheCustomizer: Option[FileCache[Task] => FileCache[Task]] = None,
resolveFilter: os.Path => Boolean = _ => true,
artifactTypes: Option[Set[Type]] = None
artifactTypes: Option[Set[Type]] = None,
bomDeps: IterableOnce[Dependency] = Nil
): Result[Agg[PathRef]] = {
def isLocalTestDep(dep: Dependency): Option[Seq[PathRef]] = {
val org = dep.module.organization.value
Expand All @@ -61,12 +62,8 @@ trait CoursierSupport {
classpathResourceText.map(_.linesIterator.map(s => PathRef(os.Path(s))).toSeq)
}

val (localTestDeps, remoteDeps) = deps.iterator.toSeq.partitionMap(d =>
isLocalTestDep(d) match {
case None => Right(d)
case Some(vs) => Left(vs)
}
)
val (localTestDeps, remoteDeps) =
deps.iterator.toSeq.partitionMap(d => isLocalTestDep(d).toLeft(d))

val resolutionRes = resolveDependenciesMetadataSafe(
repositories,
Expand All @@ -75,7 +72,8 @@ trait CoursierSupport {
mapDependencies,
customizer,
ctx,
coursierCacheCustomizer
coursierCacheCustomizer,
bomDeps
)

resolutionRes.flatMap { resolution =>
Expand Down Expand Up @@ -159,7 +157,8 @@ trait CoursierSupport {
mapDependencies,
customizer,
ctx,
coursierCacheCustomizer
coursierCacheCustomizer,
Nil
)
(deps0, res.getOrThrow)
}
Expand All @@ -171,13 +170,18 @@ trait CoursierSupport {
mapDependencies: Option[Dependency => Dependency] = None,
customizer: Option[Resolution => Resolution] = None,
ctx: Option[mill.api.Ctx.Log] = None,
coursierCacheCustomizer: Option[FileCache[Task] => FileCache[Task]] = None
coursierCacheCustomizer: Option[FileCache[Task] => FileCache[Task]] = None,
bomDeps: IterableOnce[Dependency] = Nil
): Result[Resolution] = {

val rootDeps = deps.iterator
.map(d => mapDependencies.fold(d)(_.apply(d)))
.toSeq

val bomDeps0 = bomDeps.iterator
.map(d => mapDependencies.fold(d)(_.apply(d)))
.toSeq

val forceVersions = force.iterator
.map(mapDependencies.getOrElse(identity[Dependency](_)))
.map { d => d.module -> d.version }
Expand All @@ -191,6 +195,7 @@ trait CoursierSupport {
val resolve = Resolve()
.withCache(coursierCache0)
.withDependencies(rootDeps)
.withBomDependencies(bomDeps0)
.withRepositories(repositories)
.withResolutionParams(resolutionParams)
.withMapDependenciesOpt(mapDependencies)
Expand Down
19 changes: 15 additions & 4 deletions scalalib/src/mill/scalalib/CoursierModule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,14 @@ trait CoursierModule extends mill.Module {
def resolveDeps(
deps: Task[Agg[BoundDep]],
sources: Boolean = false,
artifactTypes: Option[Set[Type]] = None
artifactTypes: Option[Set[Type]] = None,
bomDeps: Task[Agg[BoundDep]] = Task.Anon(Agg.empty[BoundDep])
): Task[Agg[PathRef]] =
Task.Anon {
Lib.resolveDependencies(
repositories = repositoriesTask(),
deps = deps(),
bomDeps = bomDeps(),
sources = sources,
artifactTypes = artifactTypes,
mapDependencies = Some(mapDependencies()),
Expand All @@ -74,7 +76,7 @@ trait CoursierModule extends mill.Module {
deps: Task[Agg[BoundDep]],
sources: Boolean
): Task[Agg[PathRef]] =
resolveDeps(deps, sources, None)
resolveDeps(deps, sources, None, Task.Anon(Agg.empty[BoundDep]))

/**
* Map dependencies before resolving them.
Expand Down Expand Up @@ -148,11 +150,13 @@ object CoursierModule {
def resolveDeps[T: CoursierModule.Resolvable](
deps: IterableOnce[T],
sources: Boolean = false,
artifactTypes: Option[Set[coursier.Type]] = None
artifactTypes: Option[Set[coursier.Type]] = None,
bomDeps: IterableOnce[T] = Nil
): Agg[PathRef] = {
Lib.resolveDependencies(
repositories = repositories,
deps = deps.map(implicitly[CoursierModule.Resolvable[T]].bind(_, bind)),
bomDeps = bomDeps.map(implicitly[CoursierModule.Resolvable[T]].bind(_, bind)),
sources = sources,
artifactTypes = artifactTypes,
mapDependencies = mapDependencies,
Expand All @@ -162,12 +166,19 @@ object CoursierModule {
).getOrThrow
}

def resolveDeps[T: CoursierModule.Resolvable](
deps: IterableOnce[T],
sources: Boolean,
artifactTypes: Option[Set[coursier.Type]]
): Agg[PathRef] =
resolveDeps(deps, sources, artifactTypes, Nil)

@deprecated("Use the override accepting artifactTypes", "Mill after 0.12.0-RC3")
def resolveDeps[T: CoursierModule.Resolvable](
deps: IterableOnce[T],
sources: Boolean
): Agg[PathRef] =
resolveDeps(deps, sources, None)
resolveDeps(deps, sources, None, Nil)
}

sealed trait Resolvable[T] {
Expand Down
20 changes: 15 additions & 5 deletions scalalib/src/mill/scalalib/JavaModule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,12 @@ trait JavaModule
*/
def runIvyDeps: T[Agg[Dep]] = Task { Agg.empty[Dep] }

/**
* Any BOM dependencies you want to add to this Module, in the format
* ivy"org:name:version"
*/
def bomDeps: T[Agg[Dep]] = Task { Agg.empty[Dep] }

/**
* Default artifact types to fetch and put in the classpath. Add extra types
* here if you'd like fancy artifact extensions to be fetched.
Expand Down Expand Up @@ -327,7 +333,7 @@ trait JavaModule
* This is calculated from [[ivyDeps]], [[mandatoryIvyDeps]] and recursively from [[moduleDeps]].
*/
def transitiveIvyDeps: T[Agg[BoundDep]] = Task {
(ivyDeps() ++ mandatoryIvyDeps()).map(bindDependency()) ++
allIvyDeps().map(bindDependency()) ++
T.traverse(moduleDepsChecked)(_.transitiveIvyDeps)().flatten
}

Expand Down Expand Up @@ -604,7 +610,8 @@ trait JavaModule
def resolvedIvyDeps: T[Agg[PathRef]] = Task {
defaultResolver().resolveDeps(
transitiveCompileIvyDeps() ++ transitiveIvyDeps(),
artifactTypes = Some(artifactTypes())
artifactTypes = Some(artifactTypes()),
bomDeps = bomDeps().map(bindDependency())
)
}

Expand All @@ -619,7 +626,8 @@ trait JavaModule
def resolvedRunIvyDeps: T[Agg[PathRef]] = Task {
defaultResolver().resolveDeps(
transitiveRunIvyDeps() ++ transitiveIvyDeps(),
artifactTypes = Some(artifactTypes())
artifactTypes = Some(artifactTypes()),
bomDeps = bomDeps().map(bindDependency())
)
}

Expand Down Expand Up @@ -1096,13 +1104,15 @@ trait JavaModule
Task.Anon {
defaultResolver().resolveDeps(
transitiveCompileIvyDeps() ++ transitiveIvyDeps(),
sources = true
sources = true,
bomDeps = bomDeps().map(bindDependency())
)
},
Task.Anon {
defaultResolver().resolveDeps(
transitiveRunIvyDeps() ++ transitiveIvyDeps(),
sources = true
sources = true,
bomDeps = bomDeps().map(bindDependency())
)
}
)
Expand Down
4 changes: 4 additions & 0 deletions scalalib/src/mill/scalalib/JsonFormatters.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ trait JsonFormatters {
implicit lazy val configurationFormat: RW[coursier.core.Configuration] = upickle.default.macroRW
implicit lazy val typeFormat: RW[coursier.core.Type] = upickle.default.macroRW
implicit lazy val classifierFormat: RW[coursier.core.Classifier] = upickle.default.macroRW
implicit lazy val depMgmtKeyFormat: RW[coursier.core.DependencyManagement.Key] =
upickle.default.macroRW
implicit lazy val depMgmtValuesFormat: RW[coursier.core.DependencyManagement.Values] =
upickle.default.macroRW

}
object JsonFormatters extends JsonFormatters
13 changes: 9 additions & 4 deletions scalalib/src/mill/scalalib/Lib.scala
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ object Lib {
ctx: Option[Ctx.Log] = None,
coursierCacheCustomizer: Option[
coursier.cache.FileCache[Task] => coursier.cache.FileCache[Task]
] = None
] = None,
bomDeps: IterableOnce[BoundDep] = Nil
): Result[Resolution] = {
val depSeq = deps.iterator.toSeq
mill.util.Jvm.resolveDependenciesMetadataSafe(
Expand All @@ -69,7 +70,8 @@ object Lib {
mapDependencies = mapDependencies,
customizer = customizer,
ctx = ctx,
coursierCacheCustomizer = coursierCacheCustomizer
coursierCacheCustomizer = coursierCacheCustomizer,
bomDeps = bomDeps.iterator.toSeq.map(_.dep)
)
}

Expand All @@ -90,12 +92,14 @@ object Lib {
coursierCacheCustomizer: Option[
coursier.cache.FileCache[Task] => coursier.cache.FileCache[Task]
] = None,
artifactTypes: Option[Set[Type]] = None
artifactTypes: Option[Set[Type]] = None,
bomDeps: IterableOnce[BoundDep] = Nil
): Result[Agg[PathRef]] = {
val depSeq = deps.iterator.toSeq
mill.util.Jvm.resolveDependencies(
repositories = repositories,
deps = depSeq.map(_.dep),
bomDeps = bomDeps.iterator.map(_.dep).toSeq,
force = depSeq.filter(_.force).map(_.dep),
sources = sources,
artifactTypes = artifactTypes,
Expand Down Expand Up @@ -126,7 +130,8 @@ object Lib {
customizer,
ctx,
coursierCacheCustomizer,
None
None,
Nil
)

def scalaCompilerIvyDeps(scalaOrganization: String, scalaVersion: String): Loose.Agg[Dep] =
Expand Down
7 changes: 6 additions & 1 deletion scalalib/src/mill/scalalib/PublishModule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,19 @@ trait PublishModule extends JavaModule { outer =>
compileModulePomDeps.map(Dependency(_, Scope.Provided))
}

def publishXmlBomDeps: Task[Agg[Dependency]] = Task.Anon {
bomDeps().map(resolvePublishDependency.apply().apply(_))
}

def pom: T[PathRef] = Task {
val pom = Pom(
artifactMetadata(),
publishXmlDeps(),
artifactId(),
pomSettings(),
publishProperties(),
packagingType = pomPackagingType
packagingType = pomPackagingType,
bomDependencies = publishXmlBomDeps()
)
val pomPath = T.dest / s"${artifactId()}-${publishVersion()}.pom"
os.write.over(pomPath, pom)
Expand Down
Loading
Loading