[2.x] fix: handle NoSuchFileException during cache storage (#8699)

This commit is contained in:
calm 2026-02-06 05:36:07 -06:00 committed by GitHub
parent 52bc35e3a9
commit c4a88328da
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 36 additions and 30 deletions

View File

@ -10,7 +10,7 @@ package sbt.util
import java.io.File
import java.nio.charset.StandardCharsets
import java.nio.file.{ Files, Path, Paths, StandardCopyOption }
import java.nio.file.{ Files, NoSuchFileException, Path, Paths, StandardCopyOption }
import sbt.internal.util.{ ActionCacheEvent, CacheEventLog, StringVirtualFile1 }
import sbt.io.syntax.*
import sbt.io.IO
@ -81,34 +81,40 @@ object ActionCache:
case e: Exception =>
cacheEventLog.append(ActionCacheEvent.Error)
throw e
val json = Converter.toJsonUnsafe(result)
val normalizedOutputDir = outputDirectory.toAbsolutePath.normalize()
val uncacheableOutputs =
outputs.filter(f =>
f match
case vf if vf.id.endsWith(ActionCache.dirZipExt) =>
false
case _ =>
val outputPath = fileConverter.toPath(f).toAbsolutePath.normalize()
!outputPath.startsWith(normalizedOutputDir)
)
if uncacheableOutputs.nonEmpty then
cacheEventLog.append(ActionCacheEvent.Error)
logger.error(
s"Cannot cache task because its output files are outside the output directory: \n" +
uncacheableOutputs.mkString(" - ", "\n - ", "")
)
result
else
cacheEventLog.append(ActionCacheEvent.OnsiteTask)
val (input, valuePath) = mkInput(key, codeContentHash, extraHash)
val valueFile = StringVirtualFile1(valuePath, CompactPrinter(json))
val newOutputs = Vector(valueFile) ++ outputs.toVector
store.put(UpdateActionResultRequest(input, newOutputs, exitCode = 0)) match
case Right(cachedResult) =>
store.syncBlobs(cachedResult.outputFiles, outputDirectory)
result
case Left(e) => throw e
try
val json = Converter.toJsonUnsafe(result)
val normalizedOutputDir = outputDirectory.toAbsolutePath.normalize()
val uncacheableOutputs =
outputs.filter(f =>
f match
case vf if vf.id.endsWith(ActionCache.dirZipExt) =>
false
case _ =>
val outputPath = fileConverter.toPath(f).toAbsolutePath.normalize()
!outputPath.startsWith(normalizedOutputDir)
)
if uncacheableOutputs.nonEmpty then
cacheEventLog.append(ActionCacheEvent.Error)
logger.error(
s"Cannot cache task because its output files are outside the output directory: \n" +
uncacheableOutputs.mkString(" - ", "\n - ", "")
)
result
else
cacheEventLog.append(ActionCacheEvent.OnsiteTask)
val (input, valuePath) = mkInput(key, codeContentHash, extraHash)
val valueFile = StringVirtualFile1(valuePath, CompactPrinter(json))
val newOutputs = Vector(valueFile) ++ outputs.toVector
store.put(UpdateActionResultRequest(input, newOutputs, exitCode = 0)) match
case Right(cachedResult) =>
store.syncBlobs(cachedResult.outputFiles, outputDirectory)
result
case Left(e) => throw e
catch
case e: NoSuchFileException =>
logger.debug(s"Skipping cache storage due to missing file: ${e.getMessage}")
cacheEventLog.append(ActionCacheEvent.Error)
result
// Single cache lookup - use exitCode to distinguish success from failure
getWithFailure(key, codeContentHash, extraHash, tags, config) match

View File

@ -74,6 +74,6 @@ trait CacheImplicits extends BasicCacheImplicits with BasicJsonProtocol:
val lastModified = attrs.lastModifiedTime().toMillis()
val sizeBytes = attrs.size()
getOrElseUpdate(ref, lastModified, sizeBytes)(fallback)
catch case _: NoSuchFileException => fallback
catch case e: NoSuchFileException => throw e
case _ => fallback
end CacheImplicits