Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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
44 changes: 29 additions & 15 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,15 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
scala: [2.12.21]
java: [temurin@8, temurin@11, temurin@17]
scala: [2.12.21, 3.8.2]
java: [temurin@17, temurin@11, temurin@8]
exclude:
- java: temurin@8
os: macos-latest
- scala: 3.8.2
java: temurin@8
- scala: 3.8.2
java: temurin@11
runs-on: ${{ matrix.os }}
steps:
- name: Ignore line ending differences in git
Expand All @@ -48,12 +52,12 @@ jobs:
with:
fetch-depth: 0

- name: Setup Java (temurin@8)
if: matrix.java == 'temurin@8'
- name: Setup Java (temurin@17)
if: matrix.java == 'temurin@17'
uses: actions/setup-java@v5
with:
distribution: temurin
java-version: 8
java-version: 17
cache: sbt

- name: Setup Java (temurin@11)
Expand All @@ -64,12 +68,12 @@ jobs:
java-version: 11
cache: sbt

- name: Setup Java (temurin@17)
if: matrix.java == 'temurin@17'
- name: Setup Java (temurin@8)
if: matrix.java == 'temurin@8'
uses: actions/setup-java@v5
with:
distribution: temurin
java-version: 17
java-version: 8
cache: sbt

- name: Setup sbt
Expand Down Expand Up @@ -104,7 +108,7 @@ jobs:
matrix:
os: [ubuntu-latest]
scala: [2.12.21]
java: [temurin@8]
java: [temurin@17]
runs-on: ${{ matrix.os }}
steps:
- name: Ignore line ending differences in git
Expand All @@ -124,12 +128,12 @@ jobs:
with:
fetch-depth: 0

- name: Setup Java (temurin@8)
if: matrix.java == 'temurin@8'
- name: Setup Java (temurin@17)
if: matrix.java == 'temurin@17'
uses: actions/setup-java@v5
with:
distribution: temurin
java-version: 8
java-version: 17
cache: sbt

- name: Setup Java (temurin@11)
Expand All @@ -140,12 +144,12 @@ jobs:
java-version: 11
cache: sbt

- name: Setup Java (temurin@17)
if: matrix.java == 'temurin@17'
- name: Setup Java (temurin@8)
if: matrix.java == 'temurin@8'
uses: actions/setup-java@v5
with:
distribution: temurin
java-version: 17
java-version: 8
cache: sbt

- name: Setup sbt
Expand All @@ -161,6 +165,16 @@ jobs:
tar xf targets.tar
rm targets.tar

- name: Download target directories (3.8.2)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

using the cache is an attack vector and this job is also used for releases - does it really make a big difference? Does this come in via githubWorkflowGenerate? Could we disable it?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This behaviour was already in the build before this PR: see line https://github.com/sbt/sbt-sbom/pull/219/changes#diff-b803fcb7f17ed9235f1e5cb1fcd2f5d3b2838429d4368ae4c57ce4436577f03fR158 which does the same for Scala 2.12.

We could disable this behavior with ThisBuild / githubWorkflowArtifactUpload := false which would make the publish job run slower but will remove caching. WDYT?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, gotcha. I think that would be good - we're not so active that it matters a lot for us anyway

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed, now the caching is disabled.

uses: actions/download-artifact@v6
with:
name: target-${{ matrix.os }}-3.8.2-${{ matrix.java }}

- name: Inflate target directories (3.8.2)
run: |
tar xf targets.tar
rm targets.tar

- name: Publish project
env:
PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }}
Expand Down
38 changes: 28 additions & 10 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,29 @@ ThisBuild / organization := Organization.organization
ThisBuild / organizationName := Organization.organizationName
ThisBuild / organizationHomepage := Organization.organizationHomepage
val scala212 = "2.12.21"
val scala3 = "3.8.2"
ThisBuild / scalaVersion := scala212
ThisBuild / crossScalaVersions := Seq(scala212)
ThisBuild / crossScalaVersions := Seq(scala212, scala3)
ThisBuild / homepage := Project.homepage
ThisBuild / developers := Project.developers
ThisBuild / licenses := Project.licenses
ThisBuild / scmInfo := Project.scmInfo
ThisBuild / description := Project.description

