Repository: scala-steward-org/scala-steward
Pull request #1779 (2020-12-01 14:36:43)

Ignore errors while cloning Git submodules
This PR replaces `--recursive` from the `git clone` options with an
[equivalent](https://git-scm.com/docs/git-clone/2.11.4#Documentation/git-clone.txt---recursive) `git submodule` call which we allow to fail. We allow it to fail
because submodules might point to private repos which may not be
necessary for updating dependencies.

This change is motivated by https://github.com/scala-steward-org/repos/pull/514#issuecomment-734213126.


Patch:
diff --git a/modules/core/src/main/scala/org/scalasteward/core/application/StewardAlg.scala b/modules/core/src/main/scala/org/scalasteward/core/application/StewardAlg.scala
index b1550567..e13c231f 100644
--- a/modules/core/src/main/scala/org/scalasteward/core/application/StewardAlg.scala
+++ b/modules/core/src/main/scala/org/scalasteward/core/application/StewardAlg.scala
@@ -84,7 +84,7 @@ final class StewardAlg[F[_]](config: Config)(implicit
   private def steward(repo: Repo): F[Either[Throwable, Unit]] = {
     val label = s"Steward ${repo.show}"
     logger.infoTotalTime(label) {
-      logger.attemptLog(util.string.lineLeftRight(label), Some(label)) {
+      logger.attemptLogInfo(util.string.lineLeftRight(label), Some(label)) {
         F.guarantee {
           for {
             fork <- repoCacheAlg.checkCache(repo)
diff --git a/modules/core/src/main/scala/org/scalasteward/core/git/FileGitAlg.scala b/modules/core/src/main/scala/org/scalasteward/core/git/FileGitAlg.scala
index 94620fd3..7a720101 100644
--- a/modules/core/src/main/scala/org/scalasteward/core/git/FileGitAlg.scala
+++ b/modules/core/src/main/scala/org/scalasteward/core/git/FileGitAlg.scala
@@ -18,13 +18,16 @@ package org.scalasteward.core.git
 
 import better.files.File
 import cats.syntax.all._
+import io.chrisdavenport.log4cats.Logger
 import org.http4s.Uri
 import org.scalasteward.core.application.Config
 import org.scalasteward.core.io.{FileAlg, ProcessAlg, WorkspaceAlg}
+import org.scalasteward.core.util.logger._
 import org.scalasteward.core.util.{BracketThrow, Nel}
 
 final class FileGitAlg[F[_]](config: Config)(implicit
     fileAlg: FileAlg[F],
+    logger: Logger[F],
     processAlg: ProcessAlg[F],
     workspaceAlg: WorkspaceAlg[F],
     F: BracketThrow[F]
@@ -36,9 +39,13 @@ final class FileGitAlg[F[_]](config: Config)(implicit
     git("checkout", branch.name)(repo).void
 
   override def clone(repo: File, url: Uri): F[Unit] =
-    workspaceAlg.rootDir.flatMap { rootDir =>
-      git("clone", "--recursive", url.toString, repo.pathAsString)(rootDir).void
-    }
+    for {
+      rootDir <- workspaceAlg.rootDir
+      _ <- git("clone", url.toString, repo.pathAsString)(rootDir)
+      _ <- logger.attemptLogError("Initializing and cloning submodules failed") {
+        git("submodule", "update", "--init", "--recursive")(repo)
+      }
+    } yield ()
 
   override def cloneExists(repo: File): F[Boolean] =
     fileAlg.isDirectory(repo / ".git")
diff --git a/modules/core/src/main/scala/org/scalasteward/core/git/GenGitAlg.scala b/modules/core/src/main/scala/org/scalasteward/core/git/GenGitAlg.scala
index 50cb3e97..b658ce96 100644
--- a/modules/core/src/main/scala/org/scalasteward/core/git/GenGitAlg.scala
+++ b/modules/core/src/main/scala/org/scalasteward/core/git/GenGitAlg.scala
@@ -19,6 +19,7 @@ package org.scalasteward.core.git
 import cats.effect.Bracket
 import cats.syntax.all._
 import cats.{FlatMap, Monad}
+import io.chrisdavenport.log4cats.Logger
 import org.http4s.Uri
 import org.scalasteward.core.application.Config
 import org.scalasteward.core.io.{FileAlg, ProcessAlg, WorkspaceAlg}
@@ -132,6 +133,7 @@ trait GenGitAlg[F[_], Repo] {
 object GenGitAlg {
   def create[F[_]](config: Config)(implicit
       fileAlg: FileAlg[F],
+      logger: Logger[F],
       processAlg: ProcessAlg[F],
       workspaceAlg: WorkspaceAlg[F],
       F: BracketThrow[F]
diff --git a/modules/core/src/main/scala/org/scalasteward/core/util/logger.scala b/modules/core/src/main/scala/org/scalasteward/core/util/logger.scala
index 987b8af0..8e868f6c 100644
--- a/modules/core/src/main/scala/org/scalasteward/core/util/logger.scala
+++ b/modules/core/src/main/scala/org/scalasteward/core/util/logger.scala
@@ -24,11 +24,16 @@ import scala.concurrent.duration.FiniteDuration
 
 object logger {
   implicit final class LoggerOps[F[_]](private val logger: Logger[F]) extends AnyVal {
-    def attemptLog[A](label: String, errorLabel: Option[String] = None)(fa: F[A])(implicit
+    def attemptLogInfo[A](label: String, errorLabel: Option[String] = None)(fa: F[A])(implicit
         F: MonadThrow[F]
     ): F[Either[Throwable, A]] =
-      logger.info(label) >> fa.attempt.flatTap {
-        case Left(t)  => logger.error(t)(s"${errorLabel.getOrElse(label)} failed")
+      logger.info(label) >> attemptLogError(s"${errorLabel.getOrElse(label)} failed")(fa)
+
+    def attemptLogError[A](message: String)(fa: F[A])(implicit
+        F: MonadThrow[F]
+    ): F[Either[Throwable, A]] =
+      fa.attempt.flatTap {
+        case Left(t)  => logger.error(t)(message)
         case Right(_) => F.unit
       }
 
diff --git a/project/plugins.sbt b/project/plugins.sbt
index b9b52198..b5b8790a 100644
--- a/project/plugins.sbt
+++ b/project/plugins.sbt
@@ -3,7 +3,7 @@ addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.15.0")
 addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.10.0")
 addSbtPlugin("com.geirsson" % "sbt-ci-release" % "1.5.4")
 addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.2")
-addSbtPlugin("com.github.cb372" % "sbt-explicit-dependencies" % "0.2.16")
+addSbtPlugin("com.github.cb372" % "sbt-explicit-dependencies" % "0.2.15")
 addSbtPlugin("com.github.tkawachi" % "sbt-doctest" % "0.9.8")
 addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.7.6")
 addSbtPlugin("de.heikoseeberger" % "sbt-header" % "5.6.0")


Test patch:
diff --git a/modules/core/src/test/scala/org/scalasteward/core/util/loggerTest.scala b/modules/core/src/test/scala/org/scalasteward/core/util/loggerTest.scala
index b67f4794..c9d8d952 100644
--- a/modules/core/src/test/scala/org/scalasteward/core/util/loggerTest.scala
+++ b/modules/core/src/test/scala/org/scalasteward/core/util/loggerTest.scala
@@ -12,7 +12,7 @@ class loggerTest extends AnyFunSuite with Matchers {
     final case class Err(msg: String) extends Throwable(msg)
     val err = Err("hmm?")
     val state = mockLogger
-      .attemptLog("run")(Sync[MockEff].raiseError(err))
+      .attemptLogInfo("run")(Sync[MockEff].raiseError(err))
       .runS(MockState.empty)
       .unsafeRunSync()
 
diff --git a/modules/core/src/test/scala/org/scalasteward/core/vcs/VCSRepoAlgTest.scala b/modules/core/src/test/scala/org/scalasteward/core/vcs/VCSRepoAlgTest.scala
index a338f430..ae39f2a4 100644
--- a/modules/core/src/test/scala/org/scalasteward/core/vcs/VCSRepoAlgTest.scala
+++ b/modules/core/src/test/scala/org/scalasteward/core/vcs/VCSRepoAlgTest.scala
@@ -11,8 +11,7 @@ import org.scalatest.matchers.should.Matchers
 class VCSRepoAlgTest extends AnyFunSuite with Matchers {
   val repo: Repo = Repo("fthomas", "datapackage")
   val repoDir: String = (config.workspace / "fthomas/datapackage").toString
-  val askPass = s"GIT_ASKPASS=${config.gitAskPass}"
-  val envVars = List(askPass, "VAR1=val1", "VAR2=val2")
+  val envVars = List(s"GIT_ASKPASS=${config.gitAskPass}", "VAR1=val1", "VAR2=val2")
 
   val parentRepoOut: RepoOut = RepoOut(
     "datapackage",
@@ -32,16 +31,11 @@ class VCSRepoAlgTest extends AnyFunSuite with Matchers {
 
   test("clone") {
     val state = vcsRepoAlg.clone(repo, forkRepoOut).runS(MockState.empty).unsafeRunSync()
+    val url = s"https://${config.vcsLogin}@github.com/scala-steward/datapackage"
     state shouldBe MockState.empty.copy(
       commands = Vector(
-        envVars ++ List(
-          config.workspace.toString,
-          "git",
-          "clone",
-          "--recursive",
-          s"https://${config.vcsLogin}@github.com/scala-steward/datapackage",
-          repoDir
-        ),
+        envVars ++ List(config.workspace.toString, "git", "clone", url, repoDir),
+        envVars ++ List(repoDir, "git", "submodule", "update", "--init", "--recursive"),
         envVars ++ List(repoDir, "git", "config", "user.email", "bot@example.org"),
         envVars ++ List(repoDir, "git", "config", "user.name", "Bot Doe")
       )