packages feed

stack-all 0.3 → 0.3.1

raw patch · 6 files changed

+99/−102 lines, 6 filesdep +cached-json-filedep −bytestringdep −timedep −xdg-basedir

Dependencies added: cached-json-file

Dependencies removed: bytestring, time, xdg-basedir

Files

ChangeLog.md view
@@ -1,5 +1,11 @@ # Release history for stack-all +## 0.3.1 (2021-09-06)+- newest LTS for a project can now be configured+- use cached-json-file for snapshots.json+- add --keep-going+- exclude lts17 now by default+ ## 0.3 (2021-06-26) - use hackage.stackage.org/snapshots.json:   - to determine the latest LTS major version
README.md view
@@ -2,13 +2,13 @@  A CLI tool for building Haskell projects easily over Stackage major versions. -This is how I do my Haskell "build ci" now locally.+This is how I do my Haskell build CI for projects locally with stack.  ## Usage  `stack-all` by default runs `stack build` over recent Stackage LTS major versions and Nightly-(current default is nightly, lts-18, lts-17, lts-16, lts-14,... , lts-11)+(current default is nightly & LTS 18, 16, 14, 13, 12, 11) corresponding to latest major ghc minor versions, using the stack's `--resolver` option. @@ -19,24 +19,42 @@  ### Overriding stack.yaml `stack-all` can use `stack-ltsXX.yaml` files to override the default `stack.yaml`-file for particular lts major versions. Note that a `stack-ltsXX.yaml` file-will also be used for older lts major versions until+file for particular LTS major versions. Note that a `stack-ltsXX.yaml` file+will also be used for older LTS major versions until another `stack-ltsYY.yaml` file is found.  For example if you have `stack-lts14.yaml` and `stack-lts12.yaml` files in your project,-then `stack.yaml` will be used as normal to build nightly, lts-17 and lts-16,+then `stack.yaml` will be used as normal to build nightly, lts-18 and lts-16, but `stack-lts14.yaml` will be used for building lts-14 and lts-13, and `stack-lts12.yaml` will be used for lts-12, lts-11 (and older). Since `stack-all` overrides the resolver with `--resolver lts-XX`-the exact minor lts version specified in the `stack*.yaml` files+the exact minor LTS version specified in the `stack*.yaml` files doesn't actually matter: `stack-all` always uses the latest minor release of-the lts major version according to Stackage.+the LTS major version according to Stackage. +`stack-ltsXX.yaml` files can be easily prepared using+`stack-all --make-lts ltsXX` (or `-s ltsXX` for short).+ (Other versioned stack.yaml filenames like stack-ghc-8.8.yaml are not currently supported.) -### Configuring the oldest lts to build+### Specifying LTS versions+You can abbreviate `lts-XX` args to `ltsXX` on the commandline.++There are `--oldest`  and `--newest` options to specify the range of+lts versions to build over:++You can specify the oldest major LTS to build for with eg `stack-all -o lts13`.+Otherwise if not configured the default oldest LTS is currently `lts-11`.++Similarly you can specify the newest LTS version to build from with+eg `stack-all -n lts16`. (The default is to build from nightly.)++Alternatively, one can give one or more explicit LTS major versions to build for+as arguments: eg `stack-all lts14` if you only wish to build that version.++### Configuring the oldest and/or newest LTS to build You can configure the oldest working LTS major version for your project by running for example `stack-all -c -o lts-13` which generates a `.stack-all` project config file like this:@@ -45,28 +63,16 @@ # lts-12 too old oldest = lts-13 ```-(the comment line can be used to document why the older lts doesn't work).-This specifies that the oldest lts version to build for is lts-13.--### Specifying lts versions-You can abbreviate `lts-XX` args to `ltsXX` on the commandline.--There are `--oldest`  and `--newest` options to specify the range of-lts versions to build over:--You can specify the oldest major lts to build for with eg `stack-all -o lts13`.-Otherwise if not configured the default oldest lts is currently `lts-11`.--Similarly you can specify the newest lts version to build from with-`stack-all -n lts16`. (The default is to build from nightly.)+(the comment line can be used to document why the older LTS doesn't work).+This specifies that the oldest LTS version to build for is lts-13. -Alternatively, one can give one or more explicit lts major versions to build for-as arguments: eg `stack-all lts14` if you only wish to build that version.+The newest LTS to build with stack-all can similarly be configured:+`stack-all -c -n lts18` or setting `newest = lts-18`.  ### Running other stack commands-By default `stack-all` just runs the stack `build` command over lts versions.+By default `stack-all` just runs the stack `build` command over LTS versions. -You can also specify the stack command to run and its options on the commandline:+You can also specify a stack command to run with options on the commandline: eg ``` $ stack-all test --no-rerun-tests@@ -78,7 +84,7 @@ ## Install The project is released on Hackage. -You can also build from source with `stack install` or `cabal install`.+You can also build from git source with `stack install` or `cabal install`.  ## Collaboration The project is hosted at https://github.com/juhp/stack-all under a BSD license.
src/Main.hs view
@@ -19,8 +19,8 @@ import Paths_stack_all (version) import Snapshots -defaultOldest :: MajorVer-defaultOldest = LTS 11+defaultOldestLTS :: MajorVer+defaultOldestLTS = LTS 11  data VersionLimit = DefaultLimit | Oldest MajorVer | AllVersions @@ -34,20 +34,22 @@     run <$>     (flagWith' CreateConfig 'c' "create-config" "Create a project .stack-all file" <|>      flagWith DefaultRun MakeStackLTS 's' "make-lts" "Create a stack-ltsXX.yaml file") <*>+    switchWith 'k' "keep-going" "Keep going even if an LTS fails" <*>     switchWith 'd' "debug" "Verbose stack build output on error" <*>     optional (readMajor <$> strOptionWith 'n' "newest" "MAJOR" "Newest LTS release to build from") <*>     (Oldest . readMajor <$> strOptionWith 'o' "oldest" "MAJOR" "Oldest compatible LTS release" <|>      flagWith DefaultLimit AllVersions 'a' "all-lts" "Try to build back to LTS 1 even") <*>     many (strArg "MAJORVER... [COMMAND...]") -run :: Command -> Bool -> Maybe MajorVer -> VersionLimit -> [String] -> IO ()-run command debug mnewest verlimit verscmd = do+run :: Command -> Bool ->Bool -> Maybe MajorVer -> VersionLimit -> [String]+    -> IO ()+run command keepgoing debug mnewest verlimit verscmd = do   findStackProjectDir Nothing   case command of     CreateConfig ->       case verlimit of-        Oldest oldest -> createStackAll oldest-        _ -> error' "creating .stack-all requires --oldest LTS"+        Oldest oldest -> createStackAll (Just oldest) mnewest+        _ -> createStackAll Nothing mnewest     MakeStackLTS -> do       (versions, _) <- getVersionsCmd       if null versions@@ -57,7 +59,7 @@       (versions, cargs) <- getVersionsCmd       configs <- mapMaybe readStackConf <$> listDirectory "."       let newestFilter = maybe id (filter . (>=)) mnewest-      mapM_ (stackBuild configs debug cargs) (newestFilter versions)+      mapM_ (stackBuild configs keepgoing debug cargs) (newestFilter versions)   where     findStackProjectDir :: Maybe FilePath -> IO ()     findStackProjectDir mcwd = do@@ -79,7 +81,7 @@             -- FIXME stack init content too verbose             unlessM (cmdBool "stack" ["init"]) $               -- FIXME determine latest stable snapshot automatically-              writeFile "stack.yaml" "resolver: lts-17.15\n"+              writeFile "stack.yaml" "resolver: lts-18.8\n"             else error' "no package/project found"      getVersionsCmd :: IO ([MajorVer],[String])@@ -91,17 +93,20 @@         if null verlist then           case verlimit of             DefaultLimit -> do-              oldest <- fromMaybeM (return defaultOldest) readOldestLTS+              (newestLTS, oldestLTS) <- readNewestOldestLTS               return $ case mnewest of                          Just newest ->-                           if newest < oldest-                           then filter (newest >=) allMajors-                           else filter (\ s ->  s >= oldest && newest >= s) allMajors-                         Nothing -> filter (>= oldest) allMajors+                           if newest < oldestLTS+                           then filter (inRange newest (LTS 1)) allMajors+                           else filter (inRange newest oldestLTS) allMajors+                         Nothing -> filter (inRange newestLTS oldestLTS) allMajors             AllVersions -> return allMajors-            Oldest ver -> return $ filter (>= ver) allMajors+            Oldest ver -> return $ filter (inRange Nightly ver) allMajors         else return verlist       return (versions,if null cmds then ["build"] else cmds)+      where+        inRange :: MajorVer -> MajorVer -> MajorVer -> Bool+        inRange newest oldest v = v >= oldest && v <= newest  readStackConf :: FilePath -> Maybe MajorVer readStackConf "stack-lts.yaml" = error' "unversioned stack-lts.yaml is unsupported"@@ -111,34 +116,44 @@ stackAllFile :: FilePath stackAllFile = ".stack-all" -createStackAll :: MajorVer -> IO ()-createStackAll ver = do+createStackAll :: Maybe MajorVer -> Maybe MajorVer -> IO ()+createStackAll Nothing Nothing =+  error' "creating .stack-all requires --oldest LTS and/or --newest LTS"+createStackAll moldest mnewest = do   exists <- doesFileExist stackAllFile   if exists then error' $ stackAllFile ++ " already exists"     else do     allMajors <- getMajorVers-    let older =-          let molder = listToMaybe $ dropWhile (>= ver) allMajors-          in maybe "" (\s -> showMajor s ++ " too old") molder     writeFile stackAllFile $-      "[versions]\n# " ++ older ++ "\noldest = " ++ showMajor ver ++ "\n"+      "[versions]\n" +++      case mnewest of+        Nothing -> ""+        Just newest ->+          "newest = " ++ showMajor newest ++ "\n"+      +++      case moldest of+        Nothing -> ""+        Just oldest ->+          let older =+                let molder = listToMaybe $ dropWhile (>= oldest) allMajors+                in maybe "" (\s -> showMajor s ++ " too old") molder+          in "# " ++ older ++ "\noldest = " ++ showMajor oldest ++ "\n" -readOldestLTS :: IO (Maybe MajorVer)-readOldestLTS = do+readNewestOldestLTS :: IO (MajorVer,MajorVer)+readNewestOldestLTS = do   haveConfig <- doesFileExist stackAllFile   if haveConfig then-    Just . readMajor <$> readIniConfig stackAllFile rcParser id-    else return Nothing+    readIniConfig stackAllFile $+    section "versions" $ do+    mnewest <- fmap readMajor <$> fieldMbOf "newest" string+    moldest <- fmap readMajor <$> fieldMbOf "oldest" string+    return (fromMaybe Nightly mnewest, fromMaybe defaultOldestLTS moldest)+    else return (Nightly, defaultOldestLTS)   where-    rcParser :: IniParser String-    rcParser =-      section "versions" $-      fieldOf "oldest" string--    readIniConfig :: FilePath -> IniParser a -> (a -> b) -> IO b-    readIniConfig inifile iniparser fn = do+    readIniConfig :: FilePath -> IniParser a -> IO a+    readIniConfig inifile iniparser = do       ini <- T.readFile inifile-      return $ either error fn $ parseIniFile ini iniparser+      return $ either error id $ parseIniFile ini iniparser  makeStackLTS :: [MajorVer] -> IO () makeStackLTS vers = do@@ -162,8 +177,8 @@     compactMajor Nightly = "nightly"     compactMajor (LTS ver) = "lts" ++ show ver -stackBuild :: [MajorVer] -> Bool -> [String] -> MajorVer -> IO ()-stackBuild configs debug command ver = do+stackBuild :: [MajorVer] -> Bool -> Bool -> [String] -> MajorVer -> IO ()+stackBuild configs keepgoing debug command ver = do   let config =         case sort (filter (ver <=) configs) of           [] -> []@@ -178,7 +193,7 @@         then debugBuild $ opts ++ command         else do         ok <- cmdBool "stack" $ opts ++ command-        unless ok $ do+        unless (ok || keepgoing) $ do           putStr "\nsnapshot-pkg-db: "           cmd_ "stack" $ "--silent" : opts ++ ["path", "--snapshot-pkg-db"]           error' $ "failed for " ++ showMajor ver
src/MajorVer.hs view
@@ -34,7 +34,7 @@   case maybeReadMajor ver of     Just s -> s     Nothing ->-      error' $ "couldn't parse " ++ ver ++ " (expected lts-XX or ltsXX)"+      error' $! "couldn't parse " ++ ver ++ " (expected lts-XX or ltsXX)"  -- readCompactMajor "lts16" readCompactMajor :: String -> Maybe MajorVer@@ -43,7 +43,7 @@   if "lts" `isPrefixOf` ver then     case readMaybe (dropPrefix "lts" ver) of       Just major -> Just (LTS major)-      Nothing -> error' $ "couldn't parse compact " ++ ver ++  " (expected ltsXX)"+      Nothing -> error' $! "couldn't parse compact " ++ ver ++  " (expected ltsXX)"   else Nothing  eitherReadMajor :: String -> Either String MajorVer
src/Snapshots.hs view
@@ -6,23 +6,17 @@   ) where -import Control.Monad import Data.Aeson-import qualified Data.ByteString.Lazy.Char8 as B import Data.List.Extra import qualified Data.HashMap.Strict as H import qualified Data.Text as T-import Data.Time.Clock (diffUTCTime, getCurrentTime) import Network.HTTP.Query-import SimpleCmd (error')-import System.Directory-import System.Environment.XDG.BaseDir-import System.FilePath+import System.Cached.JSON  import MajorVer  excludedMajors :: [MajorVer]-excludedMajors = [LTS 15, LTS 7, LTS 3, LTS 0]+excludedMajors = [LTS 17, LTS 15, LTS 7, LTS 3, LTS 0]  getMajorVers :: IO [MajorVer] getMajorVers = do@@ -33,28 +27,6 @@ latestSnapshot ver = do   lookupKey (T.pack (showMajor ver)) <$> getSnapshots --- FIXME handle network failure getSnapshots :: IO Object-getSnapshots = do-  file <- getUserCacheFile "stack-all" "snapshots.json"-  exists <- doesFileExist file-  unless exists $ do-    putStrLn $ "Creating " ++ file ++ " ..."-    createDirectoryIfMissing True (takeDirectory file)-  recent <- do-    if exists then do-      ts <- getModificationTime file-      t <- getCurrentTime-      -- < 3 hours-      return $ diffUTCTime t ts < 10000-      else return False-  if recent-    then do-    eobj <- eitherDecode <$> B.readFile file-    case eobj of-      Left err -> error' err-      Right obj -> return obj-    else do-    obj <- webAPIQuery "http://haddock.stackage.org/snapshots.json" []-    B.writeFile file $ encode obj-    return obj+getSnapshots =+  getCachedJSON "stackage-snapshots" "snapshots.json" "http://haddock.stackage.org/snapshots.json" 200
stack-all.cabal view
@@ -1,5 +1,5 @@ name:                stack-all-version:             0.3+version:             0.3.1 synopsis:            CLI tool for building across Stackage major versions description:         Build your Haskell project over Stackage major LTS versions.@@ -16,7 +16,7 @@                      ChangeLog.md cabal-version:       1.18 tested-with:         GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.4, GHC == 8.6.5,-                     GHC == 8.8.4, GHC == 8.10.4, GHC == 9.0.1+                     GHC == 8.8.4, GHC == 8.10.5, GHC == 9.0.1  source-repository head   type:                git@@ -30,7 +30,7 @@   hs-source-dirs:      src   build-depends:       base < 5,                        aeson,-                       bytestring,+                       cached-json-file,                        config-ini,                        directory >= 1.2.5,                        extra >= 1.6.15,@@ -40,9 +40,7 @@                        simple-cmd >= 0.1.4,                        simple-cmd-args,                        text,-                       time,-                       unordered-containers,-                       xdg-basedir+                       unordered-containers   default-language:    Haskell2010   ghc-options:         -Wall   if impl(ghc >= 8.0)