Repository: scala-steward-org/scala-steward
Pull request #1850 (2020-12-30 15:42:50)

Add minimal CLI help
A first attempt at documenting all CLI arguments.
I'm open for other formatting ideas. 
Sadly [casa-app](https://github.com/alexarchambault/case-app) does not provide a markdown help on its own.


Patch:
diff --git a/docs/help.md b/docs/help.md
new file mode 100644
index 00000000..4076e6ad
--- /dev/null
+++ b/docs/help.md
@@ -0,0 +1,39 @@
+# CLI help
+
+All command line arguments for the `scala-steward` application.
+
+### Mandatory arguments
+```
+  --workspace  DIRECTORY     Location for cache and temporary files
+  --repos-file  FILE         A markdown formatted file with a repository list
+  --git-author-email  EMAIL  Email address of the git user
+  --vcs-login  USERNAME      The user name for the git hoster
+  --git-ask-pass  FILE       An executable file that returns the git credentials
+```
+
+### Optional arguments
+```
+  --default-repo-conf  FILE                          A .scala-steward.conf file with default values
+  --git-author-name  NAME                            Git "user.name", default: "Scala Steward"
+  --git-author-signing-key  KEY                      Git "user.signingKey"
+  --vcs-type  VCS_TYPE                               One of "github", "gitlab", "bitbucket" or "bitbucket-server", default: "github"
+  --vcs-api-host  URI                                API uri of the git hoster, default: "https://api.github.com"
+  --sign-commits  BOOLEAN                            Wether to sign commits, default: "false"
+  --whitelist  DIRECTORY                             Directory white listed for the sandbox (can be used multiple times)
+  --read-only  DIRECTORY                             Read only directory for the sandbox (can be used multiple times)
+  --enable-sandbox  BOOLEAN                          Wether to use the sandbox, overwrites "--disable-sandbox", default: "false"
+  --disable-sandbox  BOOLEAN                         Wether to not use the sandbox, default: "true"
+  --do-not-fork  BOOLEAN                             Wether to not push the update branches to a fork, default: "false"
+  --ignore-opts-files  BOOLEAN                       Wether to remove ".jvmopts" and ".sbtopts" files before invoking the build tool  
+  --env-var VAR=VALUE                                Assigns the VALUE to the environment variable VAR (can be used multiple times)
+  --process-timeout  DURATION                        Timeout for external process invokations, default: "10min"
+  --max-buffer-size  LINES                           Size of the buffer for the output of an external process in lines, default: "8192"
+  --scalafix-migrations  URI                         Additional scalafix migrations configuraton file (can be used multiple times)
+  --disable-default-scalafix-migrations  BOOLEAN     Wether to disable the default scalafix migration file
+  --artifact-migrations  FILE                        An additional file with artifact migration configurations
+  --cache-ttl  DURATION                              TTL for the caches, default: "2hours"
+  --bitbucket-server-use-default-reviewers  BOOLEAN  Wether to assign the default reviewers to a bitbucket pull request, default: "false"
+  --gitlab-merge-when-pipeline-succeeds  BOOLEAN     Wether to merge a gitlab merge request when the pipeline succeeds
+  --github-app-key-file  FILE                        Github application key file
+  --github-app-id  ID                                Github application id
+```
diff --git a/docs/running.md b/docs/running.md
index 2e799fd3..9c697bbb 100644
--- a/docs/running.md
+++ b/docs/running.md
@@ -1,5 +1,7 @@
 ## Running Scala Steward
 
+A complete list of all command line arguments can be found [here](help.md).
+
 ```bash
 sbt stage
 
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 85f26800..205cecfc 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
@@ -85,7 +85,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.attemptLogLabel(util.string.lineLeftRight(label), Some(label)) {
+      logger.attemptLogInfo(util.string.lineLeftRight(label), Some(label)) {
         F.guarantee {
           for {
             (cache, fork) <- repoCacheAlg.checkCache(repo)
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
index d25d599f..5038a120 100644
--- 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
@@ -52,7 +52,7 @@ final class HookExecutor[F[_]](implicit
     for {
       _ <- logger.info(s"Executing post-update hook for ${hook.groupId}:${hook.artifactId.name}")
       repoDir <- workspaceAlg.repoDir(repo)
-      _ <- logger.attemptLogWarn("Post-update hook failed") {
+      _ <- logger.attemptLogError("Post-update hook failed") {
         processAlg.execMaybeSandboxed(hook.useSandbox)(hook.command, repoDir)
       }
       maybeCommit <- gitAlg.commitAllIfDirty(repo, hook.commitMessage(update))
diff --git a/modules/core/src/main/scala/org/scalasteward/core/nurture/PullRequestRepository.scala b/modules/core/src/main/scala/org/scalasteward/core/nurture/PullRequestRepository.scala
index 5fe6e795..80c9ca7c 100644
--- a/modules/core/src/main/scala/org/scalasteward/core/nurture/PullRequestRepository.scala
+++ b/modules/core/src/main/scala/org/scalasteward/core/nurture/PullRequestRepository.scala
@@ -79,7 +79,7 @@ final class PullRequestRepository[F[_]](
               Version(data.update.nextVersion) < Version(update.nextVersion) &&
               data.state === PullRequestState.Open =>
           data.number.orElse(vcs.extractPullRequestNumberFrom(url)).map((_, url, data.update))
-      }.flatten.toList.sortBy { case (number, _, _) => number.value }
+      }.flatten.toList
     }
 
   def findLatestPullRequest(
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 0fe7f2b2..919c844f 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,25 +24,18 @@ import scala.concurrent.duration.FiniteDuration
 
 object logger {
   implicit final class LoggerOps[F[_]](private val logger: Logger[F]) extends AnyVal {
-    def attemptLogLabel[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) >> attemptLogError(s"${errorLabel.getOrElse(label)} failed")(fa)
 
-    def attemptLogWarn[A](message: String)(fa: F[A])(implicit
-        F: MonadThrow[F]
-    ): F[Either[Throwable, A]] =
-      attemptLogImpl(fa, logger.warn(_)(message))
-
     def attemptLogError[A](message: String)(fa: F[A])(implicit
         F: MonadThrow[F]
     ): F[Either[Throwable, A]] =
-      attemptLogImpl(fa, logger.error(_)(message))
-
-    private def attemptLogImpl[A](fa: F[A], log: Throwable => F[Unit])(implicit
-        F: MonadThrow[F]
-    ): F[Either[Throwable, A]] =
-      fa.attempt.flatTap(_.fold(log, _ => F.unit))
+      fa.attempt.flatTap {
+        case Left(t)  => logger.error(t)(message)
+        case Right(_) => F.unit
+      }
 
     def infoTimed[A](msg: FiniteDuration => String)(fa: F[A])(implicit
         dateTimeAlg: DateTimeAlg[F],
diff --git a/modules/core/src/main/scala/org/scalasteward/core/vcs/VCSRepoAlg.scala b/modules/core/src/main/scala/org/scalasteward/core/vcs/VCSRepoAlg.scala
index 11694d35..c10536a8 100644
--- a/modules/core/src/main/scala/org/scalasteward/core/vcs/VCSRepoAlg.scala
+++ b/modules/core/src/main/scala/org/scalasteward/core/vcs/VCSRepoAlg.scala
@@ -39,7 +39,7 @@ final class VCSRepoAlg[F[_]](config: Config)(implicit
         else logger.info(s"Clone and synchronize ${repo.show}")
       _ <- clone(repo, repoOut)
       _ <- syncFork(repo, repoOut)
-      _ <- logger.attemptLogWarn("Initializing and cloning submodules failed") {
+      _ <- logger.attemptLogError("Initializing and cloning submodules failed") {
         gitAlg.initSubmodules(repo)
       }
     } yield ()
diff --git a/modules/core/src/main/scala/org/scalasteward/core/vcs/data/NewPullRequestData.scala b/modules/core/src/main/scala/org/scalasteward/core/vcs/data/NewPullRequestData.scala
index 5421b7cb..9377478c 100644
--- a/modules/core/src/main/scala/org/scalasteward/core/vcs/data/NewPullRequestData.scala
+++ b/modules/core/src/main/scala/org/scalasteward/core/vcs/data/NewPullRequestData.scala
@@ -26,7 +26,7 @@ import org.scalasteward.core.git.Branch
 import org.scalasteward.core.nurture.UpdateData
 import org.scalasteward.core.repoconfig.RepoConfigAlg
 import org.scalasteward.core.scalafix.Migration
-import org.scalasteward.core.util.Details
+import org.scalasteward.core.util.{Details, Nel}
 
 final case class UpdateState(
     state: PullRequestState
@@ -56,17 +56,17 @@ object NewPullRequestData {
     val artifacts = artifactsWithOptionalUrl(update, artifactIdToUrl)
     val (migrationLabel, appliedMigrations) = migrationNote(migrations)
     val (oldVersionLabel, oldVersionDetails) = oldVersionNote(filesWithOldVersion, update)
-    val details = appliedMigrations.toList ++
-      oldVersionDetails.toList ++
-      List(ignoreFutureUpdates(update))
-    val labels = List(updateType(update)) ++
-      semVerLabel(update).toList ++
-      migrationLabel.toList ++
-      oldVersionLabel.toList
+    val details = ignoreFutureUpdates(update) :: appliedMigrations.toList
+    val labels = Nel.fromList(
+      List(updateType(update)) ++
+        semVerLabel(update).toList ++
+        migrationLabel.toList ++
+        oldVersionLabel.toList
+    )
 
     s"""|Updates $artifacts ${fromTo(update)}.
         |${releaseNote(releaseRelatedUrls).getOrElse("")}
-        |
+        |${oldVersionDetails.map(_.toHtml).getOrElse("")}
         |I'll automatically update this PR to resolve conflicts as long as you don't change it yourself.
         |
         |If you'd like to skip this version, you can just close this PR. If you have any feedback, just mention me in the comments below.
@@ -77,7 +77,7 @@ object NewPullRequestData {
         |
         |${details.map(_.toHtml).mkString("\n")}
         |
-        |${labels.mkString("labels: ", ", ", "")}
+        |${labels.fold("")(_.mkString_("labels: ", ", ", ""))}
         |""".stripMargin.trim
   }
 
@@ -148,7 +148,7 @@ object NewPullRequestData {
                |```
                |${files.mkString("\n")}
                |```
-               |""".stripMargin.trim
+               |""".stripMargin
           )
         )
       )


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 eccf1767..df1cbd28 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
@@ -1,6 +1,6 @@
 package org.scalasteward.core.util
 
-import cats.{Applicative, ApplicativeThrow}
+import cats.effect.Sync
 import munit.FunSuite
 import org.scalasteward.core.mock.MockContext._
 import org.scalasteward.core.mock.{MockEff, MockState}
@@ -11,9 +11,10 @@ class loggerTest extends FunSuite {
     final case class Err(msg: String) extends Throwable(msg)
     val err = Err("hmm?")
     val state = mockLogger
-      .attemptLogLabel("run")(ApplicativeThrow[MockEff].raiseError(err))
+      .attemptLogInfo("run")(Sync[MockEff].raiseError(err))
       .runS(MockState.empty)
       .unsafeRunSync()
+
     assertEquals(state.logs, Vector((None, "run"), (Some(err), "run failed")))
   }
 
@@ -22,14 +23,7 @@ class loggerTest extends FunSuite {
       .infoTimed(_ => "timed")(mockLogger.info("inner"))
       .runS(MockState.empty)
       .unsafeRunSync()
-    assertEquals(state.logs, Vector((None, "inner"), (None, "timed")))
-  }
 
-  test("infoTotalTime") {
-    val state = mockLogger
-      .infoTotalTime("run")(Applicative[MockEff].unit)
-      .runS(MockState.empty)
-      .unsafeRunSync()
-    assertEquals(state.logs.size, 1)
+    assertEquals(state.logs, Vector((None, "inner"), (None, "timed")))
   }
 }
diff --git a/modules/core/src/test/scala/org/scalasteward/core/vcs/data/NewPullRequestDataTest.scala b/modules/core/src/test/scala/org/scalasteward/core/vcs/data/NewPullRequestDataTest.scala
index ee248281..f2437dbe 100644
--- a/modules/core/src/test/scala/org/scalasteward/core/vcs/data/NewPullRequestDataTest.scala
+++ b/modules/core/src/test/scala/org/scalasteward/core/vcs/data/NewPullRequestDataTest.scala
@@ -206,6 +206,7 @@ class NewPullRequestDataTest extends FunSuite {
         |Readme.md
         |travis.yml
         |```
+        |
         |</details>
       """.stripMargin.trim
     )