mirror of https://github.com/sbt/sbt.git
Merge pull request #512 from coursier/topic/sbt-release
Use sbt-release
This commit is contained in:
commit
916488393a
|
|
@ -5,7 +5,7 @@
|
|||
A Scala library to fetch dependencies from Maven / Ivy repositories
|
||||
|
||||
[](https://travis-ci.org/coursier/coursier)
|
||||
[](https://ci.appveyor.com/project/coursier/coursier)
|
||||
[](https://ci.appveyor.com/project/alexarchambault/coursier-a7n6k)
|
||||
[](https://gitter.im/coursier/coursier?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[](https://maven-badges.herokuapp.com/maven-central/io.get-coursier/coursier_2.11)
|
||||
[](http://javadoc-badge.appspot.com/io.get-coursier/coursier_2.11)
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
A Scala library to fetch dependencies from Maven / Ivy repositories
|
||||
|
||||
[](https://travis-ci.org/coursier/coursier)
|
||||
[](https://ci.appveyor.com/project/coursier/coursier)
|
||||
[](https://ci.appveyor.com/project/alexarchambault/coursier-a7n6k)
|
||||
[](https://gitter.im/coursier/coursier?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[](https://maven-badges.herokuapp.com/maven-central/io.get-coursier/coursier_2.11)
|
||||
[](http://javadoc-badge.appspot.com/io.get-coursier/coursier_2.11)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
import argonaut._
|
||||
import argonaut.Argonaut._
|
||||
import argonaut.ArgonautShapeless._
|
||||
|
||||
import sbt.Logger
|
||||
|
||||
object Appveyor {
|
||||
|
||||
final case class Build(
|
||||
buildId: Long,
|
||||
branch: String,
|
||||
commitId: String,
|
||||
status: String
|
||||
)
|
||||
|
||||
def branchLastBuild(repo: String, branch: String, log: Logger): Build = {
|
||||
|
||||
final case class Response(build: Build)
|
||||
|
||||
val url = s"https://ci.appveyor.com/api/projects/$repo/branch/$branch"
|
||||
val rawResp = HttpUtil.fetch(url, log)
|
||||
|
||||
rawResp.decodeEither[Response] match {
|
||||
case Left(err) =>
|
||||
sys.error(s"Error decoding response from $url: $err")
|
||||
case Right(resp) =>
|
||||
resp.build
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
import java.io.{ByteArrayOutputStream, InputStream}
|
||||
import java.net.{HttpURLConnection, URL, URLConnection}
|
||||
import java.nio.charset.StandardCharsets
|
||||
|
||||
import sbt.Logger
|
||||
|
||||
object HttpUtil {
|
||||
|
||||
private def readFully(is: InputStream): Array[Byte] = {
|
||||
val buffer = new ByteArrayOutputStream
|
||||
val data = Array.ofDim[Byte](16384)
|
||||
|
||||
var nRead = 0
|
||||
while ({
|
||||
nRead = is.read(data, 0, data.length)
|
||||
nRead != -1
|
||||
})
|
||||
buffer.write(data, 0, nRead)
|
||||
|
||||
buffer.flush()
|
||||
buffer.toByteArray
|
||||
}
|
||||
|
||||
def fetch(url: String, log: Logger): String = {
|
||||
|
||||
val url0 = new URL(url)
|
||||
|
||||
log.info(s"Fetching $url")
|
||||
|
||||
val (rawResp, code) = {
|
||||
|
||||
var conn: URLConnection = null
|
||||
var httpConn: HttpURLConnection = null
|
||||
var is: InputStream = null
|
||||
|
||||
try {
|
||||
conn = url0.openConnection()
|
||||
httpConn = conn.asInstanceOf[HttpURLConnection]
|
||||
httpConn.setRequestProperty("Accept", "application/vnd.travis-ci.2+json")
|
||||
is = conn.getInputStream
|
||||
|
||||
(readFully(is), httpConn.getResponseCode)
|
||||
} finally {
|
||||
if (is != null)
|
||||
is.close()
|
||||
if (httpConn != null)
|
||||
httpConn.disconnect()
|
||||
}
|
||||
}
|
||||
|
||||
if (code / 100 != 2)
|
||||
sys.error(s"Unexpected response code when getting $url: $code")
|
||||
|
||||
new String(rawResp, StandardCharsets.UTF_8)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -62,6 +62,6 @@ object Publish {
|
|||
}
|
||||
)
|
||||
|
||||
lazy val released = pomStuff ++ pushToSonatypeStuff
|
||||
lazy val released = pomStuff ++ pushToSonatypeStuff ++ Release.settings
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,287 @@
|
|||
import java.nio.charset.StandardCharsets
|
||||
import java.nio.file.Files
|
||||
import java.util.regex.Pattern
|
||||
|
||||
import com.typesafe.sbt.pgp.PgpKeys
|
||||
import sbt._
|
||||
import sbt.Keys._
|
||||
import sbtrelease.ReleasePlugin.autoImport._
|
||||
import sbtrelease.ReleasePlugin.autoImport.ReleaseTransformations._
|
||||
|
||||
import scala.io._
|
||||
|
||||
object Release {
|
||||
|
||||
implicit final class StateOps(val state: State) extends AnyVal {
|
||||
def vcs: sbtrelease.Vcs =
|
||||
Project.extract(state).get(releaseVcs).getOrElse {
|
||||
sys.error("VCS not set")
|
||||
}
|
||||
}
|
||||
|
||||
val checkTravisStatus = ReleaseStep { state =>
|
||||
|
||||
val currentHash = state.vcs.currentHash
|
||||
|
||||
val build = Travis.builds("coursier/coursier", state.log)
|
||||
.find { build =>
|
||||
build.job_ids.headOption.exists { id =>
|
||||
Travis.job(id, state.log).commit.sha == currentHash
|
||||
}
|
||||
}
|
||||
.getOrElse {
|
||||
sys.error(s"Status for commit $currentHash not found on Travis")
|
||||
}
|
||||
|
||||
state.log.info(s"Found build ${build.id.value} for commit $currentHash, state: ${build.state}")
|
||||
|
||||
build.state match {
|
||||
case "passed" =>
|
||||
case _ =>
|
||||
sys.error(s"Build for $currentHash in state ${build.state}")
|
||||
}
|
||||
|
||||
state
|
||||
}
|
||||
|
||||
val checkAppveyorStatus = ReleaseStep { state =>
|
||||
|
||||
val currentHash = state.vcs.currentHash
|
||||
|
||||
val build = Appveyor.branchLastBuild("alexarchambault/coursier-a7n6k", "master", state.log)
|
||||
|
||||
state.log.info(s"Found last build ${build.buildId} for branch master, status: ${build.status}")
|
||||
|
||||
if (build.commitId != currentHash)
|
||||
sys.error(s"Last master Appveyor build corresponds to commit ${build.commitId}, expected $currentHash")
|
||||
|
||||
if (build.status != "success")
|
||||
sys.error(s"Last master Appveyor build status: ${build.status}")
|
||||
|
||||
state
|
||||
}
|
||||
|
||||
val previousReleaseVersion = AttributeKey[String]("previousReleaseVersion")
|
||||
val initialVersion = AttributeKey[String]("initialVersion")
|
||||
|
||||
val saveInitialVersion = ReleaseStep { state =>
|
||||
val currentVer = Project.extract(state).get(version)
|
||||
state.put(initialVersion, currentVer)
|
||||
}
|
||||
|
||||
def versionChanges(state: State): Boolean = {
|
||||
|
||||
val initialVer = state.get(initialVersion).getOrElse {
|
||||
sys.error(s"${initialVersion.label} key not set")
|
||||
}
|
||||
val (_, nextVer) = state.get(ReleaseKeys.versions).getOrElse {
|
||||
sys.error(s"${ReleaseKeys.versions.label} key not set")
|
||||
}
|
||||
|
||||
initialVer == nextVer
|
||||
}
|
||||
|
||||
|
||||
val updateVersionPattern = "(?m)^VERSION=.*$".r
|
||||
def updateVersionInScript(file: File, newVersion: String): Unit = {
|
||||
val content = Source.fromFile(file)(Codec.UTF8).mkString
|
||||
|
||||
updateVersionPattern.findAllIn(content).toVector match {
|
||||
case Seq() => sys.error(s"Found no matches in $file")
|
||||
case Seq(_) =>
|
||||
case _ => sys.error(s"Found too many matches in $file")
|
||||
}
|
||||
|
||||
val newContent = updateVersionPattern.replaceAllIn(content, "VERSION=" + newVersion)
|
||||
Files.write(file.toPath, newContent.getBytes(StandardCharsets.UTF_8))
|
||||
}
|
||||
|
||||
|
||||
val updateScripts = ReleaseStep { state =>
|
||||
|
||||
val (releaseVer, _) = state.get(ReleaseKeys.versions).getOrElse {
|
||||
sys.error(s"${ReleaseKeys.versions.label} key not set")
|
||||
}
|
||||
|
||||
val scriptsDir = Project.extract(state).get(baseDirectory.in(ThisBuild)) / "scripts"
|
||||
val scriptFiles = Seq(
|
||||
scriptsDir / "generate-launcher.sh",
|
||||
scriptsDir / "generate-sbt-launcher.sh"
|
||||
)
|
||||
|
||||
val vcs = state.vcs
|
||||
|
||||
for (f <- scriptFiles) {
|
||||
updateVersionInScript(f, releaseVer)
|
||||
vcs.add(f.getAbsolutePath).!!(state.log)
|
||||
}
|
||||
|
||||
state
|
||||
}
|
||||
|
||||
val updateLaunchers = ReleaseStep { state =>
|
||||
|
||||
val baseDir = Project.extract(state).get(baseDirectory.in(ThisBuild))
|
||||
val scriptsDir = baseDir / "scripts"
|
||||
val scriptFiles = Seq(
|
||||
(scriptsDir / "generate-launcher.sh") -> (baseDir / "coursier"),
|
||||
(scriptsDir / "generate-sbt-launcher.sh") -> (baseDir / "csbt")
|
||||
)
|
||||
|
||||
val vcs = state.vcs
|
||||
|
||||
for ((f, output) <- scriptFiles) {
|
||||
sbt.Process(Seq(f.getAbsolutePath, "-f")).!!(state.log)
|
||||
vcs.add(output.getAbsolutePath).!!(state.log)
|
||||
}
|
||||
|
||||
state
|
||||
}
|
||||
|
||||
val savePreviousReleaseVersion = ReleaseStep { state =>
|
||||
|
||||
val cmd = Seq(state.vcs.commandName, "tag", "-l")
|
||||
|
||||
val tag = scala.sys.process.Process(cmd)
|
||||
.!!
|
||||
.linesIterator
|
||||
.toVector
|
||||
.lastOption
|
||||
.getOrElse {
|
||||
sys.error(s"Found no tags when running ${cmd.mkString(" ")}")
|
||||
}
|
||||
|
||||
val ver =
|
||||
if (tag.startsWith("v"))
|
||||
tag.stripPrefix("v")
|
||||
else
|
||||
sys.error(s"Last tag '$tag' doesn't start with 'v'")
|
||||
|
||||
state.put(previousReleaseVersion, ver)
|
||||
}
|
||||
|
||||
val updateTutReadme = ReleaseStep { state =>
|
||||
|
||||
val previousVer = state.get(previousReleaseVersion).getOrElse {
|
||||
sys.error(s"${previousReleaseVersion.label} key not set")
|
||||
}
|
||||
val (releaseVer, _) = state.get(ReleaseKeys.versions).getOrElse {
|
||||
sys.error(s"${ReleaseKeys.versions.label} key not set")
|
||||
}
|
||||
|
||||
val readmeFile = Project.extract(state).get(baseDirectory.in(ThisBuild)) / "doc" / "README.md"
|
||||
val pattern = Pattern.quote(previousVer).r
|
||||
|
||||
val content = Source.fromFile(readmeFile)(Codec.UTF8).mkString
|
||||
val newContent = pattern.replaceAllIn(content, releaseVer)
|
||||
Files.write(readmeFile.toPath, newContent.getBytes(StandardCharsets.UTF_8))
|
||||
|
||||
state.vcs.add(readmeFile.getAbsolutePath).!!(state.log)
|
||||
|
||||
state
|
||||
}
|
||||
|
||||
val stageReadme = ReleaseStep { state =>
|
||||
|
||||
val baseDir = Project.extract(state).get(baseDirectory.in(ThisBuild))
|
||||
val processedReadmeFile = baseDir / "README.md"
|
||||
|
||||
state.vcs.add(processedReadmeFile.getAbsolutePath).!!(state.log)
|
||||
|
||||
state
|
||||
}
|
||||
|
||||
|
||||
val coursierVersionPattern = s"(?m)^${Pattern.quote("def coursierVersion = \"")}[^${'"'}]*${Pattern.quote("\"")}$$".r
|
||||
|
||||
val updatePluginsSbt = ReleaseStep { state =>
|
||||
|
||||
val vcs = state.vcs
|
||||
|
||||
val (releaseVer, _) = state.get(ReleaseKeys.versions).getOrElse {
|
||||
sys.error(s"${ReleaseKeys.versions.label} key not set")
|
||||
}
|
||||
|
||||
val baseDir = Project.extract(state).get(baseDirectory.in(ThisBuild))
|
||||
val pluginsSbtFile = baseDir / "project" / "plugins.sbt"
|
||||
val projectPluginsSbtFile = baseDir / "project" / "project" / "plugins.sbt"
|
||||
|
||||
val files = Seq(
|
||||
pluginsSbtFile,
|
||||
projectPluginsSbtFile
|
||||
)
|
||||
|
||||
for (f <- files) {
|
||||
val content = Source.fromFile(f)(Codec.UTF8).mkString
|
||||
|
||||
coursierVersionPattern.findAllIn(content).toVector match {
|
||||
case Seq() => sys.error(s"Found no matches in $f")
|
||||
case Seq(_) =>
|
||||
case _ => sys.error(s"Found too many matches in $f")
|
||||
}
|
||||
|
||||
val newContent = coursierVersionPattern.replaceAllIn(content, "def coursierVersion = \"" + releaseVer + "\"")
|
||||
Files.write(f.toPath, newContent.getBytes(StandardCharsets.UTF_8))
|
||||
vcs.add(f.getAbsolutePath).!!(state.log)
|
||||
}
|
||||
|
||||
state
|
||||
}
|
||||
|
||||
val commitUpdates = ReleaseStep(
|
||||
action = { state =>
|
||||
|
||||
val (releaseVer, _) = state.get(ReleaseKeys.versions).getOrElse {
|
||||
sys.error(s"${ReleaseKeys.versions.label} key not set")
|
||||
}
|
||||
|
||||
state.vcs.commit(s"Updates for $releaseVer", sign = true).!(state.log)
|
||||
|
||||
state
|
||||
},
|
||||
check = { state =>
|
||||
|
||||
val vcs = state.vcs
|
||||
|
||||
if (vcs.hasModifiedFiles)
|
||||
sys.error("Aborting release: unstaged modified files")
|
||||
|
||||
if (vcs.hasUntrackedFiles && !Project.extract(state).get(releaseIgnoreUntrackedFiles))
|
||||
sys.error(
|
||||
"Aborting release: untracked files. Remove them or specify 'releaseIgnoreUntrackedFiles := true' in settings"
|
||||
)
|
||||
|
||||
state
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
val settings = Seq(
|
||||
releaseProcess := Seq[ReleaseStep](
|
||||
checkTravisStatus,
|
||||
checkAppveyorStatus,
|
||||
savePreviousReleaseVersion,
|
||||
checkSnapshotDependencies,
|
||||
inquireVersions,
|
||||
saveInitialVersion,
|
||||
setReleaseVersion,
|
||||
commitReleaseVersion,
|
||||
publishArtifacts,
|
||||
releaseStepCommand("sonatypeRelease"),
|
||||
updateScripts,
|
||||
updateLaunchers,
|
||||
updateTutReadme,
|
||||
releaseStepCommand("tut"),
|
||||
stageReadme,
|
||||
updatePluginsSbt,
|
||||
commitUpdates,
|
||||
tagRelease,
|
||||
setNextVersion,
|
||||
commitNextVersion,
|
||||
ReleaseStep(_.reload),
|
||||
pushChanges
|
||||
),
|
||||
releasePublishArtifactsAction := PgpKeys.publishSigned.value
|
||||
)
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
import argonaut._
|
||||
import argonaut.Argonaut._
|
||||
import argonaut.ArgonautShapeless._
|
||||
|
||||
import sbt.Logger
|
||||
|
||||
object Travis {
|
||||
|
||||
final case class BuildId(value: Long) extends AnyVal
|
||||
object BuildId {
|
||||
implicit val decode: DecodeJson[BuildId] =
|
||||
DecodeJson.LongDecodeJson.map(BuildId(_))
|
||||
}
|
||||
|
||||
final case class JobId(value: Long) extends AnyVal
|
||||
object JobId {
|
||||
implicit val decode: DecodeJson[JobId] =
|
||||
DecodeJson.LongDecodeJson.map(JobId(_))
|
||||
}
|
||||
|
||||
final case class CommitId(value: Long) extends AnyVal
|
||||
object CommitId {
|
||||
implicit val decode: DecodeJson[CommitId] =
|
||||
DecodeJson.LongDecodeJson.map(CommitId(_))
|
||||
}
|
||||
|
||||
final case class Build(
|
||||
id: BuildId,
|
||||
job_ids: List[JobId],
|
||||
pull_request: Boolean,
|
||||
state: String,
|
||||
commit_id: CommitId
|
||||
)
|
||||
|
||||
final case class Builds(
|
||||
builds: List[Build]
|
||||
)
|
||||
|
||||
final case class Commit(
|
||||
id: CommitId,
|
||||
sha: String,
|
||||
branch: String
|
||||
)
|
||||
|
||||
final case class JobDetails(
|
||||
state: String
|
||||
)
|
||||
|
||||
final case class Job(
|
||||
commit: Commit,
|
||||
job: JobDetails
|
||||
)
|
||||
|
||||
|
||||
def builds(repo: String, log: Logger): List[Build] = {
|
||||
|
||||
val url = s"https://api.travis-ci.org/repos/$repo/builds"
|
||||
val resp = HttpUtil.fetch(url, log)
|
||||
|
||||
resp.decodeEither[Builds] match {
|
||||
case Left(err) =>
|
||||
sys.error(s"Error decoding response from $url: $err")
|
||||
case Right(builds) =>
|
||||
log.info(s"Got ${builds.builds.length} builds")
|
||||
builds.builds
|
||||
}
|
||||
}
|
||||
|
||||
def job(id: JobId, log: Logger): Job = {
|
||||
|
||||
val url = s"https://api.travis-ci.org/jobs/${id.value}"
|
||||
val resp = HttpUtil.fetch(url, log)
|
||||
|
||||
resp.decodeEither[Job] match {
|
||||
case Left(err) =>
|
||||
sys.error(s"Error decoding response from $url: $err")
|
||||
case Right(job) =>
|
||||
job
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1 +1 @@
|
|||
sbt.version=0.13.8
|
||||
sbt.version=0.13.15
|
||||
|
|
|
|||
|
|
@ -1,10 +1,27 @@
|
|||
addSbtPlugin("org.xerial.sbt" % "sbt-pack" % "0.8.2")
|
||||
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.15")
|
||||
addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.0.0")
|
||||
addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.4.0")
|
||||
addSbtPlugin("org.tpolecat" % "tut-plugin" % "0.4.8")
|
||||
addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.0.0-RC1")
|
||||
addSbtPlugin("io.get-coursier" % "sbt-shading" % "1.0.0-RC1")
|
||||
addSbtPlugin("com.typesafe.sbt" % "sbt-proguard" % "0.2.2")
|
||||
addSbtPlugin("com.typesafe" % "sbt-mima-plugin" % "0.1.13")
|
||||
libraryDependencies += "org.scala-sbt" % "scripted-plugin" % sbtVersion.value
|
||||
|
||||
plugins_(
|
||||
"io.get-coursier" % "sbt-coursier" % coursierVersion,
|
||||
"com.typesafe" % "sbt-mima-plugin" % "0.1.13",
|
||||
"org.xerial.sbt" % "sbt-pack" % "0.8.2",
|
||||
"com.jsuereth" % "sbt-pgp" % "1.0.0",
|
||||
"com.typesafe.sbt" % "sbt-proguard" % "0.2.2",
|
||||
"com.github.gseitz" % "sbt-release" % "1.0.4",
|
||||
"org.scala-js" % "sbt-scalajs" % "0.6.15",
|
||||
"org.scoverage" % "sbt-scoverage" % "1.4.0",
|
||||
"io.get-coursier" % "sbt-shading" % coursierVersion,
|
||||
"org.xerial.sbt" % "sbt-sonatype" % "1.1",
|
||||
"org.tpolecat" % "tut-plugin" % "0.4.8"
|
||||
)
|
||||
|
||||
libs ++= Seq(
|
||||
"org.scala-sbt" % "scripted-plugin" % sbtVersion.value,
|
||||
compilerPlugin("org.scalamacros" % "paradise" % "2.1.0" cross CrossVersion.full), // for shapeless / auto type class derivations
|
||||
"com.github.alexarchambault" %% "argonaut-shapeless_6.2" % "1.2.0-M5"
|
||||
)
|
||||
|
||||
// important: this line is matched / substituted during releases (via sbt-release)
|
||||
def coursierVersion = "1.0.0-RC1"
|
||||
|
||||
|
||||
def plugins_(modules: ModuleID*) = modules.map(addSbtPlugin)
|
||||
def libs = libraryDependencies
|
||||
|
|
|
|||
|
|
@ -1 +1,4 @@
|
|||
addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.0.0-RC1")
|
||||
addSbtPlugin("io.get-coursier" % "sbt-coursier" % coursierVersion)
|
||||
|
||||
// important: this line is matched / substituted during releases (via sbt-release)
|
||||
def coursierVersion = "1.0.0-RC1"
|
||||
|
|
|
|||
|
|
@ -1,12 +1,14 @@
|
|||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
COURSIER_VERSION=1.0.0-M15-2
|
||||
VERSION=1.0.0-M15-2
|
||||
|
||||
"$(dirname "$0")/../coursier" bootstrap \
|
||||
"io.get-coursier:sbt-launcher_2.12:$COURSIER_VERSION" \
|
||||
"io.get-coursier:sbt-launcher_2.12:$VERSION" \
|
||||
-r sonatype:releases \
|
||||
--no-default \
|
||||
-i launcher \
|
||||
-I launcher:org.scala-sbt:launcher-interface:1.0.0 \
|
||||
-o csbt \
|
||||
-J -Djline.shutdownhook=false
|
||||
-J -Djline.shutdownhook=false \
|
||||
"$@"
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ object CentralTests extends TestSuite {
|
|||
): Future[T] = async {
|
||||
val res = await(resolve(deps, extraRepo = extraRepo))
|
||||
|
||||
assert(res.errors.isEmpty)
|
||||
assert(res.metadataErrors.isEmpty)
|
||||
assert(res.conflicts.isEmpty)
|
||||
assert(res.isDone)
|
||||
|
||||
|
|
@ -444,7 +444,7 @@ object CentralTests extends TestSuite {
|
|||
|
||||
val res = await(resolve(deps))
|
||||
|
||||
assert(res.errors.isEmpty)
|
||||
assert(res.metadataErrors.isEmpty)
|
||||
assert(res.conflicts.isEmpty)
|
||||
assert(res.isDone)
|
||||
|
||||
|
|
@ -479,7 +479,7 @@ object CentralTests extends TestSuite {
|
|||
|
||||
val res = await(resolve(deps))
|
||||
|
||||
assert(res.errors.isEmpty)
|
||||
assert(res.metadataErrors.isEmpty)
|
||||
assert(res.conflicts.isEmpty)
|
||||
assert(res.isDone)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue