Repository: scala-steward-org/scala-steward (scala)

Issue:
Enhancement: Understanding sbt-github-actions
When upgrading sbt-github-actions, you almost always need to re-run `sbt githubWorkflowGenerate`, otherwise the workflow will be out of date. Technically, this is probably also a good idea when upgrading *anything* build-related in a project using sbt-github-actions, since plugins could (for example) set `crossScalaVersions`, which in turn dictates the contents of the workflow.

Without this feature, scala-steward updates of sbt-github-actions dependencies are mostly useless. *With* this feature, updates of this plugin are almost magic because your CI build immediately begins evolving with the same ease as your dependencies.

Pull request description:
This generalizes the code for running scalafmt after updating it to executing arbitrary commands for any update by introducing `PostUpdateHook`s and a `HookExecutor` that runs them. A `PostUpdateHook` associates an artifact with the command to run if that artifact is updated. It also allows to en- or disable it via a flag in `RepoConfig` and has a function to create a commit message from an `Update`. The list of supported `PostUpdateHook`s is static and defined in `HookExecutor`'s companion object. It curently contains hooks for running scalafmt and sbt-github-actions' `githubWorkflowGenerate` command.

Closes #1745.

Patch:
diff --git a/modules/core/src/main/scala/org/scalasteward/core/application/Context.scala b/modules/core/src/main/scala/org/scalasteward/core/application/Context.scala
index 71daff0ec8..807984ed05 100644
--- a/modules/core/src/main/scala/org/scalasteward/core/application/Context.scala
+++ b/modules/core/src/main/scala/org/scalasteward/core/application/Context.scala
@@ -29,6 +29,7 @@ import org.scalasteward.core.buildtool.mill.MillAlg
 import org.scalasteward.core.buildtool.sbt.SbtAlg
 import org.scalasteward.core.coursier.{CoursierAlg, VersionsCache}
 import org.scalasteward.core.edit.EditAlg
+import org.scalasteward.core.edit.hooks.HookExecutor
 import org.scalasteward.core.git.GitAlg
 import org.scalasteward.core.io.{FileAlg, ProcessAlg, WorkspaceAlg}
 import org.scalasteward.core.nurture.{NurtureAlg, PullRequestRepository}
@@ -69,6 +70,7 @@ object Context {
       implicit val repoConfigAlg: RepoConfigAlg[F] = new RepoConfigAlg[F](config)
       implicit val filterAlg: FilterAlg[F] = new FilterAlg[F]
       implicit val gitAlg: GitAlg[F] = GitAlg.create[F](config)
+      implicit val hookExecutor: HookExecutor[F] = new HookExecutor[F]
       implicit val httpJsonClient: HttpJsonClient[F] = new HttpJsonClient[F]
       implicit val repoCacheRepository: RepoCacheRepository[F] =
         new RepoCacheRepository[F](new JsonKeyValueStore("repo_cache", "1", kvsPrefix))
diff --git a/modules/core/src/main/scala/org/scalasteward/core/edit/hooks/HookExecutor.scala b/modules/core/src/main/scala/org/scalasteward/core/edit/hooks/HookExecutor.scala
new file mode 100644
index 0000000000..d1ba045108
--- /dev/null
+++ b/modules/core/src/main/scala/org/scalasteward/core/edit/hooks/HookExecutor.scala
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2018-2020 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.edit.hooks
+
+import cats.Monad
+import cats.syntax.all._
+import org.scalasteward.core.data.{ArtifactId, GroupId, Update}
+import org.scalasteward.core.git.{Commit, GitAlg}
+import org.scalasteward.core.io.{ProcessAlg, WorkspaceAlg}
+import org.scalasteward.core.repoconfig.RepoConfig
+import org.scalasteward.core.scalafmt.{scalafmtArtifactId, scalafmtBinary, scalafmtGroupId}
+import org.scalasteward.core.util.Nel
+import org.scalasteward.core.vcs.data.Repo
+
+final class HookExecutor[F[_]](implicit
+    gitAlg: GitAlg[F],
+    processAlg: ProcessAlg[F],
+    workspaceAlg: WorkspaceAlg[F],
+    F: Monad[F]
+) {
+  def execPostUpdateHooks(repo: Repo, repoConfig: RepoConfig, update: Update): F[List[Commit]] =
+    HookExecutor.postUpdateHooks
+      .filter { hook =>
+        hook.enabledByConfig(repoConfig) &&
+        update.groupId === hook.groupId &&
+        update.artifactIds.exists(_.name === hook.artifactId.name)
+      }
+      .flatTraverse(execPostUpdateHook(repo, update, _))
+
+  private def execPostUpdateHook(
+      repo: Repo,
+      update: Update,
+      hook: PostUpdateHook
+  ): F[List[Commit]] =
+    for {
+      repoDir <- workspaceAlg.repoDir(repo)
+      _ <- processAlg.execSandboxed(hook.command, repoDir)
+      maybeCommit <- gitAlg.commitAllIfDirty(repo, hook.commitMessage(update))
+    } yield maybeCommit.toList
+}
+
+object HookExecutor {
+  val postUpdateHooks: List[PostUpdateHook] =
+    List(
+      PostUpdateHook(
+        groupId = scalafmtGroupId,
+        artifactId = scalafmtArtifactId,
+        command = Nel.of(scalafmtBinary, "--non-interactive"),
+        commitMessage = update => s"Reformat with scalafmt ${update.nextVersion}",
+        enabledByConfig = _.scalafmt.runAfterUpgradingOrDefault
+      ),
+      PostUpdateHook(
+        groupId = GroupId("com.codecommit"),
+        artifactId = ArtifactId("sbt-github-actions"),
+        command = Nel.of("sbt", "githubWorkflowGenerate"),
+        commitMessage =
+          update => s"Regenerate workflow with sbt-github-actions ${update.nextVersion}",
+        enabledByConfig = _ => true
+      )
+    )
+}
diff --git a/modules/core/src/main/scala/org/scalasteward/core/edit/hooks/PostUpdateHook.scala b/modules/core/src/main/scala/org/scalasteward/core/edit/hooks/PostUpdateHook.scala
new file mode 100644
index 0000000000..43170bb4f9
--- /dev/null
+++ b/modules/core/src/main/scala/org/scalasteward/core/edit/hooks/PostUpdateHook.scala
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2018-2020 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.edit.hooks
+
+import org.scalasteward.core.data.{ArtifactId, GroupId, Update}
+import org.scalasteward.core.repoconfig.RepoConfig
+import org.scalasteward.core.util.Nel
+
+final case class PostUpdateHook(
+    groupId: GroupId,
+    artifactId: ArtifactId,
+    command: Nel[String],
+    commitMessage: Update => String,
+    enabledByConfig: RepoConfig => Boolean
+)
diff --git a/modules/core/src/main/scala/org/scalasteward/core/io/package.scala b/modules/core/src/main/scala/org/scalasteward/core/io/package.scala
index 95a6804982..95e2e951a4 100644
--- a/modules/core/src/main/scala/org/scalasteward/core/io/package.scala
+++ b/modules/core/src/main/scala/org/scalasteward/core/io/package.scala
@@ -19,6 +19,7 @@ package org.scalasteward.core
 import better.files.File
 import cats.syntax.all._
 import org.scalasteward.core.data.{GroupId, Update}
+import org.scalasteward.core.scalafmt.{scalafmtArtifactId, scalafmtGroupId}
 
 package object io {
   def isSourceFile(update: Update, fileExtensions: Set[String])(file: File): Boolean = {
@@ -43,6 +44,6 @@ package object io {
       update.artifactIds.exists(_.name === "sbt")
 
   private def isScalafmtCoreUpdate(update: Update): Boolean =
-    update.groupId === GroupId("org.scalameta") &&
-      update.artifactIds.exists(_.name === "scalafmt-core")
+    update.groupId === scalafmtGroupId &&
+      update.artifactIds.exists(_.name === scalafmtArtifactId.name)
 }
diff --git a/modules/core/src/main/scala/org/scalasteward/core/nurture/NurtureAlg.scala b/modules/core/src/main/scala/org/scalasteward/core/nurture/NurtureAlg.scala
index 5cc36ef8ad..541d817298 100644
--- a/modules/core/src/main/scala/org/scalasteward/core/nurture/NurtureAlg.scala
+++ b/modules/core/src/main/scala/org/scalasteward/core/nurture/NurtureAlg.scala
@@ -27,11 +27,11 @@ import org.scalasteward.core.coursier.CoursierAlg
 import org.scalasteward.core.data.ProcessResult.{Ignored, Updated}
 import org.scalasteward.core.data.{ProcessResult, Scope, Update}
 import org.scalasteward.core.edit.EditAlg
+import org.scalasteward.core.edit.hooks.HookExecutor
 import org.scalasteward.core.git.{Branch, Commit, GitAlg}
 import org.scalasteward.core.repocache.RepoCacheRepository
 import org.scalasteward.core.repoconfig.{PullRequestUpdateStrategy, RepoConfigAlg}
 import org.scalasteward.core.scalafix.MigrationAlg
-import org.scalasteward.core.scalafmt.ScalafmtAlg
 import org.scalasteward.core.util.{BracketThrow, HttpExistenceClient}
 import org.scalasteward.core.vcs.data._
 import org.scalasteward.core.vcs.{VCSApiAlg, VCSExtraAlg, VCSRepoAlg}
@@ -39,19 +39,19 @@ import org.scalasteward.core.{git, util, vcs}
 import scala.util.control.NonFatal
 
 final class NurtureAlg[F[_]](config: Config)(implicit
-    editAlg: EditAlg[F],
-    repoConfigAlg: RepoConfigAlg[F],
-    gitAlg: GitAlg[F],
     coursierAlg: CoursierAlg[F],
-    vcsApiAlg: VCSApiAlg[F],
-    vcsRepoAlg: VCSRepoAlg[F],
-    vcsExtraAlg: VCSExtraAlg[F],
-    scalafmtAlg: ScalafmtAlg[F],
+    editAlg: EditAlg[F],
     existenceClient: HttpExistenceClient[F],
+    gitAlg: GitAlg[F],
+    hookExecutor: HookExecutor[F],
     logger: Logger[F],
     migrationAlg: MigrationAlg,
     pullRequestRepository: PullRequestRepository[F],
     repoCacheRepository: RepoCacheRepository[F],
+    repoConfigAlg: RepoConfigAlg[F],
+    vcsApiAlg: VCSApiAlg[F],
+    vcsExtraAlg: VCSExtraAlg[F],
+    vcsRepoAlg: VCSRepoAlg[F],
     streamCompiler: Stream.Compiler[F, F],
     F: BracketThrow[F]
 ) {
@@ -151,12 +151,12 @@ final class NurtureAlg[F[_]](config: Config)(implicit
           _ <- logger.info(s"Create branch ${data.updateBranch.name}")
           _ <- gitAlg.createBranch(data.repo, data.updateBranch)
           maybeCommit <- commitChanges(data)
-          _ <- scalafmtAlg.runScalafmt(data.repo, data.update.mainArtifactId)
-          maybeScalafmtCommit <- gitAlg.commitAllIfDirty(
+          postUpdateCommits <- hookExecutor.execPostUpdateHooks(
             data.repo,
-            s"Reformat with scalafmt ${data.update.nextVersion}"
+            data.repoConfig,
+            data.update
           )
-          _ <- pushCommits(data, List(maybeCommit, maybeScalafmtCommit).flatten)
+          _ <- pushCommits(data, maybeCommit.toList ++ postUpdateCommits)
           _ <- createPullRequest(data)
         } yield Updated
       },
diff --git a/modules/core/src/main/scala/org/scalasteward/core/scalafmt/ScalafmtAlg.scala b/modules/core/src/main/scala/org/scalasteward/core/scalafmt/ScalafmtAlg.scala
index 215aa18d44..ac05cc404b 100644
--- a/modules/core/src/main/scala/org/scalasteward/core/scalafmt/ScalafmtAlg.scala
+++ b/modules/core/src/main/scala/org/scalasteward/core/scalafmt/ScalafmtAlg.scala
@@ -21,13 +21,10 @@ import cats.syntax.all._
 import cats.{Functor, Monad}
 import org.scalasteward.core.data.{Dependency, Version}
 import org.scalasteward.core.io.{FileAlg, ProcessAlg, WorkspaceAlg}
-import org.scalasteward.core.repoconfig.RepoConfigAlg
 import org.scalasteward.core.util.Nel
 import org.scalasteward.core.vcs.data.Repo
 
 trait ScalafmtAlg[F[_]] {
-  def runScalafmt(repo: Repo, mainArtifactId: String): F[Unit]
-
   def getScalafmtVersion(repo: Repo): F[Option[Version]]
 
   def version: F[String]
@@ -40,7 +37,6 @@ object ScalafmtAlg {
   def create[F[_]](implicit
       fileAlg: FileAlg[F],
       workspaceAlg: WorkspaceAlg[F],
-      repoConfigAlg: RepoConfigAlg[F],
       processAlg: ProcessAlg[F],
       F: Monad[F]
   ): ScalafmtAlg[F] =
@@ -52,25 +48,9 @@ object ScalafmtAlg {
           fileContent <- fileAlg.readFile(scalafmtConfFile)
         } yield fileContent.flatMap(parseScalafmtConf)
 
-      override def runScalafmt(repo: Repo, mainArtifactId: String): F[Unit] =
-        for {
-          repoDir <- workspaceAlg.repoDir(repo)
-          shouldRunScalafmt <-
-            if (mainArtifactId === scalafmtArtifactId) {
-              repoConfigAlg
-                .readRepoConfigWithDefault(repo)
-                .map(_.scalafmt.runAfterUpgradingOrDefault)
-            } else {
-              F.pure(false)
-            }
-          _ <- F.whenA(shouldRunScalafmt) {
-            processAlg.exec(Nel.of("scalafmt", "--non-interactive"), repoDir)
-          }
-        } yield ()
-
       override def version: F[String] =
         workspaceAlg.rootDir
-          .flatMap(processAlg.exec(Nel.of("scalafmt", "--version"), _))
+          .flatMap(processAlg.exec(Nel.of(scalafmtBinary, "--version"), _))
           .map(_.mkString.trim)
     }
 }
diff --git a/modules/core/src/main/scala/org/scalasteward/core/scalafmt/package.scala b/modules/core/src/main/scala/org/scalasteward/core/scalafmt/package.scala
index 6c4eaf1dd5..38250a3873 100644
--- a/modules/core/src/main/scala/org/scalasteward/core/scalafmt/package.scala
+++ b/modules/core/src/main/scala/org/scalasteward/core/scalafmt/package.scala
@@ -21,12 +21,18 @@ import org.scalasteward.core.buildtool.sbt.defaultScalaBinaryVersion
 import org.scalasteward.core.data.{ArtifactId, Dependency, GroupId, Version}
 
 package object scalafmt {
-  val scalafmtArtifactId: String = "scalafmt-core"
+  val scalafmtGroupId: GroupId =
+    GroupId("org.scalameta")
+
+  val scalafmtArtifactId: ArtifactId =
+    ArtifactId("scalafmt-core", s"scalafmt-core_$defaultScalaBinaryVersion")
+
+  val scalafmtBinary: String = "scalafmt"
 
   def scalafmtDependency(scalafmtVersion: Version): Dependency =
     Dependency(
-      GroupId(if (scalafmtVersion > Version("2.0.0-RC1")) "org.scalameta" else "com.geirsson"),
-      ArtifactId(scalafmtArtifactId, s"${scalafmtArtifactId}_$defaultScalaBinaryVersion"),
+      if (scalafmtVersion > Version("2.0.0-RC1")) scalafmtGroupId else GroupId("com.geirsson"),
+      scalafmtArtifactId,
       scalafmtVersion.value
     )
 


Test patch:
diff --git a/modules/core/src/test/scala/org/scalasteward/core/edit/hooks/HookExecutorTest.scala b/modules/core/src/test/scala/org/scalasteward/core/edit/hooks/HookExecutorTest.scala
new file mode 100644
index 0000000000..5d4caec452
--- /dev/null
+++ b/modules/core/src/test/scala/org/scalasteward/core/edit/hooks/HookExecutorTest.scala
@@ -0,0 +1,118 @@
+package org.scalasteward.core.edit.hooks
+
+import org.scalasteward.core.TestSyntax._
+import org.scalasteward.core.data.Update
+import org.scalasteward.core.mock.MockContext.{hookExecutor, workspaceAlg}
+import org.scalasteward.core.mock.MockState
+import org.scalasteward.core.repoconfig.{RepoConfig, ScalafmtConfig}
+import org.scalasteward.core.scalafmt.{scalafmtArtifactId, scalafmtGroupId}
+import org.scalasteward.core.util.Nel
+import org.scalasteward.core.vcs.data.Repo
+import org.scalatest.funsuite.AnyFunSuite
+import org.scalatest.matchers.should.Matchers
+
+class HookExecutorTest extends AnyFunSuite with Matchers {
+  private val repo = Repo("scala-steward-org", "scala-steward")
+  private val repoDir = workspaceAlg.repoDir(repo).runA(MockState.empty).unsafeRunSync()
+  private val envVars = List("GIT_ASKPASS=/tmp/askpass.sh", "VAR1=val1", "VAR2=val2")
+
+  test("no hook") {
+    val update = Update.Single("org.typelevel" % "cats-core" % "1.2.0", Nel.of("1.3.0"))
+    val state = hookExecutor
+      .execPostUpdateHooks(repo, RepoConfig.empty, update)
+      .runS(MockState.empty)
+      .unsafeRunSync()
+
+    state shouldBe MockState.empty
+  }
+
+  test("scalafmt: enabled by config") {
+    val update =
+      Update.Single(scalafmtGroupId.value % scalafmtArtifactId % "2.7.4", Nel.of("2.7.5"))
+    val initial = MockState.empty.copy(commandOutputs =
+      Map(
+        List("git", "status", "--porcelain", "--untracked-files=no", "--ignore-submodules") ->
+          List("build.sbt")
+      )
+    )
+    val state = hookExecutor
+      .execPostUpdateHooks(repo, RepoConfig.empty, update)
+      .runS(initial)
+      .unsafeRunSync()
+
+    state shouldBe initial.copy(commands =
+      Vector(
+        List(
+          repoDir.toString,
+          "firejail",
+          s"--whitelist=$repoDir",
+          "--env=VAR1=val1",
+          "--env=VAR2=val2",
+          "scalafmt",
+          "--non-interactive"
+        ),
+        envVars ++ List(
+          repoDir.toString,
+          "git",
+          "status",
+          "--porcelain",
+          "--untracked-files=no",
+          "--ignore-submodules"
+        ),
+        envVars ++ List(
+          repoDir.toString,
+          "git",
+          "commit",
+          "--all",
+          "--no-gpg-sign",
+          "-m",
+          "Reformat with scalafmt 2.7.5"
+        )
+      )
+    )
+
+  }
+
+  test("scalafmt: disabled by config") {
+    val repoConfig =
+      RepoConfig.empty.copy(scalafmt = ScalafmtConfig(runAfterUpgrading = Some(false)))
+    val update =
+      Update.Single(scalafmtGroupId.value % scalafmtArtifactId % "2.7.4", Nel.of("2.7.5"))
+    val state = hookExecutor
+      .execPostUpdateHooks(repo, repoConfig, update)
+      .runS(MockState.empty)
+      .unsafeRunSync()
+
+    state shouldBe MockState.empty
+  }
+
+  test("sbt-github-actions") {
+    val update = Update.Single("com.codecommit" % "sbt-github-actions" % "0.9.4", Nel.of("0.9.5"))
+    val state = hookExecutor
+      .execPostUpdateHooks(repo, RepoConfig.empty, update)
+      .runS(MockState.empty)
+      .unsafeRunSync()
+
+    state shouldBe MockState.empty.copy(commands =
+      Vector(
+        List(
+          repoDir.toString,
+          "firejail",
+          s"--whitelist=$repoDir",
+          "--env=VAR1=val1",
+          "--env=VAR2=val2",
+          "sbt",
+          "githubWorkflowGenerate"
+        ),
+        envVars ++ List(
+          repoDir.toString,
+          "git",
+          "status",
+          "--porcelain",
+          "--untracked-files=no",
+          "--ignore-submodules"
+        )
+      )
+    )
+  }
+}
diff --git a/modules/core/src/test/scala/org/scalasteward/core/mock/MockContext.scala b/modules/core/src/test/scala/org/scalasteward/core/mock/MockContext.scala
index 8fd468b5aa..3a5a47f7ed 100644
--- a/modules/core/src/test/scala/org/scalasteward/core/mock/MockContext.scala
+++ b/modules/core/src/test/scala/org/scalasteward/core/mock/MockContext.scala
@@ -14,6 +14,7 @@ import org.scalasteward.core.buildtool.mill.MillAlg
 import org.scalasteward.core.buildtool.sbt.SbtAlg
 import org.scalasteward.core.coursier.{CoursierAlg, VersionsCache}
 import org.scalasteward.core.edit.EditAlg
+import org.scalasteward.core.edit.hooks.HookExecutor
 import org.scalasteward.core.git.GitAlg
 import org.scalasteward.core.io._
 import org.scalasteward.core.nurture.PullRequestRepository
@@ -62,6 +63,7 @@ object MockContext {
   implicit val coursierAlg: CoursierAlg[MockEff] = CoursierAlg.create
   implicit val dateTimeAlg: DateTimeAlg[MockEff] = DateTimeAlg.create
   implicit val gitAlg: GitAlg[MockEff] = GitAlg.create(config)
+  implicit val hookExecutor: HookExecutor[MockEff] = new HookExecutor[MockEff]
   implicit val user: AuthenticatedUser = AuthenticatedUser("scala-steward", "token")
   implicit val vcsRepoAlg: VCSRepoAlg[MockEff] = VCSRepoAlg.create(config)
   implicit val repoConfigAlg: RepoConfigAlg[MockEff] = new RepoConfigAlg[MockEff](config)
diff --git a/modules/core/src/test/scala/org/scalasteward/core/scalafmt/ScalafmtAlgTest.scala b/modules/core/src/test/scala/org/scalasteward/core/scalafmt/ScalafmtAlgTest.scala
index 48ee93f591..4d5e54a75b 100644
--- a/modules/core/src/test/scala/org/scalasteward/core/scalafmt/ScalafmtAlgTest.scala
+++ b/modules/core/src/test/scala/org/scalasteward/core/scalafmt/ScalafmtAlgTest.scala
@@ -53,77 +53,4 @@ class ScalafmtAlgTest extends AnyFunSuite with Matchers {
   test("editScalafmtConf") {
     // Tested in EditAlgTest
   }
-
-  test("runScalafmt on explicit opt-out: Read config, but do not run scalafmt") {
-    val repo = Repo("fthomas", "scala-steward")
-    val rootDir = config.workspace.parent
-    val repoDir = config.workspace / repo.owner / repo.repo
-    val repoConf = repoDir / ".scala-steward.conf"
-    val initialState = MockState.empty
-      .add(repoConf, "scalafmt.runAfterUpgrading = false")
-    val mainArtifactId = "scalafmt-core"
-
-    val (state, _) = scalafmtAlg.runScalafmt(repo, mainArtifactId).run(initialState).unsafeRunSync()
-    state shouldBe MockState.empty.copy(
-      logs = state.logs, // do not care
-      commands = Vector(
-        List("read", s"$repoDir/.scala-steward.conf"),
-        List("read", s"$rootDir/default.scala-steward.conf")
-      ),
-      files = Map(
-        repoConf -> "scalafmt.runAfterUpgrading = false"
-      )
-    )
-  }
-
-  test("runScalafmt on explicit opt-in: Read config and run scalafmt") {
-    val repo = Repo("fthomas", "scala-steward")
-    val rootDir = config.workspace.parent
-    val repoDir = config.workspace / repo.owner / repo.repo
-    val repoConf = repoDir / ".scala-steward.conf"
-    val initialState = MockState.empty
-      .add(repoConf, "scalafmt.runAfterUpgrading = true")
-    val mainArtifactId = "scalafmt-core"
-
-    val (state, _) = scalafmtAlg.runScalafmt(repo, mainArtifactId).run(initialState).unsafeRunSync()
-    state shouldBe MockState.empty.copy(
-      logs = state.logs, // do not care
-      commands = Vector(
-        List("read", s"$repoDir/.scala-steward.conf"),
-        List("read", s"$rootDir/default.scala-steward.conf"),
-        List("VAR1=val1", "VAR2=val2", repoDir.toString, "scalafmt", "--non-interactive")
-      ),
-      files = Map(
-        repoConf -> "scalafmt.runAfterUpgrading = true"
-      )
-    )
-  }
-
-  test("runScalafmt by default (implicitly enabled): Read config and run scalafmt") {
-    val repo = Repo("fthomas", "scala-steward")
-    val rootDir = config.workspace.parent
-    val repoDir = config.workspace / repo.owner / repo.repo
-    val initialState = MockState.empty
-    val mainArtifactId = "scalafmt-core"
-
-    val (state, _) = scalafmtAlg.runScalafmt(repo, mainArtifactId).run(initialState).unsafeRunSync()
-    state shouldBe MockState.empty.copy(
-      logs = state.logs, // do not care
-      commands = Vector(
-        List("read", s"$repoDir/.scala-steward.conf"),
-        List("read", s"$rootDir/default.scala-steward.conf"),
-        List("VAR1=val1", "VAR2=val2", repoDir.toString, "scalafmt", "--non-interactive")
-      ),
-      files = Map()
-    )
-  }
-
-  test("runScalafmt: Do nothing when scalafmt-core is NOT updated") {
-    val repo = Repo("fthomas", "scala-steward")
-    val initialState = MockState.empty
-    val mainArtifactId = "foo-bar"
-
-    val (state, _) = scalafmtAlg.runScalafmt(repo, mainArtifactId).run(initialState).unsafeRunSync()
-    state shouldBe MockState.empty
-  }
 }