Skip to content

Commit

Permalink
Merge pull request #2249 from scala-steward-org/topic/load-latest-art…
Browse files Browse the repository at this point in the history
…ifact-migrations

Load artifact migrations from this repository
  • Loading branch information
fthomas authored Sep 23, 2021
2 parents a890c3d + f17d24a commit 8a251e7
Show file tree
Hide file tree
Showing 15 changed files with 336 additions and 271 deletions.
17 changes: 10 additions & 7 deletions docs/artifact-migrations.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

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

## Adding artifact migration rules to Scala Steward
## Adding artifact migrations to Scala Steward

By default, scala-steward applies the artifact migrations rules defined in the [default list][migrations]. When running
Scala Steward you can also specify a file (via the `--artifact-migrations` command-line option) that contains
additional migrations.

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

Pull requests that added artifact migrations can be found [here][migration-prs].

[migrations]: https://github.com/scala-steward-org/scala-steward/blob/master/modules/core/src/main/resources/artifact-migrations.conf
[HOCON]: https://github.com/lightbend/config/blob/master/HOCON.md
[migration-prs]: https://github.com/scala-steward-org/scala-steward/pulls?q=label%3Aartifact-migration
[HOCON]: https://github.com/lightbend/config/blob/master/HOCON.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ object Cli {
maxBufferSize: Int = 8192,
scalafixMigrations: List[Uri] = Nil,
disableDefaultScalafixMigrations: Boolean = false,
artifactMigrations: Option[File] = None,
artifactMigrations: List[Uri] = Nil,
cacheTtl: FiniteDuration = 2.hours,
bitbucketServerUseDefaultReviewers: Boolean = false,
gitlabMergeWhenPipelineSucceeds: Boolean = false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ final case class Config(
ignoreOptsFiles: Boolean,
processCfg: ProcessCfg,
scalafixCfg: ScalafixCfg,
artifactMigrations: Option[File],
artifactMigrations: List[Uri],
cacheTtl: FiniteDuration,
bitbucketServerCfg: BitbucketServerCfg,
gitLabCfg: GitLabCfg,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ import org.scalasteward.core.persistence.{CachingKeyValueStore, JsonKeyValueStor
import org.scalasteward.core.repocache._
import org.scalasteward.core.repoconfig.RepoConfigAlg
import org.scalasteward.core.scalafmt.ScalafmtAlg
import org.scalasteward.core.update.{ArtifactMigrations, FilterAlg, PruningAlg, UpdateAlg}
import org.scalasteward.core.update.artifact.{ArtifactMigrationsFinder, ArtifactMigrationsLoader}
import org.scalasteward.core.update.{FilterAlg, PruningAlg, UpdateAlg}
import org.scalasteward.core.util._
import org.scalasteward.core.util.uri._
import org.scalasteward.core.vcs.data.Repo
Expand Down Expand Up @@ -96,7 +97,8 @@ object Context {
for {
_ <- printBanner[F]
vcsUser <- config.vcsUser[F]
artifactMigrations0 <- ArtifactMigrations.create[F](config)
artifactMigrationsLoader0 = new ArtifactMigrationsLoader[F]
artifactMigrationsFinder0 <- artifactMigrationsLoader0.createFinder(config.artifactMigrations)
scalafixMigrationsLoader0 = new ScalafixMigrationsLoader[F]
scalafixMigrationsFinder0 <- scalafixMigrationsLoader0.createFinder(config.scalafixCfg)
urlChecker0 <- UrlChecker.create[F](config)
Expand All @@ -111,7 +113,7 @@ object Context {
versionsStore <- JsonKeyValueStore
.create[F, VersionsCache.Key, VersionsCache.Value]("versions", "2")
} yield {
implicit val artifactMigrations: ArtifactMigrations = artifactMigrations0
implicit val artifactMigrationsFinder: ArtifactMigrationsFinder = artifactMigrationsFinder0
implicit val scalafixMigrationsLoader: ScalafixMigrationsLoader[F] = scalafixMigrationsLoader0
implicit val scalafixMigrationsFinder: ScalafixMigrationsFinder = scalafixMigrationsFinder0
implicit val urlChecker: UrlChecker[F] = urlChecker0
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,14 @@ import cats.syntax.all._
import org.scalasteward.core.coursier.VersionsCache
import org.scalasteward.core.data._
import org.scalasteward.core.repoconfig.RepoConfig
import org.scalasteward.core.update.artifact.ArtifactMigrationsFinder
import org.scalasteward.core.util.Nel
import scala.concurrent.duration.FiniteDuration

final class UpdateAlg[F[_]](implicit
artifactMigrationsFinder: ArtifactMigrationsFinder,
filterAlg: FilterAlg[F],
versionsCache: VersionsCache[F],
artifactMigrations: ArtifactMigrations,
F: Monad[F]
) {
def findUpdate(
Expand All @@ -40,7 +41,7 @@ final class UpdateAlg[F[_]](implicit
maybeNewerVersions = Nel.fromList(versions.filter(_ > current))
maybeUpdate = maybeNewerVersions
.map(vs => Update.Single(CrossDependency(dependency.value), vs.map(_.value)))
.orElse(artifactMigrations.findUpdateWithRenamedArtifact(dependency.value))
.orElse(artifactMigrationsFinder.findUpdateWithRenamedArtifact(dependency.value))
} yield maybeUpdate

def findUpdates(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright 2018-2021 Scala Steward contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.scalasteward.core.update.artifact

import io.circe.Decoder
import io.circe.generic.extras.{semiauto, Configuration}
import org.scalasteward.core.data.GroupId

final case class ArtifactChange(
groupIdBefore: Option[GroupId],
groupIdAfter: GroupId,
artifactIdBefore: Option[String],
artifactIdAfter: String,
initialVersion: String
)

object ArtifactChange {
implicit val configuration: Configuration =
Configuration.default.withDefaults

implicit val decoder: Decoder[ArtifactChange] =
semiauto.deriveConfiguredDecoder
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright 2018-2021 Scala Steward contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.scalasteward.core.update.artifact

import io.circe.Decoder
import io.circe.generic.extras.{semiauto, Configuration}

final case class ArtifactChanges(changes: List[ArtifactChange])

object ArtifactChanges {
implicit val configuration: Configuration =
Configuration.default.withDefaults

implicit val artifactChangesDecoder: Decoder[ArtifactChanges] =
semiauto.deriveConfiguredDecoder
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright 2018-2021 Scala Steward contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.scalasteward.core.update.artifact

import cats.syntax.all._
import org.scalasteward.core.data.{CrossDependency, Dependency, Update}
import org.scalasteward.core.util.Nel

final class ArtifactMigrationsFinder(migrations: List[ArtifactChange]) {
def findUpdateWithRenamedArtifact(dependency: Dependency): Option[Update.Single] =
migrations
.find { migration =>
(migration.groupIdBefore, migration.artifactIdBefore) match {
case (Some(groupId), Some(artifactId)) =>
groupId === dependency.groupId &&
artifactId === dependency.artifactId.name
case (Some(groupId), None) =>
groupId === dependency.groupId &&
migration.artifactIdAfter === dependency.artifactId.name
case (None, Some(artifactId)) =>
migration.groupIdAfter === dependency.groupId &&
artifactId === dependency.artifactId.name
case (None, None) => false
}
}
.map { migration =>
Update.Single(
CrossDependency(dependency),
Nel.one(migration.initialVersion),
Some(migration.groupIdAfter),
Some(migration.artifactIdAfter)
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright 2018-2021 Scala Steward contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.scalasteward.core.update.artifact

import cats.MonadThrow
import cats.syntax.all._
import io.circe.config.parser.decode
import org.http4s.Uri
import org.http4s.implicits.http4sLiteralsSyntax
import org.scalasteward.core.io.FileAlg
import org.scalasteward.core.update.artifact.ArtifactMigrationsLoader.defaultArtifactMigrationsUrl
import org.typelevel.log4cats.Logger

final class ArtifactMigrationsLoader[F[_]](implicit
fileAlg: FileAlg[F],
logger: Logger[F],
F: MonadThrow[F]
) {
def createFinder(artifactMigrations: List[Uri]): F[ArtifactMigrationsFinder] =
loadAll(artifactMigrations).map(new ArtifactMigrationsFinder(_))

def loadAll(artifactMigrations: List[Uri]): F[List[ArtifactChange]] =
(defaultArtifactMigrationsUrl :: artifactMigrations)
.flatTraverse(loadMigrations)
.flatTap(migrations => logger.info(s"Loaded ${migrations.size} artifact migrations"))

private def loadMigrations(uri: Uri): F[List[ArtifactChange]] =
logger.debug(s"Loading artifact migrations from $uri") >>
fileAlg.readUri(uri).flatMap(decodeMigrations(_, uri)).map(_.changes)

private def decodeMigrations(content: String, uri: Uri): F[ArtifactChanges] =
F.fromEither(decode[ArtifactChanges](content))
.adaptErr(new Throwable(s"Failed to load artifact migrations from ${uri.renderString}", _))
}

object ArtifactMigrationsLoader {
val defaultArtifactMigrationsUrl: Uri =
uri"https://raw.githubusercontent.com/scala-steward-org/scala-steward/master/modules/core/src/main/resources/artifact-migrations.conf"
}
Loading

0 comments on commit 8a251e7

Please sign in to comment.