{-# LANGUAGE ScopedTypeVariables #-} module Hercules.Agent.EnvironmentInfo where import Data.ByteString qualified as BS import Data.Set qualified as S import Data.Text qualified as T import Hercules.API.Agent.LifeCycle.AgentInfo qualified as AgentInfo import Hercules.Agent.CabalInfo as CabalInfo import Hercules.Agent.Cachix.Info as Cachix.Info import Hercules.Agent.Config qualified as Config import Hercules.Agent.Env as Env import Hercules.Agent.Log import Hercules.CNix qualified as CNix import Hercules.CNix.Settings qualified as Settings import Hercules.CNix.Store (withStoreFromURI) import Hercules.CNix.Store qualified as Store import Network.HostName (getHostName) import Protolude hiding (to) extractAgentInfo :: App AgentInfo.AgentInfo extractAgentInfo = do cfg <- asks Env.config hostname <- liftIO getHostName nix <- liftIO getNixInfo cachixPushCaches <- Cachix.Info.activePushCaches pushCaches <- Env.activePushCaches nixClientProtocolVersion <- liftIO Store.getClientProtocolVersion nixStoreProtocolVersion <- liftIO $ Store.withStore Store.getStoreProtocolVersion let s = AgentInfo.AgentInfo { hostname = toS hostname, agentVersion = CabalInfo.herculesAgentVersion, nixVersion = nixLibVersion nix, nixClientProtocolVersion = nixClientProtocolVersion, nixDaemonProtocolVersion = nixStoreProtocolVersion, platforms = map fromUtf8Lenient (nixPlatforms nix) <> fromMaybe [] cfg.remotePlatformsWithSameFeatures, cachixPushCaches = cachixPushCaches, pushCaches = pushCaches, systemFeatures = map fromUtf8Lenient $ nixSystemFeatures nix, substituters = map fromUtf8Lenient $ nixSubstituters nix, concurrentTasks = fromIntegral $ Config.concurrentTasks cfg, labels = Config.labels cfg } logLocM DebugS $ "Determined environment info: " <> logStr (show s :: Text) pure s data NixInfo = NixInfo { nixLibVersion :: Text, nixPlatforms :: [ByteString], nixSystemFeatures :: [ByteString], nixSubstituters :: [ByteString], nixTrustedPublicKeys :: [ByteString], nixNarinfoCacheNegativeTTL :: Word64, nixNetrcFile :: Maybe ByteString } deriving (Show) fromUtf8Lenient :: ByteString -> Text fromUtf8Lenient = decodeUtf8With lenientDecode getNixInfo :: IO NixInfo getNixInfo = do extraPlatforms <- Settings.getExtraPlatforms system <- Settings.getSystem systemFeatures <- Settings.getSystemFeatures substituters <- Settings.getSubstituters trustedPublicKeys <- Settings.getTrustedPublicKeys narinfoCacheNegativeTTL <- Settings.getNarinfoCacheNegativeTtl netrcFile <- Settings.getNetrcFile cleanSubstituters <- ordNub <$> traverse cleanUrl substituters pure NixInfo { nixLibVersion = T.dropAround isSpace (fromUtf8Lenient CNix.nixVersion), nixPlatforms = toList (S.singleton system <> extraPlatforms), nixSystemFeatures = toList systemFeatures, nixSubstituters = cleanSubstituters, nixTrustedPublicKeys = trustedPublicKeys, nixNarinfoCacheNegativeTTL = narinfoCacheNegativeTTL, nixNetrcFile = guard (netrcFile /= "") $> netrcFile } cleanUrl :: ByteString -> IO ByteString cleanUrl t | "@" `BS.isInfixOf` t = pure "" cleanUrl t = do withStoreFromURI (decodeUtf8With lenientDecode t) Store.storeUri