Skip to content

updates - #398

Merged
mr-git merged 4 commits into
masterfrom
m/updates
Aug 10, 2026
Merged

updates#398
mr-git merged 4 commits into
masterfrom
m/updates

Conversation

@mr-git

@mr-git mr-git commented Aug 10, 2026

Copy link
Copy Markdown
Contributor
  • update Scala 3 to 3.3.8
  • introduce and apply scalafmt
  • update SBT to 2.0.6
  • introduce sbt-version-policy 3.3.0

Summary by CodeRabbit

  • Chores

    • Updated the build toolchain and release automation.
    • Added standardized Scala formatting and version-policy checks.
    • Refreshed project metadata and build configuration.
  • Documentation

    • Improved API documentation, examples, and timeout guidance.
  • Style

    • Applied consistent formatting and import ordering across production and test code, with no behavior changes.

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The pull request adds Scalafmt and version-policy configuration, updates SBT and release workflow versions, and reformats production and test Scala sources. It does not change public APIs or runtime behavior.

Changes

Build and formatting modernization

Layer / File(s) Summary
Build workflow and policy configuration
.github/workflows/release.yml, build.sbt, project/*
The release workflow uses version v5. SBT updates its plugins, Scala version, compiler settings, project metadata, commands, root project name, and binary compatibility checks.
Scalafmt rules
.scalafmt.conf
The repository adds formatting, import-rewrite, modifier-ordering, documentation, and file-filtering rules.
Production and test source formatting
core/src/main/scala/*, core/src/test/scala/*, logback/src/main/scala/*, testkit/src/*
Scala sources and tests receive import-order, spacing, Scaladoc, multiline declaration, trailing-comma, and matcher-syntax updates. Runtime behavior and test assertions remain unchanged.

Estimated code review effort: 2 (Simple) | ~15 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title "updates" is too vague and does not identify the toolchain or formatting changes in the pull request. Use a specific title such as "Update Scala, SBT, and Scalafmt toolchain configuration".
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch m/updates

Comment @coderabbitai help to get the list of available commands.

@mr-git
mr-git merged commit 8d49e47 into master Aug 10, 2026
3 of 5 checks passed
@mr-git
mr-git deleted the m/updates branch August 10, 2026 21:10

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/release.yml:
- Around line 10-11: Update the release workflow reference in the reusable
workflow call to use its resolved 40-character commit SHA instead of `@v5`.
Replace secrets: inherit with an explicit JFROG_ACCESS_TOKEN mapping, relying on
the automatically provided GITHUB_TOKEN and passing no other secrets.

In @.scalafmt.conf:
- Around line 8-11: Update the Scalafmt configuration by adding an .sbt-specific
override with runner.dialect set to sbt1, while retaining scala213source3 as the
default dialect and project.git tracking behavior.

In `@core/src/main/scala/com/evolutiongaming/catshelper/CountLatch.scala`:
- Around line 97-106: Update the release method so values of n less than 1
return F.unit without modifying state, matching acquire’s validation behavior.
Preserve the existing Awaiting and Done handling for valid releases.

In `@core/src/main/scala/com/evolutiongaming/catshelper/FeatureToggled.scala`:
- Around line 10-24: Update the public Scaladoc description above the affected
API: state that a Resource[F, A] produces the nested resource and manages A’s
lifecycle “according to the state of a boolean toggle,” adding the missing “it”
after Resource[F, A] while preserving the rest of the documentation.

In `@core/src/main/scala/com/evolutiongaming/catshelper/Log.scala`:
- Line 326: Update the error method’s log label in the override of error(msg: =>
String, mdc: Mdc) from the misspelled value to "ERROR", matching the throwable
overload and preserving consistent error output.

In `@core/src/main/scala/com/evolutiongaming/catshelper/ReadWriteRef.scala`:
- Around line 36-39: Update the Scaladoc for the public read member near
ReadWriteRef to reference read.use(...) instead of reads.use(...), and correct
the duplicated “in in use” wording to state that write is in use.

In
`@testkit/src/main/scala/com/evolutiongaming/catshelper/testkit/PureTest.scala`:
- Around line 86-87: Correct the Scaladoc sentence for hotLoopTimeout to read:
“Use it when a CPU-bound part of your SUT or test requires more time.”
- Around line 25-27: Update the Scaladoc example in PureTest to use the actual
ioTest entry point instead of PureTest[IO].of, and restore a valid multiline
Scala layout with a separator between import env._ and the for-comprehension.
Preserve the example’s existing sleep and elapsed-time assertion behavior.
- Around line 91-93: Update PureTestRunner’s hot-loop cancellation task to use
the configured config.backgroundEc instead of mainRuntime, preserving the
documented background execution behavior. Add a regression test that verifies
the configured ExecutionContext is used; alternatively, remove the backgroundEc
setting and its documentation if it is not intended to be supported.

In
`@testkit/src/main/scala/com/evolutiongaming/catshelper/testkit/TestRuntime.scala`:
- Around line 18-20: Update the Scaladoc for the relevant method in TestRuntime
to replace the Cats Effect 2 timer.sleep example and timer argument wording with
the Cats Effect 3 Temporal[F].sleep API and corresponding argument text.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 869c82f3-8ee3-4671-97d8-a5757a042c1d

📥 Commits

Reviewing files that changed from the base of the PR and between 9634a0f and a883641.

📒 Files selected for processing (73)
  • .github/workflows/ci.yml
  • .github/workflows/release.yml
  • .scalafmt.conf
  • build.sbt
  • core/src/main/scala/com/evolutiongaming/catshelper/Blocking.scala
  • core/src/main/scala/com/evolutiongaming/catshelper/CatsHelper.scala
  • core/src/main/scala/com/evolutiongaming/catshelper/ClockHelper.scala
  • core/src/main/scala/com/evolutiongaming/catshelper/CountLatch.scala
  • core/src/main/scala/com/evolutiongaming/catshelper/DataHelper.scala
  • core/src/main/scala/com/evolutiongaming/catshelper/EffectHelper.scala
  • core/src/main/scala/com/evolutiongaming/catshelper/FeatureToggled.scala
  • core/src/main/scala/com/evolutiongaming/catshelper/Foldable1.scala
  • core/src/main/scala/com/evolutiongaming/catshelper/FromFuture.scala
  • core/src/main/scala/com/evolutiongaming/catshelper/FromTry.scala
  • core/src/main/scala/com/evolutiongaming/catshelper/GroupWithin.scala
  • core/src/main/scala/com/evolutiongaming/catshelper/LazyVal.scala
  • core/src/main/scala/com/evolutiongaming/catshelper/Log.scala
  • core/src/main/scala/com/evolutiongaming/catshelper/LogOf.scala
  • core/src/main/scala/com/evolutiongaming/catshelper/MeasureDuration.scala
  • core/src/main/scala/com/evolutiongaming/catshelper/Memoize.scala
  • core/src/main/scala/com/evolutiongaming/catshelper/ParallelHelper.scala
  • core/src/main/scala/com/evolutiongaming/catshelper/Partitions.scala
  • core/src/main/scala/com/evolutiongaming/catshelper/RandomId.scala
  • core/src/main/scala/com/evolutiongaming/catshelper/RandomIdOf.scala
  • core/src/main/scala/com/evolutiongaming/catshelper/ReadWriteRef.scala
  • core/src/main/scala/com/evolutiongaming/catshelper/ResourceCounter.scala
  • core/src/main/scala/com/evolutiongaming/catshelper/ResourceFenced.scala
  • core/src/main/scala/com/evolutiongaming/catshelper/Runtime.scala
  • core/src/main/scala/com/evolutiongaming/catshelper/Schedule.scala
  • core/src/main/scala/com/evolutiongaming/catshelper/SerParQueue.scala
  • core/src/main/scala/com/evolutiongaming/catshelper/Serial.scala
  • core/src/main/scala/com/evolutiongaming/catshelper/SerialKey.scala
  • core/src/main/scala/com/evolutiongaming/catshelper/SerialRef.scala
  • core/src/main/scala/com/evolutiongaming/catshelper/ThreadLocalRef.scala
  • core/src/main/scala/com/evolutiongaming/catshelper/TimerHelper.scala
  • core/src/main/scala/com/evolutiongaming/catshelper/ToFuture.scala
  • core/src/main/scala/com/evolutiongaming/catshelper/ToTry.scala
  • core/src/main/scala/com/evolutiongaming/catshelper/package.scala
  • core/src/main/scala/com/evolutiongaming/catshelper/syntax/MeasureDurationSyntax.scala
  • core/src/test/scala/com/evolutiongaming/catshelper/CatsHelperSpec.scala
  • core/src/test/scala/com/evolutiongaming/catshelper/ClockHelperSpec.scala
  • core/src/test/scala/com/evolutiongaming/catshelper/DataHelperTest.scala
  • core/src/test/scala/com/evolutiongaming/catshelper/FeatureToggledSpec.scala
  • core/src/test/scala/com/evolutiongaming/catshelper/FromFutureSpec.scala
  • core/src/test/scala/com/evolutiongaming/catshelper/FromTrySpec.scala
  • core/src/test/scala/com/evolutiongaming/catshelper/GroupWithinSpec.scala
  • core/src/test/scala/com/evolutiongaming/catshelper/LazyValSpec.scala
  • core/src/test/scala/com/evolutiongaming/catshelper/LogSpec.scala
  • core/src/test/scala/com/evolutiongaming/catshelper/MeasureDurationSpec.scala
  • core/src/test/scala/com/evolutiongaming/catshelper/MemoizeTest.scala
  • core/src/test/scala/com/evolutiongaming/catshelper/ParallelHelperTest.scala
  • core/src/test/scala/com/evolutiongaming/catshelper/PartitionsTest.scala
  • core/src/test/scala/com/evolutiongaming/catshelper/ReadWriteRefSpec.scala
  • core/src/test/scala/com/evolutiongaming/catshelper/ResourceBreakFlatMapChainTest.scala
  • core/src/test/scala/com/evolutiongaming/catshelper/ResourceCounterSpec.scala
  • core/src/test/scala/com/evolutiongaming/catshelper/ResourceFencedTest.scala
  • core/src/test/scala/com/evolutiongaming/catshelper/RuntimeSpec.scala
  • core/src/test/scala/com/evolutiongaming/catshelper/SerParQueueTest.scala
  • core/src/test/scala/com/evolutiongaming/catshelper/SerialKeyTest.scala
  • core/src/test/scala/com/evolutiongaming/catshelper/SerialRefSpec.scala
  • core/src/test/scala/com/evolutiongaming/catshelper/SerialTest.scala
  • core/src/test/scala/com/evolutiongaming/catshelper/ThreadLocalRefSpec.scala
  • core/src/test/scala/com/evolutiongaming/catshelper/ToFutureSpec.scala
  • core/src/test/scala/com/evolutiongaming/catshelper/ToTrySpec.scala
  • logback/src/main/scala/com/evolutiongaming/catshelper/LogOfFromLogback.scala
  • project/build.properties
  • project/plugins.sbt
  • testkit/src/main/scala/com/evolutiongaming/catshelper/testkit/AbnormalTermination.scala
  • testkit/src/main/scala/com/evolutiongaming/catshelper/testkit/PureTest.scala
  • testkit/src/main/scala/com/evolutiongaming/catshelper/testkit/PureTestRunner.scala
  • testkit/src/main/scala/com/evolutiongaming/catshelper/testkit/TestFrameworkApi.scala
  • testkit/src/main/scala/com/evolutiongaming/catshelper/testkit/TestRuntime.scala
  • testkit/src/test/scala/com/evolutiongaming/catshelper/testkit/PureTestSpec.scala
💤 Files with no reviewable changes (3)
  • core/src/test/scala/com/evolutiongaming/catshelper/CatsHelperSpec.scala
  • .github/workflows/ci.yml
  • core/src/test/scala/com/evolutiongaming/catshelper/PartitionsTest.scala

Comment on lines +10 to 11
uses: evolution-gaming/scala-github-actions/.github/workflows/release.yml@v5
secrets: inherit

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -eu
printf '%s\n' '--- workflow files ---'
git ls-files '.github/workflows/*'
printf '%s\n' '--- release.yml ---'
cat -n .github/workflows/release.yml
printf '%s\n' '--- ci.yml references ---'
rg -n -C 3 'evolution-gaming/scala-github-actions|secrets:' .github/workflows/ci.yml .github/workflows
printf '%s\n' '--- repository and references ---'
rg -n -C 2 'secrets: inherit|evolution-gaming/scala-github-actions' .

Repository: evolution-gaming/cats-helper

Length of output: 1365


🏁 Script executed:

#!/bin/bash
set -eu
api='https://api.github.com/repos/evolution-gaming/scala-github-actions'
printf '%s\n' '--- v5 tag reference ---'
curl -fsSL "$api/git/refs/tags/v5" | jq '{ref, object}'
printf '%s\n' '--- v5 tag target ---'
tag_sha="$(curl -fsSL "$api/git/refs/tags/v5" | jq -r '.object.sha')"
tag_type="$(curl -fsSL "$api/git/refs/tags/v5" | jq -r '.object.type')"
if [ "$tag_type" = tag ]; then
  commit_sha="$(curl -fsSL "$api/git/tags/$tag_sha" | jq -r '.object.sha')"
else
  commit_sha="$tag_sha"
fi
printf 'resolved_commit=%s\n' "$commit_sha"
printf '%s\n' '--- commit existence ---'
curl -fsSL "$api/commits/$commit_sha" | jq -r '.sha'
printf '%s\n' '--- release workflow at v5 ---'
curl -fsSL "https://raw.githubusercontent.com/evolution-gaming/scala-github-actions/v5/.github/workflows/release.yml" | nl -ba

Repository: evolution-gaming/cats-helper

Length of output: 549


🏁 Script executed:

#!/bin/bash
set -eu
printf '%s\n' '--- v5 tag and peeled commit ---'
git ls-remote --tags https://github.com/evolution-gaming/scala-github-actions.git 'refs/tags/v5' 'refs/tags/v5^{}'
printf '%s\n' '--- release workflow at v5 ---'
curl -fsSL 'https://raw.githubusercontent.com/evolution-gaming/scala-github-actions/v5/.github/workflows/release.yml' | cat -n

Repository: evolution-gaming/cats-helper

Length of output: 2830


🌐 Web query:

"evolution-gaming/scala-github-actions" "v5" "b4557d9a82c03596dc2425e19b3cb9a6280a4739"

💡 Result:

The repository evolution-gaming/scala-github-actions is a collection of reusable GitHub Actions workflows designed to streamline the release process for Scala projects [1][2]. It allows developers to automate tasks such as publishing artifacts to repositories like Artifactory or JFrog, typically by leveraging sbt-dynver to derive version numbers from Git tags (e.g., vX.Y.Z) [2][3][4]. Regarding the specific reference v5 b4557d9a82c03596dc2425e19b3cb9a6280a4739: 1. Versioning: As of August 2026, the repository has multiple release versions (e.g., v1 through v4 are documented in use) [1][5]. If v5 has been tagged, it represents a newer iteration of the release workflows [1]. 2. Commit Hash: The string b4557d9a82c03596dc2425e19b3cb9a6280a4739 is a Git commit hash. In the context of GitHub Actions, referencing a workflow using a specific commit hash (e.g., uses: evolution-gaming/scala-github-actions/.github/workflows/release.yml@b4557d9...) is a common practice to pin a workflow to an exact state, ensuring build reproducibility and preventing unexpected behavior from upstream changes [1][3]. If you are seeing this reference in a project's .github/workflows/release.yml file, it indicates that the project is pinned to that specific version of the Evolution Gaming release automation logic [1][3].

Citations:


🌐 Web query:

GitHub Actions reusable workflow secrets inherit GITHUB_TOKEN explicitly named secrets called workflow

💡 Result:

In GitHub Actions, reusable workflows do not automatically inherit secrets from the calling workflow. To make secrets available to a reusable workflow, you must explicitly pass them [1][2]. There are two primary ways to pass secrets to a reusable workflow: 1. Explicit Mapping: You can explicitly pass named secrets using the secrets keyword in your workflow call [3][4]. The secret name in the caller must be mapped to the name expected by the reusable workflow [1]. jobs: call-workflow: uses: owner/repo/.github/workflows/reusable.yml@main secrets: MY_SECRET: ${{ secrets.MY_SECRET }} 2. Implicit Inheritance: You can use the secrets: inherit keyword to pass all secrets available to the calling workflow to the reusable workflow [5][6]. This is often used for simplicity but should be used with caution, as it grants the reusable workflow access to all secrets available in the caller [1]. jobs: call-workflow: uses: owner/repo/.github/workflows/reusable.yml@main secrets: inherit Regarding the GITHUB_TOKEN, it is automatically available to all workflows, including reusable workflows, through the github.token context [7]. It does not need to be passed explicitly as a secret [7]. Actions within the workflow can access it regardless of whether the workflow explicitly passes it, provided the appropriate permissions are configured via the permissions key [7]. Important considerations: - Secret pass-through is not recursive; in a chain of workflows (A calls B, B calls C), workflow C only receives secrets if they are explicitly passed from A to B, and then again from B to C [3][8]. - You cannot use the secrets context inside the with: block (used for passing inputs) because with: is evaluated on the caller side before the reusable workflow's context is fully active [9]. If a reusable workflow needs to use a secret value, pass the secret name as an input and resolve it dynamically within the reusable workflow using the syntax ${{ secrets[inputs.secret_name] }} [9].

Citations:


🏁 Script executed:

#!/bin/bash
set -eu
sha='b4557d9a82c03596dc2425e19b3cb9a6280a4739'
url="https://github.com/evolution-gaming/scala-github-actions/commit/$sha"
printf '%s\n' '--- commit page status and identity ---'
curl -fsSL -o /tmp/scala-actions-commit.html "$url"
printf 'http_body_bytes='
wc -c </tmp/scala-actions-commit.html
rg -o -m 3 "commit[^<]{0,120}|$sha" /tmp/scala-actions-commit.html || true
printf '%s\n' '--- v5 ref and SHA ref ---'
git ls-remote --tags https://github.com/evolution-gaming/scala-github-actions.git 'refs/tags/v5' "refs/tags/$sha"

Repository: evolution-gaming/cats-helper

Length of output: 438


Pin the release workflow and pass only the required secret.

Replace @v5 with the resolved 40-character commit SHA. Replace secrets: inherit with an explicit JFROG_ACCESS_TOKEN mapping. GITHUB_TOKEN is available automatically to the called workflow.

🧰 Tools
🪛 zizmor (1.29.0)

[warning] 10-10: secrets unconditionally inherited by called workflow (secrets-inherit): this reusable workflow

(secrets-inherit)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release.yml around lines 10 - 11, Update the release
workflow reference in the reusable workflow call to use its resolved
40-character commit SHA instead of `@v5`. Replace secrets: inherit with an
explicit JFROG_ACCESS_TOKEN mapping, relying on the automatically provided
GITHUB_TOKEN and passing no other secrets.

Source: Linters/SAST tools

Comment thread .scalafmt.conf
Comment on lines +8 to +11
runner.dialect = scala213source3

# only format files tracked by git
project.git = true

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Tracked SBT files:"
git ls-files '*.sbt'

echo "Scalafmt dialect configuration:"
rg -n -C 3 'project\.git|runner\.dialect|fileOverride' .scalafmt.conf

Repository: evolution-gaming/cats-helper

Length of output: 420


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Relevant repository files:"
git ls-files | rg '(^|/)(build\.sbt|plugins\.sbt|\.scalafmt\.conf|.*scalafmt.*|.*github.*|.*workflow.*)$' || true

echo "Formatting configuration and references:"
cat -n .scalafmt.conf
rg -n -C 3 'scalafmt|scalafmtCheck|scalafmtAll|project\.git|fileOverride|build\.sbt|plugins\.sbt' -g '!**/target/**' .

echo "SBT source samples:"
for f in build.sbt project/plugins.sbt; do
  if test -f "$f"; then
    echo "--- $f"
    cat -n "$f"
  fi
done

Repository: evolution-gaming/cats-helper

Length of output: 8488


🌐 Web query:

Scalafmt project.git default file extensions .sbt fileOverride runner.dialect sbt1 sbt-scalafmt scalafmtRepo

💡 Result:

In Scalafmt, configuration is managed via the.scalafmt.conf file [1][2]. Below is a synthesis of the specific configuration topics requested: Project Git Integration The project.git setting (e.g., project.git = true) instructs Scalafmt to automatically use git to identify the files that should be formatted, typically by excluding files that are not tracked or are ignored by git [3][4]. This is often preferred over manually managing excludeFilters for generated files [4]. File Overrides and Dialects The fileOverride setting allows you to apply specific configuration parameters, such as changing the runner.dialect, to files that match a particular pattern [2]. Since Scalafmt v3.2.0, you can use shortcuts for file extensions or glob patterns [5]. Example of using fileOverride for.sbt files with the sbt1 dialect: fileOverride { "glob:/*.sbt" { runner.dialect = sbt1 } } Alternatively, you can use the extension shortcut syntax: fileOverride { ".sbt" { runner.dialect = sbt1 } } Runner Dialect The runner.dialect setting is mandatory in modern Scalafmt configurations [1]. It specifies the dialect used by the parser. For.sbt files, sbt1 is the standard dialect [5][6][7]. Scalafmt Repository Scalafmt does not have a single "scalafmtRepo" configuration key for standard usage. If you are referring to integration within an sbt project, the sbt-scalafmt plugin handles the connection to the formatter, and configuration is typically localized to the.scalafmt.conf file in your project root [1][8]. If you are working on a custom build or plugin integration that requires specifying a repository for a custom version of Scalafmt, you would generally handle that via build tool dependencies (e.g., in build.sbt) rather than inside.scalafmt.conf [8].

Citations:


🌐 Web query:

sbt-scalafmt 2.6.2 scalafmtRepo scalafmtCheckRepo format .sbt files

💡 Result:

In sbt-scalafmt version 2.6.2, the newly introduced scalafmtRepo and scalafmtCheckRepo are build-root tasks designed to operate across the entire repository [1][2][3]. Formatting.sbt files in sbt-scalafmt is primarily handled through the scalafmtSbt and scalafmtSbtCheck tasks [4][5]. Key details regarding your query: 1. scalafmtRepo / scalafmtCheckRepo: These tasks were added in v2.6.2 to facilitate repository-wide formatting and checking [1][3]. The scalafmtRepo task formats files across the build root, while scalafmtCheckRepo validates that these files are correctly formatted, failing if they are not (typically used for CI) [1][2][3]. They utilize ScalafmtSession.listFiles for file discovery [1][2]. 2. Formatting.sbt files: - To format .sbt and project/.scala files, use the scalafmtSbt task [4][5]. - To check that these files are properly formatted, use the scalafmtSbtCheck task [4][5]. - These tasks are distinct from the standard scalafmt / scalafmtCheck tasks, which target compile and test source files [4][5]. The official documentation for sbt-scalafmt can be found via the scalameta/sbt-scalafmt repository [6][5][7], which provides guidance on usage and configuration [5].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

base='https://raw.githubusercontent.com/scalameta/sbt-scalafmt/v2.6.2'
for path in plugin/src/main/scala/org/scalafmt/sbt/ScalafmtPlugin.scala plugin/src/main/scala/org/scalafmt/sbt/ScalafmtCorePlugin.scala; do
  echo "--- $path"
  curl -fsSL "$base/$path" | rg -n -C 5 'scalafmtRepo|scalafmtCheckRepo|scalafmtSbt|scalafmtSbtCheck|listFiles|FileExtension|\.sbt'
done

Repository: evolution-gaming/cats-helper

Length of output: 7795


🏁 Script executed:

#!/bin/bash
set -euo pipefail

for url in \
  'https://raw.githubusercontent.com/scalameta/sbt-scalafmt/v2.6.2/plugin/src/main/scala/org/scalafmt/sbt/ScalafmtPlugin.scala' \
  'https://raw.githubusercontent.com/scalameta/scalafmt/v3.11.5/scalafmt-core/src/main/scala/org/scalafmt/ScalafmtSession.scala' \
  'https://raw.githubusercontent.com/scalameta/scalafmt/v3.11.5/scalafmt-core/src/main/scala/org/scalafmt/config/ScalafmtConfig.scala'; do
  echo "--- $url"
  curl -fsSL "$url" | rg -n -C 12 'getScalafmtRepoTask|repoSources|listFiles|project\.git|extensions|sbt|fileOverride' || true
done

Repository: evolution-gaming/cats-helper

Length of output: 19108


🏁 Script executed:

#!/bin/bash
set -euo pipefail

tree=$(curl -fsSL 'https://api.github.com/repos/scalameta/scalafmt/git/trees/v3.11.5?recursive=1')
printf '%s' "$tree" |
  jq -r '.tree[].path' |
  rg '(^|/)(ScalafmtSession|.*Session.*|.*File.*|.*Config.*)\.scala$|project.*\.scala$' |
  head -80

echo "Potential source references:"
printf '%s' "$tree" |
  jq -r '.tree[].path' |
  rg 'scalafmt.*(core|cli)|src/main/scala' |
  head -120

Repository: evolution-gaming/cats-helper

Length of output: 8563


🏁 Script executed:

#!/bin/bash
set -euo pipefail

base='https://raw.githubusercontent.com/scalameta/scalafmt/v3.11.5'
for path in \
  scalafmt-core/shared/src/main/scala/org/scalafmt/config/ProjectFiles.scala \
  scalafmt-core/shared/src/main/scala/org/scalafmt/config/ScalafmtConfig.scala \
  scalafmt-interfaces/jvm/src/main/java/org/scalafmt/interfaces/ScalafmtSession.scala \
  scalafmt-interfaces/shared/src/main/scala/org/scalafmt/interfaces/ScalafmtSession.scala; do
  echo "--- $path"
  curl -fsSL "$base/$path" | rg -n -C 15 'listFiles|\.sbt|extension|project\.git|fileOverride|dialect' || true
done

Repository: evolution-gaming/cats-helper

Length of output: 18251


Configure the SBT dialect for tracked .sbt files.

scalafmtRepo and scalafmtCheckRepo include tracked .sbt files. Add an .sbt override with runner.dialect = sbt1 to prevent parsing errors in build.sbt and project/plugins.sbt.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.scalafmt.conf around lines 8 - 11, Update the Scalafmt configuration by
adding an .sbt-specific override with runner.dialect set to sbt1, while
retaining scala213source3 as the default dialect and project.git tracking
behavior.

Source: MCP tools

Comment on lines +97 to +106
override def release(n: Int): F[Unit] =
state
.modify {
case Done => Done -> F.unit
case Awaiting(l, await) =>
if (l > n) Awaiting(l - n, await) -> F.unit
else Done -> await.complete(()).void
}
}
.flatten
.uncancelable

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Prevent negative releases from increasing the latch count.

When latches = 1, release(-1) takes the l > n branch and stores Awaiting(2, await). A caller can therefore increase the latch through release, which can keep await() blocked. Match acquire by returning F.unit for n < 1, or reject invalid values.

Proposed fix
 override def release(n: Int): F[Unit] =
-  state
+  if (n < 1) F.unit
+  else
+    state
       .modify {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
override def release(n: Int): F[Unit] =
state
.modify {
case Done => Done -> F.unit
case Awaiting(l, await) =>
if (l > n) Awaiting(l - n, await) -> F.unit
else Done -> await.complete(()).void
}
}
.flatten
.uncancelable
override def release(n: Int): F[Unit] =
if (n < 1) F.unit
else
state
.modify {
case Done => Done -> F.unit
case Awaiting(l, await) =>
if (l > n) Awaiting(l - n, await) -> F.unit
else Done -> await.complete(()).void
}
.flatten
.uncancelable
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/src/main/scala/com/evolutiongaming/catshelper/CountLatch.scala` around
lines 97 - 106, Update the release method so values of n less than 1 return
F.unit without modifying state, matching acquire’s validation behavior. Preserve
the existing Awaiting and Done handling for valid releases.

Comment on lines 10 to 24
/**
* Given a `Resource[F, A]` produces `Resource[F, Resource[F, Option[A]]]` which,
* while being in `use`, manages lifecycle of `A` according the state of a boolean
* toggle, providing access to `A` only when the toggle is `true`.
* Given a `Resource[F, A]` produces `Resource[F, Resource[F, Option[A]]]` which, while being in
* `use`, manages lifecycle of `A` according the state of a boolean toggle, providing access to `A`
* only when the toggle is `true`.
*
* @define ra the base resource.
* @define ra
* the base resource.
*
* @define gracePeriod defines an interval which is counted from the moment the toggle
* goes off. During this interval the managed resource `A` is kept alive while
* there is at least one "user" active. After `gracePeriod` expires the resource
* will be released unconditionally. It is ''up to the client'' to resolve any
* errors that may come from a forceful termination of a resource that is still
* in use.
* @define gracePeriod
* defines an interval which is counted from the moment the toggle goes off. During this interval
* the managed resource `A` is kept alive while there is at least one "user" active. After
* `gracePeriod` expires the resource will be released unconditionally. It is ''up to the client''
* to resolve any errors that may come from a forceful termination of a resource that is still in
* use.
*/

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Correct the public Scaladoc sentence.

