diff --git a/README.md b/README.md index 42487aa..15fb3df 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ The plugin also brings in - sbt-header to automate copyright header maintenance - sbt-mima-plugin to maintain binary compatibility - sbt-osgi, if enabled with `scalaModuleOsgiSettings` + - sbt-version-policy to check the versioning policy ## Usage @@ -53,7 +54,7 @@ name := "" repoName := "" // the repo under github.com/scala/, only required if different from name organization := "" // only required if different from "org.scala-lang.modules" -scalaModuleMimaPreviousVersion := Some("1.0.0") // enables MiMa (`None` by default, which disables it) +versionPolicyIntention := Compatibility.BinaryAndSourceCompatible // enables MiMa (`Compatibility.None` by default, which disables it) OsgiKeys.exportPackage := Seq(s";version=${version.value}") @@ -77,7 +78,7 @@ The following settings are also available: ## Set up tag-based publishing -The instructions here are a summary of the readme in https://github.com/olafurpg/sbt-ci-release +The instructions here are a summary of the readme in https://github.com/olafurpg/sbt-ci-release and https://github.com/scalacenter/sbt-version-policy - Create a fresh GPG key: `gpg --gen-key` - Real name: use "project-name bot" @@ -97,3 +98,5 @@ The instructions here are a summary of the readme in https://github.com/olafurpg - ubuntu: `gpg --armor --export-secret-keys $LONG_ID | base64 -w0` - `SONATYPE_PASSWORD`: need that one - `SONATYPE_USERNAME`: that one too + + - Run `versionCheck` in the publishing process: `sbt versionCheck ci-release` diff --git a/build.sbt b/build.sbt index cdbb5ce..9758332 100644 --- a/build.sbt +++ b/build.sbt @@ -9,6 +9,6 @@ developers := List(Developer("", "", "", url("https://scala-lang.org")) addSbtPlugin("com.typesafe.sbt" % "sbt-osgi" % "0.9.6") addSbtPlugin("de.heikoseeberger" % "sbt-header" % "5.6.0") -addSbtPlugin("com.typesafe" % "sbt-mima-plugin" % "0.9.2") addSbtPlugin("com.dwijnand" % "sbt-travisci" % "1.2.0") // set scalaVersion and crossScalaVersions addSbtPlugin("com.geirsson" % "sbt-ci-release" % "1.5.7") // set version, scmInfo, publishing settings +addSbtPlugin("ch.epfl.scala" % "sbt-version-policy" % "1.2.1") diff --git a/src/main/scala/ScalaModulePlugin.scala b/src/main/scala/ScalaModulePlugin.scala index d9c690a..aca2714 100644 --- a/src/main/scala/ScalaModulePlugin.scala +++ b/src/main/scala/ScalaModulePlugin.scala @@ -1,22 +1,19 @@ package com.lightbend.tools.scalamoduleplugin import com.typesafe.sbt.osgi.{OsgiKeys, SbtOsgi} -import com.typesafe.tools.mima.plugin.MimaKeys._ -import com.typesafe.tools.mima.plugin.MimaPlugin import de.heikoseeberger.sbtheader.HeaderPlugin.autoImport.{HeaderLicense, headerLicense} import sbt.Keys._ -import sbt._ -import sbt.internal.librarymanagement.IvySbt -import sbt.librarymanagement.ivy.IvyDependencyResolution -import sbt.librarymanagement.{UnresolvedWarningConfiguration, UpdateConfiguration} +import sbt.{Def, _} import sbtdynver.DynVerPlugin import sbtdynver.DynVerPlugin.autoImport.dynverGitDescribeOutput import xerial.sbt.Sonatype.autoImport.{sonatypeProfileName, sonatypeSessionName} +import sbtversionpolicy.SbtVersionPolicyPlugin.autoImport.{Compatibility, versionPolicyCheck, versionPolicyIgnoredInternalDependencyVersions, versionPolicyIntention} object ScalaModulePlugin extends AutoPlugin { object autoImport { val scalaModuleRepoName = settingKey[String]("The name of the repository under github.com/scala/.") val scalaModuleAutomaticModuleName = settingKey[Option[String]]("Automatic-Module-Name setting for manifest") + @deprecated("Previous version is now automatically computed by sbt-version-policy. Setting this key has no effect", "2.4.0") val scalaModuleMimaPreviousVersion = settingKey[Option[String]]("The version of this module to compare against when running MiMa.") val scalaModuleEnableOptimizerInlineFrom = settingKey[String]("The value passed to -opt-inline-from by `enableOptimizer` on 2.13 and higher.") } @@ -36,7 +33,7 @@ object ScalaModulePlugin extends AutoPlugin { dv.copy(ref = sbtdynver.GitRef(dv.ref.value.split('#').head)))), ) - // Settings added to the global scope + // Settings added to the project scope override def projectSettings: Seq[Setting[_]] = Seq( // The staging profile is called `org.scala-lang`, the default is `org.scala-lang.modules` sonatypeProfileName := "org.scala-lang", @@ -53,6 +50,12 @@ object ScalaModulePlugin extends AutoPlugin { }, ) + // Global settings + override def globalSettings: Seq[Def.Setting[_]] = Seq( + // Since we use sbt-dynver, see https://github.com/scalacenter/sbt-version-policy#how-to-integrate-with-sbt-dynver + versionPolicyIgnoredInternalDependencyVersions := Some("^\\d+\\.\\d+\\.\\d+\\+\\d+".r) + ) + /** * Enable `-opt:l:inline`, `-opt:l:project` or `-optimize`, depending on the scala version. */ @@ -167,47 +170,21 @@ object ScalaModulePlugin extends AutoPlugin { // a setting-transform to turn the regular version into something osgi can deal with private val osgiVersion = version(_.replace('-', '.')) - // adapted from https://github.com/lightbend/migration-manager/blob/0.3.0/sbtplugin/src/main/scala/com/typesafe/tools/mima/plugin/SbtMima.scala#L112 - private def artifactExists(organization: String, name: String, scalaBinaryVersion: String, version: String, ivy: IvySbt, s: TaskStreams): Boolean = { - val moduleId = ModuleID(organization, s"${name}_$scalaBinaryVersion", version) - val depRes = IvyDependencyResolution(ivy.configuration) - val module = depRes.wrapDependencyInModule(moduleId) - val updateConf = UpdateConfiguration() withLogging UpdateLogging.DownloadOnly - val reportEither = depRes.update(module, updateConf, UnresolvedWarningConfiguration(), s.log) - reportEither.fold(_ => false, _ => true) - } - - // Internal task keys for the MiMa settings - private val canRunMima = taskKey[Boolean]("Decides if MiMa should run.") - private val runMimaIfEnabled = taskKey[Unit]("Run MiMa if mimaPreviousVersion and the module can be resolved against the current scalaBinaryVersion.") + // Internal task keys for the versionPolicy settings + private val runVersionPolicyCheckIfEnabled = taskKey[Unit]("Run versionPolicyCheck if versionPolicyIntention is not set to Compatibility.None.") private lazy val mimaSettings: Seq[Setting[_]] = Seq( - scalaModuleMimaPreviousVersion := None, - - // We're not using `%%` here in order to support both jvm and js projects (cross version `_2.12` / `_sjs0.6_2.12`) - mimaPreviousArtifacts := scalaModuleMimaPreviousVersion.value.map(v => organization.value % moduleName.value % v cross crossVersion.value).toSet, - - canRunMima := { - val log = streams.value.log - scalaModuleMimaPreviousVersion.value match { - case None => - log.warn("MiMa will NOT run because no mimaPreviousVersion is provided.") - false - case Some(mimaVer) => - val exists = artifactExists(organization.value, name.value, scalaBinaryVersion.value, mimaVer, ivySbt.value, streams.value) - if (!exists) - log.warn(s"""MiMa will NOT run because the previous artifact "${organization.value}" % "${name.value}_${scalaBinaryVersion.value}" % "$mimaVer" could not be resolved (note the binary Scala version).""") - exists - } - }, + versionPolicyIntention := Compatibility.None, - runMimaIfEnabled := Def.taskDyn({ - if (canRunMima.value) Def.task { mimaReportBinaryIssues.value } - else Def.task { () } + runVersionPolicyCheckIfEnabled := Def.taskDyn({ + if (versionPolicyIntention.value != Compatibility.None) Def.task { versionPolicyCheck.value } + else Def.task { + streams.value.log.warn("versionPolicyCheck will NOT run because versionPolicyIntention is set to Compatibility.None.") + } }).value, Test / test := { - runMimaIfEnabled.value + runVersionPolicyCheckIfEnabled.value (Test / test).value } )