def sbtVersionForPlugin(scalaBinary: String): String =
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe name this clearer to reflect that this is the version we run the scripted tests with?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one is not only for the scripted tests but also for the plugin itself - it is used twice in this file.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, right, I didn't notice. In that case are we sure we want these to be the same? I'd say we'd want to build with the "latest" sbt but test against the "minimum supported".

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, fixed this. Testing against minimal sbt 1.6.0 as per README, and 2.0.0-RC11 for sbt 2. I don't think it's reasonable to specify a minimal supported version for sbt 2 to be an RC version; we should wait until 2.0.0 and set the minimal to it.

scalaBinary match {
case "2.12" => "1.10.7"
case _ => "2.0.0-RC11"
}

lazy val root = (project in file("."))
.enablePlugins(ScriptedPlugin, BuildInfoPlugin)
.enablePlugins(SbtPlugin, ScriptedPlugin, BuildInfoPlugin)
.settings(
name := "sbt-sbom",
sbtPlugin := true,
libraryDependencies ++= Dependencies.library,
addSbtPlugin("com.github.sbt" % "sbt2-compat" % "0.1.0"),
buildInfoPackage := "com.github.sbt.sbom",
(pluginCrossBuild / sbtVersion) := sbtVersionForPlugin(scalaBinaryVersion.value),
scriptedLaunchOpts := {
scriptedLaunchOpts.value ++ Seq(
"-Xmx1024M",
Expand All @@ -29,7 +37,7 @@ lazy val root = (project in file("."))
)
},
scriptedBufferLog := false,
scriptedSbt := "1.6.0",
scriptedSbt := sbtVersionForPlugin(scalaBinaryVersion.value),
)

