Skip to content

Add tlLatestVersion, tlLatestPreReleaseVersion to versioning plugin #333

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

Merged
merged 10 commits into from
Jul 16, 2022
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

package org.typelevel.sbt

import org.typelevel.sbt.kernel.GitHelper
import org.typelevel.sbt.kernel.V
import sbt._
import sbt.plugins.JvmPlugin

Expand All @@ -37,6 +39,7 @@ object TypelevelKernelPlugin extends AutoPlugin {
BasicCommands.addAlias(BasicCommands.removeAlias(s, name), name, contents)
}
})

}

import autoImport._
Expand Down Expand Up @@ -83,4 +86,34 @@ object TypelevelKernelPlugin extends AutoPlugin {
}
}

private[sbt] lazy val currentRelease: Def.Initialize[Option[String]] = Def.setting {
// some tricky logic here ...
// if the latest release is a pre-release (e.g., M or RC)
// and there are no stable releases it is bincompatible with,
// then for all effective purposes it is the current release

val release = previousReleases.value match {
case head :: tail if head.isPrerelease =>
tail
.filterNot(_.isPrerelease)
.find(head.copy(prerelease = None).mustBeBinCompatWith(_))
.orElse(Some(head))
case releases => releases.headOption
}

release.map(_.toString)
}
Comment on lines +89 to +105
Copy link
Member

Choose a reason for hiding this comment

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

Shoot, still not quite right 😂 I thought this was using version in here, but you are right that it's not. Sorry, I was confusing with the change I made in #282 which does use version.

So as it's currently defined, even if you've bumped your base version, if you haven't actually tagged anything with that new base version then it will still use whatever the latest tag is under the old base version. I guess this makes sense. But, now to explain it 🤔 tl;dr we do some blackbox heuristics to get you a sensible number, take it or leave it 😛


// latest tagged release, including pre-releases
private[sbt] lazy val currentPreRelease: Def.Initialize[Option[String]] = Def.setting {
previousReleases.value.headOption.map(_.toString)
}

private[this] lazy val previousReleases: Def.Initialize[List[V]] = Def.setting {
val currentVersion = V(version.value).map(_.copy(prerelease = None))
GitHelper.previousReleases(fromHead = true, strict = false).filter { v =>
currentVersion.forall(v.copy(prerelease = None) <= _)
}
}

}
33 changes: 1 addition & 32 deletions site/src/main/scala/org/typelevel/sbt/TypelevelSitePlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ import laika.helium.config.ImageLink
import laika.sbt.LaikaPlugin
import laika.theme.ThemeProvider
import mdoc.MdocPlugin
import org.typelevel.sbt.kernel.GitHelper
import org.typelevel.sbt.kernel.V
import org.typelevel.sbt.site._
import sbt._

Expand All @@ -38,6 +36,7 @@ import MdocPlugin.autoImport._
import LaikaPlugin.autoImport._
import gha.GenerativePlugin
import GenerativePlugin.autoImport._
import TypelevelKernelPlugin._
import TypelevelKernelPlugin.autoImport._

object TypelevelSitePlugin extends AutoPlugin {
Expand Down Expand Up @@ -250,36 +249,6 @@ object TypelevelSitePlugin extends AutoPlugin {
)
)

private lazy val currentRelease = Def.setting {
// some tricky logic here ...
// if the latest release is a pre-release (e.g., M or RC)
// and there are no stable releases it is bincompatible with,
// then for all effective purposes it is the current release

val release = previousReleases.value match {
case head :: tail if head.isPrerelease =>
tail
.filterNot(_.isPrerelease)
.find(head.copy(prerelease = None).mustBeBinCompatWith(_))
.orElse(Some(head))
case releases => releases.headOption
}

release.map(_.toString)
}

// latest tagged release, including pre-releases
private lazy val currentPreRelease = Def.setting {
previousReleases.value.headOption.map(_.toString)
}