The sentence is missing it after Resource[F, A]. according the state must be according to the state.

Proposed documentation fix
- * Given a `Resource[F, A]` produces `Resource[F, Resource[F, Option[A]]]` which, while being in
- * `use`, manages lifecycle of `A` according the state of a boolean toggle, providing access to `A`
+ * Given a `Resource[F, A]`, this object produces `Resource[F, Resource[F, Option[A]]]` which, while
+ * being in `use`, manages the lifecycle of `A` according to the state of a boolean toggle,
+ * providing access to `A`
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/**
* Given a `Resource[F, A]` produces `Resource[F, Resource[F, Option[A]]]` which,
* while being in `use`, manages lifecycle of `A` according the state of a boolean
* toggle, providing access to `A` only when the toggle is `true`.
* Given a `Resource[F, A]` produces `Resource[F, Resource[F, Option[A]]]` which, while being in
* `use`, manages lifecycle of `A` according the state of a boolean toggle, providing access to `A`
* only when the toggle is `true`.
*
* @define ra the base resource.
* @define ra
* the base resource.
*
* @define gracePeriod defines an interval which is counted from the moment the toggle
* goes off. During this interval the managed resource `A` is kept alive while
* there is at least one "user" active. After `gracePeriod` expires the resource
* will be released unconditionally. It is ''up to the client'' to resolve any
* errors that may come from a forceful termination of a resource that is still
* in use.
* @define gracePeriod
* defines an interval which is counted from the moment the toggle goes off. During this interval
* the managed resource `A` is kept alive while there is at least one "user" active. After
* `gracePeriod` expires the resource will be released unconditionally. It is ''up to the client''
* to resolve any errors that may come from a forceful termination of a resource that is still in
* use.
*/
/**
* Given a `Resource[F, A]`, this object produces `Resource[F, Resource[F, Option[A]]]` which, while
* being in `use`, manages the lifecycle of `A` according to the state of a boolean toggle,
* providing access to `A` only when the toggle is `true`.
*
* `@define` ra
* the base resource.
*
* `@define` gracePeriod
* defines an interval which is counted from the moment the toggle goes off. During this interval
* the managed resource `A` is kept alive while there is at least one "user" active. After
* `gracePeriod` expires the resource will be released unconditionally. It is ''up to the client''
* to resolve any errors that may come from a forceful termination of a resource that is still in
* use.
*/
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/src/main/scala/com/evolutiongaming/catshelper/FeatureToggled.scala`
around lines 10 - 24, Update the public Scaladoc description above the affected
API: state that a Resource[F, A] produces the nested resource and manages A’s
lifecycle “according to the state of a boolean toggle,” adding the missing “it”
after Resource[F, A] while preserving the rest of the documentation.

override def warn(msg: => String, cause: Throwable, mdc: Mdc): F[Unit] = C.println(log("WARN", msg, mdc)) >>
C.printStackTrace(cause)

override def error(msg: => String, mdc: Mdc): F[Unit] = C.errorln(log("ERRROR", msg, mdc))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Correct the error log label.

Line 326 emits "ERRROR" while the throwable overload emits "ERROR" on Line 328. Change the label to "ERROR" so both error methods produce consistent output.

Proposed fix
-    override def error(msg: => String, mdc: Mdc): F[Unit] = C.errorln(log("ERRROR", msg, mdc))
+    override def error(msg: => String, mdc: Mdc): F[Unit] = C.errorln(log("ERROR", msg, mdc))
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
override def error(msg: => String, mdc: Mdc): F[Unit] = C.errorln(log("ERRROR", msg, mdc))
override def error(msg: => String, mdc: Mdc): F[Unit] = C.errorln(log("ERROR", msg, mdc))
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/src/main/scala/com/evolutiongaming/catshelper/Log.scala` at line 326,
Update the error method’s log label in the override of error(msg: => String,
mdc: Mdc) from the misspelled value to "ERROR", matching the throwable overload
and preserving consistent error output.

