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

Extract list of dependencies from the BOM #13

Merged
merged 4 commits into from
Feb 12, 2024
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
45 changes: 39 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,51 @@ This plugin is compatible with:
## How to use it
The following text provides a step-by-step guide on how to import [Jackson BOM](https://github.com/FasterXML/jackson-bom) into an sbt project.

Enable the `MAVEN_CENTRAL` repository with a special `pattern` configuration:
### Load the plugin

Add the `sbt-bom` plugin to `plugins.sbt` file.
```scala
addSbtPlugin("com.here.platform" % "sbt-bom" % "1.0.7")
```

If you're encountering issues or using earlier versions, you might have to explicitly declare the Maven Central repository:
```scala
resolvers += Resolver.url(
"MAVEN_CENTRAL",
url("https://repo.maven.apache.org/maven2"))(
Patterns("[organisation]/[module]/[revision]/[artifact]-[revision](-[classifier]).[ext]") )
```
This will enable the project to access plugin files stored in Maven Central, https://repo.maven.apache.org/maven2/com/here/platform/sbt-bom_2.12_1.0/.

Add the `sbt-bom` plugin to `plugins.sbt` file.
### Read & use a BOM

#### In a `dependencyOverrides` context

If you want to get all the dependencies declared in the BOM and use their version to override yours, follow this step.
If you're looking for more control, go to the [general context](#in-a-general-context) section below.

Add BOM dependency to the `build.sbt`:
```scala
import com.here.bom.Bom
lazy val jacksonDependencies = Bom.dependencies("com.fasterxml.jackson" % "jackson-bom" % "2.14.2")
```
addSbtPlugin("com.here.platform" % "sbt-bom" % "1.0.1")

This creates an sbt `Setting` that resolves the list of `ModuleID` declared in a desired BOM.

Enable this setting in the module configuration and use this setting in `dependencyOverrides`:
```scala
lazy val `demo` = project
.in(file("."))
.settings(jacksonDependencies)
.settings(
dependencyOverrides ++= jacksonDependencies.key.value
)
```

#### In a general context

Add BOM dependency to the `build.sbt`:
```
```scala
import com.here.bom.Bom
lazy val jacksonBom = Bom.read("com.fasterxml.jackson" % "jackson-bom" % "2.14.2")(bom => Dependencies(bom))
```
Expand All @@ -44,19 +73,22 @@ This creates an sbt `Setting` that resolves a desired BOM, creates a `Bom` objec
Under the `project` directory, create a `Dependencies` class that takes a `Bom` as a constructor parameter.
Inside this class, we can refer to the versions from the BOM.
The class should expose a list of dependencies that used as `libraryDependencies`
```
```scala
import sbt._
import com.here.bom.Bom

case class Dependencies(bom: Bom) {
val dependencies: Seq[ModuleID] = Seq(
"com.fasterxml.jackson.core" % "jackson-databind" % bom
)

// Note: you may also use bom.bomDependencies which gives you the list of all dependencies declared in the BOM.
// This gives the same result as Bom.dependencies (see above).
}
```

Enable this setting in the module configuration and use this setting in `libraryDependencies`:
```
```scala
lazy val `demo` = project
.in(file("."))
.settings(jacksonBom)
Expand Down Expand Up @@ -108,6 +140,7 @@ The credentials can be supplied through these methods, with the following preced
- Andrii Banias (https://github.com/abanias)
- Anton Wilhelm (https://github.com/devtonhere)
- Dmitry Abramov (https://github.com/dmitriy-abramov)
- Gaël Jourdan-Weil (https://github.com/gaeljw)

## License
Copyright (C) 2019-2024 HERE Europe B.V.
Expand Down
9 changes: 9 additions & 0 deletions plugin/src/main/scala/com/here/bom/Bom.scala
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ object Bom {
}
}

def dependencies(bomArtifact: ModuleID): Def.Setting[Seq[ModuleID]] = {
read(bomArtifact)(bom => bom.bomDependencies)
}

implicit def addBomSyntax(dep: OrganizationArtifactName): BomSyntax = new BomSyntax(dep)

class BomSyntax(dep: OrganizationArtifactName) {
Expand Down Expand Up @@ -85,4 +89,9 @@ object Bom {

trait Bom {
def version(dependency: OrganizationArtifactName): String

/**
* List of all dependencies declared in the BOM
*/
def bomDependencies: Seq[ModuleID]
}
7 changes: 7 additions & 0 deletions plugin/src/main/scala/com/here/bom/internal/BomReader.scala
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,13 @@ class BomReader(pomLocator: IvyPomLocator, logger: Logger, scalaBinaryVersion: S
sys.error(s"Version for ${normalized.group}.${normalized.name} not found in BOM")
)
}

override def bomDependencies: Seq[ModuleID] = {
effectiveVersions.map { case ((group, name), version) =>
ModuleID(group, name, version)
}.toSeq
}

}
}

Expand Down
23 changes: 16 additions & 7 deletions plugin/src/test/scala/com/here/bom/internal/BomReaderSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ class BomReaderSpec extends AnyFlatSpec with Matchers with MockFactory {

val dependency = "com.test" %% "test_module" % bom
dependency.revision should be("1.0")

bom.bomDependencies shouldBe Seq("com.test" % "test_module_2.12" % "1.0")
}

"BomReader" should "assemble the BOM correctly with parent" in {
Expand All @@ -55,13 +57,15 @@ class BomReaderSpec extends AnyFlatSpec with Matchers with MockFactory {

(pomLocatorMock.getPomFile _)
.expects(where((moduleId: NormalizedArtifact) => {
moduleId.group.equals("com.test") && moduleId.name.equals("test_bom_parent") && moduleId.version.equals("1.0")
moduleId.group.equals("com.test") && moduleId.name
.equals("test_bom_parent") && moduleId.version.equals("1.0")
}))
.returns(Some(createMockPomFile("com.test", "test_bom_parent", "1.0", false)))

(pomLocatorMock.getPomFile _)
.expects(where((moduleId: NormalizedArtifact) => {
moduleId.group.equals("com.test") && moduleId.name.equals("test_bom") && moduleId.version.equals("1.0")
moduleId.group.equals("com.test") && moduleId.name.equals("test_bom") && moduleId.version
.equals("1.0")
}))
.returns(Some(createMockPomFile("com.test", "test_bom", "1.0", true)))

Expand All @@ -70,9 +74,16 @@ class BomReaderSpec extends AnyFlatSpec with Matchers with MockFactory {

val dependency = "com.test" %% "test_module" % bom
dependency.revision should be("1.0")

bom.bomDependencies shouldBe Seq("com.test" % "test_module_2.12" % "1.0")
}

private def createMockPomFile(groupId: String, artifactId: String, version: String, addParent: Boolean): File = {
private def createMockPomFile(
molekyla marked this conversation as resolved.
Show resolved Hide resolved
groupId: String,
artifactId: String,
version: String,
addParent: Boolean
): File = {
val tempFile = File.createTempFile("mock", ".xml")

val pomContent =
Expand All @@ -81,8 +92,7 @@ class BomReaderSpec extends AnyFlatSpec with Matchers with MockFactory {
| <groupId>$groupId</groupId>
| <artifactId>$artifactId</artifactId>
| <version>$version</version>
| ${
if (addParent)
| ${if (addParent)
s"""
| <parent>
| <groupId>$groupId</groupId>
Expand All @@ -101,8 +111,7 @@ class BomReaderSpec extends AnyFlatSpec with Matchers with MockFactory {
| | </dependency>
| | </dependencies>
|</dependencyManagement>
|""".stripMargin
}
|""".stripMargin}
|</project >
| """.stripMargin

Expand Down
Loading