private lazy val previousReleases = Def.setting {
val currentVersion = V(version.value).map(_.copy(prerelease = None))
GitHelper.previousReleases(fromHead = true, strict = false).filter { v =>
currentVersion.forall(v.copy(prerelease = None) <= _)
}
}

private def previewTask = Def
.taskDyn {
// inlined from https://github.com/planet42/Laika/blob/9022f6f37c9017f7612fa59398f246c8e8c42c3e/sbt/src/main/scala/laika/sbt/Tasks.scala#L192
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package org.typelevel.sbt

import com.typesafe.sbt.GitPlugin
import com.typesafe.sbt.SbtGit.git
import org.typelevel.sbt.TypelevelKernelPlugin._
import org.typelevel.sbt.kernel.GitHelper
import org.typelevel.sbt.kernel.V
import sbt._
Expand All @@ -37,6 +38,12 @@ object TypelevelVersioningPlugin extends AutoPlugin {
lazy val tlUntaggedAreSnapshots =
settingKey[Boolean](
"If true, an untagged commit is given a snapshot version, e.g. 0.4-00218f9-SNAPSHOT. If false, it is given a release version, e.g. 0.4-00218f9. (default: true)")

lazy val tlLatestVersion = settingKey[Option[String]](
"The latest tagged version on this branch. Priority is given to the latest stable version, but if you have tagged a binary-breaking prelease version (such as a milestone or release candidate), that will be selected instead. If applicable, this will be the current tagged version.")

lazy val tlLatestPreReleaseVersion = settingKey[Option[String]](
"The latest tagged version on this branch, including milestones and release candidates. If applicable, this will be the current tagged version.")
Comment on lines +42 to +46
Copy link
Member

Choose a reason for hiding this comment

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

ok, @bplommer, what do you think? phew 😓

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm happy with that 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

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

On second thought, what do you think about tlLatestVersionOnBranch and tlLatestPreReleaseVersionOnBranch? It's a bit wordy, but for me it's really counterintuitive that (for example) these would be 0.22 versions when running on the http4s 0.22.x branch, so they're not really the latest versions.

Copy link
Member

@armanbilge armanbilge Jul 16, 2022

Choose a reason for hiding this comment

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

but for me it's really counterintuitive that (for example) these would be 0.22 versions when running on the http4s 0.22.x branch

Ok yeah that's super fair. But that is quite a mouthful. What if we used the terminology "previous version" instead of "latest"? Then maybe it would be more clear it's relative to our current context. The problem is that it muddies the fact that this can be the current version if the current commit is tagged.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't like "previous", for the reason you give - to me that explicitly rules out it being the current one. But I don't have any other suggestions at the moment 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I guess my question is, what are you doing with tlLatestVersion on the 0.22.x branch, where you want it to be an 0.23+ version?

I can't think of anything! But I can imagine wanting the "latest prerelease" version on the 0.23.x branch to be a 1.0 milestone, so I could populate the website's landing page accordingly.

Copy link
Member

Choose a reason for hiding this comment

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

In that case, shouldn't the landing page be published from main instead of series/0.23? (This is how we do it in http4s).

Copy link
Member

Choose a reason for hiding this comment

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

Hmm, I guess not necessarily. My proposal in #317 aims to reduce that complexity, so that you only publish the website from the stable branch. Blah again 😂

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Blah indeed. Let's just go with it as it is, I think it's good enoigh?

Copy link
Member

Choose a reason for hiding this comment

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

Yolo. We might end up adding a couple more of these as the complaints roll in 😂 thank you so much for your work on this.

}

import autoImport._
Expand Down Expand Up @@ -123,7 +130,9 @@ object TypelevelVersioningPlugin extends AutoPlugin {
if (isSnapshot.value) version += "-SNAPSHOT"

version
}
},
tlLatestVersion := currentRelease.value,
tlLatestPreReleaseVersion := currentPreRelease.value
)

private val Description = """^.*-(\d+)-[a-zA-Z0-9]+$""".r
Expand Down