Comment on lines 36 to 39
/**
* "Read" operation. Multiple reads may be in use simultaneously.
* `reads.use(…)` blocks semantically while [[write]] in in use.
* "Read" operation. Multiple reads may be in use simultaneously. `reads.use(…)` blocks
* semantically while [[write]] in in use.
*/

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Fix the read Scaladoc identifiers.

The public member is read, not reads. The sentence also contains duplicated wording: in in use. Use read.use(...) and state that write is in use.

Proposed fix
- *   - "Read" operation. Multiple reads may be in use simultaneously. `reads.use(…)` blocks
- *     semantically while [[write]] in in use.
+ *   - "Read" operation. Multiple reads may be in use simultaneously. `read.use(…)` blocks
+ *     semantically while [[write]] is in use.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/**
* "Read" operation. Multiple reads may be in use simultaneously.
* `reads.use(…)` blocks semantically while [[write]] in in use.
* "Read" operation. Multiple reads may be in use simultaneously. `reads.use(…)` blocks
* semantically while [[write]] in in use.
*/
/**
* "Read" operation. Multiple reads may be in use simultaneously. `read.use(…)` blocks
* semantically while [[write]] is in use.
*/
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/src/main/scala/com/evolutiongaming/catshelper/ReadWriteRef.scala` around
lines 36 - 39, Update the Scaladoc for the public read member near ReadWriteRef
to reference read.use(...) instead of reads.use(...), and correct the duplicated
“in in use” wording to state that write is in use.

Comment on lines +25 to +27
* @example
* {{{ "what time is it now?" in PureTest[IO].of { env => import env._ for { _ <- IO.sleep(1.hour)
* _ <- testRuntime.getTimeSinceStart.map(_ shouldBe 1.hour) } yield () } }}}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Keep the Scaladoc example valid.

The reflow removed the separator between import env._ and for, so the example now contains import env._ for {, which is not valid Scala. The supplied PureTest API exposes ioTest; it does not define PureTest[IO].of. Restore a multiline example that uses the actual entry point.

Proposed fix
- *   {{{ "what time is it now?" in PureTest[IO].of { env => import env._ for { _ <- IO.sleep(1.hour)
- *   _ <- testRuntime.getTimeSinceStart.map(_ shouldBe 1.hour) } yield () } }}}}
+ *   {{{
+ *   PureTest.ioTest { env =>
+ *     import env._
+ *     for {
+ *       _ <- IO.sleep(1.hour)
+ *       _ <- testRuntime.getTimeSinceStart.map(_ shouldBe 1.hour)
+ *     } yield ()
+ *   }
+ *   }}}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
* @example
* {{{ "what time is it now?" in PureTest[IO].of { env => import env._ for { _ <- IO.sleep(1.hour)
* _ <- testRuntime.getTimeSinceStart.map(_ shouldBe 1.hour) } yield () } }}}
* {{{
* PureTest.ioTest { env =>
* import env._
* for {
* _ <- IO.sleep(1.hour)
* _ <- testRuntime.getTimeSinceStart.map(_ shouldBe 1.hour)
* } yield ()
* }
* }}}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@testkit/src/main/scala/com/evolutiongaming/catshelper/testkit/PureTest.scala`
around lines 25 - 27, Update the Scaladoc example in PureTest to use the actual
ioTest entry point instead of PureTest[IO].of, and restore a valid multiline
Scala layout with a separator between import env._ and the for-comprehension.
Preserve the example’s existing sleep and elapsed-time assertion behavior.

