{-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE ExtendedDefaultRules #-} {-# LANGUAGE NoMonomorphismRestriction #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE StandaloneKindSignatures #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeApplications #-} module FlakeToGitlabCI (main) where import Control.Lens (ix, view) import Data.Aeson (FromJSON, ToJSON, Value) import qualified Data.Aeson as A import Data.Aeson.KeyMap (toMapText) import Data.Aeson.Lens (_Object) import qualified Data.ByteString as BS import qualified Data.ByteString.Char8 as BSC import Data.Kind (Type) import qualified Data.Map as Map import Data.Text (Text) import qualified Data.Yaml.Pretty as Y import Formatting (Format, sformat, stext, (%)) import GHC.Generics (Generic) import Shh (Proc, capture, mkProc, (|>)) import System.Which (staticWhich) nixBin :: FilePath nixBin = $(staticWhich "nix") type Step :: Type newtype Step = Step { script :: [Text] } deriving stock (Show, Eq, Generic) deriving anyclass (FromJSON, ToJSON) nixFlakeShowJson :: Proc () nixFlakeShowJson = mkProc (BSC.fromStrict $ BSC.pack nixBin) ["flake", "show", "--allow-import-from-derivation", "--json"] nixBuildCmd :: Format r (Text -> Text -> r) nixBuildCmd = "nix build -L .#" % stext % "." % stext getChecksJSON :: Value -> [Text] getChecksJSON = Map.keys . toMapText . view (_Object . ix "checks" . _Object . ix "x86_64-linux" . _Object) getPackagesJSON :: Value -> [Text] getPackagesJSON = Map.keys . toMapText . view (_Object . ix "packages" . _Object . ix "x86_64-linux" . _Object) getDevShellsJSON :: Value -> [Text] getDevShellsJSON = Map.keys . toMapText . view (_Object . ix "devShells" . _Object . ix "x86_64-linux" . _Object) mkCheck :: Text -> (Text, Step) mkCheck x = (sformat ("checks." % stext) x, Step [sformat nixBuildCmd "checks.x86_64-linux" x] ) mkPkg :: Text -> (Text, Step) mkPkg x = (sformat ("packages." % stext) x, Step [sformat nixBuildCmd "packages.x86_64-linux" x]) mkDevShell :: Text -> (Text, Step) mkDevShell x = (sformat ("devShells." % stext) x, Step [sformat nixBuildCmd "devShells.x86_64-linux" x]) main :: IO () main = do x <- nixFlakeShowJson |> capture case A.eitherDecode @Value x of Left e -> error $ "Could not decode nix flake show --allow-import-from-derivation --json" <> show e Right r -> do let pkgs = mkPkg <$> getPackagesJSON r chks = mkCheck <$> getChecksJSON r ds = mkDevShell <$> getDevShellsJSON r BS.putStr $ Y.encodePretty Y.defConfig $ Map.fromList $ pkgs <> chks <> ds