stack-all (empty) → 0.1
raw patch · 5 files changed
+252/−0 lines, 5 filesdep +basedep +config-inidep +directory
Dependencies added: base, config-ini, directory, extra, filepath, process, simple-cmd, simple-cmd-args, text
Files
- ChangeLog.md +5/−0
- LICENSE +30/−0
- Main.hs +141/−0
- README.md +28/−0
- stack-all.cabal +48/−0
+ ChangeLog.md view
@@ -0,0 +1,5 @@+# Revision history for stack-all++## 0.1.0 -- 2020-11-14+- initial release with --create-config, --debug, --cmd, --newest+- VersionSpec: --all-lts, --oldest, and lts args
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2020, Jens Petersen++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Jens Petersen nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Main.hs view
@@ -0,0 +1,141 @@+{-# LANGUAGE OverloadedStrings #-}++import Control.Monad.Extra+import Data.Ini.Config+import Data.List.Extra+import qualified Data.Text.IO as T+import SimpleCmd+import SimpleCmdArgs+import System.Directory+import System.Exit+import System.FilePath+import System.IO+import System.Process++import Paths_stack_all (version)++-- FIXME allow specific snapshots?+-- FIXME lts latest+data Snapshot = LTS Int | Nightly+ deriving (Eq, Ord)++readSnap :: String -> Snapshot+readSnap "nightly" = Nightly+readSnap snap =+ if "lts" `isPrefixOf` snap then+ let major = read (dropPrefix "lts-" snap) in LTS major+ else error' $ "malformed snapshot " ++ snap++showSnap :: Snapshot -> String+showSnap Nightly = "nightly"+showSnap (LTS ver) = "lts-" ++ show ver++defaultOldest :: Snapshot+defaultOldest = LTS 11++allSnaps :: [Snapshot]+allSnaps = [Nightly, LTS 16, LTS 14, LTS 13, LTS 12, LTS 11,+ LTS 10, LTS 9, LTS 8, LTS 6, LTS 5, LTS 4, LTS 2, LTS 1]++data VersionSpec = DefaultVersions | Oldest Snapshot | AllVersions | VersionList [Snapshot]++main :: IO ()+main = do+ hSetBuffering stdout NoBuffering+ unlessM (doesFileExist "stack.yaml") $+ error' "no stack.yaml found"+ simpleCmdArgs (Just version) "Build over Stackage versions"+ "stack-all builds projects easily across different Stackage versions" $+ main' <$>+ switchWith 'c' "create-config" "Create a project .stack-all file" <*>+ switchWith 'd' "debug" "Verbose stack build output on error" <*>+ optional (readSnap <$> strOptionWith 'n' "newest" "lts-MAJOR" "Newest LTS release to build from") <*>+ optional (strOptionWith 'C' "cmd" "COMMAND" "Specify a stack command [default: build]") <*>+ versionSpec+ where+ versionSpec =+ Oldest . readSnap <$> strOptionWith 'o' "oldest" "lts-MAJOR" "Oldest compatible LTS release" <|>+ VersionList . map readSnap <$> some (strArg "LTS") <|>+ flagWith DefaultVersions AllVersions 'a' "all-lts" "Try to build back to LTS 1 even"++main' :: Bool -> Bool -> Maybe Snapshot -> Maybe String -> VersionSpec -> IO ()+main' createConfig debug mnewest mcmd versionSpec = do+ if createConfig then+ case versionSpec of+ Oldest oldest -> createStackAll oldest+ _ -> error' "creating .stack-all requires --oldest LTS"+ else do+ versions <-+ case versionSpec of+ DefaultVersions -> do+ oldest <- fromMaybeM (return defaultOldest) getOldestLTS+ return $ filter (>= oldest) allSnaps+ AllVersions -> return allSnaps+ Oldest ver -> return $ filter (>= ver) allSnaps+ VersionList vers -> return vers+ configs <- filter isStackConf <$> listDirectory "."+ let newestFilter = maybe id (filter . (>=)) mnewest+ mapM_ (stackBuild configs debug mcmd) (newestFilter versions)+ where+ isStackConf :: FilePath -> Bool+ isStackConf f = "stack-" `isPrefixOf` f && "yaml" `isExtensionOf` f++stackAllFile :: FilePath+stackAllFile = ".stack-all"++createStackAll :: Snapshot -> IO ()+createStackAll snap = do+ exists <- doesFileExist stackAllFile+ if exists then error' $ stackAllFile ++ " already exists"+ else do+ writeFile stackAllFile $+ "[versions]\n# reason comment\noldest = " ++ showSnap snap ++ "\n"++getOldestLTS :: IO (Maybe Snapshot)+getOldestLTS = do+ haveConfig <- doesFileExist stackAllFile+ if haveConfig then+ Just . readSnap <$> readIniConfig stackAllFile rcParser id+ else return Nothing+ where+ rcParser :: IniParser String+ rcParser =+ section "versions" $+ fieldOf "oldest" string++ readIniConfig :: FilePath -> IniParser a -> (a -> b) -> IO b+ readIniConfig inifile iniparser fn = do+ ini <- T.readFile inifile+ return $ either error fn $ parseIniFile ini iniparser++stackBuild :: [FilePath] -> Bool -> Maybe String -> Snapshot -> IO ()+stackBuild configs debug mcmd snap = do+ let command = maybe ["build"] words mcmd+ config =+ case sort (filter (snapConfig <=) configs) of+ [] -> []+ (cfg:_) -> ["--stack-yaml", cfg]+ args = ["-v" | debug] ++ ["--resolver", showSnap snap] +++ config ++ command+ if debug+ then debugBuild args+ else cmd_ "stack" args+ putStrLn ""+ where+ snapConfig :: FilePath+ snapConfig = "stack-" ++ compactSnap snap <.> "yaml"+ where+ compactSnap :: Snapshot -> String+ compactSnap Nightly = "nightly"+ compactSnap (LTS ver) = "lts" ++ show ver++ debugBuild :: [String] -> IO ()+ debugBuild args = do+ putStr $ "stack " ++ unwords args+ (ret,out,err) <- readProcessWithExitCode "stack" args ""+ putStrLn "\n"+ unless (null out) $ putStrLn out+ unless (ret == ExitSuccess) $ do+ -- stack verbose includes info line with all stackages (> 500kbytes)+ mapM_ putStrLn $ filter ((<10000) . length) . lines $ err+ error' $ showSnap snap ++ " build failed"
+ README.md view
@@ -0,0 +1,28 @@+# stack-all++A CLI tool for building Haskell projects easily over Stackage major versions.++This is how I do my Haskell "build ci" now locally.++## Usage++`stack-all` runs `stack build` over recent Stackage LTS major versions+and Nightly: by default currently: nightly, lts-16, ..., lts-11.++Note that stack-all will automatically use `stack-ltsXX.yaml`, even for older lts releases: eg say you have `stack-lts13.yaml` in your project, then it will also be used for building lts-12 (unless you have a `stack-lts12.yaml` config file of course).++You can specify the oldest working LTS for a project with `stack-all -o lts-13` or set it in a `.stack-all` file containing:+```+[versions]+# lts-12 foo-bar too old+oldest = lts-13+```+which can be created with `stack-all -c -o lts-13`.++Happy stack building!++## Install+Run `stack install` or `cabal install` in the source.++## Contribute+See https://github.com/juhp/stack-all
+ stack-all.cabal view
@@ -0,0 +1,48 @@+name: stack-all+version: 0.1+synopsis: CLI tool for building across Stackage major versions+description:+ Build your Haskell project over Stackage major versions.+license: BSD3+license-file: LICENSE+author: Jens Petersen <juhpetersen@gmail.com>+maintainer: Jens Petersen <juhpetersen@gmail.com>+copyright: 2020 Jens Petersen <juhpetersen@gmail.com>+category: Distribution+homepage: https://github.com/juhp/stack-all+bug-reports: https://github.com/juhp/stack-all/issues+build-type: Simple+extra-doc-files: README.md+ ChangeLog.md+cabal-version: 1.18+tested-with: GHC == 8.4.4, GHC == 8.6.5, GHC == 8.8.4, GHC == 8.10.2++source-repository head+ type: git+ location: https://github.com/juhp/stack-all.git++executable stack-all+ main-is: Main.hs+ other-modules: Paths_stack_all+ build-depends: base < 5,+ config-ini,+ directory,+ extra >= 1.6.15,+ filepath,+ process,+ simple-cmd >= 0.1.4,+ simple-cmd-args,+ text+ default-language: Haskell2010+ ghc-options: -Wall+ if impl(ghc >= 8.0)+ ghc-options: -Wcompat+ -Widentities+ -Wincomplete-uni-patterns+ -Wincomplete-record-updates+ -Wredundant-constraints+ if impl(ghc >= 8.2)+ ghc-options: -fhide-source-paths+ if impl(ghc >= 8.4)+ ghc-options: -Wmissing-export-lists+ -Wpartial-fields