From b98c443b5c3a1d5a1b5521b253358805f69b4d9d Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Sat, 25 Jul 2026 19:37:29 -0400 Subject: [PATCH] Add remote-cache test --- .github/workflows/server-test.yml | 70 ++++++++++++++++--- build.sbt | 1 + .../sbt-test/remote-cache/basic/Hello.scala | 2 + .../src/sbt-test/remote-cache/basic/build.sbt | 23 ++++++ .../remote-cache/basic/project/plugins.sbt | 1 + sbt-app/src/sbt-test/remote-cache/basic/test | 5 ++ .../sbt/internal/util/CacheEventLog.scala | 10 ++- .../scala/sbt/util/CacheEventLogTest.scala | 5 +- 8 files changed, 102 insertions(+), 15 deletions(-) create mode 100644 sbt-app/src/sbt-test/remote-cache/basic/Hello.scala create mode 100644 sbt-app/src/sbt-test/remote-cache/basic/build.sbt create mode 100644 sbt-app/src/sbt-test/remote-cache/basic/project/plugins.sbt create mode 100644 sbt-app/src/sbt-test/remote-cache/basic/test diff --git a/.github/workflows/server-test.yml b/.github/workflows/server-test.yml index 720e0a00d..786034b87 100644 --- a/.github/workflows/server-test.yml +++ b/.github/workflows/server-test.yml @@ -14,14 +14,62 @@ jobs: JVM_OPTS: -Xms800M -Xmx2G -Xss6M -XX:ReservedCodeCacheSize=128M -server -Dsbt.io.virtual=false -Dfile.encoding=UTF-8 SBT_ETC_FILE: $HOME/etc/sbt/sbtopts steps: - - uses: actions/checkout@v7 - - name: Setup JDK - uses: actions/setup-java@v5 - with: - distribution: "zulu" - java-version: "17" - cache: sbt - - uses: sbt/setup-sbt@v1 - - name: Server test - shell: bash - run: sbt -v --client "serverTestProj/test" + - uses: actions/checkout@v7 + - name: Setup JDK + uses: actions/setup-java@v5 + with: + distribution: "zulu" + java-version: "17" + cache: sbt + - uses: sbt/setup-sbt@v1 + with: + disk-cache: false + - name: Set bazel-remote version + id: bazel-remote-version + run: echo "version=2.6.2" >> "$GITHUB_OUTPUT" + - name: Cache bazel-remote + id: cache-bazel-remote + uses: actions/cache@v4 + with: + path: $RUNNER_TOOL_CACHE/local/bazel-remote + key: bazel-remote-v${{ steps.bazel-remote-version.outputs.version }}-${{ runner.os }}-${{ runner.arch }} + - name: Download bazel-remote + if: steps.cache-bazel-remote.outputs.cache-hit != 'true' + shell: bash + env: + BAZEL_REMOTE_VERSION: ${{ steps.bazel-remote-version.outputs.version }} + run: | + mkdir -p "$RUNNER_TOOL_CACHE/local" + curl -sL -o "$RUNNER_TOOL_CACHE/local/bazel-remote" "https://github.com/buchgr/bazel-remote/releases/download/v${BAZEL_REMOTE_VERSION}/bazel-remote-${BAZEL_REMOTE_VERSION}-linux-amd64" + chmod +x "$RUNNER_TOOL_CACHE/local/bazel-remote" + - name: Add bazel-remote to PATH + run: echo "$RUNNER_TOOL_CACHE/local" >> "$GITHUB_PATH" + - name: Start bazel-remote + shell: bash + run: | + mkdir -p "$HOME/bazel-remote/temp" + nohup "$RUNNER_TOOL_CACHE/local/bazel-remote" --max_size 5 --dir "$HOME/bazel-remote/temp" \ + --http_address localhost:8000 --grpc_address localhost:2024 \ + > /tmp/bazel-remote.log 2>&1 & + echo $! > /tmp/bazel-remote.pid + for i in $(seq 1 30); do + curl -sf http://localhost:8000/status > /dev/null && exit 0 + sleep 1 + done + echo "bazel-remote did not start in time" + cat /tmp/bazel-remote.log + exit 1 + - name: Remote cache scripted test + shell: bash + run: | + sbt -v --client "doc; publishLocal" + sbt -v --client "scripted remote-cache/*" + - name: Server test + shell: bash + run: sbt -v --client "serverTestProj/test" + - name: Stop bazel-remote + if: always() + run: | + if [ -f /tmp/bazel-remote.pid ]; then + kill "$(cat /tmp/bazel-remote.pid)" || true + fi diff --git a/build.sbt b/build.sbt index fc666c5f9..27736ccd0 100644 --- a/build.sbt +++ b/build.sbt @@ -391,6 +391,7 @@ lazy val utilCache = project contrabandSettings, mimaSettings, mimaBinaryIssueFilters ++= Seq( + exclude[DirectMissingMethodProblem]("sbt.internal.util.CacheEventSummary#Data.*"), ), Test / fork := true, ) diff --git a/sbt-app/src/sbt-test/remote-cache/basic/Hello.scala b/sbt-app/src/sbt-test/remote-cache/basic/Hello.scala new file mode 100644 index 000000000..8e9836d74 --- /dev/null +++ b/sbt-app/src/sbt-test/remote-cache/basic/Hello.scala @@ -0,0 +1,2 @@ +object Hello: + def main(args: Array[String]): Unit = println("Hello, world!") diff --git a/sbt-app/src/sbt-test/remote-cache/basic/build.sbt b/sbt-app/src/sbt-test/remote-cache/basic/build.sbt new file mode 100644 index 000000000..310376625 --- /dev/null +++ b/sbt-app/src/sbt-test/remote-cache/basic/build.sbt @@ -0,0 +1,23 @@ +import sbt.internal.util.CacheEventSummary + +scalaVersion := "3.8.4" + +Global / remoteCache := Some(new java.net.URI("grpc://127.0.0.1:2024")) +Global / localCacheDirectory := baseDirectory.value / "diskcache" + +val checkHit = taskKey[Unit]("asserts the previous compile was served from the remote cache") + +checkHit := Def.uncached { + val config = Def.cacheConfiguration.value + val prev = config.cacheEventLog.previous match + case data: CacheEventSummary.Data => data + case _ => sys.error("empty event log") + streams.value.log.info( + s"prev hitCount=${prev.hitCount} missCount=${prev.missCount} remoteHitCount=${prev.remoteHitCount}" + ) + assert(prev.missCount == 0, s"expected 100% hit rate but missCount=${prev.missCount}") + assert( + prev.remoteHitCount == prev.hitCount, + s"expected 100% remote hit rate but remoteHitCount=${prev.remoteHitCount} hitCount=${prev.hitCount}" + ) +} diff --git a/sbt-app/src/sbt-test/remote-cache/basic/project/plugins.sbt b/sbt-app/src/sbt-test/remote-cache/basic/project/plugins.sbt new file mode 100644 index 000000000..a41304ee3 --- /dev/null +++ b/sbt-app/src/sbt-test/remote-cache/basic/project/plugins.sbt @@ -0,0 +1 @@ +addRemoteCachePlugin diff --git a/sbt-app/src/sbt-test/remote-cache/basic/test b/sbt-app/src/sbt-test/remote-cache/basic/test new file mode 100644 index 000000000..29e096be4 --- /dev/null +++ b/sbt-app/src/sbt-test/remote-cache/basic/test @@ -0,0 +1,5 @@ +> compile +$ delete diskcache +> clean +> compile +> checkHit diff --git a/util-cache/src/main/scala/sbt/internal/util/CacheEventLog.scala b/util-cache/src/main/scala/sbt/internal/util/CacheEventLog.scala index 16c88b39f..6e026eca3 100644 --- a/util-cache/src/main/scala/sbt/internal/util/CacheEventLog.scala +++ b/util-cache/src/main/scala/sbt/internal/util/CacheEventLog.scala @@ -18,7 +18,8 @@ enum CacheEventSummary: missCount: Long, hitRate: Double, onsiteCount: Option[Long], - errorCount: Option[Long] + errorCount: Option[Long], + remoteHitCount: Long ) override def toString(): String = this match case Empty => "" @@ -28,7 +29,8 @@ enum CacheEventSummary: missCount, hitRate, onsiteCount, - errorCount + errorCount, + remoteHitCount ) => val hitDescs = hits.map { case (id, 1) => s"1 $id cache hit" @@ -74,12 +76,14 @@ class CacheEventLog: val hitRate = if total > 0 then (hitCount.toDouble / total.toDouble) else 0.0 val onsiteCount = events.get(ActionCacheEvent.OnsiteTask) val errorCount = events.get(ActionCacheEvent.Error) + val remoteHitCount = hits.view.collect { case (id, v) if id.startsWith("remote") => v }.sum CacheEventSummary.Data( hits.toSeq, hitCount, missCount, hitRate, onsiteCount, - errorCount + errorCount, + remoteHitCount ) end CacheEventLog diff --git a/util-cache/src/test/scala/sbt/util/CacheEventLogTest.scala b/util-cache/src/test/scala/sbt/util/CacheEventLogTest.scala index ffd7310fc..2b3e89515 100644 --- a/util-cache/src/test/scala/sbt/util/CacheEventLogTest.scala +++ b/util-cache/src/test/scala/sbt/util/CacheEventLogTest.scala @@ -1,6 +1,6 @@ package sbt.util -import sbt.internal.util.{ ActionCacheEvent, CacheEventLog } +import sbt.internal.util.{ ActionCacheEvent, CacheEventLog, CacheEventSummary } import verify.BasicTestSuite object CacheEventLogTest extends BasicTestSuite: @@ -59,6 +59,9 @@ object CacheEventLogTest extends BasicTestSuite: logger.append(ActionCacheEvent.OnsiteTask) val expectedSummary = "cache 75%, 1 disk cache hit, 2 remote cache hits, 1 onsite task" assertEquals(logger.summary.toString(), expectedSummary) + logger.summary match + case data: CacheEventSummary.Data => assert(data.remoteHitCount == 2L) + case _ => sys.error("expected CacheEventSummary.Data") } test("summary of 1 disk event after clear") {