Comment on lines +86 to +87
* Sets hot-loop detection timeout. Use it CPU-bound part of your SUT or test requires longer
* time.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Correct the hotLoopTimeout Scaladoc sentence.

The text “Use it CPU-bound part of your SUT or test requires longer time” is incomplete. Use: “Use it when a CPU-bound part of your SUT or test requires more time.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@testkit/src/main/scala/com/evolutiongaming/catshelper/testkit/PureTest.scala`
around lines 86 - 87, Correct the Scaladoc sentence for hotLoopTimeout to read:
“Use it when a CPU-bound part of your SUT or test requires more time.”

Comment on lines 91 to +93
/**
* Sets an `ExecutionContext` used for background tasks, such as hot loop detection.
* Defaults to `ExecutionContext.global`.
* Sets an `ExecutionContext` used for background tasks, such as hot loop detection. Defaults to
* `ExecutionContext.global`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n -C 4 '\bbackgroundEc\b' testkit/src/main/scala/com/evolutiongaming/catshelper/testkit

Repository: evolution-gaming/cats-helper

Length of output: 2235


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- PureTestRunner.scala ---'
cat -n testkit/src/main/scala/com/evolutiongaming/catshelper/testkit/PureTestRunner.scala

printf '%s\n' '--- PureTest.scala relevant sections ---'
sed -n '1,125p' testkit/src/main/scala/com/evolutiongaming/catshelper/testkit/PureTest.scala

printf '%s\n' '--- testkit Scala files ---'
git ls-files 'testkit/src/test' 'testkit/src/main' | sed -n '1,160p'

printf '%s\n' '--- runner/config references ---'
rg -n -C 3 'PureTestRunner|Config\[|hotLoopTimeout|mainRuntime|backgroundEc' testkit/src/main testkit/src/test

Repository: evolution-gaming/cats-helper

Length of output: 18412


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- all backgroundEc references ---'
rg -n -C 2 '\bbackgroundEc\b' .

printf '%s\n' '--- PureTestSpec.scala ---'
cat -n testkit/src/test/scala/com/evolutiongaming/catshelper/testkit/PureTestSpec.scala

printf '%s\n' '--- runtime construction and cancellation APIs ---'
rg -n -C 4 'materializeRuntime|unsafeRunCancelable|IORuntime\(' testkit/src/main testkit/src/test

printf '%s\n' '--- read-only invariant check ---'
python3 - <<'PY'
from pathlib import Path

runner = Path("testkit/src/main/scala/com/evolutiongaming/catshelper/testkit/PureTestRunner.scala").read_text()
pure_test = Path("testkit/src/main/scala/com/evolutiongaming/catshelper/testkit/PureTest.scala").read_text()

print("runner_reads_config_backgroundEc =", "config.backgroundEc" in runner)
print("runner_mentions_backgroundEc =", "backgroundEc" in runner)
print("config_declares_backgroundEc =", "backgroundEc:" in pure_test)
print("public_setter_copies_backgroundEc =", "copy(backgroundEc = v)" in pure_test)
print("runner_starts_timeout_with_mainRuntime =", "stopHotLoop.unsafeRunCancelable()(mainRuntime)" in runner)
PY

Repository: evolution-gaming/cats-helper

Length of output: 6605


Honor the documented backgroundEc setting.

PureTestRunner never reads config.backgroundEc; hot-loop cancellation always runs on mainRuntime. Use config.backgroundEc for this task and add a regression test, or remove the setting and its documentation.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@testkit/src/main/scala/com/evolutiongaming/catshelper/testkit/PureTest.scala`
around lines 91 - 93, Update PureTestRunner’s hot-loop cancellation task to use
the configured config.backgroundEc instead of mainRuntime, preserving the
documented background execution behavior. Add a regression test that verifies
the configured ExecutionContext is used; alternatively, remove the backgroundEc
setting and its documentation if it is not intended to be supported.

