Skip to content

Commit 8a251e7

Browse files
authored
Merge pull request #2249 from scala-steward-org/topic/load-latest-artifact-migrations
Load artifact migrations from this repository
2 parents a890c3d + f17d24a commit 8a251e7

File tree

15 files changed

+336
-271
lines changed

15 files changed

+336
-271
lines changed

docs/artifact-migrations.md

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22

33
Scala Steward can look for newer versions of artifacts with different group Ids, artifact ids, or both different.
44

5-
## Adding artifact migration rules to Scala Steward
5+
## Adding artifact migrations to Scala Steward
66

7-
By default, scala-steward applies the artifact migrations rules defined in the [default list][migrations]. When running
8-
Scala Steward you can also specify a file (via the `--artifact-migrations` command-line option) that contains
9-
additional migrations.
10-
11-
These files are in [HOCON][HOCON] format and should look like this:
7+
By default, Scala Steward applies the artifact migrations defined in the
8+
[default list][migrations]. When running Scala Steward you can also specify
9+
files or URLs (via the `--artifact-migrations` command-line option) that
10+
contain additional migrations. These files are in [HOCON][HOCON] format and
11+
should look like this:
1212
```hocon
1313
changes = [
1414
{
@@ -28,5 +28,8 @@ The fields `groupIdBefore` and `artifactIdBefore` are optional. If just `groupId
2828
example, then only the group id will get renamed. If just `artifactIdBefore` is specified, then only the artifact id
2929
will get renamed. Specifying both `groupIdBefore` and `artifactIdBefore` will rename both.
3030

31+
Pull requests that added artifact migrations can be found [here][migration-prs].
32+
3133
[migrations]: https://github.com/scala-steward-org/scala-steward/blob/master/modules/core/src/main/resources/artifact-migrations.conf
32-
[HOCON]: https://github.com/lightbend/config/blob/master/HOCON.md
34+
[migration-prs]: https://github.com/scala-steward-org/scala-steward/pulls?q=label%3Aartifact-migration
35+
[HOCON]: https://github.com/lightbend/config/blob/master/HOCON.md

