Skip to content
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

Fix latest-by-scala-version badge summary to prefer releases #1330

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
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,13 @@ object SemanticVersion {
)
}

/**
* Often we will prefer the latest release, but if there is no full release, we will select the most recent
* pre-release.
*/
val PreferReleases: Ordering[SemanticVersion] =
Ordering.by[SemanticVersion, Boolean](_.isRelease).orElse(ordering)

private def MajorP[A: P]: P[Int] = Number

// http://semver.org/#spec-item-10
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package scaladex.core.model
import org.scalatest.funspec.AsyncFunSpec
import org.scalatest.matchers.should.Matchers
import org.scalatest.prop.TableDrivenPropertyChecks
import scaladex.core.model.SemanticVersion.PreferReleases
import scaladex.core.test.Values._

class SemanticVersionTests extends AsyncFunSpec with Matchers with TableDrivenPropertyChecks {
it("should parse any version") {
Expand Down Expand Up @@ -39,6 +41,12 @@ class SemanticVersionTests extends AsyncFunSpec with Matchers with TableDrivenPr
forAll(inputs)((lower, higher) => lower shouldBe <(higher))
}

it("should allow us to prefer releases over pre-releases") {
val versions = Seq(`7.0.0`, `7.1.0`, `7.2.0-PREVIEW.1`)
versions.max shouldBe `7.2.0-PREVIEW.1`
versions.max(PreferReleases) shouldBe `7.1.0`
}

it("should encode and decode any version") {
val inputs = Table[SemanticVersion](
"semanticVersion",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ object Values {
val `2.7.0` = PatchVersion(2, 7, 0)
val `7.0.0` = PatchVersion(7, 0, 0)
val `7.1.0` = PatchVersion(7, 1, 0)
val `7.2.0-PREVIEW.1` = SemanticVersion.parse("7.2.0-PREVIEW.1").get
val `7.2.0-PREVIEW.2` = SemanticVersion.parse("7.2.0-PREVIEW.2").get
val `7.2.0` = PatchVersion(7, 2, 0)
val `7.3.0` = PatchVersion(7, 3, 0)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import scaladex.core.model.Scala
import scaladex.core.model.ScalaJs
import scaladex.core.model.ScalaNative
import scaladex.core.model.SemanticVersion
import scaladex.core.model.SemanticVersion.PreferReleases
import scaladex.core.service.WebDatabase

class Badges(database: WebDatabase)(implicit executionContext: ExecutionContext) {
Expand Down Expand Up @@ -173,7 +174,7 @@ object Badges {

private[route] def summaryOfLatestVersions(versionsByScalaVersions: Map[Scala, Seq[SemanticVersion]]): String =
versionsByScalaVersions.view
.mapValues(_.max)
.mapValues(_.max(PreferReleases))
.groupMap { case (_, latestVersion) => latestVersion } { case (scalaVersion, _) => scalaVersion }
.toSeq
.sortBy(_._1)(SemanticVersion.ordering.reverse)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@ import akka.http.scaladsl.model.Uri
import akka.http.scaladsl.model.headers.Location
import akka.http.scaladsl.server.Route
import org.scalatest.BeforeAndAfterAll
import org.scalatest.funspec.AnyFunSpec
import org.scalatest.matchers.should.Matchers
import scaladex.core.model.Scala._
import scaladex.core.test.Values._
import scaladex.core.util.ScalaExtensions._
import scaladex.server.route.Badges.summaryOfLatestVersions

class BadgesTests extends ControllerBaseSuite with BeforeAndAfterAll {

Expand All @@ -22,17 +25,6 @@ class BadgesTests extends ControllerBaseSuite with BeforeAndAfterAll {
def insertCats(): Future[Unit] =
Cats.allArtifacts.map(database.insertArtifact(_, Seq.empty, now)).sequence.map(_ => ())

it("should provide a concise summary of latest versions") {
Badges.summaryOfLatestVersions(
Map(
`2.11` -> Seq(`7.0.0`, `7.1.0`),
`2.12` -> Seq(`7.0.0`, `7.1.0`, `7.2.0`),
`2.13` -> Seq(`7.0.0`, `7.1.0`, `7.2.0`, `7.3.0`),
`3` -> Seq(`7.2.0`, `7.3.0`)
)
) shouldBe "7.3.0 (Scala 3.x, 2.13), 7.2.0 (Scala 2.12), 7.1.0 (Scala 2.11)"
}

Comment on lines -25 to -35
Copy link
Contributor Author

@rtyley rtyley Jan 13, 2024

Choose a reason for hiding this comment

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

To take advantage of this being a simple unit test, I've moved it further down the file (along with a couple of other new unit tests) into BadgesUnitTests - this doesn't extend ControllerBaseSuite and so can be quickly run in IntelliJ, etc, without having to start docker.

it("should fallback to JVM artifacts") {
Get(s"/${Cats.reference}/cats-core/latest-by-scala-version.svg") ~> badgesRoute ~> check {
status shouldEqual StatusCodes.TemporaryRedirect
Expand Down Expand Up @@ -73,3 +65,27 @@ class BadgesTests extends ControllerBaseSuite with BeforeAndAfterAll {
}
}
}

class BadgesUnitTests extends AnyFunSpec with Matchers {
it("should provide a concise summary of latest versions") {
summaryOfLatestVersions(
Map(
`2.11` -> Seq(`7.0.0`, `7.1.0`),
`2.12` -> Seq(`7.0.0`, `7.1.0`, `7.2.0`),
`2.13` -> Seq(`7.0.0`, `7.1.0`, `7.2.0`, `7.3.0`),
`3` -> Seq(`7.2.0`, `7.3.0`)
)
) shouldBe "7.3.0 (Scala 3.x, 2.13), 7.2.0 (Scala 2.12), 7.1.0 (Scala 2.11)"
}

it("should prefer releases to pre-releases if both are available") {
summaryOfLatestVersions(Map(`2.13` -> Seq(`7.0.0`, `7.1.0`, `7.2.0-PREVIEW.1`))) shouldBe "7.1.0 (Scala 2.13)"
}

it("should display latest pre-release if no full release is available") {
summaryOfLatestVersions(
Map(`2.13` -> Seq(`7.2.0-PREVIEW.1`, `7.2.0-PREVIEW.2`))
) shouldBe s"${`7.2.0-PREVIEW.2`} (Scala 2.13)"
}

}