From cf340eccc5783bad36a423af3a1608628f3e66bd Mon Sep 17 00:00:00 2001 From: eugene yokota Date: Thu, 24 Sep 2026 16:57:45 -0400 Subject: [PATCH] [2.0.x] Update user-agent to major.minor (#9818) To avoid user-agent being used for tracking, use only major.minor. --- .../CoursierDependencyResolution.scala | 2 + .../scala/sbt/coursierint/LMCoursier.scala | 6 ++- .../scala/sbt/coursierint/UserAgentSpec.scala | 41 +++++++++++++++++++ 3 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 main/src/test/scala/sbt/coursierint/UserAgentSpec.scala diff --git a/lm-coursier/src/main/scala/lmcoursier/CoursierDependencyResolution.scala b/lm-coursier/src/main/scala/lmcoursier/CoursierDependencyResolution.scala index df8d22817..d162ca083 100644 --- a/lm-coursier/src/main/scala/lmcoursier/CoursierDependencyResolution.scala +++ b/lm-coursier/src/main/scala/lmcoursier/CoursierDependencyResolution.scala @@ -604,6 +604,8 @@ object CoursierDependencyResolution: .toOption .flatten } + .flatMap(CrossVersion.partialVersion) + .map((major, minor) => s"$major.$minor") .getOrElse("2.1") s"Coursier/$version (+https://github.com/coursier)" diff --git a/main/src/main/scala/sbt/coursierint/LMCoursier.scala b/main/src/main/scala/sbt/coursierint/LMCoursier.scala index 947466de2..70233ac7e 100644 --- a/main/src/main/scala/sbt/coursierint/LMCoursier.scala +++ b/main/src/main/scala/sbt/coursierint/LMCoursier.scala @@ -38,7 +38,11 @@ object LMCoursier { def defaultUserAgent(sbtVer: String): String = sys.props.get("sbt.http.agent").getOrElse { val cs = CoursierDependencyResolution.coursierUserAgent - s"$cs sbt/$sbtVer (+https://www.scala-sbt.org/)".trim + val sbtMajorMinor = CrossVersion + .partialVersion(sbtVer) + .map((major, minor) => s"$major.$minor") + .getOrElse(sbtVer) + s"$cs sbt/$sbtMajorMinor (+https://www.scala-sbt.org/)".trim } def defaultCacheLocation: File = diff --git a/main/src/test/scala/sbt/coursierint/UserAgentSpec.scala b/main/src/test/scala/sbt/coursierint/UserAgentSpec.scala new file mode 100644 index 000000000..85f8c103a --- /dev/null +++ b/main/src/test/scala/sbt/coursierint/UserAgentSpec.scala @@ -0,0 +1,41 @@ +/* + * sbt + * Copyright 2023, Scala center + * Copyright 2011 - 2022, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * Licensed under Apache License 2.0 (see LICENSE) + */ + +package sbt.coursierint + +import hedgehog.* +import hedgehog.runner.* + +object UserAgentSpec extends Properties: + private val UserAgent = + raw"""Coursier/\d+\.\d+ \(\+https://github\.com/coursier\) sbt/2\.0 \(\+https://www\.scala-sbt\.org/\)""".r + + override def tests: List[Test] = + List( + property( + "defaultUserAgent only includes major.minor of sbt", + versionGen.forAll.map { (major, minor, rest) => + val ua = LMCoursier.defaultUserAgent(s"$major.$minor$rest") + Result.assert(ua.endsWith(s" sbt/$major.$minor (+https://www.scala-sbt.org/)")) + } + ), + example( + "defaultUserAgent only includes major.minor of Coursier", + Result.assert(UserAgent.matches(LMCoursier.defaultUserAgent("2.0.0"))) + ), + ) + + private def versionGen: Gen[(Int, Int, String)] = + for + major <- Gen.int(Range.linear(0, 100)) + minor <- Gen.int(Range.linear(0, 100)) + patch <- Gen.int(Range.linear(0, 100)) + suffix <- Gen.element1("", "-M2", "-RC1", "-SNAPSHOT", "-bin-20260924") + rest <- Gen.element1("", s".$patch$suffix") + yield (major, minor, rest) +end UserAgentSpec