modules/core/src/main/scala/org/scalasteward/core/application/Cli.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ object Cli {
5151
maxBufferSize: Int = 8192,
5252
scalafixMigrations: List[Uri] = Nil,
5353
disableDefaultScalafixMigrations: Boolean = false,
54-
artifactMigrations: Option[File] = None,
54+
artifactMigrations: List[Uri] = Nil,
5555
cacheTtl: FiniteDuration = 2.hours,
5656
bitbucketServerUseDefaultReviewers: Boolean = false,
5757
gitlabMergeWhenPipelineSucceeds: Boolean = false,

modules/core/src/main/scala/org/scalasteward/core/application/Config.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ final case class Config(
7070
ignoreOptsFiles: Boolean,
7171
processCfg: ProcessCfg,
7272
scalafixCfg: ScalafixCfg,
73-
artifactMigrations: Option[File],
73+
artifactMigrations: List[Uri],
7474
cacheTtl: FiniteDuration,
7575
bitbucketServerCfg: BitbucketServerCfg,
7676
gitLabCfg: GitLabCfg,

modules/core/src/main/scala/org/scalasteward/core/application/Context.scala

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ import org.scalasteward.core.persistence.{CachingKeyValueStore, JsonKeyValueStor
3737
import org.scalasteward.core.repocache._
3838
import org.scalasteward.core.repoconfig.RepoConfigAlg
3939
import org.scalasteward.core.scalafmt.ScalafmtAlg
40-
import org.scalasteward.core.update.{ArtifactMigrations, FilterAlg, PruningAlg, UpdateAlg}
40+
import org.scalasteward.core.update.artifact.{ArtifactMigrationsFinder, ArtifactMigrationsLoader}
41+
import org.scalasteward.core.update.{FilterAlg, PruningAlg, UpdateAlg}
4142
import org.scalasteward.core.util._
4243
import org.scalasteward.core.util.uri._
4344
import org.scalasteward.core.vcs.data.Repo
@@ -96,7 +97,8 @@ object Context {
9697
for {
9798
_ <- printBanner[F]
9899
vcsUser <- config.vcsUser[F]
99-
artifactMigrations0 <- ArtifactMigrations.create[F](config)
100+
artifactMigrationsLoader0 = new ArtifactMigrationsLoader[F]
101+
artifactMigrationsFinder0 <- artifactMigrationsLoader0.createFinder(config.artifactMigrations)
100102
scalafixMigrationsLoader0 = new ScalafixMigrationsLoader[F]
101103
scalafixMigrationsFinder0 <- scalafixMigrationsLoader0.createFinder(config.scalafixCfg)
102104
urlChecker0 <- UrlChecker.create[F](config)
@@ -111,7 +113,7 @@ object Context {
111113
versionsStore <- JsonKeyValueStore
112114
.create[F, VersionsCache.Key, VersionsCache.Value]("versions", "2")
113115
} yield {
114-
implicit val artifactMigrations: ArtifactMigrations = artifactMigrations0
116+
implicit val artifactMigrationsFinder: ArtifactMigrationsFinder = artifactMigrationsFinder0
115117
implicit val scalafixMigrationsLoader: ScalafixMigrationsLoader[F] = scalafixMigrationsLoader0
116118
implicit val scalafixMigrationsFinder: ScalafixMigrationsFinder = scalafixMigrationsFinder0
117119
implicit val urlChecker: UrlChecker[F] = urlChecker0

modules/core/src/main/scala/org/scalasteward/core/update/ArtifactMigrations.scala

Lines changed: 0 additions & 117 deletions
This file was deleted.

modules/core/src/main/scala/org/scalasteward/core/update/UpdateAlg.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,14 @@ import cats.syntax.all._
2121
import org.scalasteward.core.coursier.VersionsCache
2222
import org.scalasteward.core.data._
2323
import org.scalasteward.core.repoconfig.RepoConfig
24+
import org.scalasteward.core.update.artifact.ArtifactMigrationsFinder
2425
import org.scalasteward.core.util.Nel
2526
import scala.concurrent.duration.FiniteDuration
2627

2728
final class UpdateAlg[F[_]](implicit
29+
artifactMigrationsFinder: ArtifactMigrationsFinder,
2830
filterAlg: FilterAlg[F],
2931
versionsCache: VersionsCache[F],
30-
artifactMigrations: ArtifactMigrations,
3132
F: Monad[F]
3233
) {
3334
def findUpdate(
@@ -40,7 +41,7 @@ final class UpdateAlg[F[_]](implicit
4041
maybeNewerVersions = Nel.fromList(versions.filter(_ > current))
4142
maybeUpdate = maybeNewerVersions
4243
.map(vs => Update.Single(CrossDependency(dependency.value), vs.map(_.value)))
43-
.orElse(artifactMigrations.findUpdateWithRenamedArtifact(dependency.value))
44+
.orElse(artifactMigrationsFinder.findUpdateWithRenamedArtifact(dependency.value))
4445
} yield maybeUpdate
4546

4647
def findUpdates(
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright 2018-2021 Scala Steward contributors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.scalasteward.core.update.artifact
18+
19+
import io.circe.Decoder
20+
import io.circe.generic.extras.{semiauto, Configuration}
21+
import org.scalasteward.core.data.GroupId
22+
23+
final case class ArtifactChange(
24+
groupIdBefore: Option[GroupId],
25+
groupIdAfter: GroupId,
26+
artifactIdBefore: Option[String],
27+
artifactIdAfter: String,
28+
initialVersion: String
29+
)
30+
31+
object ArtifactChange {
32+
implicit val configuration: Configuration =
33+
Configuration.default.withDefaults
34+
35+
implicit val decoder: Decoder[ArtifactChange] =
36+
semiauto.deriveConfiguredDecoder
37+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Copyright 2018-2021 Scala Steward contributors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.scalasteward.core.update.artifact
18+
19+
import io.circe.Decoder
20+
import io.circe.generic.extras.{semiauto, Configuration}
21+
22+
final case class ArtifactChanges(changes: List[ArtifactChange])
23+
24+
object ArtifactChanges {
25+
implicit val configuration: Configuration =
26+
Configuration.default.withDefaults
27+
28+
implicit val artifactChangesDecoder: Decoder[ArtifactChanges] =
29+
semiauto.deriveConfiguredDecoder
30+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Copyright 2018-2021 Scala Steward contributors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.scalasteward.core.update.artifact
18+
19+
import cats.syntax.all._
20+
import org.scalasteward.core.data.{CrossDependency, Dependency, Update}
21+
import org.scalasteward.core.util.Nel
22+
23+
final class ArtifactMigrationsFinder(migrations: List[ArtifactChange]) {
24+
def findUpdateWithRenamedArtifact(dependency: Dependency): Option[Update.Single] =
25+
migrations
26+
.find { migration =>
27+
(migration.groupIdBefore, migration.artifactIdBefore) match {
28+
case (Some(groupId), Some(artifactId)) =>
29+
groupId === dependency.groupId &&
30+
artifactId === dependency.artifactId.name
31+
case (Some(groupId), None) =>
32+
groupId === dependency.groupId &&
33+
migration.artifactIdAfter === dependency.artifactId.name
34+
case (None, Some(artifactId)) =>
35+
migration.groupIdAfter === dependency.groupId &&
36+
artifactId === dependency.artifactId.name
37+
case (None, None) => false
38+
}
39+
}
40+
.map { migration =>
41+
Update.Single(
42+
CrossDependency(dependency),
43+
Nel.one(migration.initialVersion),
44+
Some(migration.groupIdAfter),
45+
Some(migration.artifactIdAfter)
46+
)
47+
}
48+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright 2018-2021 Scala Steward contributors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.scalasteward.core.update.artifact
18+
19+
import cats.MonadThrow
20+
import cats.syntax.all._
21+
import io.circe.config.parser.decode
22+
import org.http4s.Uri
23+
import org.http4s.implicits.http4sLiteralsSyntax
24+
import org.scalasteward.core.io.FileAlg
25+
import org.scalasteward.core.update.artifact.ArtifactMigrationsLoader.defaultArtifactMigrationsUrl
26+
import org.typelevel.log4cats.Logger
27+
28+
final class ArtifactMigrationsLoader[F[_]](implicit
29+
fileAlg: FileAlg[F],
30+
logger: Logger[F],
31+
F: MonadThrow[F]
32+
) {
33+
def createFinder(artifactMigrations: List[Uri]): F[ArtifactMigrationsFinder] =
34+
loadAll(artifactMigrations).map(new ArtifactMigrationsFinder(_))
35+
36+
def loadAll(artifactMigrations: List[Uri]): F[List[ArtifactChange]] =
37+
(defaultArtifactMigrationsUrl :: artifactMigrations)
38+
.flatTraverse(loadMigrations)
39+
.flatTap(migrations => logger.info(s"Loaded ${migrations.size} artifact migrations"))
40+
41+
private def loadMigrations(uri: Uri): F[List[ArtifactChange]] =
42+
logger.debug(s"Loading artifact migrations from $uri") >>
43+
fileAlg.readUri(uri).flatMap(decodeMigrations(_, uri)).map(_.changes)
44+
45+
private def decodeMigrations(content: String, uri: Uri): F[ArtifactChanges] =
46+
F.fromEither(decode[ArtifactChanges](content))
47+
.adaptErr(new Throwable(s"Failed to load artifact migrations from ${uri.renderString}", _))
48+
}
49+
50+
object ArtifactMigrationsLoader {
51+
val defaultArtifactMigrationsUrl: Uri =
52+
uri"https://raw.githubusercontent.com/scala-steward-org/scala-steward/master/modules/core/src/main/resources/artifact-migrations.conf"
53+
}

0 commit comments

Comments
 (0)