-
Notifications
You must be signed in to change notification settings - Fork 131
/
Build.purs
303 lines (259 loc) Β· 14.1 KB
/
Build.purs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
module Test.Spago.Build where
import Test.Prelude
import Data.Foldable (fold)
import Data.String as String
import Node.FS.Aff as FSA
import Node.Path as Path
import Node.Platform as Platform
import Node.Process as Process
import Spago.Command.Init as Init
import Spago.Core.Config as Config
import Spago.FS as FS
import Spago.Paths as Paths
import Test.Spago.Build.BuildInfo as BuildInfo
import Test.Spago.Build.Monorepo as Monorepo
import Test.Spago.Build.Pedantic as Pedantic
import Test.Spec (Spec)
import Test.Spec as Spec
import Test.Spec.Assertions as Assert
import Test.Spec.Assertions.String (shouldContain)
spec :: Spec Unit
spec = Spec.around withTempDir do
Spec.describe "build" do
Spec.it "builds successfully" \{ spago } -> do
spago [ "init" ] >>= shouldBeSuccess
spago [ "build" ] >>= shouldBeSuccess
Spec.it "builds successfully a solver-only package" \{ spago } -> do
spago [ "init", "--name", "aaa", "--use-solver" ] >>= shouldBeSuccess
spago [ "build" ] >>= shouldBeSuccess
Spec.it "passes options to purs" \{ spago } -> do
spago [ "init" ] >>= shouldBeSuccess
spago [ "build", "--purs-args", "--verbose-errors", "--purs-args", "--json-errors" ] >>= shouldBeSuccess
Spec.it "can use a different output folder" \{ spago } -> do
spago [ "init" ] >>= shouldBeSuccess
spago [ "build", "--output", "myOutput" ] >>= shouldBeSuccess
FS.exists "myOutput" `Assert.shouldReturn` true
FS.exists "output" `Assert.shouldReturn` false
Spec.it "can build with a local custom package set" \{ spago, fixture } -> do
spago [ "init" ] >>= shouldBeSuccess
FS.unlink "spago.yaml"
FS.copyFileSync { src: fixture "local-package-set-config.yaml", dst: "spago.yaml" }
FS.copyFileSync { src: fixture "local-package-set.json", dst: "local-package-set.json" }
spago [ "build" ] >>= shouldBeSuccess
Spec.it "can build with a local custom package set in a parent directory" \{ spago, fixture } -> do
FS.copyFileSync { src: fixture "local-package-set.json", dst: "local-package-set.json" }
FS.mkdirp "subdir"
liftEffect $ Process.chdir "subdir"
spago [ "init" ] >>= shouldBeSuccess
FS.unlink "spago.yaml"
FS.copyFileSync { src: fixture "local-package-set-config2.yaml", dst: "spago.yaml" }
spago [ "build" ] >>= shouldBeSuccess
Spec.it "there's only one output folder in a monorepo" \{ spago } -> do
spago [ "init" ] >>= shouldBeSuccess
FS.mkdirp (Path.concat [ "subpackage", "src" ])
FS.mkdirp (Path.concat [ "subpackage", "test" ])
FS.writeTextFile (Path.concat [ "subpackage", "src", "Main.purs" ]) (Init.srcMainTemplate "Subpackage.Main")
FS.writeTextFile (Path.concat [ "subpackage", "test", "Main.purs" ]) (Init.testMainTemplate "Subpackage.Test.Main")
FS.writeYamlFile Config.configCodec (Path.concat [ "subpackage", "spago.yaml" ])
( Init.defaultConfig
{ name: mkPackageName "subpackage"
, testModuleName: "Subpackage.Test.Main"
, withWorkspace: Nothing
}
)
spago [ "build" ] >>= shouldBeSuccess
spago [ "build", "-p", "subpackage" ] >>= shouldBeSuccess
FS.exists "output" `Assert.shouldReturn` true
FS.exists (Path.concat [ "subpackage", "output" ]) `Assert.shouldReturn` false
Spec.it "--strict causes build to fail if there are warnings" \{ spago, fixture } -> do
spago [ "init" ] >>= shouldBeSuccess
let srcMain = Path.concat [ "src", "Main.purs" ]
FS.unlink srcMain
FS.copyFile
{ src: fixture "check-strict.purs"
, dst: srcMain
}
spago [ "build", "--strict" ] >>= shouldBeFailure
Spec.it "having 'strict: true' in a package config fails the build if there are warnings" \{ spago, fixture } -> do
spago [ "init" ] >>= shouldBeSuccess
let
srcMain = Path.concat [ "src", "Main.purs" ]
spagoYaml = "spago.yaml"
FS.unlink srcMain
FS.copyFile
{ src: fixture "check-strict.purs"
, dst: srcMain
}
FS.unlink spagoYaml
FS.copyFile
{ src: fixture "check-strict.yaml"
, dst: spagoYaml
}
spago [ "build" ] >>= shouldBeFailure
Spec.it "respects the --censor-stats flag" \{ spago, fixture } -> do
spago [ "init", "--name", "aaa" ] >>= shouldBeSuccess
spago [ "build" ] >>= shouldBeSuccess
spago [ "build", "--censor-stats" ] >>= shouldBeSuccessErr (fixture "censor-stats-output.txt")
Spec.it "should censor warnings with given errorcode and prefix messsage" \{ spago, fixture } -> do
FS.copyTree { src: fixture "build/censor-warnings", dst: "." }
let
remainingWarningPath = [ escapePathInErrMsg [ "src", "Main.purs:5:1" ] ]
filteredWarningPath =
[ escapePathInErrMsg [ "src", "Main.purs:3:1" ]
, escapePathInErrMsg [ "src", "Main.purs:10:6" ]
]
shouldHaveWarning = assertWarning remainingWarningPath true
shouldNotHaveWarning = assertWarning filteredWarningPath false
spago [ "build" ] >>= check
{ stdout: mempty
, stderr: fold <<< flap [ shouldHaveWarning, shouldNotHaveWarning ]
, result: isRight
}
Spec.describe "lockfile" do
Spec.it "building with a lockfile doesn't need the Registry repo" \{ spago, fixture } -> do
spago [ "init", "--name", "aaa", "--package-set", "33.0.0" ] >>= shouldBeSuccess
spago [ "build" ] >>= shouldBeSuccess
-- Check that we have written the lockfile
checkFixture "spago.lock" (fixture "spago.lock")
-- Then remove the registry repo
FSA.rm' Paths.registryPath { force: true, recursive: true, retryDelay: 0, maxRetries: 0 }
-- And check that we can still build
spago [ "build" ] >>= shouldBeSuccess
-- And that we still don't have the registry
FS.exists Paths.registryPath `Assert.shouldReturn` false
Spec.it "using the --pure flag does not refresh the lockfile" \{ spago, fixture } -> do
spago [ "init", "--name", "aaa", "--package-set", "33.0.0" ] >>= shouldBeSuccess
spago [ "build" ] >>= shouldBeSuccess
-- Check that we have written the lockfile
checkFixture "spago.lock" (fixture "spago.lock")
-- Update the config
let
conf = Init.defaultConfig
{ name: mkPackageName "aaa"
, testModuleName: "Test.Main"
, withWorkspace: Just { setVersion: Just $ mkVersion "33.0.0" }
}
FS.writeYamlFile Config.configCodec "spago.yaml"
(conf { package = conf.package # map (\pkg -> pkg { dependencies = pkg.dependencies <> mkDependencies [ "maybe" ] }) })
-- Check that building with --pure does not refresh the lockfile
spago [ "build", "--pure" ] >>= shouldBeSuccess
checkFixture "spago.lock" (fixture "spago.lock")
Spec.it "lockfile is refreshed when the local package set changes" \{ spago, fixture } -> do
FS.copyTree { src: fixture "build/local-package-set-lockfile", dst: "." }
spago [ "build" ] >>= shouldBeSuccess
checkFixture "spago.lock" (fixture "build/local-package-set-lockfile/spago.lock.old")
FS.moveSync { src: "local-package-set.json", dst: "old-package-set.json" }
FS.moveSync { src: "new-package-set.json", dst: "local-package-set.json" }
spago [ "build" ] >>= shouldBeSuccess
checkFixture "spago.lock" (fixture "build/local-package-set-lockfile/spago.lock.new")
Spec.it "compiles with the specified backend" \{ spago, fixture } -> do
spago [ "init" ] >>= shouldBeSuccess
let
conf = Init.defaultConfig
{ name: mkPackageName "subpackage"
, testModuleName: "Test.Main"
, withWorkspace: Just
{ setVersion: Just $ mkVersion "0.0.1"
}
}
FS.writeYamlFile Config.configCodec "spago.yaml"
(conf { workspace = conf.workspace # map (_ { backend = Just { cmd: "echo", args: Just [ "hello" ] } }) })
spago [ "build" ] >>= shouldBeSuccess
spago [ "run" ] >>= shouldBeSuccessErr (fixture "alternate-backend-output.txt")
-- We also make sure that no js files are produced, only corefn
FS.exists "output/Main/index.js" `Assert.shouldReturn` false
FS.exists "output/Main/corefn.json" `Assert.shouldReturn` true
Spec.it "passing the --codegen flag to purs fails" \{ spago, fixture } -> do
spago [ "init", "--name", "7368613235362d68766258694c614d517a3667747a58725778" ] >>= shouldBeSuccess
spago [ "build" ] >>= shouldBeSuccess
spago [ "build", "--purs-args", "--codegen", "--purs-args", "corefn" ] >>= shouldBeFailureErr (fixture "codegen-opt.txt")
Spec.it "passing the --ensure-ranges flag without package selection adds ranges to root package when it exists" \{ spago } -> do
spago [ "init", "--package-set", "0.0.1" ] >>= shouldBeSuccess
spago [ "build", "--ensure-ranges" ] >>= shouldBeSuccess
spagoYaml <- FS.readTextFile "spago.yaml"
spagoYaml `shouldContain` "- prelude: \">=6.0.1 <7.0.0\""
Spec.it "failed build with many warnings and --json-errors does not truncate output" \{ spago, fixture } -> do
FS.copyTree { src: fixture "build/json-truncated-many-warnings", dst: "." }
spago [ "build", "--json-errors" ] >>= shouldBeFailureOutput case Process.platform of
Just Platform.Win32 -> fixture "build/json-truncated-many-warnings/warnings-windows.json"
_ -> fixture "build/json-truncated-many-warnings/warnings.json"
Spec.it "building with old-format config files works, as well as migrating them" \{ spago, fixture } -> do
FS.copyTree { src: fixture "build/migrate-config", dst: "." }
spago [ "build" ] >>= shouldBeSuccess
spago [ "build" ] >>= shouldBeSuccessErr (fixture "build/migrate-config/unmigrated-warning.txt")
spago [ "build", "--migrate" ] >>= shouldBeSuccessErr (fixture "build/migrate-config/migrating-output.txt")
spago [ "build" ] >>= shouldBeSuccessErr (fixture "build/migrate-config/migrated-output.txt")
checkFixture "spago.yaml" (fixture "build/migrate-config/migrated-spago.yaml")
Spec.it "#1148: outputs errors and warnings after build" \{ spago, fixture } -> do
let
shouldBeSuccessErr' = checkOutputsWithPathSeparatorPatchErr isRight
shouldBeFailureErr' = checkOutputsWithPathSeparatorPatchErr isLeft
checkOutputsWithPathSeparatorPatchErr result expectedFixture =
checkOutputs'
{ stdoutFile: Nothing
, stderrFile: Just $ fixture expectedFixture
, result
, sanitize:
String.trim
>>> String.replaceAll (String.Pattern $ "src\\") (String.Replacement "src/")
>>> String.replaceAll (String.Pattern $ "\r\n") (String.Replacement "\n")
}
FS.copyTree { src: fixture "build/1148-warnings-diff-errors", dst: "." }
liftEffect $ Process.chdir "errors"
spago [ "install" ] >>= shouldBeSuccess
spago [ "build" ] >>= shouldBeFailureErr' "build/1148-warnings-diff-errors/errors/expected-stderr.txt"
liftEffect $ Process.chdir "../warnings"
spago [ "install" ] >>= shouldBeSuccess
spago [ "build" ] >>= shouldBeSuccessErr' "build/1148-warnings-diff-errors/warnings/expected-stderr.txt"
Pedantic.spec
Monorepo.spec
BuildInfo.spec
-- Spec.it "runs a --before command" \{ spago } -> do
-- spago [ "init" ] >>= shouldBeSuccess
-- let dumpFile = "testOutput"
-- spago [ "build", "--before", "echo before>> " <> dumpFile ] >>= shouldBeSuccess
-- test <- FS.readTextFile dumpFile
-- test `Assert.shouldEqual` "before"
-- Spec.it "runs a --then command" \{ spago } -> do
-- spago [ "init" ] >>= shouldBeSuccess
-- let dumpFile = "testOutput"
-- spago [ "build", "--then", "echo then>> " <> dumpFile, "--else", "echo else>> " <> dumpFile ] >>= shouldBeSuccess
-- test <- FS.readTextFile dumpFile
-- test `Assert.shouldEqual` "then"
-- Spec.it "runs a --before command before a --then command" \{ spago } -> do
-- spago [ "init" ] >>= shouldBeSuccess
-- let dumpFile = "testOutput"
-- spago [ "build", "--before", "echo before>> " <> dumpFile, "--then", "echo then>> " <> dumpFile ] >>= shouldBeSuccess
-- test <- FS.readTextFile dumpFile
-- test `Assert.shouldEqual` "before\nthen"
-- Spec.it "runs an --else command if there is an error in the build" \{ spago } -> do
-- spago [ "init" ] >>= shouldBeSuccess
-- let dumpFile = "testOutput"
-- FS.writeTextFile "src/Main.purs" "Invalid Purescript code"
-- spago [ "build", "--then", "echo then>> " <> dumpFile, "--else", "echo else>> " <> dumpFile ] >>= shouldBeFailure
-- test <- FS.readTextFile dumpFile
-- test `Assert.shouldEqual` "else"
-- Spec.it "runs an --else command if there is an error in the run file" \{ spago } -> do
-- spago [ "init" ] >>= shouldBeSuccess
-- spago [ "install", "exceptions" ] >>= shouldBeSuccess
-- let dumpFile = "testOutput"
-- FS.writeTextFile "src/Main.purs" "module Main where\nimport Effect.Exception\nmain = throw \"error\""
-- spago [ "run", "--else", "echo else>> " <> dumpFile ] >>= shouldBeFailure
-- test <- FS.readTextFile dumpFile
-- test `Assert.shouldEqual` "else"
-- Spec.it "runs multiple commands in order" \{ spago } -> do
-- spago [ "init" ] >>= shouldBeSuccess
-- let dumpFile = "testOutput"
-- spago [ "build", "--before", "echo before1>> " <> dumpFile, "--before", "echo before2>> " <> dumpFile, "--then", "echo then1>> " <> dumpFile, "--then", "echo then2>> " <> dumpFile ] >>= shouldBeSuccess
-- test <- FS.readTextFile dumpFile
-- test `Assert.shouldEqual` "before1\nbefore2\nthen1\nthen2"
-- Spec.it "fails the build if a --before command fails" \{ spago } -> do
-- spago [ "init" ] >>= shouldBeSuccess
-- spago [ "build", "--before", "exit 1" ] >>= shouldBeFailure
-- Spec.it "fails the build if a --then command fails" \{ spago } -> do
-- spago [ "init" ] >>= shouldBeSuccess
-- spago [ "build", "--then", "exit 1" ] >>= shouldBeFailure
-- Spec.it "still fails the build if an --else command fails" \{ spago } -> do
-- spago [ "init" ] >>= shouldBeSuccess
-- FS.writeTextFile "src/Main.purs" "Invalid Purescript code"
-- spago [ "build", "--else", "exit 1" ] >>= shouldBeFailure