Skip to content

Commit

Permalink
Merge pull request #3369 from guardian/only-use-failure-exit-code-whe…
Browse files Browse the repository at this point in the history
…n-all-repos-have-failed

Only return a failure exit code when all repos have failed
  • Loading branch information
alejandrohdezma committed Jun 11, 2024
2 parents 6259adb + 0607cfc commit 9d9460a
Show file tree
Hide file tree
Showing 8 changed files with 75 additions and 8 deletions.
4 changes: 3 additions & 1 deletion docs/help.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ All command line arguments for the `scala-steward` application.

```
Usage:
scala-steward --workspace <file> --repos-file <uri> [--repos-file <uri>]... [--git-author-name <string>] --git-author-email <string> [--git-author-signing-key <string>] --git-ask-pass <file> [--sign-commits] [--forge-type <forge-type>] [--forge-api-host <uri>] --forge-login <string> [--do-not-fork] [--add-labels] [--ignore-opts-files] [--env-var <name=value>]... [--process-timeout <duration>] [--whitelist <string>]... [--read-only <string>]... [--enable-sandbox | --disable-sandbox] [--max-buffer-size <integer>] [--repo-config <uri>]... [--disable-default-repo-config] [--scalafix-migrations <uri>]... [--disable-default-scalafix-migrations] [--artifact-migrations <uri>]... [--disable-default-artifact-migrations] [--cache-ttl <duration>] [--bitbucket-use-default-reviewers] [--bitbucket-server-use-default-reviewers] [--gitlab-merge-when-pipeline-succeeds] [--gitlab-required-reviewers <integer>] [--gitlab-remove-source-branch] [--azure-repos-organization <string>] [--github-app-id <integer> --github-app-key-file <file>] [--url-checker-test-url <uri>]... [--default-maven-repo <string>] [--refresh-backoff-period <duration>]
scala-steward --workspace <file> --repos-file <uri> [--repos-file <uri>]... [--git-author-name <string>] --git-author-email <string> [--git-author-signing-key <string>] --git-ask-pass <file> [--sign-commits] [--forge-type <forge-type>] [--forge-api-host <uri>] --forge-login <string> [--do-not-fork] [--add-labels] [--ignore-opts-files] [--env-var <name=value>]... [--process-timeout <duration>] [--whitelist <string>]... [--read-only <string>]... [--enable-sandbox | --disable-sandbox] [--max-buffer-size <integer>] [--repo-config <uri>]... [--disable-default-repo-config] [--scalafix-migrations <uri>]... [--disable-default-scalafix-migrations] [--artifact-migrations <uri>]... [--disable-default-artifact-migrations] [--cache-ttl <duration>] [--bitbucket-use-default-reviewers] [--bitbucket-server-use-default-reviewers] [--gitlab-merge-when-pipeline-succeeds] [--gitlab-required-reviewers <integer>] [--gitlab-remove-source-branch] [--azure-repos-organization <string>] [--github-app-id <integer> --github-app-key-file <file>] [--url-checker-test-url <uri>]... [--default-maven-repo <string>] [--refresh-backoff-period <duration>] [--exit-code-success-if-any-repo-succeeds]
scala-steward validate-repo-config
Expand Down Expand Up @@ -94,6 +94,8 @@ Options and flags:
default: https://repo1.maven.org/maven2/
--refresh-backoff-period <duration>
Period of time a failed build won't be triggered again; default: 0days
--exit-code-success-if-any-repo-succeeds
Whether the Scala Steward process should exit with success (exit code 0) if any repo succeeds; default: false
Subcommands:
validate-repo-config
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,25 @@ package org.scalasteward.core.application

import better.files.File
import cats.data.Validated
import cats.effect.ExitCode
import cats.syntax.all._
import com.monovore.decline.Opts.{flag, option, options}
import com.monovore.decline._
import org.http4s.Uri
import org.http4s.syntax.literals._
import org.scalasteward.core.application.Config._
import org.scalasteward.core.application.ExitCodePolicy.{
SuccessIfAnyRepoSucceeds,
SuccessOnlyIfAllReposSucceed
}
import org.scalasteward.core.data.Resolver
import org.scalasteward.core.forge.ForgeType
import org.scalasteward.core.forge.ForgeType.{AzureRepos, GitHub}
import org.scalasteward.core.forge.github.GitHubApp
import org.scalasteward.core.git.Author
import org.scalasteward.core.util.Nel
import org.scalasteward.core.util.dateTime.renderFiniteDuration

import scala.concurrent.duration._

object Cli {
Expand Down Expand Up @@ -337,6 +343,13 @@ object Cli {
.withDefault(default)
}

private val exitCodePolicy: Opts[ExitCodePolicy] = flag(
"exit-code-success-if-any-repo-succeeds",
s"Whether the Scala Steward process should exit with success (exit code ${ExitCode.Success.code}) if any repo succeeds; default: false"
).orFalse.map { ifAnyRepoSucceeds =>
if (ifAnyRepoSucceeds) SuccessIfAnyRepoSucceeds else SuccessOnlyIfAllReposSucceed
}

private val regular: Opts[Usage] = (
workspace,
reposFiles,
Expand All @@ -355,7 +368,8 @@ object Cli {
gitHubApp,
urlCheckerTestUrls,
defaultMavenRepo,
refreshBackoffPeriod
refreshBackoffPeriod,
exitCodePolicy
).mapN(Config.apply).map(Usage.Regular.apply)

private val validateRepoConfig: Opts[Usage] =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ final case class Config(
githubApp: Option[GitHubApp],
urlCheckerTestUrls: Nel[Uri],
defaultResolver: Resolver,
refreshBackoffPeriod: FiniteDuration
refreshBackoffPeriod: FiniteDuration,
exitCodePolicy: ExitCodePolicy
) {
def forgeSpecificCfg: ForgeSpecificCfg =
forgeCfg.tpe match {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright 2018-2023 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.application

import cats.effect.ExitCode

trait ExitCodePolicy {
def exitCodeFor(runResults: RunResults): ExitCode
}

object ExitCodePolicy {
def successIf(isSuccess: RunResults => Boolean): ExitCodePolicy =
(runResults: RunResults) => if (isSuccess(runResults)) ExitCode.Success else ExitCode.Error

val SuccessIfAnyRepoSucceeds: ExitCodePolicy = successIf(_.successRepos.nonEmpty)

val SuccessOnlyIfAllReposSucceed: ExitCodePolicy = successIf(_.reposWithFailures.nonEmpty)
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,12 @@

package org.scalasteward.core.application

import cats.effect.ExitCode
import cats.syntax.all._
import org.scalasteward.core.data.Repo

case class RunResults(results: List[Either[(Repo, Throwable), Repo]]) {
val (reposWithFailures, successRepos) = results.separate

val exitCode: ExitCode = if (reposWithFailures.isEmpty) ExitCode.Success else ExitCode.Error

val markdownSummary: String = {
val failuresSummaryOpt = Option.when(reposWithFailures.nonEmpty) {
(Seq(s"# Job failed for ${reposWithFailures.size} out of ${results.size} repos") ++ (for {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ final class StewardAlg[F[_]](config: Config)(implicit
for {
summaryFile <- workspaceAlg.runSummaryFile
_ <- fileAlg.writeFile(summaryFile, runResults.markdownSummary)
} yield runResults.exitCode
} yield config.exitCodePolicy.exitCodeFor(runResults)
}
} yield exitCode
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,14 @@ import munit.FunSuite
import org.http4s.syntax.literals._
import org.scalasteward.core.application.Cli.ParseResult._
import org.scalasteward.core.application.Cli.{EnvVar, Usage}
import org.scalasteward.core.application.ExitCodePolicy.{
SuccessIfAnyRepoSucceeds,
SuccessOnlyIfAllReposSucceed
}
import org.scalasteward.core.forge.ForgeType
import org.scalasteward.core.forge.github.GitHubApp
import org.scalasteward.core.util.Nel

import scala.concurrent.duration._

class CliTest extends FunSuite {
Expand Down Expand Up @@ -207,6 +212,19 @@ class CliTest extends FunSuite {
assert(!obtained.forgeCfg.addLabels)
}

test("parseArgs: exit code policy: --exit-code-success-if-any-repo-succeeds") {
val params = minimumRequiredParams ++ List(
List("--exit-code-success-if-any-repo-succeeds")
)
val Success(Usage.Regular(obtained)) = Cli.parseArgs(params.flatten)
assert(obtained.exitCodePolicy == SuccessIfAnyRepoSucceeds)
}

test("parseArgs: exit code policy: default") {
val Success(Usage.Regular(obtained)) = Cli.parseArgs(minimumRequiredParams.flatten)
assert(obtained.exitCodePolicy == SuccessOnlyIfAllReposSucceed)
}

test("parseArgs: validate pull request labeling enabled") {
val params = minimumRequiredParams ++ List(
List("--forge-type", "bitbucket"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import org.scalasteward.core.mock.{MockConfig, MockState}
class StewardAlgTest extends CatsEffectSuite {
test("runF") {
val exitCode = stewardAlg.runF.runA(MockState.empty.addUris(MockConfig.reposFile -> ""))
assertIO(exitCode, ExitCode.Success)
assertIO(
exitCode,
ExitCode.Error
) // We have not passed any repos to Scala Steward therefore it's reasonable that it will return error code.
}
}

0 comments on commit 9d9460a

Please sign in to comment.