forked from commercialhaskell/stack
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrelease.hs
More file actions
executable file
·576 lines (515 loc) · 23.4 KB
/
release.hs
File metadata and controls
executable file
·576 lines (515 loc) · 23.4 KB
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
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
#!/usr/bin/env stack
-- stack --install-ghc runghc --package=shake --package=extra --package=zip-archive --package=mime-types --package=http-types --package=http-conduit --package=text --package=conduit-combinators --package=conduit --package=case-insensitive --package=aeson --package=zlib --package tar
{-# OPTIONS_GHC -Wall -Werror #-}
{-# LANGUAGE RecordWildCards #-}
import Control.Applicative
import Control.Exception
import Control.Monad
import Control.Monad.Trans.Resource (runResourceT)
import qualified Data.ByteString.Char8 as S8
import qualified Data.ByteString.Lazy.Char8 as L8
import Data.List
import Data.Maybe
import Distribution.PackageDescription.Parse
import Distribution.Text
import Distribution.System
import Distribution.Package
import Distribution.PackageDescription hiding (options)
import Distribution.Verbosity
import System.Console.GetOpt
import System.Environment
import System.Directory
import System.IO.Error
import System.Process
import qualified Codec.Archive.Tar as Tar
import qualified Codec.Archive.Zip as Zip
import qualified Codec.Compression.GZip as GZip
import Data.Aeson
import qualified Data.CaseInsensitive as CI
import Data.Conduit
import qualified Data.Conduit.Combinators as CC
import Data.List.Extra
import qualified Data.Text as T
import Development.Shake
import Development.Shake.FilePath
import Network.HTTP.Conduit
import Network.HTTP.Types
import Network.Mime
import Prelude -- Silence AMP warning
-- | Entrypoint.
main :: IO ()
main =
shakeArgsWith
shakeOptions { shakeFiles = releaseDir
, shakeVerbosity = Chatty
, shakeChange = ChangeModtimeAndDigestInput }
options $
\flags args -> do
gStackPackageDescription <-
packageDescription <$> readPackageDescription silent "stack.cabal"
gGithubAuthToken <- lookupEnv githubAuthTokenEnvVar
gGitRevCount <- length . lines <$> readProcess "git" ["rev-list", "HEAD"] ""
gGitSha <- trim <$> readProcess "git" ["rev-parse", "HEAD"] ""
gHomeDir <- getHomeDirectory
let -- @gScriptPath@ was retrived using the @executable-path@ package, but it
-- has trouble with GHC 7.10.2 on OS X
gScriptPath = "scripts/release/release.hs"
gGpgKey = "9BEFB442"
gAllowDirty = False
gGithubReleaseTag = Nothing
Platform arch _ = buildPlatform
gArch = arch
gBinarySuffix = ""
gLocalInstallRoot = "" -- Set to real value below.
gProjectRoot = "" -- Set to real value velow.
global0 = foldl (flip id) Global{..} flags
-- Need to get paths after options since the '--arch' argument can effect them.
localInstallRoot' <- getStackPath global0 "local-install-root"
projectRoot' <- getStackPath global0 "project-root"
let global = global0
{ gLocalInstallRoot = localInstallRoot'
, gProjectRoot = projectRoot' }
return $ Just $ rules global args
where
getStackPath global path = do
out <- readProcess stackProgName (stackArgs global ++ ["path", "--" ++ path]) ""
return $ trim $ fromMaybe out $ stripPrefix (path ++ ":") out
-- | Additional command-line options.
options :: [OptDescr (Either String (Global -> Global))]
options =
[ Option "" [gpgKeyOptName]
(ReqArg (\v -> Right $ \g -> g{gGpgKey = v}) "USER-ID")
"GPG user ID to sign distribution package with."
, Option "" [allowDirtyOptName] (NoArg $ Right $ \g -> g{gAllowDirty = True})
"Allow a dirty working tree for release."
, Option "" [githubAuthTokenOptName]
(ReqArg (\v -> Right $ \g -> g{gGithubAuthToken = Just v}) "TOKEN")
("Github personal access token (defaults to " ++
githubAuthTokenEnvVar ++
" environment variable).")
, Option "" [githubReleaseTagOptName]
(ReqArg (\v -> Right $ \g -> g{gGithubReleaseTag = Just v}) "TAG")
"Github release tag to upload to."
, Option "" [archOptName]
(ReqArg
(\v -> case simpleParse v of
Nothing -> Left $ "Unknown architecture in --arch option: " ++ v
Just arch -> Right $ \g -> g{gArch = arch})
"ARCHITECTURE")
"Architecture to build (e.g. 'i386' or 'x86_64')."
, Option "" [binaryVariantOptName]
(ReqArg (\v -> Right $ \g -> g{gBinarySuffix = v}) "SUFFIX")
"Extra suffix to add to binary executable archive filename." ]
-- | Shake rules.
rules :: Global -> [String] -> Rules ()
rules global@Global{..} args = do
case args of
[] -> error "No wanted target(s) specified."
_ -> want args
phony releasePhony $ do
need [checkPhony]
need [uploadPhony]
phony cleanPhony $
removeFilesAfter releaseDir ["//*"]
phony checkPhony $
need [releaseCheckDir </> binaryExeFileName]
phony uploadPhony $
mapM_ (\f -> need [releaseDir </> f <.> uploadExt]) binaryFileNames
phony buildPhony $
mapM_ (\f -> need [releaseDir </> f]) binaryFileNames
forM_ distros $ \distro -> do
phony (distroUploadPhony distro) $
mapM_
(\v -> need [distroVersionDir (DistroVersion distro (fst v)) </> distroPackageFileName distro <.> uploadExt])
(distroVersions distro)
phony (distroPackagesPhony distro) $
mapM_
(\v -> need [distroVersionDir (DistroVersion distro (fst v)) </> distroPackageFileName distro])
(distroVersions distro)
releaseDir </> "*" <.> uploadExt %> \out -> do
need [dropExtension out]
uploadToGithubRelease global (dropExtension out)
copyFile' (dropExtension out) out
releaseCheckDir </> binaryExeFileName %> \out -> do
need [installBinDir </> stackOrigExeFileName]
Stdout dirty <- cmd "git status --porcelain"
when (not gAllowDirty && not (null (trim dirty))) $
error ("Working tree is dirty. Use --" ++ allowDirtyOptName ++ " option to continue anyway.")
let instExeFile = installBinDir </> stackOrigExeFileName
tmpExeFile = installBinDir </> stackOrigExeFileName <.> "tmp"
--EKB FIXME: once 'stack install --path' implemented, use it instead of this temp file.
liftIO $ renameFile instExeFile tmpExeFile
actionFinally
(do opt <- addPath [installBinDir] []
() <- cmd opt stackProgName (stackArgs global) "build --pedantic --haddock --no-haddock-deps"
() <- cmd opt stackProgName (stackArgs global) "clean"
() <- cmd opt stackProgName (stackArgs global) "build"
() <- cmd opt stackProgName (stackArgs global) "test --flag stack:integration-tests"
return ())
(renameFile tmpExeFile instExeFile)
copyFileChanged (installBinDir </> stackOrigExeFileName) out
releaseDir </> binaryExeZipFileName %> \out -> do
need [releaseDir </> binaryExeFileName]
putNormal $ "zip " ++ (releaseDir </> binaryExeFileName)
liftIO $ do
entry <- Zip.readEntry [] (releaseDir </> binaryExeFileName)
let entry' = entry{Zip.eRelativePath = binaryExeFileName}
archive = Zip.addEntryToArchive entry' Zip.emptyArchive
L8.writeFile out (Zip.fromArchive archive)
releaseDir </> binaryExeTarGzFileName %> \out -> do
need [releaseDir </> binaryExeFileName]
putNormal $ "tar gzip " ++ (releaseDir </> binaryExeFileName)
liftIO $ do
content <- Tar.pack releaseDir [binaryExeFileName]
L8.writeFile out $ GZip.compress $ Tar.write content
releaseDir </> binaryExeFileName %> \out -> do
need [installBinDir </> stackOrigExeFileName]
case platformOS of
Windows ->
-- Windows doesn't have or need a 'strip' command, so skip it.
liftIO $ copyFile (installBinDir </> stackOrigExeFileName) out
Linux ->
cmd "strip -p --strip-unneeded --remove-section=.comment -o"
[out, installBinDir </> stackOrigExeFileName]
_ ->
cmd "strip -o"
[out, installBinDir </> stackOrigExeFileName]
releaseDir </> binaryExeCompressedAscFileName %> \out -> do
need [out -<.> ""]
_ <- liftIO $ tryJust (guard . isDoesNotExistError) (removeFile out)
cmd "gpg --detach-sig --armor"
[ "-u", gGpgKey
, dropExtension out ]
installBinDir </> stackOrigExeFileName %> \_ -> do
alwaysRerun
cmd stackProgName (stackArgs global) "build"
forM_ distros $ \distro0 -> do
distroVersionDir (anyDistroVersion' distro0) </> distroPackageFileName distro0 <.> uploadExt %> \out -> do
let dv@DistroVersion{..} = distroVersionFromPath out
need [dropExtension out]
uploadPackage dvDistro dv (dropExtension out)
copyFileChanged (dropExtension out) out
distroVersionDir (anyDistroVersion' distro0) </> distroPackageFileName distro0 %> \out -> do
alwaysRerun
let dv@DistroVersion{..} = distroVersionFromPath out
need [distroVersionDir dv </> imageIDFileName]
liftIO $ createDirectoryIfMissing True (takeDirectory out)
cmd "docker run --rm"
[ "--volume=" ++ gProjectRoot </> distroVersionDir dv </> "stack-root" ++
":/mnt/stack-root"
, "--env=STACK_ROOT=/mnt/stack-root"
, "--volume=" ++ gProjectRoot </> distroVersionDir dv </> "stack-work" ++
":/mnt/src/.stack-work"
, "--volume=" ++ gProjectRoot ++ ":/mnt/src"
, "--workdir=/mnt/src"
, "--volume=" ++ gProjectRoot </> distroVersionDir dv ++ ":/mnt/out"
, "--env=OUTPUT_PKG=/mnt/out/" ++ distroPackageFileName dvDistro
, "--env=PKG_VERSION=" ++ distroPackageVersionStr dvDistro
, "--env=PKG_MAINTAINER=" ++ maintainer gStackPackageDescription
, "--env=PKG_DESCRIPTION=" ++ synopsis gStackPackageDescription
, "--env=PKG_LICENSE=" ++ display (license gStackPackageDescription)
, "--env=PKG_URL=" ++ homepage gStackPackageDescription
, distroVersionDockerImageTag dv ]
distroVersionDir anyDistroVersion </> imageIDFileName %> \out -> do
alwaysRerun
let dv@DistroVersion{..} = distroVersionFromPath out
imageTag = distroVersionDockerImageTag dv
need
[ distroVersionDockerDir dv </> "Dockerfile"
, distroVersionDockerDir dv </> "run.sh" ]
_ <- buildDockerImage (distroVersionDockerDir dv) imageTag out
return ()
distroVersionDockerDir anyDistroVersion </> "Dockerfile" %> \out -> do
let DistroVersion{..} = distroVersionFromPath out
template <- readTemplate (distroTemplateDir dvDistro </> "docker/Dockerfile")
writeFileChanged out $
replace "<<DISTRO-VERSION>>" dvVersion $
replace "<<DISTRO>>" dvDistro template
distroVersionDockerDir anyDistroVersion </> "run.sh" %> \out -> do
let DistroVersion{..} = distroVersionFromPath out
writeFileChanged out =<< readTemplate (distroTemplateDir dvDistro </> "docker/run.sh")
where
distroVersionFromPath path =
case stripPrefix (releaseDir ++ "/") path of
Nothing -> error ("Cannot determine Ubuntu version from path: " ++ path)
Just path' -> DistroVersion (takeDirectory1 path') (takeDirectory1 (dropDirectory1 path'))
readTemplate path =
readFile' (takeDirectory gScriptPath </> "templates" </> path)
releasePhony = "release"
checkPhony = "check"
uploadPhony = "upload"
cleanPhony = "clean"
buildPhony = "build"
distroPackagesPhony distro = distro ++ "-packages"
distroUploadPhony distro = distro ++ "-upload"
releaseCheckDir = releaseDir </> "check"
installBinDir = gLocalInstallRoot </> "bin"
distroVersionDockerDir dv = distroVersionDir dv </> "docker"
distroVersionDir DistroVersion{..} = releaseDir </> dvDistro </> dvVersion
binaryFileNames = [binaryExeCompressedFileName, binaryExeCompressedAscFileName]
binaryExeCompressedAscFileName = binaryExeCompressedFileName <.> ascExt
binaryExeCompressedFileName =
case platformOS of
Windows -> binaryExeZipFileName
_ -> binaryExeTarGzFileName
binaryExeZipFileName = binaryName global <.> zipExt
binaryExeTarGzFileName = binaryName global <.> tarGzExt
binaryExeFileName = stackOrigExeFileName
stackOrigExeFileName = stackProgName <.> exe
distroPackageFileName distro
| distroPackageExt distro == debExt =
concat [stackProgName, "_", distroPackageVersionStr distro, "_amd64"] <.> debExt
| distroPackageExt distro == rpmExt =
concat [stackProgName, "-", distroPackageVersionStr distro] <.> "x86_64" <.> rpmExt
| distro == archDistro =
concat [stackProgName, "_", distroPackageVersionStr distro, "-", "x86_64"] <.> tarGzExt
| otherwise = error ("distroPackageFileName: unknown distro: " ++ distro)
imageIDFileName = "image-id"
zipExt = "zip"
tarGzExt = tarExt <.> gzExt
gzExt = "gz"
tarExt = "tar"
ascExt = "asc"
uploadExt = "upload"
debExt = "deb"
rpmExt = "rpm"
distroVersionDockerImageTag DistroVersion{..} =
"stack_release_tool/" ++ dvDistro ++ ":" ++ dvVersion
distroPackageVersionStr distro
| distroPackageExt distro == debExt =
concat [stackVersionStr global, "-", show gGitRevCount, "-", gGitSha]
| distroPackageExt distro == rpmExt =
concat [stackVersionStr global, "_", show gGitRevCount, "_", gGitSha]
| distro == archDistro =
stackVersionStr global
| otherwise = error ("distroPackageVersionStr: unknown distro: " ++ distro)
distroTemplateDir distro
| distroPackageExt distro `elem` [debExt, rpmExt] = distroPackageExt distro
| distro == archDistro = "arch"
| otherwise = error ("distroTemplateDir: unknown distro: " ++ distro)
distroPackageExt distro
| distro `elem` [ubuntuDistro, debianDistro] = debExt
| distro `elem` [centosDistro, fedoraDistro] = rpmExt
| distro == archDistro = tarGzExt
| otherwise = error ("distroPackageExt: unknown distro: " ++ distro)
distroVersions distro
| distro == ubuntuDistro =
[ ("12.04", "precise")
, ("14.04", "trusty")
, ("14.10", "utopic")
, ("15.04", "vivid") ]
| distro == debianDistro =
[ ("7", "wheezy")
, ("8", "jessie") ]
| distro == centosDistro =
[ ("7", "7")
, ("6", "6") ]
| distro == fedoraDistro =
[ ("21", "21")
, ("22", "22") ]
| distro == archDistro =
[ ("current", "current") ]
| otherwise = error ("distroVersions: unknown distro: " ++ distro)
distroVersionCodeName DistroVersion{..} =
fromMaybe
("distroVersionCodeName: unknown " ++ dvDistro ++ " version: " ++ dvVersion)
(lookup dvVersion (distroVersions dvDistro))
distros =
[ ubuntuDistro
, debianDistro
, centosDistro
, fedoraDistro
, archDistro ]
ubuntuDistro = "ubuntu"
debianDistro = "debian"
centosDistro = "centos"
fedoraDistro = "fedora"
archDistro = "arch"
anyDistroVersion = DistroVersion "*" "*"
anyDistroVersion' distro = DistroVersion distro "*"
uploadPackage :: String -> DistroVersion -> FilePath -> Action ()
uploadPackage distro dv@DistroVersion{..} pkgFile
| distroPackageExt distro == debExt =
cmd "deb-s3 upload -b download.fpcomplete.com --preserve-versions"
[ "--sign=" ++ gGpgKey
, "--prefix=" ++ dvDistro ++ "/" ++ distroVersionCodeName dv
, pkgFile ]
| distroPackageExt distro == rpmExt = do
let rpmmacrosFile = gHomeDir </> ".rpmmacros"
rpmmacrosExists <- liftIO $ System.Directory.doesFileExist rpmmacrosFile
when rpmmacrosExists $
error ("'" ++ rpmmacrosFile ++ "' already exists. Move it out of the way first.")
actionFinally
(do writeFileLines rpmmacrosFile
[ "%_signature gpg"
, "%_gpg_name " ++ gGpgKey ]
cmd "rpm-s3 --verbose --sign --bucket=download.fpcomplete.com"
[ "--repopath=" ++ dvDistro ++ "/" ++ dvVersion
, pkgFile ])
(liftIO $ removeFile rpmmacrosFile)
| distro == archDistro = do
() <- cmd "aws s3 cp"
[ pkgFile
, "s3://download.fpcomplete.com/archlinux/" ++ takeFileName pkgFile ]
putNormal "WARNING: Arch package uploaded, but applying the AUR patch is a manual step."
| otherwise = error ("uploadPackage: unknown distro: " ++ distro)
-- | Upload file to Github release.
uploadToGithubRelease :: Global -> FilePath -> Action ()
uploadToGithubRelease global@Global{..} file = do
putNormal $ "Uploading to Github: " ++ file
GithubRelease{..} <- getGithubRelease
resp <- liftIO $ callGithubApi global
[(CI.mk $ S8.pack "Content-Type", defaultMimeLookup (T.pack file))]
(Just file)
(replace
"{?name}"
("?name=" ++ S8.unpack (urlEncode True (S8.pack (takeFileName file))))
relUploadUrl)
case eitherDecode resp of
Left e -> error ("Could not parse Github asset upload response (" ++ e ++ "):\n" ++ L8.unpack resp ++ "\n")
Right (GithubReleaseAsset{..}) ->
when (assetState /= "uploaded") $
error ("Invalid asset state after Github asset upload: " ++ assetState)
where
getGithubRelease = do
releases <- getGithubReleases
let tag = fromMaybe ("v" ++ stackVersionStr global) gGithubReleaseTag
return $ fromMaybe
(error ("Could not find Github release with tag '" ++ tag ++ "'.\n" ++
"Use --" ++ githubReleaseTagOptName ++ " option to specify a different tag."))
(find (\r -> relTagName r == tag) releases)
getGithubReleases :: Action [GithubRelease]
getGithubReleases = do
resp <- liftIO $ callGithubApi global
[] Nothing "https://api.github.com/repos/commercialhaskell/stack/releases"
case eitherDecode resp of
Left e -> error ("Could not parse Github releases (" ++ e ++ "):\n" ++ L8.unpack resp ++ "\n")
Right r -> return r
-- | Make a request to the Github API and return the response.
callGithubApi :: Global -> RequestHeaders -> Maybe FilePath -> String -> IO L8.ByteString
callGithubApi Global{..} headers mpostFile url = do
req0 <- parseUrl url
let authToken =
fromMaybe
(error $
"Github auth token required.\n" ++
"Use " ++ githubAuthTokenEnvVar ++ " environment variable\n" ++
"or --" ++ githubAuthTokenOptName ++ " option to specify.")
gGithubAuthToken
req1 =
req0
{ checkStatus = \_ _ _ -> Nothing
, requestHeaders =
[ (CI.mk $ S8.pack "Authorization", S8.pack $ "token " ++ authToken)
, (CI.mk $ S8.pack "User-Agent", S8.pack "commercialhaskell/stack") ] ++
headers }
req <- case mpostFile of
Nothing -> return req1
Just postFile -> do
lbs <- L8.readFile postFile
return $ req1
{ method = S8.pack "POST"
, requestBody = RequestBodyLBS lbs }
manager <- newManager tlsManagerSettings
runResourceT $ do
res <- http req manager
responseBody res $$+- CC.sinkLazy
-- | Build a Docker image and write its ID to a file if changed.
buildDockerImage :: FilePath -> String -> FilePath -> Action String
buildDockerImage buildDir imageTag out = do
alwaysRerun
() <- cmd "docker build" ["--tag=" ++ imageTag, buildDir]
(Stdout imageIdOut) <- cmd "docker inspect --format={{.Id}}" [imageTag]
writeFileChanged out imageIdOut
return (trim imageIdOut)
-- | Name of the release binary (e.g. @stack-x.y.x-arch-os@)
binaryName :: Global -> String
binaryName global@Global{..} =
concat
[ stackProgName
, "-"
, stackVersionStr global
, "-"
, platformName global
, if null gBinarySuffix then "" else "-" ++ gBinarySuffix ]
-- | String representation of stack package version.
stackVersionStr :: Global -> String
stackVersionStr =
display . pkgVersion . package . gStackPackageDescription
-- | Name of current platform.
platformName :: Global -> String
platformName Global{..} =
display (Platform gArch platformOS)
-- | Current operating system.
platformOS :: OS
platformOS =
let Platform _ os = buildPlatform
in os
-- | Directory in which to store build and intermediate files.
releaseDir :: FilePath
releaseDir = "_release"
-- | @GITHUB_AUTH_TOKEN@ environment variale name.
githubAuthTokenEnvVar :: String
githubAuthTokenEnvVar = "GITHUB_AUTH_TOKEN"
-- | @--github-auth-token@ command-line option name.
githubAuthTokenOptName :: String
githubAuthTokenOptName = "github-auth-token"
-- | @--github-release-tag@ command-line option name.
githubReleaseTagOptName :: String
githubReleaseTagOptName = "github-release-tag"
-- | @--gpg-key@ command-line option name.
gpgKeyOptName :: String
gpgKeyOptName = "gpg-key"
-- | @--allow-dirty@ command-line option name.
allowDirtyOptName :: String
allowDirtyOptName = "allow-dirty"
-- | @--arch@ command-line option name.
archOptName :: String
archOptName = "arch"
-- | @--binary-variant@ command-line option name.
binaryVariantOptName :: String
binaryVariantOptName = "binary-variant"
-- | Arguments to pass to all 'stack' invocations.
stackArgs :: Global -> [String]
stackArgs Global{..} = ["--arch=" ++ display gArch]
-- | Name of the 'stack' program.
stackProgName :: FilePath
stackProgName = "stack"
-- | Linux distribution/version combination.
data DistroVersion = DistroVersion
{ dvDistro :: !String
, dvVersion :: !String }
-- | A Github release, as returned by the Github API.
data GithubRelease = GithubRelease
{ relUploadUrl :: !String
, relTagName :: !String }
deriving (Show)
instance FromJSON GithubRelease where
parseJSON = withObject "GithubRelease" $ \o ->
GithubRelease
<$> o .: T.pack "upload_url"
<*> o .: T.pack "tag_name"
-- | A Github release asset, as returned by the Github API.
data GithubReleaseAsset = GithubReleaseAsset
{ assetState :: !String }
deriving (Show)
instance FromJSON GithubReleaseAsset where
parseJSON = withObject "GithubReleaseAsset" $ \o ->
GithubReleaseAsset
<$> o .: T.pack "state"
-- | Global values and options.
data Global = Global
{ gStackPackageDescription :: !PackageDescription
, gLocalInstallRoot :: !FilePath
, gGpgKey :: !String
, gAllowDirty :: !Bool
, gGithubAuthToken :: !(Maybe String)
, gGithubReleaseTag :: !(Maybe String)
, gGitRevCount :: !Int
, gGitSha :: !String
, gProjectRoot :: !FilePath
, gHomeDir :: !FilePath
, gScriptPath :: !FilePath
, gArch :: !Arch
, gBinarySuffix :: !String }
deriving (Show)