Initial commit

+1
.gitignore
··· 1 + result
+182
blup.cabal
··· 1 + cabal-version: 1.12 2 + 3 + -- This file has been generated from package.yaml by hpack version 0.36.1. 4 + -- 5 + -- see: https://github.com/sol/hpack 6 + 7 + name: blup 8 + version: 0.0.0.0 9 + synopsis: A blueprint-based CLI tool 10 + description: This package provides an executable to help manager Nix blueprint-based projects (see https://github.com/numtide/blueprint). 11 + homepage: https://github.com/garnix-io/blup#readme 12 + bug-reports: https://github.com/garnix-io/blup/issues 13 + author: garnix team <dev@garnix.io> 14 + maintainer: garnix team <dev@garnix.io> 15 + build-type: Simple 16 + 17 + source-repository head 18 + type: git 19 + location: https://github.com/garnix-io/blup 20 + 21 + library 22 + exposed-modules: 23 + Blueprint 24 + Blueprint.CLIOptions 25 + Blueprint.Run 26 + Blueprint.Templates 27 + other-modules: 28 + Paths_blup 29 + hs-source-dirs: 30 + src 31 + default-extensions: 32 + BangPatterns 33 + ConstraintKinds 34 + DataKinds 35 + DeriveAnyClass 36 + DeriveFunctor 37 + DeriveTraversable 38 + DeriveGeneric 39 + DerivingStrategies 40 + DerivingVia 41 + FunctionalDependencies 42 + FlexibleContexts 43 + FlexibleInstances 44 + GADTs 45 + GeneralizedNewtypeDeriving 46 + InstanceSigs 47 + LambdaCase 48 + MultiParamTypeClasses 49 + MultiWayIf 50 + NamedFieldPuns 51 + OverloadedLabels 52 + PolyKinds 53 + QuantifiedConstraints 54 + RankNTypes 55 + RecordWildCards 56 + TupleSections 57 + TypeApplications 58 + TypeFamilies 59 + TypeOperators 60 + ScopedTypeVariables 61 + StandaloneDeriving 62 + ghc-options: -Wall -Wno-name-shadowing -threaded 63 + build-depends: 64 + base >=4.5 && <5 65 + , bytestring 66 + , directory 67 + , interpolate 68 + , optparse-applicative 69 + , process 70 + , string-conversions 71 + , text 72 + , unix 73 + default-language: Haskell2010 74 + 75 + executable blup 76 + main-is: exe/Blup.hs 77 + other-modules: 78 + Paths_blup 79 + default-extensions: 80 + BangPatterns 81 + ConstraintKinds 82 + DataKinds 83 + DeriveAnyClass 84 + DeriveFunctor 85 + DeriveTraversable 86 + DeriveGeneric 87 + DerivingStrategies 88 + DerivingVia 89 + FunctionalDependencies 90 + FlexibleContexts 91 + FlexibleInstances 92 + GADTs 93 + GeneralizedNewtypeDeriving 94 + InstanceSigs 95 + LambdaCase 96 + MultiParamTypeClasses 97 + MultiWayIf 98 + NamedFieldPuns 99 + OverloadedLabels 100 + PolyKinds 101 + QuantifiedConstraints 102 + RankNTypes 103 + RecordWildCards 104 + TupleSections 105 + TypeApplications 106 + TypeFamilies 107 + TypeOperators 108 + ScopedTypeVariables 109 + StandaloneDeriving 110 + ghc-options: -Wall -Wno-name-shadowing -threaded 111 + build-depends: 112 + base >=4.5 && <5 113 + , blup 114 + , bytestring 115 + , directory 116 + , interpolate 117 + , optparse-applicative 118 + , process 119 + , string-conversions 120 + , text 121 + , unix 122 + default-language: Haskell2010 123 + 124 + test-suite spec 125 + type: exitcode-stdio-1.0 126 + main-is: spec/Spec.hs 127 + other-modules: 128 + Blueprint 129 + Blueprint.CLIOptions 130 + Blueprint.Run 131 + Blueprint.Templates 132 + Paths_blup 133 + hs-source-dirs: 134 + test 135 + src 136 + default-extensions: 137 + BangPatterns 138 + ConstraintKinds 139 + DataKinds 140 + DeriveAnyClass 141 + DeriveFunctor 142 + DeriveTraversable 143 + DeriveGeneric 144 + DerivingStrategies 145 + DerivingVia 146 + FunctionalDependencies 147 + FlexibleContexts 148 + FlexibleInstances 149 + GADTs 150 + GeneralizedNewtypeDeriving 151 + InstanceSigs 152 + LambdaCase 153 + MultiParamTypeClasses 154 + MultiWayIf 155 + NamedFieldPuns 156 + OverloadedLabels 157 + PolyKinds 158 + QuantifiedConstraints 159 + RankNTypes 160 + RecordWildCards 161 + TupleSections 162 + TypeApplications 163 + TypeFamilies 164 + TypeOperators 165 + ScopedTypeVariables 166 + StandaloneDeriving 167 + ghc-options: -Wall -Wno-name-shadowing -threaded 168 + build-depends: 169 + base >=4.5 && <5 170 + , bytestring 171 + , directory 172 + , filepath 173 + , hspec 174 + , hspec-discover 175 + , interpolate 176 + , optparse-applicative 177 + , process 178 + , string-conversions 179 + , text 180 + , transformers 181 + , unix 182 + default-language: Haskell2010
+6
exe/Blup.hs
··· 1 + module Main where 2 + 3 + import qualified Blueprint 4 + 5 + main :: IO () 6 + main = Blueprint.main
+64
flake.lock
··· 1 + { 2 + "nodes": { 3 + "blueprint": { 4 + "inputs": { 5 + "nixpkgs": [ 6 + "nixpkgs" 7 + ], 8 + "systems": "systems" 9 + }, 10 + "locked": { 11 + "lastModified": 1724053269, 12 + "narHash": "sha256-DinmPyxmUSLjBUYMe3eK0GKykwe33vWbVTmp7++P4Ng=", 13 + "owner": "numtide", 14 + "repo": "blueprint", 15 + "rev": "766302be9063650ca6578e5ba09cc4260b0da29c", 16 + "type": "github" 17 + }, 18 + "original": { 19 + "owner": "numtide", 20 + "repo": "blueprint", 21 + "type": "github" 22 + } 23 + }, 24 + "nixpkgs": { 25 + "locked": { 26 + "lastModified": 1724819573, 27 + "narHash": "sha256-GnR7/ibgIH1vhoy8cYdmXE6iyZqKqFxQSVkFgosBh6w=", 28 + "owner": "NixOS", 29 + "repo": "nixpkgs", 30 + "rev": "71e91c409d1e654808b2621f28a327acfdad8dc2", 31 + "type": "github" 32 + }, 33 + "original": { 34 + "owner": "NixOS", 35 + "ref": "nixos-unstable", 36 + "repo": "nixpkgs", 37 + "type": "github" 38 + } 39 + }, 40 + "root": { 41 + "inputs": { 42 + "blueprint": "blueprint", 43 + "nixpkgs": "nixpkgs" 44 + } 45 + }, 46 + "systems": { 47 + "locked": { 48 + "lastModified": 1681028828, 49 + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", 50 + "owner": "nix-systems", 51 + "repo": "default", 52 + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", 53 + "type": "github" 54 + }, 55 + "original": { 56 + "owner": "nix-systems", 57 + "repo": "default", 58 + "type": "github" 59 + } 60 + } 61 + }, 62 + "root": "root", 63 + "version": 7 64 + }
+16
flake.nix
··· 1 + { 2 + description = "my flake"; 3 + 4 + # Add all your dependencies here 5 + inputs = { 6 + nixpkgs.url = "github:NixOS/nixpkgs?ref=nixos-unstable"; 7 + blueprint.url = "github:numtide/blueprint"; 8 + blueprint.inputs.nixpkgs.follows = "nixpkgs"; 9 + }; 10 + 11 + # Load the blueprint 12 + outputs = inputs: inputs.blueprint { 13 + inherit inputs; 14 + prefix = ./nix; 15 + }; 16 + }
+9
nix/devshell.nix
··· 1 + { pkgs, perSystem }: 2 + pkgs.mkShell { 3 + packages = [ 4 + (pkgs.ghc.withPackages (p: perSystem.self.blup.buildInputs)) 5 + pkgs.cabal-install 6 + pkgs.hpack 7 + pkgs.ghciwatch 8 + ]; 9 + }
+3
nix/packages/blup/default.nix
··· 1 + { pkgs, ... }: 2 + 3 + pkgs.haskellPackages.callCabal2nix "blup" ../../.. { }
+2
nix/packages/foo/default.nix
··· 1 + { pkgs, perSystem, ... }: 2 +
+80
package.yaml
··· 1 + name: blup 2 + version: 0.0.0.0 3 + synopsis: A blueprint-based CLI tool 4 + description: | 5 + This package provides an executable to help manager Nix blueprint-based projects (see https://github.com/numtide/blueprint). 6 + author: garnix team <dev@garnix.io> 7 + maintainer: garnix team <dev@garnix.io> 8 + github: garnix-io/blup 9 + 10 + dependencies: 11 + - base >= 4.5 && < 5 12 + - bytestring 13 + - directory 14 + - interpolate 15 + - optparse-applicative 16 + - process 17 + - string-conversions 18 + - text 19 + - unix 20 + 21 + ghc-options: 22 + - -Wall 23 + - -Wno-name-shadowing 24 + - -threaded 25 + 26 + library: 27 + source-dirs: 28 + - src 29 + 30 + executables: 31 + blup: 32 + main: exe/Blup.hs 33 + dependencies: 34 + - blup 35 + 36 + tests: 37 + spec: 38 + main: Spec.hs 39 + source-dirs: 40 + - test/spec 41 + - src 42 + dependencies: 43 + - directory 44 + - filepath 45 + - hspec 46 + - hspec-discover 47 + - interpolate 48 + - transformers 49 + 50 + default-extensions: 51 + - BangPatterns 52 + - ConstraintKinds 53 + - DataKinds 54 + - DeriveAnyClass 55 + - DeriveFunctor 56 + - DeriveTraversable 57 + - DeriveGeneric 58 + - DerivingStrategies 59 + - DerivingVia 60 + - FunctionalDependencies 61 + - FlexibleContexts 62 + - FlexibleInstances 63 + - GADTs 64 + - GeneralizedNewtypeDeriving 65 + - InstanceSigs 66 + - LambdaCase 67 + - MultiParamTypeClasses 68 + - MultiWayIf 69 + - NamedFieldPuns 70 + - OverloadedLabels 71 + - PolyKinds 72 + - QuantifiedConstraints 73 + - RankNTypes 74 + - RecordWildCards 75 + - TupleSections 76 + - TypeApplications 77 + - TypeFamilies 78 + - TypeOperators 79 + - ScopedTypeVariables 80 + - StandaloneDeriving
+7
src/Blueprint.hs
··· 1 + module Blueprint where 2 + 3 + import Blueprint.CLIOptions 4 + import Blueprint.Run 5 + 6 + main :: IO () 7 + main = getOptions >>= run
+176
src/Blueprint/CLIOptions.hs
··· 1 + module Blueprint.CLIOptions where 2 + 3 + import Options.Applicative 4 + import Data.Tuple 5 + import Data.List 6 + 7 + data Options where 8 + OptionsCreate :: CreateOptions -> Options 9 + OptionsEdit :: EditOptions -> Options 10 + OptionsInitialize :: InitializeOptions -> Options 11 + OptionsCheck :: CheckOptions -> Options 12 + OptionsRun :: RunOptions -> Options 13 + deriving (Eq, Show) 14 + 15 + data CreateOptions where 16 + CreateOptionsPackage :: String -> CreateOptions 17 + CreateOptionsCheck :: String -> CreateOptions 18 + CreateOptionsDevShell :: String -> CreateOptions 19 + CreateOptionsHost :: String -> CreateOptions 20 + deriving (Eq, Show) 21 + 22 + data EditOptions where 23 + EditOptionsPackage :: String -> EditOptions 24 + EditOptionsCheck :: String -> EditOptions 25 + EditOptionsDevShell :: String -> EditOptions 26 + deriving (Eq, Show) 27 + 28 + data CheckOptions = CheckOptions 29 + { checkName :: String } 30 + deriving (Eq, Show) 31 + 32 + data InitializeOptions = InitializeOptions 33 + { nixpkgs :: NixpkgsVersion } 34 + deriving (Eq, Show) 35 + 36 + data RunOptions where 37 + RunOptionsVM :: String -> RunOptions 38 + deriving (Eq, Show) 39 + 40 + options :: Parser Options 41 + options = hsubparser 42 + (command "init" 43 + (info 44 + (OptionsInitialize <$> initializeOptions) 45 + (progDesc "Initialize a new blueprint project" 46 + <> defaultHeader 47 + )) 48 + <> 49 + command "create" 50 + (info 51 + (OptionsCreate <$> createOptions) 52 + (progDesc "Create a new package, check, host, or devshell" 53 + <> defaultHeader 54 + )) 55 + <> command "edit" 56 + (info 57 + (OptionsEdit <$> editOptions) 58 + (progDesc "Edit an existing package, check, host, or devshell" 59 + <> defaultHeader 60 + )) 61 + <> command "check" 62 + (info 63 + (OptionsCheck <$> checkOptions) 64 + (progDesc "Run a check" 65 + <> defaultHeader 66 + )) 67 + <> command "run" 68 + (info 69 + (OptionsRun <$> runOptions) 70 + (progDesc "Run a VM" 71 + <> defaultHeader 72 + )) 73 + ) 74 + 75 + createOptions :: Parser CreateOptions 76 + createOptions = subparser 77 + (command "package" 78 + (info 79 + (CreateOptionsPackage <$> textArg "PACKAGE") 80 + (progDesc "Create a new package")) 81 + <> command "check" 82 + (info 83 + (CreateOptionsCheck <$> textArg "CHECK") 84 + (progDesc "Create a new check")) 85 + <> command "devshell" 86 + (info 87 + (CreateOptionsDevShell <$> textArg "DEVSHELL") 88 + (progDesc "Create a new devshell")) 89 + <> command "host" 90 + (info 91 + (CreateOptionsHost <$> textArg "HOST") 92 + (progDesc "Create a new host (NixOS configuration)")) 93 + ) 94 + where 95 + textArg = argument str . metavar 96 + 97 + editOptions :: Parser EditOptions 98 + editOptions = subparser 99 + (command "package" 100 + (info 101 + (EditOptionsPackage <$> textArg "PACKAGE") 102 + (progDesc "Edit a package")) 103 + <> command "check" 104 + (info 105 + (EditOptionsCheck <$> textArg "CHECK") 106 + (progDesc "Edit a check")) 107 + <> command "devshell" 108 + (info 109 + (EditOptionsDevShell <$> textArg "DEVSHEL") 110 + (progDesc "Edit a devshell")) 111 + ) 112 + where 113 + textArg = argument str . metavar 114 + 115 + initializeOptions :: Parser InitializeOptions 116 + initializeOptions = InitializeOptions 117 + <$> option parseNixpkgsRef 118 + (long "nixpkgs" 119 + <> short 'n' 120 + <> value NixosUnstable 121 + <> metavar "VERSION" 122 + <> showDefault 123 + <> help "What nixpkgs version to use ") 124 + where 125 + parseNixpkgsRef = eitherReader $ \r -> case lookup r (swap <$> nixpkgsVersionStr) of 126 + Nothing -> Left $ 127 + "Nixpkgs version '" <> r <> "' not recognized. Allowed values:\n - " 128 + <> intercalate "\n - " (snd <$> nixpkgsVersionStr) 129 + Just v -> pure v 130 + 131 + checkOptions :: Parser CheckOptions 132 + checkOptions = CheckOptions 133 + <$> argument str (metavar "CHECK" <> help "What check to run") 134 + 135 + runOptions :: Parser RunOptions 136 + runOptions = subparser 137 + (command "vm" 138 + (info 139 + (RunOptionsVM <$> textArg "HOST") 140 + (progDesc "Runs a VM based on the specified host"))) 141 + where 142 + textArg = argument str . metavar 143 + 144 + data NixpkgsVersion 145 + = NixosUnstable 146 + | Nixos2311 147 + | Nixos2311Small 148 + | Nixos2405 149 + | Nixos2405Small 150 + deriving (Eq) 151 + 152 + instance Show NixpkgsVersion where 153 + show x = case lookup x nixpkgsVersionStr of 154 + Nothing -> error "impossible" 155 + Just v -> v 156 + 157 + nixpkgsVersionStr :: [(NixpkgsVersion, String)] 158 + nixpkgsVersionStr = 159 + [ (NixosUnstable, "unstable") 160 + , (Nixos2311, "23.11") 161 + , (Nixos2311Small, "23.11-small") 162 + , (Nixos2405, "24.05") 163 + , (Nixos2405Small, "24.05-small") 164 + ] 165 + 166 + 167 + getOptions :: IO Options 168 + getOptions = execParser opts 169 + where 170 + opts = info (options <**> helper) 171 + ( fullDesc 172 + <> progDesc "Configure and run blueprint-nix projects" 173 + <> defaultHeader) 174 + 175 + defaultHeader :: InfoMod a 176 + defaultHeader = header "blue - sane Nix"
+100
src/Blueprint/Run.hs
··· 1 + module Blueprint.Run where 2 + 3 + import Blueprint.CLIOptions 4 + import Blueprint.Templates as Templates 5 + import System.Exit 6 + import Control.Monad 7 + import System.Directory 8 + import System.Process 9 + import System.Environment 10 + 11 + run :: Options -> IO () 12 + run opts = case opts of 13 + OptionsCreate cOpts -> create cOpts 14 + OptionsEdit eOpts -> edit eOpts 15 + OptionsInitialize iOpts -> initialize iOpts 16 + OptionsCheck cOpts -> check cOpts 17 + OptionsRun rOpts -> run' rOpts 18 + 19 + create :: CreateOptions -> IO () 20 + create opts = case opts of 21 + CreateOptionsPackage pkg -> do 22 + createDirectoryIfMissing True ("nix/packages/" <> pkg) 23 + let file = "nix/packages/" <> pkg <> "/default.nix" 24 + ensureFileDoesntExist file 25 + writeFile file Templates.basicPackage 26 + openInEditor file 27 + CreateOptionsCheck check -> do 28 + createDirectoryIfMissing True ("nix/checks/" <> check) 29 + let file = "nix/checks/" <> check <> "/default.nix" 30 + ensureFileDoesntExist file 31 + writeFile file Templates.basicCheck 32 + openInEditor file 33 + CreateOptionsDevShell devShell -> do 34 + createDirectoryIfMissing True "nix/devshells" 35 + let file = "nix/devshells/" <> devShell <> ".nix" 36 + ensureFileDoesntExist file 37 + writeFile file Templates.basicDevShell 38 + openInEditor file 39 + CreateOptionsHost host -> do 40 + createDirectoryIfMissing True ("nix/hosts/" <> host) 41 + let file = "nix/hosts/" <> host <> "/configuration.nix" 42 + ensureFileDoesntExist file 43 + writeFile file Templates.basicNixosConfig 44 + openInEditor file 45 + where 46 + ensureFileDoesntExist :: FilePath -> IO () 47 + ensureFileDoesntExist path = do 48 + exists <- doesFileExist path 49 + when exists $ do 50 + putStrLn $ 51 + "File " <> path <> " already exists. Did you intend to edit it? If so, use the 'edit' command." 52 + exitFailure 53 + 54 + edit :: EditOptions -> IO () 55 + edit opts = case opts of 56 + EditOptionsPackage pkg -> do 57 + let file = "nix/packages/" <> pkg <> "/default.nix" 58 + ensureFileExists file 59 + openInEditor file 60 + EditOptionsCheck check -> do 61 + let file = "nix/checks/" <> check <> "/default.nix" 62 + ensureFileExists file 63 + openInEditor file 64 + EditOptionsDevShell devShell -> do 65 + let file = "nix/checks/" <> devShell <> ".nix" 66 + ensureFileExists file 67 + openInEditor file 68 + where 69 + ensureFileExists :: FilePath -> IO () 70 + ensureFileExists path = do 71 + exists <- doesFileExist path 72 + unless exists $ do 73 + putStrLn $ 74 + "File " <> path <> " doesn't exist. Did you intend to create it? If so, use the 'create' command." 75 + exitFailure 76 + 77 + initialize :: InitializeOptions -> IO () 78 + initialize opts = do 79 + exists <- doesFileExist "flake.nix" 80 + when exists $ do 81 + putStrLn "There's already a flake.nix file in this directory! If you want to initialize a blueprint project, delete if frirst." 82 + exitFailure 83 + writeFile "flake.nix" (basicFlake $ nixpkgs opts) 84 + 85 + check :: CheckOptions -> IO () 86 + check opts = do 87 + callProcess "nix" ["flake", "check", ".#checks." <> checkName opts ] 88 + 89 + run' :: RunOptions -> IO () 90 + run' opts = case opts of 91 + RunOptionsVM host -> do 92 + outpath <- readProcess "nix" ["build", ".#nixosConfigurations." <> host <> ".config.system.build.vm", "--print-out-paths"] "" 93 + callProcess (outpath <> "/bin/run-" <> host <> "-vm") [] 94 + 95 + openInEditor :: FilePath -> IO () 96 + openInEditor file = do 97 + mEditor <- lookupEnv "EDITOR" 98 + case mEditor of 99 + Nothing -> callProcess "nano" [file] 100 + Just editor -> callProcess editor [file]
+66
src/Blueprint/Templates.hs
··· 1 + {-# LANGUAGE QuasiQuotes #-} 2 + module Blueprint.Templates where 3 + 4 + import Data.String.Interpolate (i) 5 + import Blueprint.CLIOptions 6 + 7 + basicPackage :: String 8 + basicPackage = [i|{ pkgs, perSystem, ... }: 9 + 10 + |] 11 + 12 + basicCheck :: String 13 + basicCheck = [i|{ pkgs, perSystem, ... }: 14 + 15 + |] 16 + 17 + basicDevShell :: String 18 + basicDevShell = [i|{ pkgs, perSystem, ... }: 19 + pkgs.mkShell { 20 + packages = [ ]; 21 + } 22 + |] 23 + 24 + basicNixosConfig :: String 25 + basicNixosConfig = [i|{ flake, inputs, perSystem, ... }: 26 + { 27 + imports = [ 28 + ]; 29 + 30 + environment.systemPackages = [ 31 + ]; 32 + 33 + nixpkgs.hostPlatform = "x86_64-linux"; 34 + 35 + system.stateVersion = "24.05"; 36 + } 37 + |] 38 + 39 + basicFlake :: NixpkgsVersion -> String 40 + basicFlake version = [i| 41 + { 42 + description = "my flake"; 43 + 44 + # Add all your dependencies here 45 + inputs = { 46 + nixpkgs.url = "github:NixOS/nixpkgs?ref=#{nixpkgsVersion version}"; 47 + blueprint.url = "github:numtide/blueprint"; 48 + blueprint.inputs.nixpkgs.follows = "nixpkgs"; 49 + }; 50 + 51 + # Load the blueprint 52 + outputs = inputs: inputs.blueprint { 53 + inherit inputs; 54 + prefix = ./nix; 55 + }; 56 + } 57 + |] 58 + 59 + nixpkgsVersion :: NixpkgsVersion -> String 60 + nixpkgsVersion v = case v of 61 + NixosUnstable -> "nixos-unstable" 62 + Nixos2311 -> "nixos-23.11" 63 + Nixos2311Small -> "nixos-23.11-small" 64 + Nixos2405 -> "nixos-24.05" 65 + Nixos2405Small -> "nixos-24.05-small" 66 +
+17
test/spec/BlueprintSpec.hs
··· 1 + module BlueprintSpec (spec) where 2 + 3 + import Test.Hspec 4 + import Blueprint 5 + 6 + spec :: Spec 7 + spec = parallel $ do 8 + initializeSpec 9 + 10 + initializeSpec :: Spec 11 + initializeSpec = parallel $ describe "initialize" $ 12 + 13 + it "initializes a valid project" $ do 14 + out <- cmd ["init"] 15 + 16 + cmd :: [String] -> IO String 17 + cmd args = _
+1
test/spec/Spec.hs
··· 1 + {-# OPTIONS_GHC -F -pgmF hspec-discover #-}