Skip to content
This repository was archived by the owner on Jul 7, 2022. It is now read-only.
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
31 changes: 24 additions & 7 deletions src/main/scala/ch/epfl/scala/GithubDependencyGraphPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import scala.util.Properties
import ch.epfl.scala.githubapi._
import sbt.Scoped.richTaskSeq
import sbt._
import sbt.plugins.IvyPlugin
import sbt.internal.util.complete.Parser
import sbt.internal.util.complete.Parsers
import sbt.plugins.JvmPlugin
import sjsonnew.shaded.scalajson.ast.unsafe.JString

object GithubDependencyGraphPlugin extends AutoPlugin {
Expand All @@ -26,18 +28,18 @@ object GithubDependencyGraphPlugin extends AutoPlugin {
val githubManifestsKey: AttributeKey[Map[String, githubapi.Manifest]] = AttributeKey("githubDependencyManifests")
val githubProjectsKey: AttributeKey[Seq[ProjectRef]] = AttributeKey("githubProjectRefs")
val githubDependencyManifest: TaskKey[githubapi.Manifest] = taskKey("The dependency manifest of the project")
val githubStoreDependencyManifests: TaskKey[StateTransform] =
taskKey("Store the dependency manifests of all projects in the attribute map.")
val githubStoreDependencyManifests: InputKey[StateTransform] =
inputKey("Store the dependency manifests of all projects of a Scala version in the attribute map.")
.withRank(KeyRanks.DTask)
}

import autoImport._

override def trigger = allRequirements
override def requires: Plugins = IvyPlugin
override def requires: Plugins = JvmPlugin

override def globalSettings: Seq[Setting[_]] = Def.settings(
githubStoreDependencyManifests := storeManifestsTask.value,
githubStoreDependencyManifests := storeManifestsTask.evaluated,
Keys.commands ++= SubmitDependencyGraph.commands
)

Expand All @@ -46,12 +48,27 @@ object GithubDependencyGraphPlugin extends AutoPlugin {
githubDependencyManifest / Keys.aggregate := false
)

private def storeManifestsTask: Def.Initialize[Task[StateTransform]] = Def.taskDyn {
val projectRefs = Keys.state.value
private val scalaVersionParser = {
import Parsers._
import Parser._
val validOpChars = Set('.', '-', '+')
identifier(
charClass(alphanum, "alphanum"),
charClass(c => alphanum(c) || validOpChars.contains(c), "version character")
)
}

private def storeManifestsTask: Def.Initialize[InputTask[StateTransform]] = Def.inputTaskDyn {
val scalaVersionInput = (Parsers.Space ~> scalaVersionParser).parsed
val state = Keys.state.value

val projectRefs = state
.get(githubProjectsKey)
.getOrElse(
throw new MessageOnlyException(s"The ${githubProjectsKey.label} attribute is not initialized")
)
.filter(ref => state.setting(ref / Keys.scalaVersion) == scalaVersionInput)

Def.task {
val manifests: Map[String, Manifest] = projectRefs
.map(ref => (ref / githubDependencyManifest).?)
Expand Down
15 changes: 9 additions & 6 deletions src/main/scala/ch/epfl/scala/SubmitDependencyGraph.scala
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,14 @@ object SubmitDependencyGraph {

private def submit(state: State, input: SubmitInput): State = {
checkGithubEnv() // fail fast if the Github CI environment is incomplete
val projectRefs = getProjectRefs(state, input)
val projectRefs = getScalaProjectRefs(state, input)
val scalaVersions = getScalaVersions(state, input, projectRefs)
val initState = state
.put(githubManifestsKey, Map.empty[String, Manifest])
.put(githubProjectsKey, projectRefs)

val storeAllManifests = scalaVersions.flatMap { scalaVersion =>
Seq(s"++$scalaVersion", githubStoreDependencyManifests.key.label)
Seq(s"++$scalaVersion", s"${githubStoreDependencyManifests.key} $scalaVersion")
}
val commands = storeAllManifests :+ SubmitInternal
commands.toList ::: initState
Expand Down Expand Up @@ -89,12 +89,15 @@ object SubmitDependencyGraph {
}
}

private def getProjectRefs(state: State, input: SubmitInput): Seq[ProjectRef] = {
// project refs that have a Scala version, filtered according to input.projects
private def getScalaProjectRefs(state: State, input: SubmitInput): Seq[ProjectRef] = {
val loadedBuild = state.setting(Keys.loadedBuild)
val allProjectRefs = loadedBuild.allProjectRefs.map(_._1)
val allScalaProjectRefs = loadedBuild.allProjectRefs
.map(_._1)
.filter(ref => state.getSetting(ref / Keys.scalaVersion).isDefined)
val projectFilter = input.projects.toSet
if (projectFilter.isEmpty) allProjectRefs
else allProjectRefs.filter(ref => projectFilter.contains(ref.project))
if (projectFilter.isEmpty) allScalaProjectRefs
else allScalaProjectRefs.filter(ref => projectFilter.contains(ref.project))
}

private def getScalaVersions(state: State, input: SubmitInput, projectRefs: Seq[ProjectRef]): Seq[String] = {
Expand Down
25 changes: 18 additions & 7 deletions src/sbt-test/dependency-graph/ci-submit/build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,42 @@ inThisBuild(
Seq(
organization := "ch.epfl.scala",
version := "1.2.0-SNAPSHOT",
useCoursier := true,
scalaVersion := "2.12.15",
scalaVersion := "2.13.8"
)
)

val a = project
.in(file("a"))
.settings(
scalaVersion := "2.13.8",
crossScalaVersions := Seq(
"2.12.16",
"2.13.8",
"3.1.3"
)
)
)

val a = project.in(file("a"))

// b is not cross-compiled
// but we should still be able to resolve the manifests of the build on 2.12.16 and 3.1.3
// this pattern is taken from scalameta/metals where metals, not cross-compiled, depends on mtags
// which is cross-compiled
val b = project
.in(file("b"))
.settings(
libraryDependencies += "org.typelevel" %% "cats-core" % "2.8.0"
scalaVersion := "2.13.8"
)
.dependsOn(a)

Global / checkManifests := {
checkManifests := {
val logger = streams.value.log
val expectedSize: Int = (Space ~> NatBasic).parsed
val manifests = state.value.get(githubManifestsKey).getOrElse {
throw new MessageOnlyException(s"Not found ${githubManifestsKey.label} attribute")
}
logger.info(s"found ${manifests.size} manifests")
assert(
manifests.size == expectedSize,
s"expected $expectedSize manifests, found ${manifests.size}"
)
}
checkManifests / aggregate := false
6 changes: 5 additions & 1 deletion src/sbt-test/dependency-graph/ci-submit/test
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
> 'githubSubmitDependencyGraph {}'
> checkManifests 9
> checkManifests 5
> 'githubSubmitDependencyGraph {"projects":[], "scalaVersions":["2.13.8"]}'
> checkManifests 3
> 'githubSubmitDependencyGraph {"projects":[], "scalaVersions":["2.12.16", "2.13.8"]}'
> checkManifests 4
> 'githubSubmitDependencyGraph {"projects":["a", "b"], "scalaVersions":[]}'
> checkManifests 4
> 'githubSubmitDependencyGraph {"projects":["a"], "scalaVersions":["2.12.16", "3.1.3"]}'
> checkManifests 2