ThisBuild / pomIncludeRepository := { _ =>
Expand Down Expand Up @@ -65,20 +73,30 @@ ThisBuild / githubWorkflowPublish := Seq(
ThisBuild / githubWorkflowOSes := Seq("ubuntu-latest", "macos-latest", "windows-latest")

ThisBuild / githubWorkflowJavaVersions := Seq(
JavaSpec.temurin("8"),
// Java 17 first: publish job uses the head of this list when downloading staged artifacts; sbt 2 (Scala 3 axis) needs 17+.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW I'm proposing to make Java 17 the minimum in #205 but haven't dared pull the trigger yet.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the publish job with sbt ci-release can use java 17 and we can just use the -release:8 flag. Seems like most sbt plugins are doing that for now, see my other comment I just added to this PR.

JavaSpec.temurin("17"),
JavaSpec.temurin("11"),
JavaSpec.temurin("17")
JavaSpec.temurin("8")
)

ThisBuild / githubWorkflowBuildMatrixExclusions ++= Seq(
MatrixExclude(Map("java" -> "temurin@8", "os" -> "macos-latest")),
MatrixExclude(Map("scala" -> scala3, "java" -> "temurin@8")),
MatrixExclude(Map("scala" -> scala3, "java" -> "temurin@11"))
)

ThisBuild / githubWorkflowBuildMatrixExclusions += MatrixExclude(Map("java" -> "temurin@8", "os" -> "macos-latest"))
ThisBuild / githubWorkflowScalaVersions := Seq(scala212, scala3)

// scalafix specific settings
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we should remove this comment or move the options elsewhere :)

inThisBuild(
List(
semanticdbEnabled := true,
semanticdbVersion := scalafixSemanticdb.revision,
scalacOptions ++= Seq(
"-Ywarn-unused"
)
scalacOptions ++= {
scalaBinaryVersion.value match {
case "2.12" => Seq("-Ywarn-unused")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that makes sense to me (and would be good to include in #205 as well, bumping it to 17)

case _ => Seq("-Wunused:all")
}
}
)
)
11 changes: 11 additions & 0 deletions src/main/scala-2.12/com/github/sbt/sbom/PluginCompat.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// SPDX-FileCopyrightText: The sbt-sbom team
//
// SPDX-License-Identifier: MIT

package com.github.sbt.sbom

import sbt.librarymanagement.Configurations

private[sbt] object PluginCompat {
val integrationTest: sbt.Configuration = Configurations.IntegrationTest
}
19 changes: 19 additions & 0 deletions src/main/scala-3/com/github/sbt/sbom/PluginCompat.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// SPDX-FileCopyrightText: The sbt-sbom team
//
// SPDX-License-Identifier: MIT

package com.github.sbt.sbom

import sbt.*

private[sbt] object PluginCompat {
val integrationTest: Configuration =
Configuration.of(
"IntegrationTest",
"it",
"Integration tests",
false,
Vector(Runtime),
true
)
}
4 changes: 2 additions & 2 deletions src/main/scala/com/github/sbt/sbom/BomExtractor.scala
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,8 @@ class BomExtractor(settings: BomExtractorParams, report: UpdateReport, rootModul
configuration match {
case Test =>
Seq(Test, Runtime, Compile)
case IntegrationTest =>
Seq(IntegrationTest, Runtime, Compile)
case cfg if cfg == PluginCompat.integrationTest =>
Seq(PluginCompat.integrationTest, Runtime, Compile)
case Runtime =>
Seq(Runtime, Compile)
case Compile =>
Expand Down
61 changes: 40 additions & 21 deletions src/main/scala/com/github/sbt/sbom/BomSbtPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ package com.github.sbt.sbom
import com.github.sbt.sbom.PluginConstants.*
import org.cyclonedx.model.Component
import sbt.*
import sbt.Keys.{ artifact, configuration, packagedArtifacts, version }
import sbt.Keys.{ artifact, configuration, fileConverter, packagedArtifacts, version }
import sbt.plugins.JvmPlugin
import sbtcompat.PluginCompat.*
import xsbti.FileConverter

import scala.language.postfixOps

Expand Down Expand Up @@ -63,6 +65,12 @@ object BomSbtPlugin extends AutoPlugin {
lazy val bomOutputPath: SettingKey[String] = settingKey[String](
"Output path of the created BOM file. BOM File will be placed in target/ directory by default"
)

/**
* Integration-test configuration. On sbt 2.x, `IntegrationTest` was removed from the sbt API; use this config
* instead of `IntegrationTest` from sbt to avoid ambiguous imports when cross-building or running on sbt 1.
*/
lazy val SbomIntegrationTest: Configuration = PluginCompat.integrationTest
}

import autoImport.*
Expand All @@ -85,28 +93,39 @@ object BomSbtPlugin extends AutoPlugin {
enableBomSha3Hashes := true,
includeBomExternalReferences := true,
includeBomDependencyTree := true,
makeBom := Def.taskDyn(BomSbtSettings.makeBomTask(Classpaths.updateTask.value, Compile)).value,
listBom := Def.taskDyn(BomSbtSettings.listBomTask(Classpaths.updateTask.value, Compile)).value,
Test / makeBom := Def.taskDyn(BomSbtSettings.makeBomTask(Classpaths.updateTask.value, Test)).value,
Provided / makeBom := Def.taskDyn(BomSbtSettings.makeBomTask(Classpaths.updateTask.value, Provided)).value,
Test / listBom := Def.taskDyn(BomSbtSettings.listBomTask(Classpaths.updateTask.value, Test)).value,
IntegrationTest / makeBom := Def
.taskDyn(BomSbtSettings.makeBomTask(Classpaths.updateTask.value, IntegrationTest))
.value,
IntegrationTest / listBom := Def
.taskDyn(BomSbtSettings.listBomTask(Classpaths.updateTask.value, IntegrationTest))
.value,
bomConfigurations := Def.taskDyn(BomSbtSettings.bomConfigurationTask((configuration ?).value)).value,
makeBom := Def.uncached(Def.taskDyn(BomSbtSettings.makeBomTask(Classpaths.updateTask.value, Compile)).value),
listBom := Def.uncached(Def.taskDyn(BomSbtSettings.listBomTask(Classpaths.updateTask.value, Compile)).value),
Test / makeBom := Def.uncached(Def.taskDyn(BomSbtSettings.makeBomTask(Classpaths.updateTask.value, Test)).value),
Provided / makeBom := Def.uncached(
Def.taskDyn(BomSbtSettings.makeBomTask(Classpaths.updateTask.value, Provided)).value
),
Test / listBom := Def.uncached(Def.taskDyn(BomSbtSettings.listBomTask(Classpaths.updateTask.value, Test)).value),
SbomIntegrationTest / makeBom := Def.uncached(
Def
.taskDyn(BomSbtSettings.makeBomTask(Classpaths.updateTask.value, SbomIntegrationTest))
.value
),
SbomIntegrationTest / listBom := Def.uncached(
Def
.taskDyn(BomSbtSettings.listBomTask(Classpaths.updateTask.value, SbomIntegrationTest))
.value
),
bomConfigurations := Def.uncached(
Def.taskDyn(BomSbtSettings.bomConfigurationTask((configuration ?).value)).value
),
projectType := "library",
bomOutputPath := "",
packagedArtifacts += {
Artifact(
artifact.value.name,
"cyclonedx",
BomFormat.fromSettings(bomFormat.?.value, None, bomSchemaVersion.value).string,
"cyclonedx"
) -> makeBom.value
},
packagedArtifacts := Def.uncached({
implicit val conv: FileConverter = fileConverter.value
packagedArtifacts.value + (
Artifact(
artifact.value.name,
"cyclonedx",
BomFormat.fromSettings(bomFormat.?.value, None, bomSchemaVersion.value).string,
"cyclonedx"
) -> toFileRef(makeBom.value)
)
}),
)
}
}
11 changes: 6 additions & 5 deletions src/main/scala/com/github/sbt/sbom/BomSbtSettings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ package com.github.sbt.sbom

import com.github.sbt.sbom.BomSbtPlugin.autoImport.*
import sbt.*
import sbt.Keys.{ projectID, sLog, scalaBinaryVersion, scalaVersion, target }
import sbt.Keys.{ baseDirectory, projectID, sLog, scalaBinaryVersion, scalaVersion }

object BomSbtSettings {
def makeBomTask(report: UpdateReport, currentConfiguration: Configuration): Def.Initialize[Task[sbt.File]] =
Expand All @@ -18,7 +18,7 @@ object BomSbtSettings {
)

val outputPath = if (bomOutputPath.value.isEmpty) {
target.value
baseDirectory.value / "target"
} else {
sbt.file(bomOutputPath.value)
}
Expand Down Expand Up @@ -74,7 +74,8 @@ object BomSbtSettings {
includeBomExternalReferences.value,
includeBomDependencyTree.value,
projType,
sbt.file(bomOutputPath.value)
if (bomOutputPath.value.isEmpty) baseDirectory.value / "target"
else sbt.file(bomOutputPath.value)
)
).execute
}
Expand All @@ -93,8 +94,8 @@ object BomSbtSettings {
usedConfiguration match {
case Test =>
Seq(Test, Runtime, Compile)
case IntegrationTest =>
Seq(IntegrationTest, Runtime, Compile)
case cfg if cfg == PluginCompat.integrationTest =>
Seq(PluginCompat.integrationTest, Runtime, Compile)
case Runtime =>
Seq(Runtime, Compile)
case Compile =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@ class LicensesArchive(licenses: Seq[License]) {
}
.toList
.groupBy(_._1)
.mapValues(_.map(_._2))
.map { case (k, v) => k -> v.map(_._2) }

private val licenseByNormalizedId: Map[String, License] =
licenses
.groupBy(license => normalizeId(license.id))
.mapValues {
case Seq(license) => license
case licenses => throw new RuntimeException(s"conflicting licenses: $licenses")
.map {
case (id, Seq(license)) => id -> license
case (_, licenses) => throw new RuntimeException(s"conflicting licenses: $licenses")
}

def findByUrl(url: String): Seq[License] = licensesByNormalizedUrl.getOrElse(normalizeUrl(url), Seq.empty)
Expand Down
4 changes: 2 additions & 2 deletions src/sbt-test/dependencies/integrationTest/build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ lazy val root = (project in file("."))
name := "dependencies",
version := "0.1",
libraryDependencies ++= Dependencies.library,
IntegrationTest / bomFileName := "bom.xml",
SbomIntegrationTest / bomFileName := "bom.xml",
includeBomToolVersion := false,
enableBomSha3Hashes := false,
scalaVersion := "2.12.21",
Expand All @@ -24,7 +24,7 @@ lazy val check = taskKey[Unit]("check")
lazy val checkTask = Def.task {
val s: TaskStreams = streams.value
s.log.info("Verifying bom content...")
val bomFile = (IntegrationTest / makeBom).value
val bomFile = (SbomIntegrationTest / makeBom).value

import scala.sys.process._
val changed = Seq("diff", "-w", bomFile.getPath, s"${thisProject.value.base}/etc/bom.xml").! != 0
Expand Down
Loading
Loading