+1
.gitignore
+1
.gitignore
···
1
+
result
+182
blup.cabal
+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
+6
exe/Blup.hs
+64
flake.lock
+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
+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
+9
nix/devshell.nix
+3
nix/packages/blup/default.nix
+3
nix/packages/blup/default.nix
+80
package.yaml
+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
+7
src/Blueprint.hs
+176
src/Blueprint/CLIOptions.hs
+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
+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
+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
+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
test/spec/Spec.hs
···
1
+
{-# OPTIONS_GHC -F -pgmF hspec-discover #-}