add builtOutputs to BuildResult, more legwork

This commit is contained in:
sorki 2023-12-05 17:04:29 +01:00
parent 225b4d3f5a
commit ee4ad7b07b
6 changed files with 167 additions and 14 deletions

View File

@ -10,10 +10,14 @@ module System.Nix.Build
, OldBuildResult(..)
) where
import Data.Map (Map)
import Data.Time (UTCTime)
import Data.Text (Text)
import GHC.Generics (Generic)
import System.Nix.OutputName (OutputName)
import System.Nix.Realisation (Realisation)
-- | Mode of the build operation
-- Keep the order of these Enums to match enums from reference implementations
-- src/libstore/store-api.hh
@ -56,6 +60,11 @@ data BuildResult = BuildResult
-- ^ Start time of this build
, buildResultStopTime :: !UTCTime
-- ^ Stop time of this build
, buildResultBuiltOutputs :: !(Maybe (Map OutputName Realisation))
-- ^ Mapping of the output names to @Realisation@s
-- (paths with additional info and their dependencies)
--
-- Available for protocol version >= 1.28
}
deriving (Eq, Generic, Ord, Show)
@ -67,11 +76,16 @@ buildSuccess x =
, BuildStatus_AlreadyValid
]
-- | Result of the build, for protocol version <= 1.27
-- | Result of the build, for protocol version <= 1.28
data OldBuildResult = OldBuildResult
{ oldBuildResultStatus :: !BuildStatus
-- ^ Build status, MiscFailure should be the default
, oldBuildResultErrorMessage :: !(Maybe Text)
-- ^ Possible build error message
, oldBuildResultBuiltOutputs :: !(Maybe (Map OutputName Realisation))
-- ^ Mapping of the output names to @Realisation@s
-- (paths with additional info and their dependencies)
--
-- Available for protocol version >= 1.28
}
deriving (Eq, Generic, Ord, Show)

View File

@ -49,6 +49,8 @@ instance Serialize BuildResult where
buildResultIsNonDeterministic <- getBool
buildResultStartTime <- getTime
buildResultStopTime <- getTime
buildResultBuiltOutputs <- pure Nothing
pure BuildResult{..}
put BuildResult{..} = do
@ -67,6 +69,7 @@ instance Serialize OldBuildResult where
oldBuildResultErrorMessage <-
(\em -> Data.Bool.bool (Just em) Nothing (Data.Text.null em))
<$> get
oldBuildResultBuiltOutputs <- pure Nothing
pure OldBuildResult{..}
put OldBuildResult{..} = do

View File

