1{-# LANGUAGE NoImplicitPrelude #-}
2{-# LANGUAGE OverloadedStrings #-}
3{-# LANGUAGE RecordWildCards #-}
4module Stackage.CompleteBuild
12import Control.Concurrent (threadDelay)
13import Control.Concurrent.Async (withAsync)
14import Data.Default.Class (def)
15import Data.Semigroup (Max (..), Option (..))
16import Data.Text.Read (decimal)
18import Data.Yaml (decodeFileEither, encodeFile)
19import Network.HTTP.Client
20import Network.HTTP.Client.TLS (tlsManagerSettings)
21import Stackage.BuildConstraints
22import Stackage.BuildPlan
23import Stackage.CheckBuildPlan
24import Stackage.PerformBuild
25import Stackage.Prelude
26import Stackage.ServerBundle
27import Stackage.UpdateBuildPlan
29import System.IO (BufferMode (LineBuffering), hSetBuffering)
31-- | Flags passed in from the command line.
32data BuildFlags = BuildFlags
33 { bfEnableTests :: !Bool
35 , bfEnableLibProfile :: !Bool
39data BuildType = Nightly | LTS BumpType
40 deriving (Show, Read, Eq, Ord)
42data BumpType = Major | Minor
43 deriving (Show, Read, Eq, Ord)
45data Settings = Settings
47 , planFile :: FilePath
48 , buildDir :: FilePath
50 , title :: Text -> Text -- ^ GHC version -> title
52 , setArgs :: Text -> UploadBundle -> UploadBundle
56getSettings :: Manager -> BuildType -> IO Settings
57getSettings man Nightly = do
58 day <- tshow . utctDay <$> getCurrentTime
59 let slug' = "nightly-" ++ day
60 bc <- defaultBuildConstraints man
61 pkgs <- getLatestAllowedPlans bc
62 plan' <- newBuildPlan pkgs bc
64 { planFile = fpFromText ("nightly-" ++ day) <.> "yaml"
65 , buildDir = fpFromText $ "builds/stackage-nightly-" ++ day
66 , logDir = fpFromText $ "logs/stackage-nightly-" ++ day
67 , title = \ghcVer -> concat
74 , setArgs = \ghcVer ub -> ub { ubNightly = Just ghcVer }
76 , postBuild = return ()
78getSettings man (LTS bumpType) = do
79 Option mlts <- fmap (fmap getMax) $ runResourceT
81 $$ foldMapC (Option . fmap Max . parseLTSVer . filename)
83 (new, plan') <- case bumpType of
88 Just (LTSVer x _) -> LTSVer (x + 1) 0
89 bc <- defaultBuildConstraints man
90 pkgs <- getLatestAllowedPlans bc
91 plan' <- newBuildPlan pkgs bc
94 old <- maybe (error "No LTS plans found in current directory") return mlts
95 oldplan <- decodeFileEither (fpToString $ renderLTSVer old)
96 >>= either throwM return
97 let new = incrLTSVer old
98 let bc = updateBuildConstraints oldplan
99 pkgs <- getLatestAllowedPlans bc
100 plan' <- newBuildPlan pkgs bc
103 let newfile = renderLTSVer new
107 , buildDir = fpFromText $ "builds/stackage-lts-" ++ tshow new
108 , logDir = fpFromText $ "logs/stackage-lts-" ++ tshow new
109 , title = \ghcVer -> concat
115 , slug = "lts-" ++ tshow new
116 , setArgs = \_ ub -> ub { ubLTS = Just $ tshow new }
119 let git args = withCheckedProcess
120 (proc "git" args) $ \ClosedStream Inherited Inherited ->
122 putStrLn "Committing new LTS file to Git"
123 git ["add", fpToString newfile]
124 git ["commit", "-m", "Added new LTS release: " ++ show new]
125 putStrLn "Pushing to Git repository"
129data LTSVer = LTSVer !Int !Int
131instance Show LTSVer where
132 show (LTSVer x y) = concat [show x, ".", show y]
133incrLTSVer :: LTSVer -> LTSVer
134incrLTSVer (LTSVer x y) = LTSVer x (y + 1)
136parseLTSVer :: FilePath -> Maybe LTSVer
138 w <- stripPrefix "lts-" $ fpToText fp
139 x <- stripSuffix ".yaml" w
140 Right (major, y) <- Just $ decimal x
141 z <- stripPrefix "." y
142 Right (minor, "") <- Just $ decimal z
143 return $ LTSVer major minor
144renderLTSVer :: LTSVer -> FilePath
145renderLTSVer lts = fpFromText $ concat
151-- | Just print a message saying "still alive" every minute, to appease Travis.
152stillAlive :: IO () -> IO ()
154 withAsync (printer 1) $ const inner
156 printer i = forever $ do
158 putStrLn $ "Still alive: " ++ tshow i
161-- | Generate and check a new build plan, but do not execute it.
165justCheck = stillAlive $ withManager tlsManagerSettings $ \man -> do
166 putStrLn "Loading build constraints"
167 bc <- defaultBuildConstraints man
169 putStrLn "Creating build plan"
170 plans <- getLatestAllowedPlans bc
171 plan <- newBuildPlan plans bc
173 putStrLn $ "Writing build plan to check-plan.yaml"
174 encodeFile "check-plan.yaml" plan
176 putStrLn "Checking plan"
179 putStrLn "Plan seems valid!"
181-- | Make a complete plan, build, test and upload bundle, docs and
183completeBuild :: BuildType -> BuildFlags -> IO ()
184completeBuild buildType buildFlags = withManager tlsManagerSettings $ \man -> do
185 hSetBuffering stdout LineBuffering
187 putStrLn $ "Loading settings for: " ++ tshow buildType
188 settings@Settings {..} <- getSettings man buildType
190 putStrLn $ "Writing build plan to: " ++ fpToText planFile
191 encodeFile (fpToString planFile) plan
193 putStrLn "Checking build plan"
196 putStrLn "Performing build"
197 let pb = PerformBuild
199 , pbInstallDest = buildDir
201 , pbLog = hPut stdout
203 , pbGlobalInstall = False
204 , pbEnableTests = bfEnableTests buildFlags
205 , pbEnableLibProfiling = bfEnableLibProfile buildFlags
206 , pbVerbose = bfVerbose buildFlags
208 performBuild pb >>= mapM_ putStrLn
210 when (bfDoUpload buildFlags) $
211 finallyUpload settings man pb
213-- | The final part of the complete build process: uploading a bundle,
214-- docs and a distro to hackage.
215finallyUpload :: Settings -> Manager -> PerformBuild -> IO ()
216finallyUpload Settings{..} man pb = do
217 putStrLn "Uploading bundle to Stackage Server"
218 token <- readFile "/auth-token"
220 let ghcVer = display $ siGhcVersion $ bpSystemInfo plan
221 (ident, mloc) <- flip uploadBundle man $ setArgs ghcVer def
222 { ubContents = serverBundle now (title ghcVer) slug plan
223 , ubAuthToken = decodeUtf8 token
225 putStrLn $ "New ident: " ++ unSnapshotIdent ident
227 putStrLn $ "Track progress at: " ++ loc
229 postBuild `catchAny` print
231 putStrLn "Uploading docs to Stackage Server"
232 res1 <- uploadDocs UploadDocs
234 , udAuthToken = decodeUtf8 token
235 , udDocs = pbDocDir pb
238 putStrLn $ "Doc upload response: " ++ tshow res1
240 ecreds <- tryIO $ readFile "/hackage-creds"
241 case map encodeUtf8 $ words $ decodeUtf8 $ either (const "") id ecreds of
242 [username, password] -> do
243 putStrLn "Uploading as Hackage distro"
244 res2 <- uploadHackageDistro plan username password man
245 putStrLn $ "Distro upload response: " ++ tshow res2
246 _ -> putStrLn "No creds found, skipping Hackage distro upload"
248 putStrLn "Uploading doc map"
249 uploadDocMap UploadDocMap
251 , udmAuthToken = decodeUtf8 token
252 , udmSnapshot = ident
253 , udmDocDir = pbDocDir pb
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list