hercules-ci-agent-0.8.2: hercules-ci-agent-worker/Hercules/Agent/Worker/Build.hs
{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Hercules.Agent.Worker.Build where
import Conduit
import Data.Conduit.Katip.Orphans ()
import Hercules.Agent.Worker.Build.Prefetched (buildDerivation)
import qualified Hercules.Agent.Worker.Build.Prefetched as Build
import qualified Hercules.Agent.WorkerProtocol.Command.Build as Command.Build
import Hercules.Agent.WorkerProtocol.Event (Event)
import qualified Hercules.Agent.WorkerProtocol.Event as Event
import qualified Hercules.Agent.WorkerProtocol.Event.BuildResult as Event.BuildResult
import Hercules.CNix
( DerivationOutput (derivationOutputName, derivationOutputPath),
getDerivationOutputs,
)
import qualified Hercules.CNix as CNix
import Hercules.CNix.Store (Store, queryPathInfo, validPathInfoNarHash32, validPathInfoNarSize)
import Katip
import Protolude hiding (yield)
runBuild :: (MonadIO m, KatipContext m) => Store -> Command.Build.Build -> ConduitT i Event m ()
runBuild store build = do
let extraPaths = Command.Build.inputDerivationOutputPaths build
drvPath = encodeUtf8 $ Command.Build.drvPath build
drvStorePath <- liftIO $ CNix.parseStorePath store drvPath
x <- for extraPaths $ \input -> liftIO $ do
storePath <- CNix.parseStorePath store input
try $ CNix.ensurePath store storePath
materialize <- case sequenceA x of
Right _ ->
-- no error, proceed with requested materialization setting
pure $ Command.Build.materializeDerivation build
Left (e :: SomeException) -> liftIO do
CNix.logInfo $ "while retrieving dependencies: " <> toS (displayException e)
CNix.logInfo "unable to retrieve dependency; attempting fallback to local build"
pure True
drvName <- liftIO $ CNix.getDerivationNameFromPath drvStorePath
derivationMaybe <- liftIO $ Build.getDerivation store drvStorePath
derivation <- case derivationMaybe of
Just drv -> pure drv
Nothing -> panic $ "Could not retrieve derivation " <> show drvStorePath <> " from local store or binary caches."
nixBuildResult <- liftIO $ buildDerivation store drvStorePath derivation (extraPaths <$ guard (not materialize))
katipAddContext (sl "result" (show nixBuildResult :: Text)) $
logLocM DebugS "Build result"
buildResult <- liftIO $ enrichResult store drvName derivation nixBuildResult
yield $ Event.BuildResult buildResult
-- TODO: case distinction on BuildStatus enumeration
enrichResult :: Store -> ByteString -> CNix.Derivation -> Build.BuildResult -> IO Event.BuildResult.BuildResult
enrichResult _ _ _ result@Build.BuildResult {isSuccess = False} =
pure $
Event.BuildResult.BuildFailure {errorMessage = Build.errorMessage result}
enrichResult store drvName derivation _ = do
drvOuts <- getDerivationOutputs store drvName derivation
outputInfos <- for drvOuts $ \drvOut -> do
-- FIXME: ca-derivations: always get the built path
vpi <- for (derivationOutputPath drvOut) (queryPathInfo store)
hash_ <- traverse validPathInfoNarHash32 vpi
path <- traverse (CNix.storePathToPath store) (derivationOutputPath drvOut)
let size = fmap validPathInfoNarSize vpi
pure
Event.BuildResult.OutputInfo
{ name = derivationOutputName drvOut,
path = fromMaybe "" path,
hash = fromMaybe "" hash_,
size = fromMaybe 0 size
}
pure $ Event.BuildResult.BuildSuccess outputInfos