@ -40,6 +40,11 @@ module System.Nix.Store.Remote.Serializer
, storePathName
-- * Metadata
, pathMetadata
-- * OutputName
, outputName
-- * Realisation
, derivationOutputTyped
, realisation
-- * Signatures
, signature
, narSignature
@ -47,6 +52,8 @@ module System.Nix.Store.Remote.Serializer
, someHashAlgo
-- * Digest
, digest
-- * DSum HashAlgo Digest
, namedDigest
-- * Derivation
, derivation
-- * Derivation
@ -96,6 +103,7 @@ import Data.Map (Map)
import Data.Set (Set)
import Data.Some (Some(Some))
import Data.Text (Text)
import Data.Text.Lazy.Builder (Builder)
import Data.Time (NominalDiffTime, UTCTime)
import Data.Vector (Vector)
import Data.Word (Word8, Word32, Word64)
@ -114,6 +122,8 @@ import qualified Data.Serialize.Put
import qualified Data.Set
import qualified Data.Text
import qualified Data.Text.Encoding
import qualified Data.Text.Lazy
import qualified Data.Text.Lazy.Builder
import qualified Data.Time.Clock.POSIX
import qualified Data.Vector
@ -124,6 +134,8 @@ import System.Nix.ContentAddress (ContentAddress)
import System.Nix.Derivation (Derivation(..), DerivationOutput(..))
import System.Nix.DerivedPath (DerivedPath, ParseOutputsError)
import System.Nix.Hash (HashAlgo(..))
import System.Nix.OutputName (OutputName)
import System.Nix.Realisation (Realisation(..))
import System.Nix.Signature (Signature, NarSignature)
import System.Nix.Store.Types (FileIngestionMethod(..), RepairMode(..))
import System.Nix.StorePath (HasStoreDir(..), InvalidNameError, InvalidPathError, StorePath, StorePathHashPart, StorePathName)
@ -137,6 +149,8 @@ import qualified System.Nix.Base
import qualified System.Nix.ContentAddress
import qualified System.Nix.DerivedPath
import qualified System.Nix.Hash
import qualified System.Nix.OutputName
import qualified System.Nix.Realisation
import qualified System.Nix.Signature
import qualified System.Nix.StorePath
@ -334,6 +348,12 @@ text = mapIsoSerializer
Data.Text.Encoding.encodeUtf8
byteString
_textBuilder :: NixSerializer r SError Builder
_textBuilder = Serializer
{ getS = Data.Text.Lazy.Builder.fromText <$> getS text
, putS = putS text . Data.Text.Lazy.toStrict . Data.Text.Lazy.Builder.toLazyText
}
maybeText :: NixSerializer r SError (Maybe Text)
maybeText = mapIsoSerializer
(\case
@ -564,6 +584,44 @@ pathMetadata = Serializer
(\case BuiltElsewhere -> False; BuiltLocally -> True)
bool
-- * OutputName
outputName :: NixSerializer r SError OutputName
outputName =
mapPrismSerializer
(Data.Bifunctor.first SError_Name
. System.Nix.OutputName.mkOutputName)
System.Nix.OutputName.unOutputName
text
-- * Realisation
derivationOutputTyped :: NixSerializer r SError (System.Nix.Realisation.DerivationOutput OutputName)
derivationOutputTyped = Serializer
{ getS = do
derivationOutputHash <- getS namedDigest
derivationOutputName <- getS outputName
pure System.Nix.Realisation.DerivationOutput{..}
, putS = \System.Nix.Realisation.DerivationOutput{..} -> do
putS namedDigest derivationOutputHash
putS outputName derivationOutputName
}
realisation
:: HasStoreDir r
=> NixSerializer r SError Realisation
realisation = Serializer
{ getS = do
realisationOutPath <- getS storePath
realisationSignatures <- getS (set signature)
realisationDependencies <- getS (mapS derivationOutputTyped storePath)
pure Realisation{..}
, putS = \Realisation{..} -> do
putS storePath realisationOutPath
putS (set signature) realisationSignatures
putS (mapS derivationOutputTyped storePath) realisationDependencies
}
-- * Signatures
signature
@ -613,6 +671,28 @@ digest base =
(System.Nix.Hash.encodeDigestWith base)
$ text
-- * DSum HashAlgo Digest
namedDigest :: NixSerializer r SError (DSum HashAlgo Digest)
namedDigest = Serializer
{ getS = do
sriHash <- getS text
let (sriName, _h) = Data.Text.breakOn (Data.Text.singleton '-') sriHash
-- bit hacky since mkNamedDigest does the check
-- that the expected matches but we don't know
-- what we expect here (i.e. handle each HashAlgo)
case System.Nix.Hash.mkNamedDigest sriName sriHash of
Left e -> throwError $ SError_Digest e
Right x -> pure x
-- TODO: we also lack a builder for SRI hashes
-- , putS = putS textBuilder . System.Nix.Hash.algoDigestBuilder
, putS = \(algo :=> d) -> do
putS text
$ System.Nix.Hash.algoToText algo
<> (Data.Text.singleton '-')
<> System.Nix.Hash.encodeDigestWith NixBase32 d
}
derivationOutput
:: HasStoreDir r
=> NixSerializer r SError (DerivationOutput StorePath Text)
@ -704,7 +784,11 @@ derivedPath = Serializer
buildMode :: NixSerializer r SError BuildMode
buildMode = enum
buildResult :: NixSerializer r SError BuildResult
buildResult
:: ( HasProtoVersion r
, HasStoreDir r
)
=> NixSerializer r SError BuildResult
buildResult = Serializer
{ getS = do
buildResultStatus <- getS enum
@ -713,6 +797,11 @@ buildResult = Serializer
buildResultIsNonDeterministic <- getS bool
buildResultStartTime <- getS time
buildResultStopTime <- getS time
pv <- Control.Monad.Reader.asks hasProtoVersion
buildResultBuiltOutputs <-
if protoVersion_minor pv >= 28
then pure <$> getS (mapS outputName realisation)
else pure Nothing
pure BuildResult{..}
, putS = \BuildResult{..} -> do
@ -722,18 +811,37 @@ buildResult = Serializer
putS bool buildResultIsNonDeterministic
putS time buildResultStartTime
putS time buildResultStopTime
pv <- Control.Monad.Reader.asks hasProtoVersion
if protoVersion_minor pv >= 28
then putS (mapS outputName realisation)
$ Data.Maybe.fromMaybe mempty buildResultBuiltOutputs
else pure ()
}
oldBuildResult :: NixSerializer r SError OldBuildResult
oldBuildResult
:: ( HasProtoVersion r
, HasStoreDir r
)
=> NixSerializer r SError OldBuildResult
oldBuildResult = Serializer
{ getS = do
oldBuildResultStatus <- getS enum
oldBuildResultErrorMessage <- getS maybeText
pv <- Control.Monad.Reader.asks hasProtoVersion
oldBuildResultBuiltOutputs <-
if protoVersion_minor pv >= 28
then pure <$> getS (mapS outputName realisation)
else pure Nothing
pure OldBuildResult{..}
, putS = \OldBuildResult{..} -> do
putS enum oldBuildResultStatus
putS maybeText oldBuildResultErrorMessage
pv <- Control.Monad.Reader.asks hasProtoVersion
if protoVersion_minor pv >= 28
then putS (mapS outputName realisation)
$ Data.Maybe.fromMaybe mempty oldBuildResultBuiltOutputs
else pure ()
}
-- * Logger

View File

@ -12,12 +12,13 @@ import Test.QuickCheck (Gen, arbitrary, forAll, suchThat)
import System.Nix.Arbitrary ()
import System.Nix.Derivation (Derivation(inputDrvs))
import System.Nix.Build (BuildResult(..))
import System.Nix.StorePath (StoreDir)
import System.Nix.Store.Remote.Arbitrary ()
import System.Nix.Store.Remote.Serializer
import System.Nix.Store.Remote.Types.Logger (Logger(..))
import System.Nix.Store.Remote.Types.ProtoVersion (HasProtoVersion(..), ProtoVersion(..))
import System.Nix.Store.Remote.Types.StoreConfig (TestStoreConfig)
import System.Nix.Store.Remote.Types.StoreConfig (TestStoreConfig(..))
import System.Nix.Store.Remote.Types.StoreRequest (StoreRequest(..))
import System.Nix.Store.Remote.Types.WorkerOp (WorkerOp(..))
@ -66,8 +67,28 @@ spec = parallel $ do
prop "mapS" $ roundtripS (mapS (int @Int) byteString)
describe "Complex" $ do
prop "BuildResult" $ roundtripS buildResult
prop "OldBuildResult" $ roundtripS oldBuildResult
prop "DSum HashAlgo Digest" $ roundtripS namedDigest
describe "BuildResult" $ do
prop "< 1.28"
$ \sd -> forAll (arbitrary `suchThat` ((< 28) . protoVersion_minor))
$ \pv ->
roundtripSReader @TestStoreConfig buildResult (TestStoreConfig sd pv)
. (\x -> x { buildResultBuiltOutputs = Nothing })
prop "= 1.28"
$ \sd ->
roundtripSReader @TestStoreConfig buildResult (TestStoreConfig sd (ProtoVersion 1 28))
prop "> 1.28"
$ \sd -> forAll (arbitrary `suchThat` ((> 28) . protoVersion_minor))
$ \pv ->
roundtripSReader @TestStoreConfig buildResult (TestStoreConfig sd pv)
-- prop "OldBuildResult"
-- $ \testStoreConfig ->
-- forAll (arbitrary
-- `suchThat`
-- (restrictProtoVersionBuildResult (hasProtoVersion testStoreConfig)))
-- $ roundtripSReader oldBuildResult testStoreConfig
prop "StorePath" $
roundtripSReader @StoreDir storePath

View File

@ -14,7 +14,7 @@ import qualified Data.Either
import qualified Data.HashSet
import System.Nix.Arbitrary ()
import System.Nix.Build (BuildMode(..), BuildResult, BuildStatus(..), OldBuildResult(..))
import System.Nix.Build (BuildMode(..), BuildStatus(..))
import System.Nix.Derivation (Derivation(inputDrvs))
import System.Nix.Store.Remote.Arbitrary ()
import System.Nix.Store.Remote.Serialize (getDerivation, putDerivation)
@ -75,8 +75,6 @@ spec = parallel $ do
prop "Text" $ roundtripS @Text
prop "BuildMode" $ roundtripS @BuildMode
prop "BuildStatus" $ roundtripS @BuildStatus
prop "BuildResult" $ roundtripS @BuildResult
prop "OldBuildResult" $ roundtripS @OldBuildResult
prop "ProtoVersion" $ roundtripS @ProtoVersion

View File

@ -6,6 +6,8 @@ module System.Nix.Arbitrary.Build where
import Data.Text.Arbitrary ()
import Test.QuickCheck (Arbitrary(..), suchThat)
import Test.QuickCheck.Arbitrary.Generic (GenericArbitrary(..))
import System.Nix.Arbitrary.OutputName ()
import System.Nix.Arbitrary.Realisation ()
import System.Nix.Arbitrary.UTCTime ()
import System.Nix.Build
@ -19,14 +21,21 @@ deriving via GenericArbitrary BuildStatus
instance Arbitrary BuildResult where
arbitrary = do
buildResultStatus <- arbitrary
-- we encode empty errorMessage as Nothing
buildResultErrorMessage <- arbitrary `suchThat` (/= Just mempty)
buildResultErrorMessage <- arbitrary
buildResultTimesBuilt <- arbitrary
buildResultIsNonDeterministic <- arbitrary
buildResultStartTime <- arbitrary
buildResultStopTime <- arbitrary
buildResultBuiltOutputs <- arbitrary `suchThat` (/= Nothing)
pure BuildResult{..}
instance Arbitrary OldBuildResult where
arbitrary = do
oldBuildResultStatus <- arbitrary
oldBuildResultErrorMessage <- arbitrary
oldBuildResultBuiltOutputs <- arbitrary `suchThat` (/= Just mempty)
pure OldBuildResult{..}
pure $ BuildResult{..}
deriving via GenericArbitrary OldBuildResult
instance Arbitrary OldBuildResult