on master help sign in
Merge branch 'incremental' into new-upload
51f3aa1Michael Snoyman
.dir-locals.elnew file+3
@@ -0,0 +1,3 @@
1+((haskell-mode . ((haskell-process-type . cabal-repl)
2+ (haskell-indent-spaces . 4)
3+ (hindent-style . "johan-tibell"))))
.dockerignorenew file+8
@@ -0,0 +1,8 @@
1+dist
2+builds
3+logs
4+.cabal-sandbox
5+cabal.sandbox.config
6+tarballs
7+*.yaml
8+.git
.travis.ymlnew file+24
@@ -0,0 +1,24 @@
1+env:
2+ - CABALVER=1.20 GHCVER=7.8.4
3+
4+cache:
5+ directories:
6+ - $HOME/.ghc
7+ - $HOME/.cabal
8+
9+# Note: the distinction between `before_install` and `install` is not important.
10+before_install:
11+ - travis_retry sudo add-apt-repository -y ppa:hvr/ghc
12+ - travis_retry sudo apt-get update
13+ - travis_retry sudo apt-get install cabal-install-$CABALVER ghc-$GHCVER # see note about happy/alex
14+ - export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$PATH
15+
16+install:
17+ - cabal --version
18+ - echo "$(ghc --version) [$(ghc --print-project-git-commit-id 2> /dev/null || echo '?')]"
19+ - travis_retry cabal update
20+ - cabal install -j
21+
22+# Here starts the actual work to be performed for the package under test; any command which exits with a non-zero exit code causes the build to fail.
23+script:
24+ - ./dist/build/stackage/stackage check
ChangeLog.md+22−1
@@ -1,7 +1,28 @@
1−## 0.4.0
1+## Unreleased
2
2
3* Upload bundle V2 stuff
3* Upload bundle V2 stuff
4
4
5+## 0.5.2
6+
7+* Upload LTS to Hackage with the name LTSHaskell
8+
9+## 0.5.1
10+
11+* `loadBuildConstraints`
12+* More command line options
13+
14+## 0.5.0
15+
16+* Print "Still Alive" while checking, to avoid Travis timeouts
17+* Include `stackage upload-nightly` command
18+* Optional plan checking
19+
20+## 0.4.0
21+
22+* Command line uses optparse-applicative with additional options
23+* Library profiling support during build
24+* Remove cfGlobalFlags (just use package-specific flags)
25+
5## 0.3.1
26## 0.3.1
6
27
7* Added `justCheck` and `stackage check` command line.
28* Added `justCheck` and `stackage check` command line.
Dockerfilenew file+25
@@ -0,0 +1,25 @@
1+FROM ubuntu:12.04
2+
3+ENV HOME /home/stackage
4+ENV LANG en_US.UTF-8
5+
6+RUN mkdir /home/stackage -p
7+RUN locale-gen en_US.UTF-8
8+
9+RUN DEBIAN_FRONTEND=noninteractive apt-get update
10+RUN DEBIAN_FRONTEND=noninteractive apt-get install -y software-properties-common python-software-properties
11+RUN DEBIAN_FRONTEND=noninteractive add-apt-repository ppa:hvr/ghc -y
12+
13+ADD debian-bootstrap.sh /tmp/debian-bootstrap.sh
14+RUN DEBIAN_FRONTEND=noninteractive bash /tmp/debian-bootstrap.sh
15+RUN rm /tmp/debian-bootstrap.sh
16+
17+RUN DEBIAN_FRONTEND=noninteractive apt-get install -y cabal-install-1.20 ghc-7.8.4 alex-3.1.3 happy-1.19.4
18+
19+ENV PATH /home/stackage/.cabal/bin:/usr/local/sbin:/usr/local/bin:/opt/ghc/7.8.4/bin:/opt/cabal/1.20/bin:/opt/alex/3.1.3/bin:/opt/happy/1.19.4/bin:/usr/sbin:/usr/bin:/sbin:/bin
20+
21+RUN cabal update
22+ADD . /tmp/stackage
23+RUN cd /tmp/stackage && cabal install . hscolour cabal-install --constraint "Cabal < 1.22" && cp $HOME/.cabal/bin/* /usr/local/bin && rm -rf $HOME/.cabal $HOME/.ghc /tmp/stackage
24+
25+RUN cd /home/stackage && cabal update && stackage check
README.md+22
@@ -49,6 +49,28 @@ build by running:
49 cabal install stackage
49 cabal install stackage
50 stackage nightly
50 stackage nightly
51
51
52+### Docker
53+
54+Note: This method is currently considered experimental.
55+
56+If you'd like to check a build plan, or perform an entire build, without
57+specially configuring your system, Docker may be a good approach. To check if
58+some modifications to `build-constraints.yaml` are valid, try the following:
59+
60+1. Create a local clone of the `stackage` repo
61+2. Make modifications to your local `build-constraints.yaml`
62+3. Inside the `stackage` working directory, run the following:
63+
64+ ```
65+ $ docker run -it --rm -v $(pwd):/stackage -w /stackage snoyberg/stackage /bin/bash -c 'cabal update && stackage check'
66+ ```
67+
68+Similarly, if you'd like to perform an entire build, you can replace the last step with:
69+
70+```
71+$ docker run -it --rm -v $(pwd):/stackage -w /stackage snoyberg/stackage /bin/bash -c 'cabal update && stackage nightly --skip-upload'
72+```
73+
52## Processing
74## Processing
53
75
54The following describes at a high level the series of steps for processing
76The following describes at a high level the series of steps for processing
Stackage/BuildConstraints.hs+43−20
@@ -10,6 +10,9 @@ module Stackage.BuildConstraints
10 , SystemInfo (..)
10 , SystemInfo (..)
11 , getSystemInfo
11 , getSystemInfo
12 , defaultBuildConstraints
12 , defaultBuildConstraints
13+ , toBC
14+ , BuildConstraintsSource (..)
15+ , loadBuildConstraints
13 ) where
16 ) where
14
17
15import Control.Monad.Writer.Strict (execWriter, tell)
18import Control.Monad.Writer.Strict (execWriter, tell)
@@ -21,7 +24,7 @@ import Distribution.System (Arch, OS)
21import qualified Distribution.System
24import qualified Distribution.System
22import Distribution.Version (anyVersion)
25import Distribution.Version (anyVersion)
23import Filesystem (isFile)
26import Filesystem (isFile)
24−import Network.HTTP.Client (Manager, httpLbs, responseBody)
27+import Network.HTTP.Client (Manager, httpLbs, responseBody, Request)
25import Stackage.CorePackages
28import Stackage.CorePackages
26import Stackage.Prelude
29import Stackage.Prelude
27
30
@@ -88,12 +91,13 @@ data BuildConstraints = BuildConstraints
88 }
91 }
89
92
90data PackageConstraints = PackageConstraints
93data PackageConstraints = PackageConstraints
91− { pcVersionRange :: VersionRange
94+ { pcVersionRange :: VersionRange
92− , pcMaintainer :: Maybe Maintainer
95+ , pcMaintainer :: Maybe Maintainer
93− , pcTests :: TestState
96+ , pcTests :: TestState
94− , pcHaddocks :: TestState
97+ , pcHaddocks :: TestState
95− , pcBuildBenchmarks :: Bool
98+ , pcBuildBenchmarks :: Bool
96− , pcFlagOverrides :: Map FlagName Bool
99+ , pcFlagOverrides :: Map FlagName Bool
100+ , pcEnableLibProfile :: Bool
97 }
101 }
98 deriving (Show, Eq)
102 deriving (Show, Eq)
99instance ToJSON PackageConstraints where
103instance ToJSON PackageConstraints where
@@ -103,6 +107,7 @@ instance ToJSON PackageConstraints where
103 , "haddocks" .= pcHaddocks
107 , "haddocks" .= pcHaddocks
104 , "build-benchmarks" .= pcBuildBenchmarks
108 , "build-benchmarks" .= pcBuildBenchmarks
105 , "flags" .= Map.mapKeysWith const unFlagName pcFlagOverrides
109 , "flags" .= Map.mapKeysWith const unFlagName pcFlagOverrides
110+ , "library-profiling" .= pcEnableLibProfile
106 ]
111 ]
107 where
112 where
108 addMaintainer = maybe id (\m -> (("maintainer" .= m):)) pcMaintainer
113 addMaintainer = maybe id (\m -> (("maintainer" .= m):)) pcMaintainer
@@ -115,6 +120,7 @@ instance FromJSON PackageConstraints where
115 pcBuildBenchmarks <- o .: "build-benchmarks"
120 pcBuildBenchmarks <- o .: "build-benchmarks"
116 pcFlagOverrides <- Map.mapKeysWith const mkFlagName <$> o .: "flags"
121 pcFlagOverrides <- Map.mapKeysWith const mkFlagName <$> o .: "flags"
117 pcMaintainer <- o .:? "maintainer"
122 pcMaintainer <- o .:? "maintainer"
123+ pcEnableLibProfile <- fmap (fromMaybe True) (o .:? "library-profiling")
118 return PackageConstraints {..}
124 return PackageConstraints {..}
119
125
120-- | The proposed plan from the requirements provided by contributors.
126-- | The proposed plan from the requirements provided by contributors.
@@ -122,15 +128,32 @@ instance FromJSON PackageConstraints where
122-- Checks the current directory for a build-constraints.yaml file and uses it
128-- Checks the current directory for a build-constraints.yaml file and uses it
123-- if present. If not, downloads from Github.
129-- if present. If not, downloads from Github.
124defaultBuildConstraints :: Manager -> IO BuildConstraints
130defaultBuildConstraints :: Manager -> IO BuildConstraints
125−defaultBuildConstraints man = do
131+defaultBuildConstraints = loadBuildConstraints BCSDefault
132+
133+data BuildConstraintsSource
134+ = BCSDefault
135+ | BCSFile FilePath
136+ | BCSWeb Request
137+ deriving (Show)
138+
139+loadBuildConstraints :: BuildConstraintsSource -> Manager -> IO BuildConstraints
140+loadBuildConstraints bcs man = do
141+ case bcs of
142+ BCSDefault -> do
126− e <- isFile fp
143+ e <- isFile fp0
127− if e
144+ if e
128− then decodeFileEither (fpToString fp) >>= either throwIO toBC
145+ then loadFile fp0
129− else httpLbs req man >>=
146+ else loadReq req0
130− either throwIO toBC . decodeEither' . toStrict . responseBody
147+ BCSFile fp -> loadFile fp
148+ BCSWeb req -> loadReq req
131 where
149 where
132− fp = "build-constraints.yaml"
150+ fp0 = "build-constraints.yaml"
133− req = "https://raw.githubusercontent.com/fpco/stackage/master/build-constraints.yaml"
151+ req0 = "https://raw.githubusercontent.com/fpco/stackage/master/build-constraints.yaml"
152+
153+ loadFile fp = decodeFileEither (fpToString fp) >>= either throwIO toBC
154+ loadReq req = httpLbs req man >>=
155+ either throwIO toBC . decodeEither' . toStrict . responseBody
156+
134
157
135getSystemInfo :: IO SystemInfo
158getSystemInfo :: IO SystemInfo
136getSystemInfo = do
159getSystemInfo = do
@@ -144,24 +167,24 @@ getSystemInfo = do
144 siArch = Distribution.System.X86_64
167 siArch = Distribution.System.X86_64
145
168
146data ConstraintFile = ConstraintFile
169data ConstraintFile = ConstraintFile
147− { cfGlobalFlags :: Map FlagName Bool
148− , cfPackageFlags :: Map PackageName (Map FlagName Bool)
170+ { cfPackageFlags :: Map PackageName (Map FlagName Bool)
149 , cfSkippedTests :: Set PackageName
171 , cfSkippedTests :: Set PackageName
150 , cfExpectedTestFailures :: Set PackageName
172 , cfExpectedTestFailures :: Set PackageName
151 , cfExpectedHaddockFailures :: Set PackageName
173 , cfExpectedHaddockFailures :: Set PackageName
152 , cfSkippedBenchmarks :: Set PackageName
174 , cfSkippedBenchmarks :: Set PackageName
153 , cfPackages :: Map Maintainer (Vector Dependency)
175 , cfPackages :: Map Maintainer (Vector Dependency)
154 , cfGithubUsers :: Map Text (Set Text)
176 , cfGithubUsers :: Map Text (Set Text)
177+ , cfSkippedLibProfiling :: Set PackageName
155 }
178 }
156
179
157instance FromJSON ConstraintFile where
180instance FromJSON ConstraintFile where
158 parseJSON = withObject "ConstraintFile" $ \o -> do
181 parseJSON = withObject "ConstraintFile" $ \o -> do
159− cfGlobalFlags <- goFlagMap <$> o .: "global-flags"
160 cfPackageFlags <- (goPackageMap . fmap goFlagMap) <$> o .: "package-flags"
182 cfPackageFlags <- (goPackageMap . fmap goFlagMap) <$> o .: "package-flags"
161 cfSkippedTests <- getPackages o "skipped-tests"
183 cfSkippedTests <- getPackages o "skipped-tests"
162 cfExpectedTestFailures <- getPackages o "expected-test-failures"
184 cfExpectedTestFailures <- getPackages o "expected-test-failures"
163 cfExpectedHaddockFailures <- getPackages o "expected-haddock-failures"
185 cfExpectedHaddockFailures <- getPackages o "expected-haddock-failures"
164 cfSkippedBenchmarks <- getPackages o "skipped-benchmarks"
186 cfSkippedBenchmarks <- getPackages o "skipped-benchmarks"
187+ cfSkippedLibProfiling <- getPackages o "skipped-profiling"
165 cfPackages <- o .: "packages"
188 cfPackages <- o .: "packages"
166 >>= mapM (mapM toDep)
189 >>= mapM (mapM toDep)
167 . Map.mapKeysWith const Maintainer
190 . Map.mapKeysWith const Maintainer
@@ -196,6 +219,7 @@ toBC ConstraintFile {..} = do
196 mpair = lookup name revmap
219 mpair = lookup name revmap
197 pcMaintainer = fmap fst mpair
220 pcMaintainer = fmap fst mpair
198 pcVersionRange = maybe anyVersion snd mpair
221 pcVersionRange = maybe anyVersion snd mpair
222+ pcEnableLibProfile = not (name `member` cfSkippedLibProfiling)
199 pcTests
223 pcTests
200 | name `member` cfSkippedTests = Don'tBuild
224 | name `member` cfSkippedTests = Don'tBuild
201 | name `member` cfExpectedTestFailures = ExpectFailure
225 | name `member` cfExpectedTestFailures = ExpectFailure
@@ -205,7 +229,6 @@ toBC ConstraintFile {..} = do
205 | name `member` cfExpectedHaddockFailures = ExpectFailure
229 | name `member` cfExpectedHaddockFailures = ExpectFailure
206
230
207 | otherwise = ExpectSuccess
231 | otherwise = ExpectSuccess
208− pcFlagOverrides = fromMaybe mempty (lookup name cfPackageFlags) ++
232+ pcFlagOverrides = fromMaybe mempty $ lookup name cfPackageFlags
209− cfGlobalFlags
210
233
211 bcGithubUsers = cfGithubUsers
234 bcGithubUsers = cfGithubUsers
Stackage/BuildPlan.hs+10−3
@@ -14,6 +14,7 @@ module Stackage.BuildPlan
14 , PackagePlan (..)
14 , PackagePlan (..)
15 , newBuildPlan
15 , newBuildPlan
16 , makeToolMap
16 , makeToolMap
17+ , getLatestAllowedPlans
17 ) where
18 ) where
18
19
19import Control.Monad.State.Strict (execState, get, put)
20import Control.Monad.State.Strict (execState, get, put)
@@ -90,9 +91,9 @@ instance FromJSON PackagePlan where
90 ppDesc <- o .: "description"
91 ppDesc <- o .: "description"
91 return PackagePlan {..}
92 return PackagePlan {..}
92
93
94+-- | Make a build plan given these package set and build constraints.
93−newBuildPlan :: MonadIO m => BuildConstraints -> m BuildPlan
95+newBuildPlan :: MonadIO m => Map PackageName PackagePlan -> BuildConstraints -> m BuildPlan
94−newBuildPlan bc@BuildConstraints {..} = liftIO $ do
96+newBuildPlan packagesOrig bc@BuildConstraints {..} = liftIO $ do
95− packagesOrig <- getLatestDescriptions (isAllowed bc) (mkPackagePlan bc)
96 let toolMap = makeToolMap packagesOrig
97 let toolMap = makeToolMap packagesOrig
97 packages = populateUsers $ removeUnincluded bc toolMap packagesOrig
98 packages = populateUsers $ removeUnincluded bc toolMap packagesOrig
98 toolNames :: [ExeName]
99 toolNames :: [ExeName]
@@ -205,3 +206,9 @@ mkPackagePlan bc gpd = do
205 getFlag MkFlag {..} =
206 getFlag MkFlag {..} =
206 (flagName, fromMaybe flagDefault $ lookup flagName overrides)
207 (flagName, fromMaybe flagDefault $ lookup flagName overrides)
207 flags = mapFromList $ map getFlag $ genPackageFlags gpd
208 flags = mapFromList $ map getFlag $ genPackageFlags gpd
209+
210+getLatestAllowedPlans :: MonadIO m => BuildConstraints -> m (Map PackageName PackagePlan)
211+getLatestAllowedPlans bc =
212+ getLatestDescriptions
213+ (isAllowed bc)
214+ (mkPackagePlan bc)
Stackage/CheckBuildPlan.hs+60−9
@@ -1,3 +1,4 @@
1+{-# LANGUAGE TupleSections #-}
1{-# LANGUAGE DeriveDataTypeable #-}
2{-# LANGUAGE DeriveDataTypeable #-}
2{-# LANGUAGE GeneralizedNewtypeDeriving #-}
3{-# LANGUAGE GeneralizedNewtypeDeriving #-}
3{-# LANGUAGE NoImplicitPrelude #-}
4{-# LANGUAGE NoImplicitPrelude #-}
@@ -7,28 +8,38 @@
7-- | Confirm that a build plan has a consistent set of dependencies.
8-- | Confirm that a build plan has a consistent set of dependencies.
8module Stackage.CheckBuildPlan
9module Stackage.CheckBuildPlan
9 ( checkBuildPlan
10 ( checkBuildPlan
11+ , BadBuildPlan
10 ) where
12 ) where
11
13
12import Control.Monad.Writer.Strict (Writer, execWriter, tell)
14import Control.Monad.Writer.Strict (Writer, execWriter, tell)
13−import qualified Data.Text as T
15+import qualified Data.Map.Strict as M
16+import qualified Data.Text as T
14import Stackage.BuildConstraints
17import Stackage.BuildConstraints
15import Stackage.BuildPlan
18import Stackage.BuildPlan
16import Stackage.PackageDescription
19import Stackage.PackageDescription
17import Stackage.Prelude
20import Stackage.Prelude
18
21
19−-- FIXME check cycles in dependencies, only looking at libraries and
22+-- | Check the build plan for missing deps, wrong versions, etc.
20−-- executables
21−
22−checkBuildPlan :: MonadThrow m => BuildPlan -> m ()
23+checkBuildPlan :: (MonadThrow m) => BuildPlan -> m ()
23checkBuildPlan BuildPlan {..}
24checkBuildPlan BuildPlan {..}
24 | null errs' = return ()
25 | null errs' = return ()
25 | otherwise = throwM errs
26 | otherwise = throwM errs
26 where
27 where
27− allPackages = siCorePackages bpSystemInfo ++ map ppVersion bpPackages
28+ allPackages = map (,mempty) (siCorePackages bpSystemInfo) ++
29+ map (ppVersion &&& M.keys . M.filter libAndExe . sdPackages . ppDesc) bpPackages
28 errs@(BadBuildPlan errs') =
30 errs@(BadBuildPlan errs') =
29 execWriter $ mapM_ (checkDeps allPackages) $ mapToList bpPackages
31 execWriter $ mapM_ (checkDeps allPackages) $ mapToList bpPackages
32+ -- Only looking at libraries and executables, benchmarks and tests
33+ -- are allowed to create cycles (e.g. test-framework depends on
34+ -- text, which uses test-framework in its test-suite).
35+ libAndExe (DepInfo cs _) = any (flip elem [CompLibrary,CompExecutable]) cs
30
36
37+-- | For a given package name and plan, check that its dependencies are:
38+--
39+-- 1. Existent (existing in the provided package map)
40+-- 2. Within version range
41+-- 3. Check for dependency cycles.
31−checkDeps :: Map PackageName Version
42+checkDeps :: Map PackageName (Version,[PackageName])
32 -> (PackageName, PackagePlan)
43 -> (PackageName, PackagePlan)
33 -> Writer BadBuildPlan ()
44 -> Writer BadBuildPlan ()
34checkDeps allPackages (user, pb) =
45checkDeps allPackages (user, pb) =
@@ -37,8 +48,16 @@ checkDeps allPackages (user, pb) =
37 go (dep, diRange -> range) =
48 go (dep, diRange -> range) =
38 case lookup dep allPackages of
49 case lookup dep allPackages of
39 Nothing -> tell $ BadBuildPlan $ singletonMap (dep, Nothing) errMap
50 Nothing -> tell $ BadBuildPlan $ singletonMap (dep, Nothing) errMap
40− Just version
51+ Just (version,deps)
41− | version `withinRange` range -> return ()
52+ | version `withinRange` range ->
53+ occursCheck allPackages
54+ (\d v ->
55+ tell $ BadBuildPlan $ singletonMap
56+ (d,v)
57+ errMap)
58+ dep
59+ deps
60+ []
42 | otherwise -> tell $ BadBuildPlan $ singletonMap
61 | otherwise -> tell $ BadBuildPlan $ singletonMap
43 (dep, Just version)
62 (dep, Just version)
44 errMap
63 errMap
@@ -51,6 +70,38 @@ checkDeps allPackages (user, pb) =
51 , puGithubPings = ppGithubPings pb
70 , puGithubPings = ppGithubPings pb
52 }
71 }
53
72
73+-- | Check whether the package(s) occurs within its own dependency
74+-- tree.
75+occursCheck
76+ :: Monad m
77+ => Map PackageName (Version,[PackageName])
78+ -- ^ All packages.
79+ -> (PackageName -> Maybe Version -> m ())
80+ -- ^ Report an erroneous package.
81+ -> PackageName
82+ -- ^ Starting package to check for cycles in.
83+ -> [PackageName]
84+ -- ^ Dependencies of the package.
85+ -> [PackageName]
86+ -- ^ Previously seen packages up the dependency tree.
87+ -> m ()
88+occursCheck allPackages reportError =
89+ go
90+ where
91+ go pkg deps seen =
92+ case find (flip elem seen) deps of
93+ Just cyclic ->
94+ reportError cyclic $
95+ fmap fst (lookup cyclic allPackages)
96+ Nothing ->
97+ forM_ deps $
98+ \pkg' ->
99+ case lookup pkg' allPackages of
100+ Just (_v,deps')
101+ | pkg' /= pkg -> go pkg' deps' seen'
102+ _ -> return ()
103+ where seen' = pkg : seen
104+
54data PkgUser = PkgUser
105data PkgUser = PkgUser
55 { puName :: PackageName
106 { puName :: PackageName
56 , puVersion :: Version
107 , puVersion :: Version
Stackage/CompleteBuild.hs+124−41
@@ -4,9 +4,14 @@
4module Stackage.CompleteBuild
4module Stackage.CompleteBuild
5 ( BuildType (..)
5 ( BuildType (..)
6 , BumpType (..)
6 , BumpType (..)
7+ , BuildFlags (..)
7 , completeBuild
8 , completeBuild
8 , justCheck
9 , justCheck
10+ , justUploadNightly
9 ) where
11 ) where
12+
13+import Control.Concurrent (threadDelay)
14+import Control.Concurrent.Async (withAsync)
10import Data.Default.Class (def)
15import Data.Default.Class (def)
11import Data.Semigroup (Max (..), Option (..))
16import Data.Semigroup (Max (..), Option (..))
12import Data.Text.Read (decimal)
17import Data.Text.Read (decimal)
@@ -22,8 +27,20 @@ import Stackage.Prelude
22import Stackage.ServerBundle
27import Stackage.ServerBundle
23import Stackage.UpdateBuildPlan
28import Stackage.UpdateBuildPlan
24import Stackage.Upload
29import Stackage.Upload
30+import System.Environment (lookupEnv)
25import System.IO (BufferMode (LineBuffering), hSetBuffering)
31import System.IO (BufferMode (LineBuffering), hSetBuffering)
26
32
33+-- | Flags passed in from the command line.
34+data BuildFlags = BuildFlags
35+ { bfEnableTests :: !Bool
36+ , bfEnableHaddock :: !Bool
37+ , bfDoUpload :: !Bool
38+ , bfEnableLibProfile :: !Bool
39+ , bfEnableExecDyn :: !Bool
40+ , bfVerbose :: !Bool
41+ , bfSkipCheck :: !Bool
42+ } deriving (Show)
43+
27data BuildType = Nightly | LTS BumpType
44data BuildType = Nightly | LTS BumpType
28 deriving (Show, Read, Eq, Ord)
45 deriving (Show, Read, Eq, Ord)
29
46
@@ -39,28 +56,42 @@ data Settings = Settings
39 , slug :: Text
56 , slug :: Text
40 , setArgs :: Text -> UploadBundle -> UploadBundle
57 , setArgs :: Text -> UploadBundle -> UploadBundle
41 , postBuild :: IO ()
58 , postBuild :: IO ()
59+ , distroName :: Text -- ^ distro name on Hackage
60+ }
61+
62+nightlyPlanFile :: Text -- ^ day
63+ -> FilePath
64+nightlyPlanFile day = fpFromText ("nightly-" ++ day) <.> "yaml"
65+
66+nightlySettings :: Text -- ^ day
67+ -> BuildPlan
68+ -> Settings
69+nightlySettings day plan' = Settings
70+ { planFile = nightlyPlanFile day
71+ , buildDir = fpFromText $ "builds/nightly"
72+ , logDir = fpFromText $ "logs/stackage-nightly-" ++ day
73+ , title = \ghcVer -> concat
74+ [ "Stackage Nightly "
75+ , day
76+ , ", GHC "
77+ , ghcVer
78+ ]
79+ , slug = slug'
80+ , setArgs = \ghcVer ub -> ub { ubNightly = Just ghcVer }
81+ , plan = plan'
82+ , postBuild = return ()
83+ , distroName = "Stackage"
42 }
84 }
85+ where
86+ slug' = "nightly-" ++ day
43
87
44getSettings :: Manager -> BuildType -> IO Settings
88getSettings :: Manager -> BuildType -> IO Settings
45getSettings man Nightly = do
89getSettings man Nightly = do
46 day <- tshow . utctDay <$> getCurrentTime
90 day <- tshow . utctDay <$> getCurrentTime
47− let slug' = "nightly-" ++ day
48− plan' <- defaultBuildConstraints man >>= newBuildPlan
91+ bc <- defaultBuildConstraints man
49− return Settings
92+ pkgs <- getLatestAllowedPlans bc
50− { planFile = fpFromText ("nightly-" ++ day) <.> "yaml"
93+ plan' <- newBuildPlan pkgs bc
51− , buildDir = fpFromText $ "builds/stackage-nightly-" ++ day
94+ return $ nightlySettings day plan'
52− , logDir = fpFromText $ "logs/stackage-nightly-" ++ day
53− , title = \ghcVer -> concat
54− [ "Stackage Nightly "
55− , day
56− , ", GHC "
57− , ghcVer
58− ]
59− , slug = slug'
60− , setArgs = \ghcVer ub -> ub { ubNightly = Just ghcVer }
61− , plan = plan'
62− , postBuild = return ()
63− }
64getSettings man (LTS bumpType) = do
95getSettings man (LTS bumpType) = do
65 Option mlts <- fmap (fmap getMax) $ runResourceT
96 Option mlts <- fmap (fmap getMax) $ runResourceT
66 $ sourceDirectory "."
97 $ sourceDirectory "."
@@ -72,21 +103,25 @@ getSettings man (LTS bumpType) = do
72 case mlts of
103 case mlts of
73 Nothing -> LTSVer 0 0
104 Nothing -> LTSVer 0 0
74 Just (LTSVer x _) -> LTSVer (x + 1) 0
105 Just (LTSVer x _) -> LTSVer (x + 1) 0
106+ bc <- defaultBuildConstraints man
107+ pkgs <- getLatestAllowedPlans bc
75− plan' <- defaultBuildConstraints man >>= newBuildPlan
108+ plan' <- newBuildPlan pkgs bc
76 return (new, plan')
109 return (new, plan')
77 Minor -> do
110 Minor -> do
78 old <- maybe (error "No LTS plans found in current directory") return mlts
111 old <- maybe (error "No LTS plans found in current directory") return mlts
79 oldplan <- decodeFileEither (fpToString $ renderLTSVer old)
112 oldplan <- decodeFileEither (fpToString $ renderLTSVer old)
80 >>= either throwM return
113 >>= either throwM return
81 let new = incrLTSVer old
114 let new = incrLTSVer old
82− plan' <- updateBuildPlan oldplan
115+ let bc = updateBuildConstraints oldplan
116+ pkgs <- getLatestAllowedPlans bc
117+ plan' <- newBuildPlan pkgs bc
83 return (new, plan')
118 return (new, plan')
84
119
85 let newfile = renderLTSVer new
120 let newfile = renderLTSVer new
86
121
87 return Settings
122 return Settings
88 { planFile = newfile
123 { planFile = newfile
89− , buildDir = fpFromText $ "builds/stackage-lts-" ++ tshow new
124+ , buildDir = fpFromText $ "builds/lts"
90 , logDir = fpFromText $ "logs/stackage-lts-" ++ tshow new
125 , logDir = fpFromText $ "logs/stackage-lts-" ++ tshow new
91 , title = \ghcVer -> concat
126 , title = \ghcVer -> concat
92 [ "LTS Haskell "
127 [ "LTS Haskell "
@@ -106,6 +141,7 @@ getSettings man (LTS bumpType) = do
106 git ["commit", "-m", "Added new LTS release: " ++ show new]
141 git ["commit", "-m", "Added new LTS release: " ++ show new]
107 putStrLn "Pushing to Git repository"
142 putStrLn "Pushing to Git repository"
108 git ["push"]
143 git ["push"]
144+ , distroName = "LTSHaskell"
109 }
145 }
110
146
111data LTSVer = LTSVer !Int !Int
147data LTSVer = LTSVer !Int !Int
@@ -130,16 +166,27 @@ renderLTSVer lts = fpFromText $ concat
130 , ".yaml"
166 , ".yaml"
131 ]
167 ]
132
168
169+-- | Just print a message saying "still alive" every minute, to appease Travis.
170+stillAlive :: IO () -> IO ()
171+stillAlive inner =
172+ withAsync (printer 1) $ const inner
173+ where
174+ printer i = forever $ do
175+ threadDelay 60000000
176+ putStrLn $ "Still alive: " ++ tshow i
177+ printer $! i + 1
178+
133-- | Generate and check a new build plan, but do not execute it.
179-- | Generate and check a new build plan, but do not execute it.
134--
180--
135-- Since 0.3.1
181-- Since 0.3.1
136justCheck :: IO ()
182justCheck :: IO ()
137−justCheck = withManager tlsManagerSettings $ \man -> do
183+justCheck = stillAlive $ withManager tlsManagerSettings $ \man -> do
138 putStrLn "Loading build constraints"
184 putStrLn "Loading build constraints"
139 bc <- defaultBuildConstraints man
185 bc <- defaultBuildConstraints man
140
186
141 putStrLn "Creating build plan"
187 putStrLn "Creating build plan"
188+ plans <- getLatestAllowedPlans bc
142− plan <- newBuildPlan bc
189+ plan <- newBuildPlan plans bc
143
190
144 putStrLn $ "Writing build plan to check-plan.yaml"
191 putStrLn $ "Writing build plan to check-plan.yaml"
145 encodeFile "check-plan.yaml" plan
192 encodeFile "check-plan.yaml" plan
@@ -149,37 +196,71 @@ justCheck = withManager tlsManagerSettings $ \man -> do
149
196
150 putStrLn "Plan seems valid!"
197 putStrLn "Plan seems valid!"
151
198
199+getPerformBuild :: BuildFlags -> Settings -> PerformBuild
200+getPerformBuild buildFlags Settings {..} = PerformBuild
201+ { pbPlan = plan
202+ , pbInstallDest = buildDir
203+ , pbLogDir = logDir
204+ , pbLog = hPut stdout
205+ , pbJobs = 8
206+ , pbGlobalInstall = False
207+ , pbEnableTests = bfEnableTests buildFlags
208+ , pbEnableHaddock = bfEnableHaddock buildFlags
209+ , pbEnableLibProfiling = bfEnableLibProfile buildFlags
210+ , pbEnableExecDyn = bfEnableExecDyn buildFlags
211+ , pbVerbose = bfVerbose buildFlags
212+ , pbAllowNewer = bfSkipCheck buildFlags
213+ }
214+
215+-- | Make a complete plan, build, test and upload bundle, docs and
216+-- distro.
152−completeBuild :: BuildType -> IO ()
217+completeBuild :: BuildType -> BuildFlags -> IO ()
153−completeBuild buildType = withManager tlsManagerSettings $ \man -> do
218+completeBuild buildType buildFlags = withManager tlsManagerSettings $ \man -> do
154 hSetBuffering stdout LineBuffering
219 hSetBuffering stdout LineBuffering
155
220
156 putStrLn $ "Loading settings for: " ++ tshow buildType
221 putStrLn $ "Loading settings for: " ++ tshow buildType
157− Settings {..} <- getSettings man buildType
222+ settings@Settings {..} <- getSettings man buildType
158
223
159 putStrLn $ "Writing build plan to: " ++ fpToText planFile
224 putStrLn $ "Writing build plan to: " ++ fpToText planFile
160 encodeFile (fpToString planFile) plan
225 encodeFile (fpToString planFile) plan
161
226
227+ if bfSkipCheck buildFlags
228+ then putStrLn "Skipping build plan check"
229+ else do
162− putStrLn "Checking build plan"
230+ putStrLn "Checking build plan"
163− checkBuildPlan plan
231+ checkBuildPlan plan
164
232
165 putStrLn "Performing build"
233 putStrLn "Performing build"
166− let pb = PerformBuild
167− { pbPlan = plan
168− , pbInstallDest = buildDir
169− , pbLogDir = logDir
170− , pbLog = hPut stdout
171− , pbJobs = 8
172− , pbGlobalInstall = False
173− }
174− performBuild pb >>= mapM_ putStrLn
234+ performBuild (getPerformBuild buildFlags settings) >>= mapM_ putStrLn
235+
236+ when (bfDoUpload buildFlags) $
237+ finallyUpload settings man
238+
239+justUploadNightly
240+ :: Text -- ^ nightly date
241+ -> IO ()
242+justUploadNightly day = do
243+ plan <- decodeFileEither (fpToString $ nightlyPlanFile day)
244+ >>= either throwM return
245+ withManager tlsManagerSettings $ finallyUpload $ nightlySettings day plan
175
246
247+-- | The final part of the complete build process: uploading a bundle,
248+-- docs and a distro to hackage.
249+finallyUpload :: Settings -> Manager -> IO ()
250+finallyUpload settings@Settings{..} man = do
176 putStrLn "Uploading bundle to Stackage Server"
251 putStrLn "Uploading bundle to Stackage Server"
252+
253+ mtoken <- lookupEnv "STACKAGE_AUTH_TOKEN"
254+ token <-
255+ case mtoken of
177− token <- readFile "/auth-token"
256+ Nothing -> decodeUtf8 <$> readFile "/auth-token"
257+ Just token -> return $ pack token
258+
178 now <- epochTime
259 now <- epochTime
179 let ghcVer = display $ siGhcVersion $ bpSystemInfo plan
260 let ghcVer = display $ siGhcVersion $ bpSystemInfo plan
180 (ident, mloc) <- flip uploadBundle man $ setArgs ghcVer def
261 (ident, mloc) <- flip uploadBundle man $ setArgs ghcVer def
181 { ubContents = serverBundle now (title ghcVer) slug plan
262 { ubContents = serverBundle now (title ghcVer) slug plan
182− , ubAuthToken = decodeUtf8 token
263+ , ubAuthToken = token
183 }
264 }
184 putStrLn $ "New ident: " ++ unSnapshotIdent ident
265 putStrLn $ "New ident: " ++ unSnapshotIdent ident
185 forM_ mloc $ \loc ->
266 forM_ mloc $ \loc ->
@@ -190,7 +271,7 @@ completeBuild buildType = withManager tlsManagerSettings $ \man -> do
190 putStrLn "Uploading docs to Stackage Server"
271 putStrLn "Uploading docs to Stackage Server"
191 res1 <- uploadDocs UploadDocs
272 res1 <- uploadDocs UploadDocs
192 { udServer = def
273 { udServer = def
193− , udAuthToken = decodeUtf8 token
274+ , udAuthToken = token
194 , udDocs = pbDocDir pb
275 , udDocs = pbDocDir pb
195 , udSnapshot = ident
276 , udSnapshot = ident
196 } man
277 } man
@@ -200,15 +281,17 @@ completeBuild buildType = withManager tlsManagerSettings $ \man -> do
200 case map encodeUtf8 $ words $ decodeUtf8 $ either (const "") id ecreds of
281 case map encodeUtf8 $ words $ decodeUtf8 $ either (const "") id ecreds of
201 [username, password] -> do
282 [username, password] -> do
202 putStrLn "Uploading as Hackage distro"
283 putStrLn "Uploading as Hackage distro"
203− res2 <- uploadHackageDistro plan username password man
284+ res2 <- uploadHackageDistroNamed distroName plan username password man
204 putStrLn $ "Distro upload response: " ++ tshow res2
285 putStrLn $ "Distro upload response: " ++ tshow res2
205 _ -> putStrLn "No creds found, skipping Hackage distro upload"
286 _ -> putStrLn "No creds found, skipping Hackage distro upload"
206
287
207 putStrLn "Uploading doc map"
288 putStrLn "Uploading doc map"
208 uploadDocMap UploadDocMap
289 uploadDocMap UploadDocMap
209 { udmServer = def
290 { udmServer = def
210− , udmAuthToken = decodeUtf8 token
291+ , udmAuthToken = token
211 , udmSnapshot = ident
292 , udmSnapshot = ident
212 , udmDocDir = pbDocDir pb
293 , udmDocDir = pbDocDir pb
213 , udmPlan = plan
294 , udmPlan = plan
214 } man >>= print
295 } man >>= print
296+ where
297+ pb = getPerformBuild (error "finallyUpload.buildFlags") settings
Stackage/GhcPkg.hsnew file+90
@@ -0,0 +1,90 @@
1+{-# LANGUAGE NoImplicitPrelude #-}
2+{-# LANGUAGE OverloadedStrings #-}
3+-- | General commands related to ghc-pkg.
4+
5+module Stackage.GhcPkg
6+ ( setupPackageDatabase
7+ ) where
8+
9+import Data.Conduit
10+import qualified Data.Conduit.List as CL
11+import Data.Conduit.Process
12+import qualified Data.Conduit.Text as CT
13+import Data.Maybe
14+import Data.Text (Text)
15+import qualified Data.Text as T
16+import Distribution.Compat.ReadP
17+import Distribution.Package
18+import Distribution.Text (parse)
19+import Filesystem.Path.CurrentOS (FilePath)
20+import qualified Filesystem.Path.CurrentOS as FP
21+import Data.Map (Map)
22+import Data.Version (Version)
23+import Stackage.Prelude
24+import Filesystem (removeTree)
25+
26+setupPackageDatabase
27+ :: Maybe FilePath -- ^ database location, Nothing if using global DB
28+ -> FilePath -- ^ documentation root
29+ -> (ByteString -> IO ()) -- ^ logging
30+ -> Map PackageName Version -- ^ packages and versions to be installed
31+ -> IO (Set PackageName) -- ^ packages remaining in the database after cleanup
32+setupPackageDatabase mdb docDir log' toInstall = do
33+ registered1 <- getRegisteredPackages flags
34+ forM_ registered1 $ \pi@(PackageIdentifier name version) ->
35+ case lookup name toInstall of
36+ Just version' | version /= version' -> unregisterPackage log' docDir flags pi
37+ _ -> return ()
38+ broken <- getBrokenPackages flags
39+ forM_ broken $ unregisterPackage log' docDir flags
40+ foldMap (\(PackageIdentifier name _) -> singletonSet name)
41+ <$> getRegisteredPackages flags
42+ where
43+ flags = ghcPkgFlags mdb
44+
45+ghcPkgFlags :: Maybe FilePath -> [String]
46+ghcPkgFlags mdb =
47+ "--no-user-package-db" :
48+ case mdb of
49+ Nothing -> ["--global"]
50+ Just fp -> ["--package-db=" ++ fpToString fp]
51+
52+-- | Get broken packages.
53+getBrokenPackages :: [String] -> IO [PackageIdentifier]
54+getBrokenPackages flags = do
55+ (_,ps) <- sourceProcessWithConsumer
56+ (proc
57+ "ghc-pkg"
58+ ("check" : "--simple-output" : flags))
59+ (CT.decodeUtf8 $= CT.lines $= CL.consume)
60+ return (mapMaybe parsePackageIdent (T.words (T.unlines ps)))
61+
62+-- | Get available packages.
63+getRegisteredPackages :: [String] -> IO [PackageIdentifier]
64+getRegisteredPackages flags = do
65+ (_,ps) <- sourceProcessWithConsumer
66+ (proc
67+ "ghc-pkg"
68+ ("list" : "--simple-output" : flags))
69+ (CT.decodeUtf8 $= CT.lines $= CL.consume)
70+ return (mapMaybe parsePackageIdent (T.words (T.unlines ps)))
71+
72+-- | Parse a package identifier: foo-1.2.3
73+parsePackageIdent :: Text -> Maybe PackageIdentifier
74+parsePackageIdent = fmap fst .
75+ listToMaybe .
76+ filter (null . snd) .
77+ readP_to_S parse . T.unpack
78+
79+-- | Unregister a package.
80+unregisterPackage :: (ByteString -> IO ()) -- ^ log func
81+ -> FilePath -- ^ doc directory
82+ -> [String] -> PackageIdentifier -> IO ()
83+unregisterPackage log' docDir flags ident@(PackageIdentifier name _) = do
84+ log' $ "Unregistering " ++ encodeUtf8 (display ident) ++ "\n"
85+ void (readProcessWithExitCode
86+ "ghc-pkg"
87+ ("unregister": flags ++ ["--force", unpack $ display name])
88+ "")
89+
90+ void $ tryIO $ removeTree $ docDir </> fpFromText (display ident)
Stackage/InstallBuild.hsnew file+100
@@ -0,0 +1,100 @@
1+{-# LANGUAGE DeriveDataTypeable #-}
2+{-# LANGUAGE NoImplicitPrelude #-}
3+{-# LANGUAGE OverloadedStrings #-}
4+{-# LANGUAGE RecordWildCards #-}
5+{-# LANGUAGE ScopedTypeVariables #-}
6+module Stackage.InstallBuild
7+ ( InstallFlags (..)
8+ , BuildPlanSource (..)
9+ , installBuild
10+ ) where
11+
12+import qualified Codec.Archive.Tar as Tar
13+import qualified Codec.Compression.GZip as GZip
14+import qualified Data.Yaml as Yaml
15+import Network.HTTP.Client
16+import Network.HTTP.Client.TLS (tlsManagerSettings)
17+import Stackage.BuildPlan
18+import Stackage.CheckBuildPlan
19+import Stackage.PerformBuild
20+import Stackage.Prelude
21+import System.IO (BufferMode (LineBuffering), hSetBuffering)
22+
23+-- | Flags passed in from the command line.
24+data InstallFlags = InstallFlags
25+ { ifPlanSource :: !BuildPlanSource
26+ , ifInstallDest :: !FilePath
27+ , ifLogDir :: !(Maybe FilePath)
28+ , ifJobs :: !Int
29+ , ifGlobalInstall :: !Bool
30+ , ifEnableTests :: !Bool
31+ , ifEnableHaddock :: !Bool
32+ , ifEnableLibProfiling :: !Bool
33+ , ifEnableExecDyn :: !Bool
34+ , ifVerbose :: !Bool
35+ , ifSkipCheck :: !Bool
36+ } deriving (Show)
37+
38+-- | Source for build plan.
39+data BuildPlanSource = BPSBundleWeb String
40+ | BPSFile FilePath
41+ deriving (Show)
42+
43+getPerformBuild :: BuildPlan -> InstallFlags -> PerformBuild
44+getPerformBuild plan InstallFlags{..} =
45+ PerformBuild
46+ { pbPlan = plan
47+ , pbInstallDest = ifInstallDest
48+ , pbLogDir = fromMaybe (ifInstallDest </> "logs") ifLogDir
49+ , pbLog = hPut stdout
50+ , pbJobs = ifJobs
51+ , pbGlobalInstall = ifGlobalInstall
52+ , pbEnableTests = ifEnableTests
53+ , pbEnableHaddock = ifEnableHaddock
54+ , pbEnableLibProfiling = ifEnableLibProfiling
55+ , pbEnableExecDyn = ifEnableExecDyn
56+ , pbVerbose = ifVerbose
57+ , pbAllowNewer = ifSkipCheck
58+ }
59+
60+-- | Install stackage from an existing build plan.
61+installBuild :: InstallFlags -> IO ()
62+installBuild installFlags@InstallFlags{..} = do
63+ hSetBuffering stdout LineBuffering
64+
65+ putStrLn $ "Loading build plan"
66+ plan <- case ifPlanSource of
67+ BPSBundleWeb url -> withManager tlsManagerSettings $ \man -> do
68+ req <- parseUrl url
69+ res <- httpLbs req man
70+ planBSL <- getPlanEntry $ Tar.read $ GZip.decompress (responseBody res)
71+ decodeBuildPlan planBSL
72+ BPSFile path -> Yaml.decodeFileEither (fpToString path) >>= either throwM return
73+
74+ if ifSkipCheck
75+ then putStrLn "Skipping build plan check"
76+ else do
77+ putStrLn "Checking build plan"
78+ checkBuildPlan plan
79+
80+ putStrLn "Performing build"
81+ performBuild (getPerformBuild plan installFlags) >>= mapM_ putStrLn
82+
83+ where
84+ getPlanEntry Tar.Done = throwIO NoBuildPlanException
85+ getPlanEntry (Tar.Fail e) = throwIO e
86+ getPlanEntry (Tar.Next entry entries)
87+ | Tar.entryPath entry == "build-plan.yaml" =
88+ case Tar.entryContent entry of
89+ Tar.NormalFile bs _ -> return bs
90+ _ -> throwIO NoBuildPlanException
91+ | otherwise = getPlanEntry entries
92+
93+ decodeBuildPlan =
94+ either throwIO return . Yaml.decodeEither' . toStrict
95+
96+data InstallBuildException = NoBuildPlanException
97+ deriving (Typeable)
98+instance Exception InstallBuildException
99+instance Show InstallBuildException where
100+ show NoBuildPlanException = "Bundle has missing or invalid build-plan.yaml"
Stackage/PerformBuild.hs+148−31
@@ -19,11 +19,12 @@ import qualified Data.Map as Map
19import Data.NonNull (fromNullable)
19import Data.NonNull (fromNullable)
20import Filesystem (canonicalizePath, createTree,
20import Filesystem (canonicalizePath, createTree,
21 getWorkingDirectory, isDirectory,
21 getWorkingDirectory, isDirectory,
22− removeTree, rename)
22+ removeTree, rename, isFile, removeFile)
23import Filesystem.Path (parent)
23import Filesystem.Path (parent)
24import qualified Filesystem.Path as F
24import qualified Filesystem.Path as F
25import Stackage.BuildConstraints
25import Stackage.BuildConstraints
26import Stackage.BuildPlan
26import Stackage.BuildPlan
27+import Stackage.GhcPkg
27import Stackage.PackageDescription
28import Stackage.PackageDescription
28import Stackage.Prelude hiding (pi)
29import Stackage.Prelude hiding (pi)
29import System.Directory (findExecutable)
30import System.Directory (findExecutable)
@@ -61,6 +62,13 @@ data PerformBuild = PerformBuild
61 , pbJobs :: Int
62 , pbJobs :: Int
62 , pbGlobalInstall :: Bool
63 , pbGlobalInstall :: Bool
63 -- ^ Register packages in the global database
64 -- ^ Register packages in the global database
65+ , pbEnableTests :: Bool
66+ , pbEnableHaddock :: Bool
67+ , pbEnableLibProfiling :: Bool
68+ , pbEnableExecDyn :: Bool
69+ , pbVerbose :: Bool
70+ , pbAllowNewer :: Bool
71+ -- ^ Pass --allow-newer to cabal configure
64 }
72 }
65
73
66data PackageInfo = PackageInfo
74data PackageInfo = PackageInfo
@@ -83,7 +91,9 @@ waitForDeps toolMap packageMap activeComps bp pi action = do
83 case lookup exe toolMap >>= fromNullable . map checkPackage . setToList of
91 case lookup exe toolMap >>= fromNullable . map checkPackage . setToList of
84 Nothing
92 Nothing
85 | isCoreExe exe -> return ()
93 | isCoreExe exe -> return ()
94+ -- https://github.com/jgm/zip-archive/issues/23
86− | otherwise -> throwSTM $ ToolMissing exe
95+ -- | otherwise -> throwSTM $ ToolMissing exe
96+ | otherwise -> return ()
87 Just packages -> ofoldl1' (<|>) packages
97 Just packages -> ofoldl1' (<|>) packages
88 action
98 action
89 where
99 where
@@ -126,6 +136,10 @@ pbLibDir pb = pbInstallDest pb </> "lib"
126pbDataDir pb = pbInstallDest pb </> "share"
136pbDataDir pb = pbInstallDest pb </> "share"
127pbDocDir pb = pbInstallDest pb </> "doc"
137pbDocDir pb = pbInstallDest pb </> "doc"
128
138
139+-- | Directory keeping previous result info
140+pbPrevResDir :: PerformBuild -> FilePath
141+pbPrevResDir pb = pbInstallDest pb </> "prevres"
142+
129performBuild :: PerformBuild -> IO [Text]
143performBuild :: PerformBuild -> IO [Text]
130performBuild pb = do
144performBuild pb = do
131 cwd <- getWorkingDirectory
145 cwd <- getWorkingDirectory
@@ -153,12 +167,13 @@ performBuild' pb@PerformBuild {..} = withBuildDir $ \builddir -> do
153 $ \ClosedStream Inherited Inherited -> return ()
167 $ \ClosedStream Inherited Inherited -> return ()
154
168
155 let removeTree' fp = whenM (isDirectory fp) (removeTree fp)
169 let removeTree' fp = whenM (isDirectory fp) (removeTree fp)
156− mapM_ removeTree' [pbInstallDest, pbLogDir]
170+ removeTree' pbLogDir
157
171
158− forM_ (pbDatabase pb) $ \db -> do
172+ forM_ (pbDatabase pb) $ \db ->
173+ unlessM (isFile $ db </> "package.cache") $ do
159− createTree $ parent db
174+ createTree $ parent db
160− withCheckedProcess (proc "ghc-pkg" ["init", fpToString db])
175+ withCheckedProcess (proc "ghc-pkg" ["init", fpToString db])
161− $ \ClosedStream Inherited Inherited -> return ()
176+ $ \ClosedStream Inherited Inherited -> return ()
162 pbLog $ encodeUtf8 "Copying built-in Haddocks\n"
177 pbLog $ encodeUtf8 "Copying built-in Haddocks\n"
163 copyBuiltInHaddocks (pbDocDir pb)
178 copyBuiltInHaddocks (pbDocDir pb)
164
179
@@ -178,7 +193,14 @@ performBuild' pb@PerformBuild {..} = withBuildDir $ \builddir -> do
178 env <- getEnvironment
193 env <- getEnvironment
179 haddockFiles <- newTVarIO mempty
194 haddockFiles <- newTVarIO mempty
180
195
196+ registeredPackages <- setupPackageDatabase
197+ (pbDatabase pb)
198+ (pbDocDir pb)
199+ pbLog
200+ (ppVersion <$> bpPackages pbPlan)
201+
181− forM_ packageMap $ \pi -> void $ async $ singleBuild pb SingleBuild
202+ forM_ packageMap $ \pi -> void $ async $ singleBuild pb registeredPackages
203+ SingleBuild
182 { sbSem = sem
204 { sbSem = sem
183 , sbErrsVar = errsVar
205 , sbErrsVar = errsVar
184 , sbWarningsVar = warningsVar
206 , sbWarningsVar = warningsVar
@@ -192,7 +214,7 @@ performBuild' pb@PerformBuild {..} = withBuildDir $ \builddir -> do
192 id
214 id
193 (\db -> (("HASKELL_PACKAGE_SANDBOX", fpToString db):))
215 (\db -> (("HASKELL_PACKAGE_SANDBOX", fpToString db):))
194 (pbDatabase pb)
216 (pbDatabase pb)
195− (map fixEnv env)
217+ (filter allowedEnv $ map fixEnv env)
196 , sbHaddockFiles = haddockFiles
218 , sbHaddockFiles = haddockFiles
197 }
219 }
198
220
@@ -210,6 +232,8 @@ performBuild' pb@PerformBuild {..} = withBuildDir $ \builddir -> do
210 | toUpper p == "PATH" = (p, fpToString (pbBinDir pb) ++ pathSep : x)
232 | toUpper p == "PATH" = (p, fpToString (pbBinDir pb) ++ pathSep : x)
211 | otherwise = (p, x)
233 | otherwise = (p, x)
212
234
235+ allowedEnv (k, _) = k `notMember` bannedEnvs
236+
213 -- | Separate for the PATH environment variable
237 -- | Separate for the PATH environment variable
214 pathSep :: Char
238 pathSep :: Char
215#ifdef mingw32_HOST_OS
239#ifdef mingw32_HOST_OS
@@ -218,6 +242,12 @@ performBuild' pb@PerformBuild {..} = withBuildDir $ \builddir -> do
218 pathSep = ':'
242 pathSep = ':'
219#endif
243#endif
220
244
245+-- | Environment variables we don't allow to be passed on to child processes.
246+bannedEnvs :: Set String
247+bannedEnvs = setFromList
248+ [ "STACKAGE_AUTH_TOKEN"
249+ ]
250+
221data SingleBuild = SingleBuild
251data SingleBuild = SingleBuild
222 { sbSem :: TSem
252 { sbSem :: TSem
223 , sbErrsVar :: TVar (Map PackageName BuildFailure)
253 , sbErrsVar :: TVar (Map PackageName BuildFailure)
@@ -232,8 +262,10 @@ data SingleBuild = SingleBuild
232 , sbHaddockFiles :: TVar (Map Text FilePath) -- ^ package-version, .haddock file
262 , sbHaddockFiles :: TVar (Map Text FilePath) -- ^ package-version, .haddock file
233 }
263 }
234
264
235−singleBuild :: PerformBuild -> SingleBuild -> IO ()
265+singleBuild :: PerformBuild
266+ -> Set PackageName -- ^ registered packages
267+ -> SingleBuild -> IO ()
236−singleBuild pb@PerformBuild {..} SingleBuild {..} =
268+singleBuild pb@PerformBuild {..} registeredPackages SingleBuild {..} =
237 withCounter sbActive
269 withCounter sbActive
238 $ handle updateErrs
270 $ handle updateErrs
239 $ (`finally` void (atomically $ tryPutTMVar (piResult sbPackageInfo) False))
271 $ (`finally` void (atomically $ tryPutTMVar (piResult sbPackageInfo) False))
@@ -245,11 +277,13 @@ singleBuild pb@PerformBuild {..} SingleBuild {..} =
245 let wfd comps =
277 let wfd comps =
246 waitForDeps sbToolMap sbPackageMap comps pbPlan sbPackageInfo
278 waitForDeps sbToolMap sbPackageMap comps pbPlan sbPackageInfo
247 . withTSem sbSem
279 . withTSem sbSem
248− wfd libComps buildLibrary
280+ withUnpacked <- wfd libComps buildLibrary
249
281
250− wfd testComps runTests
282+ wfd testComps (runTests withUnpacked)
251
283
284+ pname = piName sbPackageInfo
285+ pident = PackageIdentifier pname (ppVersion $ piPlan sbPackageInfo)
252− name = display $ piName sbPackageInfo
286+ name = display pname
253 namever = concat
287 namever = concat
254 [ name
288 [ name
255 , "-"
289 , "-"
@@ -290,6 +324,7 @@ singleBuild pb@PerformBuild {..} SingleBuild {..} =
290 withBinaryFile (fpToString fp) WriteMode inner'
324 withBinaryFile (fpToString fp) WriteMode inner'
291
325
292 configArgs = ($ []) $ execWriter $ do
326 configArgs = ($ []) $ execWriter $ do
327+ when pbAllowNewer $ tell' "--allow-newer"
293 tell' "--package-db=clear"
328 tell' "--package-db=clear"
294 tell' "--package-db=global"
329 tell' "--package-db=global"
295 forM_ (pbDatabase pb) $ \db -> tell' $ "--package-db=" ++ fpToText db
330 forM_ (pbDatabase pb) $ \db -> tell' $ "--package-db=" ++ fpToText db
@@ -298,6 +333,9 @@ singleBuild pb@PerformBuild {..} SingleBuild {..} =
298 tell' $ "--datadir=" ++ fpToText (pbDataDir pb)
333 tell' $ "--datadir=" ++ fpToText (pbDataDir pb)
299 tell' $ "--docdir=" ++ fpToText (pbDocDir pb)
334 tell' $ "--docdir=" ++ fpToText (pbDocDir pb)
300 tell' $ "--flags=" ++ flags
335 tell' $ "--flags=" ++ flags
336+ when (pbEnableLibProfiling && pcEnableLibProfile) $
337+ tell' "--enable-library-profiling"
338+ when pbEnableExecDyn $ tell' "--enable-executable-dynamic"
301 where
339 where
302 tell' x = tell (x:)
340 tell' x = tell (x:)
303
341
@@ -312,20 +350,39 @@ singleBuild pb@PerformBuild {..} SingleBuild {..} =
312 PackageConstraints {..} = ppConstraints $ piPlan sbPackageInfo
350 PackageConstraints {..} = ppConstraints $ piPlan sbPackageInfo
313
351
314 buildLibrary = wf libOut $ \outH -> do
352 buildLibrary = wf libOut $ \outH -> do
353+ let run a b = do when pbVerbose $ log' (unwords (a : b))
315− let run = runChild outH
354+ runChild outH a b
355+
356+ isUnpacked <- newIORef False
357+ let withUnpacked inner = do
358+ unlessM (readIORef isUnpacked) $ do
316− log' $ "Unpacking " ++ namever
359+ log' $ "Unpacking " ++ namever
317− runParent outH "cabal" ["unpack", namever]
360+ runParent outH "cabal" ["unpack", namever]
318−
361+ writeIORef isUnpacked True
362+ inner
363+
364+ isConfiged <- newIORef False
365+ let withConfiged inner = withUnpacked $ do
366+ unlessM (readIORef isConfiged) $ do
319− log' $ "Configuring " ++ namever
367+ log' $ "Configuring " ++ namever
320− run "cabal" $ "configure" : configArgs
368+ run "cabal" $ "configure" : configArgs
321−
369+ writeIORef isConfiged True
370+ inner
371+
372+ prevBuildResult <- getPreviousResult pb Build pident
373+ unless (prevBuildResult == PRSuccess) $ withConfiged $ do
374+ assert (pname `notMember` registeredPackages) $ do
375+ deletePreviousResults pb pident
376+
322− log' $ "Building " ++ namever
377+ log' $ "Building " ++ namever
323− run "cabal" ["build"]
378+ run "cabal" ["build"]
324−
379+
325− log' $ "Copying/registering " ++ namever
380+ log' $ "Copying/registering " ++ namever
326− run "cabal" ["copy"]
381+ run "cabal" ["copy"]
327− withMVar sbRegisterMutex $ const $
382+ withMVar sbRegisterMutex $ const $
328− run "cabal" ["register"]
383+ run "cabal" ["register"]
384+
385+ savePreviousResult pb Build pident True
329
386
330 -- Even if the tests later fail, we can allow other libraries to build
387 -- Even if the tests later fail, we can allow other libraries to build
331 -- on top of our successful results
388 -- on top of our successful results
@@ -335,7 +392,11 @@ singleBuild pb@PerformBuild {..} SingleBuild {..} =
335 -- dependency's haddocks before this finishes
392 -- dependency's haddocks before this finishes
336 atomically $ putTMVar (piResult sbPackageInfo) True
393 atomically $ putTMVar (piResult sbPackageInfo) True
337
394
395+ prevHaddockResult <- getPreviousResult pb Haddock pident
396+ let needHaddock = pbEnableHaddock
397+ && checkPrevResult prevHaddockResult pcHaddocks
338− when (pcHaddocks /= Don'tBuild && not (null $ sdModules $ ppDesc $ piPlan sbPackageInfo)) $ do
398+ && not (null $ sdModules $ ppDesc $ piPlan sbPackageInfo)
399+ when needHaddock $ withConfiged $ do
339 log' $ "Haddocks " ++ namever
400 log' $ "Haddocks " ++ namever
340 hfs <- readTVarIO sbHaddockFiles
401 hfs <- readTVarIO sbHaddockFiles
341 let hfsOpts = flip map (mapToList hfs) $ \(pkgVer, hf) -> concat
402 let hfsOpts = flip map (mapToList hfs) $ \(pkgVer, hf) -> concat
@@ -370,15 +431,21 @@ singleBuild pb@PerformBuild {..} SingleBuild {..} =
370 $ modifyTVar sbHaddockFiles
431 $ modifyTVar sbHaddockFiles
371 $ insertMap namever newPath
432 $ insertMap namever newPath
372
433
434+ savePreviousResult pb Haddock pident $ either (const False) (const True) eres
373 case (eres, pcHaddocks) of
435 case (eres, pcHaddocks) of
374 (Left e, ExpectSuccess) -> throwM e
436 (Left e, ExpectSuccess) -> throwM e
375 (Right (), ExpectFailure) -> warn $ namever ++ ": unexpected Haddock success"
437 (Right (), ExpectFailure) -> warn $ namever ++ ": unexpected Haddock success"
376 _ -> return ()
438 _ -> return ()
377
439
440+ return withUnpacked
441+
378− runTests = wf testOut $ \outH -> do
442+ runTests withUnpacked = wf testOut $ \outH -> do
379 let run = runChild outH
443 let run = runChild outH
380
444
381− when (pcTests /= Don'tBuild) $ do
445+ prevTestResult <- getPreviousResult pb Test pident
446+ let needTest = pbEnableTests
447+ && checkPrevResult prevTestResult pcTests
448+ when needTest $ withUnpacked $ do
382 log' $ "Test configure " ++ namever
449 log' $ "Test configure " ++ namever
383 run "cabal" $ "configure" : "--enable-tests" : configArgs
450 run "cabal" $ "configure" : "--enable-tests" : configArgs
384
451
@@ -389,6 +456,7 @@ singleBuild pb@PerformBuild {..} SingleBuild {..} =
389 log' $ "Test run " ++ namever
456 log' $ "Test run " ++ namever
390 run "cabal" ["test", "--log=" ++ fpToText testRunOut]
457 run "cabal" ["test", "--log=" ++ fpToText testRunOut]
391
458
459+ savePreviousResult pb Test pident $ either (const False) (const True) eres
392 case (eres, pcTests) of
460 case (eres, pcTests) of
393 (Left e, ExpectSuccess) -> throwM e
461 (Left e, ExpectSuccess) -> throwM e
394 (Right (), ExpectFailure) -> warn $ namever ++ ": unexpected test success"
462 (Right (), ExpectFailure) -> warn $ namever ++ ": unexpected test success"
@@ -421,3 +489,52 @@ copyBuiltInHaddocks docdir = do
421 src <- canonicalizePath
489 src <- canonicalizePath
422 (parent (fpFromString ghc) </> "../share/doc/ghc/html/libraries")
490 (parent (fpFromString ghc) </> "../share/doc/ghc/html/libraries")
423 copyDir src docdir
491 copyDir src docdir
492+
493+------------- Previous results
494+
495+-- | The previous actions that can be run
496+data ResultType = Build | Haddock | Test
497+ deriving (Show, Enum, Eq, Ord, Bounded, Read)
498+
499+-- | The result generated on a previous run
500+data PrevResult = PRNoResult | PRSuccess | PRFailure
501+ deriving (Show, Enum, Eq, Ord, Bounded, Read)
502+
503+-- | Check if we should rerun based on a PrevResult and the expected status
504+checkPrevResult :: PrevResult -> TestState -> Bool
505+checkPrevResult _ Don'tBuild = False
506+checkPrevResult PRNoResult _ = True
507+checkPrevResult PRSuccess _ = False
508+checkPrevResult PRFailure ExpectSuccess = True
509+checkPrevResult PRFailure _ = False
510+
511+withPRPath :: PerformBuild -> ResultType -> PackageIdentifier -> (FilePath -> IO a) -> IO a
512+withPRPath pb rt ident inner = do
513+ createTree $ parent fp
514+ inner fp
515+ where
516+ fp = pbPrevResDir pb </> fpFromString (show rt) </> fpFromText (display ident)
517+
518+successBS, failureBS :: ByteString
519+successBS = "success"
520+failureBS = "failure"
521+
522+getPreviousResult :: PerformBuild -> ResultType -> PackageIdentifier -> IO PrevResult
523+getPreviousResult w x y = withPRPath w x y $ \fp -> do
524+ eres <- tryIO $ readFile fp
525+ return $ case eres of
526+ Right bs
527+ | bs == successBS -> PRSuccess
528+ | bs == failureBS -> PRFailure
529+ _ -> PRNoResult
530+
531+savePreviousResult :: PerformBuild -> ResultType -> PackageIdentifier -> Bool -> IO ()
532+savePreviousResult pb rt ident res =
533+ withPRPath pb rt ident $ \fp -> writeFile fp $
534+ if res then successBS else failureBS
535+
536+deletePreviousResults :: PerformBuild -> PackageIdentifier -> IO ()
537+deletePreviousResults pb name =
538+ forM_ [minBound..maxBound] $ \rt ->
539+ withPRPath pb rt name $ \fp ->
540+ void $ tryIO $ removeFile fp
Stackage/UpdateBuildPlan.hs+4−2
@@ -15,8 +15,9 @@ import Stackage.BuildConstraints
15import Stackage.BuildPlan
15import Stackage.BuildPlan
16import Stackage.Prelude
16import Stackage.Prelude
17
17
18−updateBuildPlan :: BuildPlan -> IO BuildPlan
18+updateBuildPlan :: Map PackageName PackagePlan -> BuildPlan -> IO BuildPlan
19+updateBuildPlan packagesOrig
19−updateBuildPlan = newBuildPlan . updateBuildConstraints
20+ = newBuildPlan packagesOrig . updateBuildConstraints
20
21
21updateBuildConstraints :: BuildPlan -> BuildConstraints
22updateBuildConstraints :: BuildPlan -> BuildConstraints
22updateBuildConstraints BuildPlan {..} =
23updateBuildConstraints BuildPlan {..} =
@@ -33,6 +34,7 @@ updateBuildConstraints BuildPlan {..} =
33 , pcHaddocks = maybe ExpectSuccess pcHaddocks moldPC
34 , pcHaddocks = maybe ExpectSuccess pcHaddocks moldPC
34 , pcBuildBenchmarks = maybe True pcBuildBenchmarks moldPC
35 , pcBuildBenchmarks = maybe True pcBuildBenchmarks moldPC
35 , pcFlagOverrides = maybe mempty pcFlagOverrides moldPC
36 , pcFlagOverrides = maybe mempty pcFlagOverrides moldPC
37+ , pcEnableLibProfile = maybe False pcEnableLibProfile moldPC
36 }
38 }
37 where
39 where
38 moldBP = lookup name bpPackages
40 moldBP = lookup name bpPackages
Stackage/Upload.hs+23−9
@@ -11,6 +11,7 @@ module Stackage.Upload
11 , UploadDocs (..)
11 , UploadDocs (..)
12 , uploadDocs
12 , uploadDocs
13 , uploadHackageDistro
13 , uploadHackageDistro
14+ , uploadHackageDistroNamed
14 , UploadDocMap (..)
15 , UploadDocMap (..)
15 , uploadDocMap
16 , uploadDocMap
16 , uploadBundleV2
17 , uploadBundleV2
@@ -145,8 +146,28 @@ uploadHackageDistro :: BuildPlan
145 -> ByteString -- ^ Hackage password
146 -> ByteString -- ^ Hackage password
146 -> Manager
147 -> Manager
147 -> IO (Response LByteString)
148 -> IO (Response LByteString)
148−uploadHackageDistro bp username password =
149+uploadHackageDistro = uploadHackageDistroNamed "Stackage"
150+
151+uploadHackageDistroNamed
152+ :: Text -- ^ distro name
153+ -> BuildPlan
154+ -> ByteString -- ^ Hackage username
155+ -> ByteString -- ^ Hackage password
156+ -> Manager
157+ -> IO (Response LByteString)
158+uploadHackageDistroNamed name bp username password manager = do
159+ req1 <- parseUrl $ concat
160+ [ "http://hackage.haskell.org/distro/"
161+ , unpack name
162+ , "/packages.csv"
163+ ]
164+ let req2 = req1
165+ { requestHeaders = [("Content-Type", "text/csv")]
166+ , requestBody = RequestBodyLBS csv
167+ , checkStatus = \_ _ _ -> Nothing
168+ , method = "PUT"
169+ }
149− httpLbs (applyBasicAuth username password req)
170+ httpLbs (applyBasicAuth username password req2) manager
150 where
171 where
151 csv = encodeUtf8
172 csv = encodeUtf8
152 $ builderToLazy
173 $ builderToLazy
@@ -164,13 +185,6 @@ uploadHackageDistro bp username password =
164 (toBuilder $ display name) ++
185 (toBuilder $ display name) ++
165 "\""
186 "\""
166
187
167− req = "http://hackage.haskell.org/distro/Stackage/packages.csv"
168− { requestHeaders = [("Content-Type", "text/csv")]
169− , requestBody = RequestBodyLBS csv
170− , checkStatus = \_ _ _ -> Nothing
171− , method = "PUT"
172− }
173−
174data UploadDocMap = UploadDocMap
188data UploadDocMap = UploadDocMap
175 { udmServer :: StackageServer
189 { udmServer :: StackageServer
176 , udmAuthToken :: Text
190 , udmAuthToken :: Text
app/stackage.hs+159−12
@@ -1,16 +1,163 @@
1+{-# LANGUAGE TupleSections #-}
2+
3+module Main where
4+
5+import Control.Monad
6+import Data.Monoid
7+import Data.String (fromString)
8+import Data.Version
9+import Options.Applicative
10+import Filesystem.Path.CurrentOS (decodeString)
11+import Paths_stackage (version)
1import Stackage.CompleteBuild
12import Stackage.CompleteBuild
2−import System.Environment (getArgs)
13+import Stackage.InstallBuild
3
14
4main :: IO ()
15main :: IO ()
5−main = do
16+main =
6− args <- getArgs
17+ join $
7− case args of
18+ execParser $
8− [x] | Just y <- lookup x m -> y
19+ info
9− _ -> error $ "Expected one argument, one of: " ++ unwords (map fst m)
20+ (helpOption <*> versionOption <*> config)
21+ (header "Stackage" <>
22+ fullDesc)
10 where
23 where
11− m =
24+ helpOption =
25+ abortOption ShowHelpText $
26+ long "help" <>
27+ help "Show this help text"
28+ versionOption =
29+ infoOption
30+ ("stackage version " ++ showVersion version)
31+ (long "version" <>
32+ help "Show stackage version")
33+ config =
34+ subparser $
35+ mconcat
36+ [ cmnd
37+ (uncurry completeBuild)
38+ (fmap (Nightly, ) buildFlags)
12− [ ("nightly", completeBuild Nightly)
39+ "nightly"
40+ "Build, test and upload the Nightly snapshot"
41+ , cmnd
13− , ("lts-major", completeBuild $ LTS Major)
42+ (uncurry completeBuild)
14− , ("lts-minor", completeBuild $ LTS Minor)
43+ (fmap (LTS Major, ) buildFlags)
44+ "lts-major"
45+ "Build, test and upload the LTS (major) snapshot"
46+ , cmnd
47+ (uncurry completeBuild)
48+ (fmap (LTS Minor, ) buildFlags)
49+ "lts-minor"
50+ "Build, test and upload the LTS (minor) snapshot"
51+ , cmnd
52+ justUploadNightly
53+ nightlyUploadFlags
54+ "upload-nightly"
55+ "Upload an already-built nightly snapshot"
56+ , cmnd
15− , ("check", justCheck)
57+ (const justCheck)
16− ]
58+ (pure ())
59+ "check"
60+ "Just check that the build plan is ok"
61+ , cmnd
62+ installBuild
63+ installFlags
64+ "install"
65+ "Install a snapshot from an existing build plan"]
66+
67+ cmnd exec parse name desc =
68+ command name $
69+ info
70+ (fmap exec (parse <**> helpOption))
71+ (progDesc desc)
72+
73+ buildFlags =
74+ BuildFlags <$>
75+ fmap
76+ not
77+ (switch
78+ (long "skip-tests" <>
79+ help "Skip build and running the test suites")) <*>
80+ fmap
81+ not
82+ (switch
83+ (long "skip-haddock" <>
84+ help "Skip generating haddock documentation")) <*>
85+ fmap
86+ not
87+ (switch
88+ (long "skip-upload" <>
89+ help "Skip uploading bundle, docs, etc.")) <*>
90+ switch
91+ (long "enable-library-profiling" <>
92+ help "Enable profiling when building") <*>
93+ switch
94+ (long "enable-executable-dynamic" <>
95+ help "Enable dynamic executables when building") <*>
96+ switch
97+ (long "verbose" <> short 'v' <>
98+ help "Output verbose detail about the build steps") <*>
99+ switch
100+ (long "skip-check" <>
101+ help "Skip the check phase, and pass --allow-newer to cabal configure")
102+
103+ nightlyUploadFlags = fromString <$> strArgument
104+ (metavar "DATE" <>
105+ help "Date, in YYYY-MM-DD format")
106+
107+ installFlags =
108+ InstallFlags <$>
109+ (fmap
110+ BPSBundleWeb
111+ (strOption
112+ (long "bundle" <>
113+ metavar "URL" <>
114+ help "Stackage bundle containing build plan")) <|>
115+ fmap
116+ (BPSFile . decodeString)
117+ (strOption
118+ (long "build-plan" <>
119+ metavar "PATH" <>
120+ help "Build-plan YAML file"))) <*>
121+ fmap
122+ decodeString
123+ (strArgument
124+ (metavar "DESTINATION-PATH" <>
125+ help "Destination directory path")) <*>
126+ (fmap
127+ (Just . decodeString)
128+ (strOption
129+ (long "log-dir" <>
130+ metavar "PATH" <>
131+ help "Location of log files (default DESTINATION-PATH/logs)")) <|>
132+ pure Nothing) <*>
133+ option
134+ auto
135+ (long "jobs" <>
136+ metavar "NUMBER" <>
137+ showDefault <> value 8 <>
138+ help "Number of threads") <*>
139+ switch
140+ (long "global" <>
141+ help "Install in global package database") <*>
142+ fmap
143+ not
144+ (switch
145+ (long "skip-tests" <>
146+ help "Skip build and running the test suites")) <*>
147+ fmap
148+ not
149+ (switch
150+ (long "skip-haddock" <>
151+ help "Skip generating haddock documentation")) <*>
152+ switch
153+ (long "enable-library-profiling" <>
154+ help "Enable profiling when building") <*>
155+ switch
156+ (long "enable-executable-dynamic" <>
157+ help "Enable dynamic executables when building") <*>
158+ switch
159+ (long "verbose" <> short 'v' <>
160+ help "Output verbose detail about the build steps") <*>
161+ switch
162+ (long "skip-check" <>
163+ help "Skip the check phase, and pass --allow-newer to cabal configure")
build-constraints.yaml+285−53
@@ -2,7 +2,7 @@
2packages:
2packages:
3 "Michael Snoyman michael@snoyman.com @snoyberg":
3 "Michael Snoyman michael@snoyman.com @snoyberg":
4 - bzlib-conduit
4 - bzlib-conduit
5− - cabal-install < 1.19
5+ - cabal-install < 1.19 # GHC 7.10 bumpd to 1.22
6 - cabal-src
6 - cabal-src
7 - case-insensitive
7 - case-insensitive
8 - classy-prelude-yesod
8 - classy-prelude-yesod
@@ -27,7 +27,10 @@ packages:
27 - warp-tls
27 - warp-tls
28 - yackage
28 - yackage
29 - yesod
29 - yesod
30+ - yesod-auth
31+ - yesod-auth-oauth
30 - yesod-auth-deskcom
32 - yesod-auth-deskcom
33+ - authenticate-oauth
31 - yesod-bin
34 - yesod-bin
32 - yesod-eventsource
35 - yesod-eventsource
33 - yesod-fay
36 - yesod-fay
@@ -42,6 +45,11 @@ packages:
42 - repa-algorithms
45 - repa-algorithms
43 - repa-devil
46 - repa-devil
44 - JuicyPixels-repa
47 - JuicyPixels-repa
48+ - cereal-conduit
49+ - binary-conduit
50+ - lzma-conduit
51+ - mutable-containers
52+ - hpc-coveralls
45
53
46 "FP Complete michael@fpcomplete.com @snoyberg":
54 "FP Complete michael@fpcomplete.com @snoyberg":
47 - alex
55 - alex
@@ -64,7 +72,7 @@ packages:
64 - fixed-list
72 - fixed-list
65 - foreign-store
73 - foreign-store
66 - formatting
74 - formatting
67− - fpco-api
75+ #- fpco-api
68 - gtk2hs-buildtools
76 - gtk2hs-buildtools
69 - happy
77 - happy
70 - histogram-fill
78 - histogram-fill
@@ -105,18 +113,18 @@ packages:
105 - distributed-process-async
113 - distributed-process-async
106 - distributed-process-client-server
114 - distributed-process-client-server
107 - distributed-process-supervisor
115 - distributed-process-supervisor
108−
109− # https://github.com/fpco/stackage/issues/381
110− #- distributed-process-task
116+ - distributed-process-task
111− #- distributed-process-execution
117+ - distributed-process-execution
112
118
113 - kure
119 - kure
114
120
115 "Omari Norman <omari@smileystation.com>":
121 "Omari Norman <omari@smileystation.com>":
116 - barecheck
122 - barecheck
117 - rainbow
123 - rainbow
118− - rainbow-tests
119 - quickpull
124 - quickpull
125+ - multiarg
126+ - prednote
127+ - cartel
120
128
121 "Neil Mitchell":
129 "Neil Mitchell":
122 - hlint
130 - hlint
@@ -144,6 +152,7 @@ packages:
144 "Jasper Van der Jeugt":
152 "Jasper Van der Jeugt":
145 - blaze-html
153 - blaze-html
146 - blaze-markup
154 - blaze-markup
155+ - hakyll
147 - stylish-haskell
156 - stylish-haskell
148
157
149 "Antoine Latter":
158 "Antoine Latter":
@@ -175,7 +184,6 @@ packages:
175 - crypto-random-api
184 - crypto-random-api
176 - hit
185 - hit
177 - language-java
186 - language-java
178− - language-java
179 - libgit
187 - libgit
180 - pem
188 - pem
181 - siphash
189 - siphash
@@ -202,8 +210,11 @@ packages:
202 - scrobble
210 - scrobble
203 - shell-conduit
211 - shell-conduit
204 - sourcemap
212 - sourcemap
213+ - hindent
214+ - descriptive
215+ - wrap
205 # requires old haddock currently - haskell-docs
216 # requires old haddock currently - haskell-docs
206− # TODO: Add hindent and structured-haskell-mode once they've been ported to HSE 1.16.
217+ # TODO: Add structured-haskell-mode once they've been ported to HSE 1.16.
207
218
208 # GHC 7.6
219 # GHC 7.6
209 # "Alberto G. Corona <agocorona@gmail.com>":
220 # "Alberto G. Corona <agocorona@gmail.com>":
@@ -253,7 +264,7 @@ packages:
253 - monad-products
264 - monad-products
254 - monad-st
265 - monad-st
255 - monad-st
266 - monad-st
256− - mtl < 2.2
267+ - mtl < 2.2 # GHC 7.10 bump
257 - nats
268 - nats
258 - numeric-extras
269 - numeric-extras
259 - parsers
270 - parsers
@@ -304,8 +315,9 @@ packages:
304
315
305 "Brent Yorgey <byorgey@gmail.com>":
316 "Brent Yorgey <byorgey@gmail.com>":
306 - active
317 - active
318+ # Temporarily disabled due to restrictive lens upper bound
307− - BlogLiterately
319+ #- BlogLiterately
308− - BlogLiterately-diagrams
320+ #- BlogLiterately-diagrams
309 - diagrams
321 - diagrams
310 - diagrams-builder
322 - diagrams-builder
311 - diagrams-contrib
323 - diagrams-contrib
@@ -325,6 +337,8 @@ packages:
325 - JuicyPixels
337 - JuicyPixels
326 - FontyFruity
338 - FontyFruity
327 - Rasterific
339 - Rasterific
340+ - svg-tree
341+ - rasterific-svg
328
342
329 "Patrick Brisbin":
343 "Patrick Brisbin":
330 - gravatar
344 - gravatar
@@ -365,6 +379,7 @@ packages:
365 - pipes
379 - pipes
366 - pipes-parse
380 - pipes-parse
367 - pipes-concurrency
381 - pipes-concurrency
382+ - pipes-safe
368
383
369 "Chris Allen <cma@bitemyapp.com>":
384 "Chris Allen <cma@bitemyapp.com>":
370 - bloodhound
385 - bloodhound
@@ -378,6 +393,10 @@ packages:
378 - fay-uri
393 - fay-uri
379 - snaplet-fay
394 - snaplet-fay
380
395
396+ "Sebastiaan Visser <haskell@fvisser.nl>":
397+ - clay
398+ - fclabels
399+
381 "Rodrigo Setti <rodrigosetti@gmail.com>":
400 "Rodrigo Setti <rodrigosetti@gmail.com>":
382 - messagepack
401 - messagepack
383 - messagepack-rpc
402 - messagepack-rpc
@@ -399,9 +418,11 @@ packages:
399 - hPDB
418 - hPDB
400 - hPDB-examples
419 - hPDB-examples
401
420
402− # https://github.com/fpco/stackage/pull/382#issuecomment-68182467
403− # - wordpass
421+ - wordpass
404− # - json-autotype
422+ - json-autotype
423+
424+ "Dominic Steinitz <dominic@steinitz.org>":
425+ - yarr
405
426
406 "Roman Cheplyaka <roma@ro-che.info>":
427 "Roman Cheplyaka <roma@ro-che.info>":
407 - action-permutations
428 - action-permutations
@@ -431,6 +452,7 @@ packages:
431 "George Giorgidze <giorgidze@gmail.com>":
452 "George Giorgidze <giorgidze@gmail.com>":
432 - HCodecs
453 - HCodecs
433 - YampaSynth
454 - YampaSynth
455+ - set-monad
434
456
435 "Phil Hargett <phil@haphazardhouse.net>":
457 "Phil Hargett <phil@haphazardhouse.net>":
436 - courier
458 - courier
@@ -444,6 +466,8 @@ packages:
444 - circle-packing
466 - circle-packing
445 - arbtt
467 - arbtt
446 - ghc-heap-view
468 - ghc-heap-view
469+ - tttool
470+ - gipeda
447
471
448 "Aditya Bhargava <adit@adit.io":
472 "Aditya Bhargava <adit@adit.io":
449 - HandsomeSoup
473 - HandsomeSoup
@@ -453,7 +477,8 @@ packages:
453 - openpgp-asciiarmor
477 - openpgp-asciiarmor
454 - MusicBrainz
478 - MusicBrainz
455 - DAV
479 - DAV
480+ # https://github.com/fpco/stackage/issues/463
456− - hopenpgp-tools
481+ #- hopenpgp-tools
457
482
458 # https://github.com/fpco/stackage/issues/160
483 # https://github.com/fpco/stackage/issues/160
459 "Ketil Malde":
484 "Ketil Malde":
@@ -483,9 +508,9 @@ packages:
483 - code-builder
508 - code-builder
484 - fay-builder
509 - fay-builder
485 - generic-aeson
510 - generic-aeson
511+ - generic-xmlpickler
486 - hxt-pickle-utils
512 - hxt-pickle-utils
487 - imagesize-conduit
513 - imagesize-conduit
488− - imagesize-conduit
489 - json-schema
514 - json-schema
490 - multipart
515 - multipart
491 - regular-xmlpickler
516 - regular-xmlpickler
@@ -498,8 +523,6 @@ packages:
498 - rest-types
523 - rest-types
499 - rest-wai
524 - rest-wai
500 - tostring
525 - tostring
501− - tostring
502− - uri-encode
503 - uri-encode
526 - uri-encode
504
527
505 "Simon Michael <simon@joyful.com>":
528 "Simon Michael <simon@joyful.com>":
@@ -509,7 +532,10 @@ packages:
509 - io-manager
532 - io-manager
510
533
511 "Dimitri Sabadie <dimitri.sabadie@gmail.com":
534 "Dimitri Sabadie <dimitri.sabadie@gmail.com":
535+ # https://github.com/fpco/stackage/pull/461#issuecomment-76914158
536+ # - al
512 - monad-journal
537 - monad-journal
538+ - smoothie
513
539
514 "Thomas Schilling <nominolo@googlemail.com>":
540 "Thomas Schilling <nominolo@googlemail.com>":
515 - ghc-syb-utils
541 - ghc-syb-utils
@@ -543,6 +569,7 @@ packages:
543
569
544 "Emanuel Borsobom <manny@fpcomplete.com>":
570 "Emanuel Borsobom <manny@fpcomplete.com>":
545 - BoundedChan
571 - BoundedChan
572+ - broadcast-chan
546 - bytestring-lexing
573 - bytestring-lexing
547 - bytestring-trie
574 - bytestring-trie
548 - data-accessor
575 - data-accessor
@@ -553,6 +580,7 @@ packages:
553 - haddock-api
580 - haddock-api
554 - here
581 - here
555 - hlibgit2
582 - hlibgit2
583+ - gitlib-libgit2
556 - hostname-validate
584 - hostname-validate
557 - interpolatedstring-perl6
585 - interpolatedstring-perl6
558 - iproute
586 - iproute
@@ -561,6 +589,7 @@ packages:
561 - multimap
589 - multimap
562 - parallel-io
590 - parallel-io
563 - text-binary
591 - text-binary
592+ - wl-pprint-text
564
593
565 "Michael Sloan <mgsloan@gmail.com":
594 "Michael Sloan <mgsloan@gmail.com":
566 - th-orphans
595 - th-orphans
@@ -574,7 +603,7 @@ packages:
574 - hasql-backend
603 - hasql-backend
575 - hasql-postgres
604 - hasql-postgres
576 - list-t
605 - list-t
577− - mtl-prelude < 2
606+ - mtl-prelude < 2 # GHC 7.10 bump
578 - neat-interpolation
607 - neat-interpolation
579 - partial-handler
608 - partial-handler
580 - postgresql-binary
609 - postgresql-binary
@@ -588,6 +617,11 @@ packages:
588 - graph-core
617 - graph-core
589 - reroute
618 - reroute
590 - Spock
619 - Spock
620+ - Spock-digestive
621+ - Spock-worker
622+ - users
623+ - users-test
624+ - users-postgresql-simple
591
625
592 "Joey Eremondi <joey@eremondi.com>":
626 "Joey Eremondi <joey@eremondi.com>":
593 - aeson-pretty
627 - aeson-pretty
@@ -617,43 +651,138 @@ packages:
617 "Samplecount stefan@samplecount.com @kaoskorobase":
651 "Samplecount stefan@samplecount.com @kaoskorobase":
618 - shake-language-c
652 - shake-language-c
619
653
654+ "Marcin Mrotek <marcin.jan.mrotek@gmail.com>":
655+ - diagrams-hsqml
656+ - type-list
657+ - vinyl-utils
658+
620 "Marcin Mrotek <marcin.jan.mrotek@gmail.com>":
659 "Marcin Mrotek <marcin.jan.mrotek@gmail.com>":
621 - type-list
660 - type-list
622−
661+
623 "David Turner <dave.c.turner@gmail.com>":
662 "David Turner <dave.c.turner@gmail.com>":
624 - alarmclock
663 - alarmclock
625 - bank-holidays-england
664 - bank-holidays-england
626
665
666+ "Haskell Servant jkarni@gmail.com @jkarni":
667+ - servant
668+ - servant-client
669+ - servant-docs
670+ - servant-jquery
671+ - servant-server
672+
673+ "Alexandr Ruchkin voidex@live.com @mvoidex":
674+ - hdocs
675+ - hsdev
676+
677+ "Aleksey Kliger aleksey@lambdageek.org @lambdageek":
678+ - unbound-generics
679+
680+ "Alois Cochard alois.cochard@gmail.com @aloiscochard":
681+ - codex
682+ - machines-directory
683+ - machines-io
684+ - machines-process
685+ # on behalf of Bryan O'Sullivan @bos
686+ - wreq
687+
688+ "Andraz Bajt andraz@bajt.me @edofic":
689+ - effect-handlers
690+ - koofr-client
691+ - snowflake
692+
693+ "Leza M. Lutonda lemol-c@hotmail.com @lemol":
694+ - HaskellNet
695+
696+ "Jens Petersen juhpetersen@gmail.com @juhp":
697+ - cabal-rpm
698+
699+ "Renzo Carbonara renzocarbonara@gmail.com @k0001":
700+ - network-simple
701+ - pipes-aeson
702+ - pipes-attoparsec
703+ - pipes-binary
704+ - pipes-network
705+
706+ "Tomas Carnecky":
707+ - rethinkdb-client-driver
708+
709+ "Alexandr Kurilin alex@kurilin.net @alex_kurilin":
710+ - bcrypt
711+
712+ "Jeffrey Rosenbluth jeffrey.rosenbluth@gmail.com":
713+ - palette
714+ - diagrams-canvas
715+ - diagrams-rasterific
716+ - lucid-svg
717+
718+ "Gabríel Arthúr Pétursson gabriel@system.is":
719+ - sdl2
720+
721+ "Leon Mergen leon@solatis.com @solatis":
722+ - network-attoparsec
723+ - network-anonymous-i2p
724+
725+ "Timothy Jones git@zmthy.io @zmthy":
726+ - cabal-test-quickcheck
727+ - http-media
728+
729+ "Greg V greg@unrelenting.technology @myfreeweb":
730+ - gitson
731+ - pcre-heavy
732+
733+ "Francesco Mazzoli f@mazzo.li @bitonic":
734+ - language-c-quote
735+
736+ "Sönke Hahn soenkehahn@gmail.com @soenkehahn":
737+ - string-conversions
738+
739+ "Oleg Grenrus oleg.grenrus@iki.fi @phadej":
740+ - waitra
741+
627 "Stackage upper bounds":
742 "Stackage upper bounds":
628
743
629 # Force a specific version that's compatible with transformers 0.3
744 # Force a specific version that's compatible with transformers 0.3
630− - transformers-compat == 0.3.3.3
745+ - transformers-compat == 0.4.0.3
631−
746+
632− # https://github.com/fpco/stackage/issues/291
747+ # https://github.com/fpco/stackage/issues/390
633− - random < 1.0.1.3
748+ # NOTE: When this issue is resolved, remove the expected test failure
634−
749+ # for language-ecmascript as well.
750+ - language-ecmascript < 0.17
751+
752+ # https://github.com/fpco/stackage/issues/407
753+ - HStringTemplate < 0.8
754+
635− # https://github.com/fpco/stackage/issues/318
755+ # https://github.com/fpco/stackage/issues/410
636− - HaXml < 1.25
756+ - elm-package < 0.4
637−
757+
638− # https://github.com/fpco/stackage/issues/319
758+ # https://github.com/fpco/stackage/issues/415
639− - polyparse < 1.10
759+ - hackage-db < 1.12
640−
760+
641− # https://github.com/fpco/stackage/issues/370
761+ # https://github.com/fpco/stackage/issues/424
642− - monad-control < 1
762+ - control-monad-free < 0.6
643− - hasql < 0.5
763+
644− - list-t < 0.4
764+ # https://github.com/fpco/stackage/issues/426
645−
765+ - utf8-string < 1
646−# Global flags are applied to all packages
766+
647−global-flags:
767+ # https://github.com/fpco/stackage/issues/440
648− blaze_html_0_5: true
768+ - th-orphans < 0.9
649− small_base: true
769+ - file-location < 0.4.7
650− https: true
770+
651− splitbase: true
771+ # https://github.com/fpco/stackage/issues/442
652− old-locale: true
772+ - blaze-builder < 0.4
653− new-base: true
773+ - blaze-markup < 0.7
654− bytestring-in-base: false
774+ - blaze-html < 0.8
655− test-hlint: false
775+
656− network-uri: true
776+ # https://github.com/fpco/stackage/issues/443
777+ - exceptions < 0.7
778+ - rest-client < 0.5
779+ - rest-types < 1.13
780+ - rest-core < 0.35
781+ - rest-gen < 0.17
782+ - rest-wai < 0.1.0.7
783+
784+ # https://github.com/fpco/stackage/issues/467
785+ - lens < 4.8
657
786
658# Package flags are applied to individual packages, and override the values of
787# Package flags are applied to individual packages, and override the values of
659# global-flags
788# global-flags
@@ -672,6 +801,44 @@ package-flags:
672 simplelocalnet: true
801 simplelocalnet: true
673 p2p: true
802 p2p: true
674
803
804+ # GHC 7.10: Remove this
805+ # Note that the flag is lower-cased, because that's what Cabal does
806+ # Perhaps the codebase should automatically lower case flag names?
807+ storable-complex:
808+ instanceinbase: false
809+
810+ logfloat:
811+ splitbase: true
812+
813+ curl:
814+ new-base: true
815+
816+ # GHC 7.10 remove
817+ aeson:
818+ old-locale: true
819+ tttool:
820+ old-locale: true
821+
822+ hxt:
823+ network-uri: true
824+ hxt-http:
825+ network-uri: true
826+ hxt-relaxng:
827+ network-uri: true
828+
829+ pandoc:
830+ https: true
831+
832+ text:
833+ integer-simple: false
834+
835+ tar:
836+ old-time: false
837+
838+ mtl-compat:
839+ two-point-one: true
840+ two-point-two: false
841+
675# By skipping a test suite, we do not pull in the build dependencies
842# By skipping a test suite, we do not pull in the build dependencies
676skipped-tests:
843skipped-tests:
677 - ReadArgs # old version of hspec
844 - ReadArgs # old version of hspec
@@ -718,17 +885,15 @@ skipped-tests:
718 # https://github.com/fpco/stackage/pull/380#issuecomment-68060871
885 # https://github.com/fpco/stackage/pull/380#issuecomment-68060871
719 - Rasterific
886 - Rasterific
720
887
888+ # https://github.com/Soostone/retry/issues/18
889+ - retry
890+
721# Tests which we should build and run, but which are expected to fail. We
891# Tests which we should build and run, but which are expected to fail. We
722# should not fail a build based on a test failure for one of these packages.
892# should not fail a build based on a test failure for one of these packages.
723expected-test-failures:
893expected-test-failures:
724 # Requires an old version of WAI and Warp for tests
894 # Requires an old version of WAI and Warp for tests
725 - HTTP
895 - HTTP
726
896
727− # text and setenv have recursive dependencies in their tests, which
728− # cabal can't (yet) handle
729− - text
730− - setenv
731−
732 # https://github.com/bos/statistics/issues/42
897 # https://github.com/bos/statistics/issues/42
733 - statistics
898 - statistics
734
899
@@ -852,6 +1017,61 @@ expected-test-failures:
852 - crypto-numbers
1017 - crypto-numbers
853 - distributed-process-task
1018 - distributed-process-task
854
1019
1020+ # https://github.com/vincenthz/hs-crypto-pubkey/issues/17
1021+ - crypto-pubkey
1022+
1023+ # https://github.com/jswebtools/language-ecmascript/issues/60
1024+ - language-ecmascript
1025+
1026+ # https://github.com/kazu-yamamoto/unix-time/issues/29
1027+ - unix-time
1028+
1029+ # Tests can fail when the build plan fails, which happens arbitrarily.
1030+ - stackage
1031+
1032+ # https://github.com/TomMD/DRBG/issues/7
1033+ - DRBG
1034+
1035+ # https://github.com/bos/wreq/issues/53
1036+ - wreq
1037+
1038+ # Requires local database running
1039+ - rethinkdb-client-driver
1040+
1041+ # https://github.com/haskell-distributed/distributed-process-execution/issues/2
1042+ - distributed-process-execution
1043+
1044+ # Seems to depend on mtl being installed in user package database, which
1045+ # isn't always the case (e.g., build server)
1046+ - happy
1047+
1048+ # https://github.com/jberryman/directory-tree/issues/4
1049+ - directory-tree
1050+
1051+ # https://github.com/zmthy/http-media/issues/11
1052+ - http-media
1053+
1054+ # https://github.com/ekmett/semigroupoids/issues/18
1055+ - semigroupoids
1056+
1057+ # https://github.com/ndmitchell/hoogle/issues/101
1058+ - hoogle
1059+
1060+ # https://github.com/myfreeweb/gitson/issues/1
1061+ - gitson
1062+
1063+ # https://github.com/jcristovao/enclosed-exceptions/issues/6
1064+ - enclosed-exceptions
1065+
1066+ # Expects a running PostgreSQL server
1067+ - users-postgresql-simple
1068+
1069+ # Problems with linking with system libraries on Ubuntu 12.04
1070+ - nettle
1071+
1072+ # Requires locally running services
1073+ - network-anonymous-i2p
1074+
855# Haddocks which are expected to fail. Same concept as expected test failures.
1075# Haddocks which are expected to fail. Same concept as expected test failures.
856expected-haddock-failures:
1076expected-haddock-failures:
857 # https://github.com/acw/bytestring-progress/issues/4
1077 # https://github.com/acw/bytestring-progress/issues/4
@@ -860,6 +1080,12 @@ expected-haddock-failures:
860 # https://github.com/ekmett/gl/issues/4
1080 # https://github.com/ekmett/gl/issues/4
861 - gl
1081 - gl
862
1082
1083+ # https://github.com/leventov/yarr/issues/5
1084+ - yarr
1085+
1086+ # https://github.com/wereHamster/rethinkdb-client-driver/issues/1
1087+ - rethinkdb-client-driver
1088+
863# Benchmarks which should not be built. Note that Stackage does *not* generally
1089# Benchmarks which should not be built. Note that Stackage does *not* generally
864# build benchmarks. The difference here will be whether dependencies for these
1090# build benchmarks. The difference here will be whether dependencies for these
865# benchmarks are included or not.
1091# benchmarks are included or not.
@@ -886,6 +1112,10 @@ skipped-benchmarks:
886 # sometimes falls out-of-sync on hasql-postgres
1112 # sometimes falls out-of-sync on hasql-postgres
887 - hasql
1113 - hasql
888
1114
1115+skipped-profiling:
1116+ # https://github.com/nomeata/ghc-heap-view/commit/8d198eb8fbbad2ce0c4527c781659f35b8909c04#diff-8288955e209cfbead5b318a8598be9c0R10
1117+ - ghc-heap-view
1118+
889# Mapping from Github account holding a package to the Github users who should
1119# Mapping from Github account holding a package to the Github users who should
890# be pinged on failure. If no value is specified here, then the owning account
1120# be pinged on failure. If no value is specified here, then the owning account
891# will be pinged.
1121# will be pinged.
@@ -908,3 +1138,5 @@ github-users:
908 - mightybyte
1138 - mightybyte
909 haskell-ro:
1139 haskell-ro:
910 - mihaimaruseac
1140 - mihaimaruseac
1141+ elm-lang:
1142+ - JoeyEremondi
cabal.config+1−1
@@ -647,7 +647,7 @@ constraints: abstract-deque ==0.3,
647 semigroups ==0.16.0.1,
647 semigroups ==0.16.0.1,
648 sendfile ==0.7.9,
648 sendfile ==0.7.9,
649 seqloc ==0.6,
649 seqloc ==0.6,
650− setenv ==0.1.1.1,
650+ setenv ==0.1.1.2,
651 SHA ==1.6.4.1,
651 SHA ==1.6.4.1,
652 shake ==0.14.2,
652 shake ==0.14.2,
653 shake-language-c ==0.6.3,
653 shake-language-c ==0.6.3,
debian-bootstrap.sh+27−5
@@ -10,13 +10,17 @@
10# instructions, see:
10# instructions, see:
11# http://www.stackage.org/install
11# http://www.stackage.org/install
12
12
13−sudo add-apt-repository -y ppa:chris-lea/zeromq
13+add-apt-repository -y ppa:chris-lea/zeromq
14−sudo add-apt-repository -y ppa:floe/libtisch
14+add-apt-repository -y ppa:floe/libtisch
15+add-apt-repository -y ppa:zoogie/sdl2-snapshots
15−sudo apt-get update
16+apt-get update
16−sudo apt-get install -y \
17+apt-get install -y \
17 build-essential \
18 build-essential \
18 libncurses-dev \
19 libncurses-dev \
19 git \
20 git \
21+ wget \
22+ m4 \
23+ texlive-full \
20 libgmp3c2 \
24 libgmp3c2 \
21 libgmp3-dev \
25 libgmp3-dev \
22 zlib1g-dev \
26 zlib1g-dev \
@@ -33,11 +37,11 @@ sudo apt-get install -y \
33 llvm \
37 llvm \
34 libbz2-dev \
38 libbz2-dev \
35 libjudy-dev \
39 libjudy-dev \
40+ libsqlite3-dev \
36 libmysqlclient-dev \
41 libmysqlclient-dev \
37 libpq-dev \
42 libpq-dev \
38 libicu-dev \
43 libicu-dev \
39 libssl-dev \
44 libssl-dev \
40− nettle-dev \
41 libgsl0-dev \
45 libgsl0-dev \
42 libblas-dev \
46 libblas-dev \
43 liblapack-dev \
47 liblapack-dev \
@@ -46,4 +50,22 @@ sudo apt-get install -y \
46 libnotify-dev \
50 libnotify-dev \
47 libgd2-xpm-dev \
51 libgd2-xpm-dev \
48 libyaml-dev \
52 libyaml-dev \
53+ liblzma-dev \
54+ libsdl2-dev \
55+ libxss-dev \
49 libzmq3-dev
56 libzmq3-dev
57+
58+mkdir /tmp/nettle-build
59+(
60+cd /tmp/nettle-build
61+wget https://ftp.gnu.org/gnu/nettle/nettle-2.7.1.tar.gz
62+tar zxf nettle-2.7.1.tar.gz
63+cd nettle-2.7.1
64+./configure --prefix=/usr
65+make
66+make install
67+
68+mkdir -p /usr/lib/x86_64-linux-gnu/
69+ln -sfv /usr/lib/libnettle.so.4.7 /usr/lib/x86_64-linux-gnu/libnettle.so.4
70+)
71+rm -rf /tmp/nettle-build
stackage.cabal+7−1
@@ -1,5 +1,5 @@
1name: stackage
1name: stackage
2−version: 0.4.0
2+version: 0.5.2
3synopsis: "Stable Hackage," tools for creating a vetted set of packages from Hackage.
3synopsis: "Stable Hackage," tools for creating a vetted set of packages from Hackage.
4description: Please see <http://www.stackage.org/package/stackage> for a description and documentation.
4description: Please see <http://www.stackage.org/package/stackage> for a description and documentation.
5homepage: https://github.com/fpco/stackage
5homepage: https://github.com/fpco/stackage
@@ -12,6 +12,7 @@ build-type: Simple
12cabal-version: >=1.10
12cabal-version: >=1.10
13extra-source-files: README.md
13extra-source-files: README.md
14 ChangeLog.md
14 ChangeLog.md
15+ test/test-build-constraints.yaml
15
16
16library
17library
17 default-language: Haskell2010
18 default-language: Haskell2010
@@ -22,7 +23,9 @@ library
22 Stackage.BuildPlan
23 Stackage.BuildPlan
23 Stackage.CheckBuildPlan
24 Stackage.CheckBuildPlan
24 Stackage.UpdateBuildPlan
25 Stackage.UpdateBuildPlan
26+ Stackage.GhcPkg
25 Stackage.GithubPings
27 Stackage.GithubPings
28+ Stackage.InstallBuild
26 Stackage.PackageDescription
29 Stackage.PackageDescription
27 Stackage.ServerBundle
30 Stackage.ServerBundle
28 Stackage.Upload
31 Stackage.Upload
@@ -62,6 +65,7 @@ library
62 , streaming-commons >= 0.1.7.1
65 , streaming-commons >= 0.1.7.1
63 , semigroups
66 , semigroups
64 , xml-conduit
67 , xml-conduit
68+ , conduit
65
69
66executable stackage
70executable stackage
67 default-language: Haskell2010
71 default-language: Haskell2010
@@ -69,6 +73,8 @@ executable stackage
69 main-is: stackage.hs
73 main-is: stackage.hs
70 build-depends: base
74 build-depends: base
71 , stackage
75 , stackage
76+ , optparse-applicative >= 0.11
77+ , system-filepath
72 ghc-options: -rtsopts -threaded -with-rtsopts=-N
78 ghc-options: -rtsopts -threaded -with-rtsopts=-N
73
79
74test-suite spec
80test-suite spec
test/Stackage/BuildPlanSpec.hs+119−14
@@ -1,21 +1,66 @@
1+{-# LANGUAGE ScopedTypeVariables #-}
1{-# LANGUAGE OverloadedStrings, NoImplicitPrelude #-}
2{-# LANGUAGE OverloadedStrings, NoImplicitPrelude #-}
2module Stackage.BuildPlanSpec (spec) where
3module Stackage.BuildPlanSpec (spec) where
3
4
4−import Stackage.BuildPlan
5−import Stackage.Prelude
6−import Stackage.BuildConstraints
7−import Stackage.UpdateBuildPlan
8−import Test.Hspec
9−import qualified Data.Yaml as Y
10−import Distribution.Version (anyVersion)
11import qualified Data.Map as Map
5import qualified Data.Map as Map
6+import qualified Data.Map.Strict as M
7+import qualified Data.Set as S
8+import Data.Yaml
9+import qualified Data.Yaml as Y
10+import Distribution.Version
12−import Network.HTTP.Client (withManager)
11+import Network.HTTP.Client
13−import Network.HTTP.Client.TLS (tlsManagerSettings)
12+import Network.HTTP.Client.TLS (tlsManagerSettings)
13+import Stackage.BuildConstraints
14+import Stackage.BuildPlan
15+import Stackage.CheckBuildPlan
16+import Stackage.PackageDescription
17+import Stackage.Prelude
18+import Stackage.UpdateBuildPlan
19+import Test.Hspec
14
20
15spec :: Spec
21spec :: Spec
22+spec = do
23+ it "simple package set" $ check testBuildConstraints $ makePackageSet
24+ [("foo", [0, 0, 0], [("bar", thisV [0, 0, 0])])
25+ ,("bar", [0, 0, 0], [])]
26+ it "bad version range on depdendency fails" $ badBuildPlan $ makePackageSet
27+ [("foo", [0, 0, 0], [("bar", thisV [1, 1, 0])])
28+ ,("bar", [0, 0, 0], [])]
29+ it "nonexistent package fails to check" $ badBuildPlan $ makePackageSet
30+ [("foo", [0, 0, 0], [("nonexistent", thisV [0, 0, 0])])
31+ ,("bar", [0, 0, 0], [])]
32+ it "mutual cycles fail to check" $ badBuildPlan $ makePackageSet
33+ [("foo", [0, 0, 0], [("bar", thisV [0, 0, 0])])
34+ ,("bar", [0, 0, 0], [("foo", thisV [0, 0, 0])])]
35+ it "nested cycles fail to check" $ badBuildPlan $ makePackageSet
36+ [("foo", [0, 0, 0], [("bar", thisV [0, 0, 0])])
37+ ,("bar", [0, 0, 0], [("mu", thisV [0, 0, 0])])
38+ ,("mu", [0, 0, 0], [("foo", thisV [0, 0, 0])])]
39+ {- Shouldn't be testing this actually
40+ it "default package set checks ok" $
41+ check defaultBuildConstraints getLatestAllowedPlans
42+ -}
43+
44+-- | Checking should be considered a bad build plan.
45+badBuildPlan :: (BuildConstraints -> IO (Map PackageName PackagePlan))
46+ -> void
47+ -> IO ()
48+badBuildPlan m _ = do
49+ mu <- try (check testBuildConstraints m)
50+ case mu of
51+ Left (_ :: BadBuildPlan) ->
52+ return ()
53+ Right () ->
54+ error "Expected bad build plan."
55+
56+-- | Check build plan with the given package set getter.
57+check :: (Manager -> IO BuildConstraints)
58+ -> (BuildConstraints -> IO (Map PackageName PackagePlan))
59+ -> IO ()
16−spec = it "works" $ withManager tlsManagerSettings $ \man -> do
60+check readPlanFile getPlans = withManager tlsManagerSettings $ \man -> do
17− bc <- defaultBuildConstraints man
61+ bc <- readPlanFile man
62+ plans <- getPlans bc
18− bp <- newBuildPlan bc
63+ bp <- newBuildPlan plans bc
19 let bs = Y.encode bp
64 let bs = Y.encode bp
20 ebp' = Y.decodeEither bs
65 ebp' = Y.decodeEither bs
21
66
@@ -25,14 +70,74 @@ spec = it "works" $ withManager tlsManagerSettings $ \man -> do
25 forM_ allPackages $ \name ->
70 forM_ allPackages $ \name ->
26 (name, lookup name (bpPackages bp')) `shouldBe`
71 (name, lookup name (bpPackages bp')) `shouldBe`
27 (name, lookup name (bpPackages bp))
72 (name, lookup name (bpPackages bp))
28−
29 bpGithubUsers bp' `shouldBe` bpGithubUsers bp
73 bpGithubUsers bp' `shouldBe` bpGithubUsers bp
74+
30 when (bp' /= bp) $ error "bp' /= bp"
75 when (bp' /= bp) $ error "bp' /= bp"
31− bp2 <- updateBuildPlan bp
76+ bp2 <- updateBuildPlan plans bp
32 when (dropVersionRanges bp2 /= dropVersionRanges bp) $ error "bp2 /= bp"
77 when (dropVersionRanges bp2 /= dropVersionRanges bp) $ error "bp2 /= bp"
78+ checkBuildPlan bp
33 where
79 where
34 dropVersionRanges bp =
80 dropVersionRanges bp =
35 bp { bpPackages = map go $ bpPackages bp }
81 bp { bpPackages = map go $ bpPackages bp }
36 where
82 where
37 go pb = pb { ppConstraints = go' $ ppConstraints pb }
83 go pb = pb { ppConstraints = go' $ ppConstraints pb }
38 go' pc = pc { pcVersionRange = anyVersion }
84 go' pc = pc { pcVersionRange = anyVersion }
85+
86+-- | Make a package set from a convenient data structure.
87+makePackageSet
88+ :: [(String,[Int],[(String,VersionRange)])]
89+ -> BuildConstraints
90+ -> IO (Map PackageName PackagePlan)
91+makePackageSet ps _ =
92+ return $
93+ M.fromList $
94+ map
95+ (\(name,ver,deps) ->
96+ ( PackageName name
97+ , dummyPackage ver $
98+ M.fromList $
99+ map
100+ (\(dname,dver) ->
101+ ( PackageName dname
102+ , DepInfo {diComponents = S.fromList
103+ [CompLibrary]
104+ ,diRange = dver}))
105+ deps))
106+ ps
107+ where
108+ dummyPackage v deps =
109+ PackagePlan
110+ {ppVersion = Version v []
111+ ,ppGithubPings = mempty
112+ ,ppUsers = mempty
113+ ,ppConstraints =
114+ PackageConstraints
115+ {pcVersionRange = anyV
116+ ,pcMaintainer = Nothing
117+ ,pcTests = Don'tBuild
118+ ,pcHaddocks = Don'tBuild
119+ ,pcBuildBenchmarks = False
120+ ,pcFlagOverrides = mempty
121+ ,pcEnableLibProfile = False}
122+ ,ppDesc =
123+ SimpleDesc
124+ {sdPackages = deps
125+ ,sdTools = mempty
126+ ,sdProvidedExes = mempty
127+ ,sdModules = mempty}}
128+
129+-- | This exact version is required.
130+thisV :: [Int] -> VersionRange
131+thisV ver = thisVersion (Version ver [])
132+
133+-- | Accept any version.
134+anyV :: VersionRange
135+anyV = anyVersion
136+
137+-- | Test plan.
138+testBuildConstraints :: void -> IO BuildConstraints
139+testBuildConstraints _ =
140+ decodeFileEither
141+ (fpToString fp) >>=
142+ either throwIO toBC
143+ where fp = "test/test-build-constraints.yaml"
test/test-build-constraints.yamlnew file+20
@@ -0,0 +1,20 @@
1+packages:
2+ "Test":
3+ - foo
4+ - bar
5+
6+global-flags: []
7+
8+skipped-tests: []
9+expected-test-failures: []
10+expected-haddock-failures: []
11+skipped-benchmarks: []
12+skipped-profiling: []
13+
14+github-users:
15+ bar:
16+ - demo
17+
18+package-flags:
19+ foo:
20+ demo: true