Comment on lines +18 to 20
* It's roughly equivalent to `getTimeSinceStart.flatMap(t => timer.sleep(dt - t))` but does not
* require a `timer: Timer[F]` argument.
*/

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

Does Cats Effect 3 expose Timer[F], or should this Scaladoc use Temporal[F].sleep?

💡 Result:

In Cats Effect 3, the Timer typeclass has been removed and replaced by the Temporal typeclass [1][2][3]. Therefore, Cats Effect 3 does not expose Timer[F] [1][2]. Yes, Scaladoc or any documentation referencing time-based operations like sleeping should use Temporal[F].sleep [2][3]. The Temporal typeclass is a lawful typeclass that extends Concurrent[F] and Clock[F], providing the ability to suspend fibers for a given duration [4][2][5]. The migration from CE2 to CE3 specifically identifies Temporal[F].sleep as the correct replacement for the former Timer[F].sleep [2][3].

Citations:


🏁 Script executed:

#!/bin/sh
set -eu
printf '%s\n' '--- candidate file ---'
cat -n testkit/src/main/scala/com/evolutiongaming/catshelper/testkit/TestRuntime.scala | sed -n '1,80p'
printf '%s\n' '--- Cats Effect API references in the repository ---'
rg -n --glob '*.scala' '(^|[^A-Za-z])(Timer|Temporal)\[|Temporal\.sleep|Timer\.sleep' .

Repository: evolution-gaming/cats-helper

Length of output: 2408


🏁 Script executed:

#!/bin/sh
set -eu
printf '%s\n' '--- Cats Effect dependency declarations ---'
rg -n --glob 'build.sbt' --glob '*.sbt' --glob '*.scala' 'cats-effect|cats\.effect' .
printf '%s\n' '--- timer-related declarations and usages ---'
rg -n --glob '*.scala' 'trait Timer|class Timer|object Timer|Timer\[|Temporal\[|TimerHelper' .

Repository: evolution-gaming/cats-helper

Length of output: 19118


Use Temporal[F].sleep in the Scaladoc.

Cats Effect 3 uses Temporal[F].sleep, and the repository uses this API. Update the example and argument text.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@testkit/src/main/scala/com/evolutiongaming/catshelper/testkit/TestRuntime.scala`
around lines 18 - 20, Update the Scaladoc for the relevant method in TestRuntime
to replace the Cats Effect 2 timer.sleep example and timer argument wording with
the Cats Effect 3 Temporal[F].sleep API and corresponding argument text.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant