{-# LANGUAGE MultiWayIf        #-}
{-# LANGUAGE NamedFieldPuns    #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards   #-}
module HaskellCI.GitHub (
    makeGitHub,
    githubHeader,
) where

import HaskellCI.Prelude

import Control.Applicative (optional)

import qualified Crypto.Hash.SHA256              as SHA256
import qualified Data.Attoparsec.Text            as Atto
import qualified Data.Binary                     as Binary
import qualified Data.Binary.Put                 as Binary
import qualified Data.ByteString.Base16          as Base16
import qualified Data.ByteString.Char8           as BS8
import qualified Data.Map.Strict                 as Map
import qualified Data.Set                        as S
import qualified Data.Text                       as T
import qualified Distribution.Fields.Pretty      as C
import qualified Distribution.Package            as C
import qualified Distribution.Pretty             as C
import qualified Distribution.Types.VersionRange as C
import qualified Distribution.Version            as C

import Cabal.Project
import HaskellCI.Auxiliary
import HaskellCI.Compiler
import HaskellCI.Config
import HaskellCI.Config.ConstraintSet
import HaskellCI.Config.Docspec
import HaskellCI.Config.Doctest
import HaskellCI.Config.HLint
import HaskellCI.Config.Installed
import HaskellCI.Config.Jobs
import HaskellCI.Config.PackageScope
import HaskellCI.Config.Ubuntu
import HaskellCI.Config.Validity
import HaskellCI.GitConfig
import HaskellCI.GitHub.Yaml
import HaskellCI.HeadHackage
import HaskellCI.Jobs
import HaskellCI.List
import HaskellCI.MonadErr
import HaskellCI.Package
import HaskellCI.Sh
import HaskellCI.ShVersionRange
import HaskellCI.Tools
import HaskellCI.VersionInfo

-- $setup
-- >>> :set -XOverloadedStrings

-------------------------------------------------------------------------------
-- GitHub header
-------------------------------------------------------------------------------

githubHeader :: Bool -> [String] -> [String]
githubHeader :: Bool -> [String] -> [String]
githubHeader Bool
insertVersion [String]
argv =
    [ String
"This GitHub workflow config has been generated by a script via"
    , String
""
    , String
"  haskell-ci " String -> String -> String
forall a. [a] -> [a] -> [a]
++ [String] -> String
unwords [ String
"'" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
a String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"'" | String
a <- [String]
argv ]
    , String
""
    , String
"To regenerate the script (for example after adjusting tested-with) run"
    , String
""
    , String
"  haskell-ci regenerate"
    , String
""
    , String
"For more information, see https://github.com/haskell-CI/haskell-ci"
    , String
""
    ] [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++
    [String]
verlines [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++
    [ String
"REGENDATA " String -> String -> String
forall a. [a] -> [a] -> [a]
++ if Bool
insertVersion then (String, [String]) -> String
forall a. Show a => a -> String
show (String
haskellCIVerStr, [String]
argv) else [String] -> String
forall a. Show a => a -> String
show [String]
argv
    , String
""
    ]
  where
    verlines :: [String]
verlines
        | Bool
insertVersion = [ String
"version: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
haskellCIVerStr , String
"" ]
        | Bool
otherwise     = []

-------------------------------------------------------------------------------
-- GitHub
-------------------------------------------------------------------------------

{-
GitHub Actions–specific notes:

* We use -j2 for parallelism, as GitHub's virtual machines use 2 cores, per
  https://docs.github.com/en/free-pro-team@latest/actions/reference/specifications-for-github-hosted-runners#supported-runners-and-hardware-resources.
-}

makeGitHub
    :: [String]
    -> Config
    -> GitConfig
    -> Project URI Void Package
    -> JobVersions
    -> Either HsCiError GitHub
makeGitHub :: [String]
-> Config
-> GitConfig
-> Project URI Void Package
-> JobVersions
-> Either HsCiError GitHub
makeGitHub [String]
_argv config :: Config
config@Config {Bool
Natural
String
[String]
[PrettyField ()]
[PackageName]
[Installed]
[ConstraintSet]
Maybe String
Maybe Version
Maybe Jobs
VersionRange
Version
Set String
Set Fold
Map Version String
Ubuntu
PackageScope
HLintConfig
DoctestConfig
DocspecConfig
CopyFields
TestedWithJobs
cfgTimeoutMinutes :: Config -> Natural
cfgGitHubActionName :: Config -> Maybe String
cfgRawTravis :: Config -> String
cfgRawProject :: Config -> [PrettyField ()]
cfgConstraintSets :: Config -> [ConstraintSet]
cfgHLint :: Config -> HLintConfig
cfgDocspec :: Config -> DocspecConfig
cfgDoctest :: Config -> DoctestConfig
cfgErrorMissingMethods :: Config -> PackageScope
cfgInsertVersion :: Config -> Bool
cfgGitHubPatches :: Config -> [String]
cfgTravisPatches :: Config -> [String]
cfgApt :: Config -> Set String
cfgGhcupVersion :: Config -> Version
cfgGhcupJobs :: Config -> VersionRange
cfgGhcupCabal :: Config -> Bool
cfgMacosJobs :: Config -> VersionRange
cfgLinuxJobs :: Config -> VersionRange
cfgLastInSeries :: Config -> Bool
cfgAllowFailures :: Config -> VersionRange
cfgEnv :: Config -> Map Version String
cfgGoogleChrome :: Config -> Bool
cfgPostgres :: Config -> Bool
cfgGhcHead :: Config -> Bool
cfgFolds :: Config -> Set Fold
cfgProjectName :: Config -> Maybe String
cfgEmailNotifications :: Config -> Bool
cfgIrcIfInOriginRepo :: Config -> Bool
cfgIrcPassword :: Config -> Maybe String
cfgIrcNickname :: Config -> Maybe String
cfgIrcChannels :: Config -> [String]
cfgOnlyBranches :: Config -> [String]
cfgCheck :: Config -> Bool
cfgTestOutputDirect :: Config -> Bool
cfgGhcjsTools :: Config -> [PackageName]
cfgGhcjsTests :: Config -> Bool
cfgHeadHackage :: Config -> VersionRange
cfgUnconstrainted :: Config -> VersionRange
cfgNoTestsNoBench :: Config -> VersionRange
cfgHaddock :: Config -> VersionRange
cfgBenchmarks :: Config -> VersionRange
cfgRunTests :: Config -> VersionRange
cfgTests :: Config -> VersionRange
cfgInstalled :: Config -> [Installed]
cfgInstallDeps :: Config -> Bool
cfgCache :: Config -> Bool
cfgSubmodules :: Config -> Bool
cfgLocalGhcOptions :: Config -> [String]
cfgCopyFields :: Config -> CopyFields
cfgEnabledJobs :: Config -> VersionRange
cfgTestedWith :: Config -> TestedWithJobs
cfgUbuntu :: Config -> Ubuntu
cfgJobs :: Config -> Maybe Jobs
cfgCabalInstallVersion :: Config -> Maybe Version
cfgTimeoutMinutes :: Natural
cfgGitHubActionName :: Maybe String
cfgRawTravis :: String
cfgRawProject :: [PrettyField ()]
cfgConstraintSets :: [ConstraintSet]
cfgHLint :: HLintConfig
cfgDocspec :: DocspecConfig
cfgDoctest :: DoctestConfig
cfgErrorMissingMethods :: PackageScope
cfgInsertVersion :: Bool
cfgGitHubPatches :: [String]
cfgTravisPatches :: [String]
cfgApt :: Set String
cfgGhcupVersion :: Version
cfgGhcupJobs :: VersionRange
cfgGhcupCabal :: Bool
cfgMacosJobs :: VersionRange
cfgLinuxJobs :: VersionRange
cfgLastInSeries :: Bool
cfgAllowFailures :: VersionRange
cfgEnv :: Map Version String
cfgGoogleChrome :: Bool
cfgPostgres :: Bool
cfgGhcHead :: Bool
cfgFolds :: Set Fold
cfgProjectName :: Maybe String
cfgEmailNotifications :: Bool
cfgIrcIfInOriginRepo :: Bool
cfgIrcPassword :: Maybe String
cfgIrcNickname :: Maybe String
cfgIrcChannels :: [String]
cfgOnlyBranches :: [String]
cfgCheck :: Bool
cfgTestOutputDirect :: Bool
cfgGhcjsTools :: [PackageName]
cfgGhcjsTests :: Bool
cfgHeadHackage :: VersionRange
cfgUnconstrainted :: VersionRange
cfgNoTestsNoBench :: VersionRange
cfgHaddock :: VersionRange
cfgBenchmarks :: VersionRange
cfgRunTests :: VersionRange
cfgTests :: VersionRange
cfgInstalled :: [Installed]
cfgInstallDeps :: Bool
cfgCache :: Bool
cfgSubmodules :: Bool
cfgLocalGhcOptions :: [String]
cfgCopyFields :: CopyFields
cfgEnabledJobs :: VersionRange
cfgTestedWith :: TestedWithJobs
cfgUbuntu :: Ubuntu
cfgJobs :: Maybe Jobs
cfgCabalInstallVersion :: Maybe Version
..} GitConfig
gitconfig Project URI Void Package
prj jobs :: JobVersions
jobs@JobVersions {Set CompilerVersion
macosVersions :: JobVersions -> Set CompilerVersion
linuxVersions :: JobVersions -> Set CompilerVersion
allVersions :: JobVersions -> Set CompilerVersion
macosVersions :: Set CompilerVersion
linuxVersions :: Set CompilerVersion
allVersions :: Set CompilerVersion
..} = do
    let envEnv :: Map String String
envEnv = [(String, String)] -> Map String String
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList
            [ (String
"HCNAME", String
"${{ matrix.compiler }}")         -- e.g. ghc-8.8.4
            , (String
"HCKIND", String
"${{ matrix.compilerKind }}")     --      ghc
            , (String
"HCVER",  String
"${{ matrix.compilerVersion }}")  --      8.8.4
            ]

    -- Validity checks
    Config -> JobVersions -> Either HsCiError ()
forall (m :: * -> *).
MonadErr HsCiError m =>
Config -> JobVersions -> m ()
checkConfigValidity Config
config JobVersions
jobs
    Bool -> Either HsCiError () -> Either HsCiError ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool
cfgSubmodules Bool -> Bool -> Bool
&& Ubuntu
cfgUbuntu Ubuntu -> Ubuntu -> Bool
forall a. Ord a => a -> a -> Bool
< Ubuntu
Focal) (Either HsCiError () -> Either HsCiError ())
-> Either HsCiError () -> Either HsCiError ()
forall a b. (a -> b) -> a -> b
$
        HsCiError -> Either HsCiError ()
forall e (m :: * -> *) a. MonadErr e m => e -> m a
throwErr (HsCiError -> Either HsCiError ())
-> HsCiError -> Either HsCiError ()
forall a b. (a -> b) -> a -> b
$ String -> HsCiError
ValidationError (String -> HsCiError) -> String -> HsCiError
forall a b. (a -> b) -> a -> b
$ [String] -> String
unwords
            [ String
"Using submodules on the GitHub Actions backend requires"
            , String
"Ubuntu 20.04 (Focal Fossa) or later."
            ]

    [GitHubStep]
steps <- [Either HsCiError GitHubStep] -> Either HsCiError [GitHubStep]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence ([Either HsCiError GitHubStep] -> Either HsCiError [GitHubStep])
-> [Either HsCiError GitHubStep] -> Either HsCiError [GitHubStep]
forall a b. (a -> b) -> a -> b
$ ListBuilder (Either HsCiError GitHubStep) ()
-> [Either HsCiError GitHubStep]
forall x. ListBuilder x () -> [x]
buildList (ListBuilder (Either HsCiError GitHubStep) ()
 -> [Either HsCiError GitHubStep])
-> ListBuilder (Either HsCiError GitHubStep) ()
-> [Either HsCiError GitHubStep]
forall a b. (a -> b) -> a -> b
$ do
        -- This have to be first, since the packages we install depend on
        -- whether we need GHCJS or not.
        Bool
-> ListBuilder (Either HsCiError GitHubStep) ()
-> ListBuilder (Either HsCiError GitHubStep) ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
anyGHCJS (ListBuilder (Either HsCiError GitHubStep) ()
 -> ListBuilder (Either HsCiError GitHubStep) ())
-> ListBuilder (Either HsCiError GitHubStep) ()
-> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ String
-> Map String String
-> ShM ()
-> ListBuilder (Either HsCiError GitHubStep) ()
githubRun' String
"Set GHCJS environment variables" Map String String
envEnv (ShM () -> ListBuilder (Either HsCiError GitHubStep) ())
-> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
"\n"
            [ String
"if [ $HCKIND = ghcjs ]; then"
            , String -> String -> String
tell_env' String
"GHCJS" String
"true"
            , String -> String -> String
tell_env' String
"GHCJSARITH" String
"1"
            , String
"else"
            , String -> String -> String
tell_env' String
"GHCJS" String
"false"
            , String -> String -> String
tell_env' String
"GHCJSARITH" String
"0"
            , String
"fi"
            ]

        String
-> Map String String
-> ShM ()
-> ListBuilder (Either HsCiError GitHubStep) ()
githubRun' String
"apt" Map String String
envEnv (ShM () -> ListBuilder (Either HsCiError GitHubStep) ())
-> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ do
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"apt-get update"
            let corePkgs :: [String]
                corePkgs :: [String]
corePkgs =
                    [ String
"gnupg"
                    , String
"ca-certificates"
                    , String
"dirmngr"
                    , String
"curl"
                    , String
"git"
                    , String
"software-properties-common"
                    , String
"libtinfo5"
                    ] [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++
                    -- Installing libnuma-dev is required to work around
                    -- https://gitlab.haskell.org/haskell/ghcup-hs/-/blob/b0522507be6fa991a819aaf22f9a551757380821/README.md#libnuma-required
                    [ String
"libnuma-dev"
                    | Version -> CompilerVersion
GHC ([Int] -> Version
C.mkVersion [Int
8,Int
4,Int
4]) CompilerVersion -> Set CompilerVersion -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` Set CompilerVersion
allVersions
                    , Version -> CompilerVersion
GHC ([Int] -> Version
C.mkVersion [Int
8,Int
4,Int
4]) CompilerVersion -> (CompilerVersion -> Bool) -> Bool
forall a b. a -> (a -> b) -> b
& CompilerVersion -> Bool
isGHCUP
                    ]
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String
"apt-get install -y --no-install-recommends " String -> String -> String
forall a. [a] -> [a] -> [a]
++ [String] -> String
unwords [String]
corePkgs

            let installGhcup :: ShM ()
                installGhcup :: ShM ()
installGhcup = do
                    let ghcupVer :: String
ghcupVer = Version -> String
forall a. Pretty a => a -> String
C.prettyShow Version
cfgGhcupVersion
                    String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String
"mkdir -p \"$HOME/.ghcup/bin\""
                    String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String
"curl -sL https://downloads.haskell.org/ghcup/" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
ghcupVer String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"/x86_64-linux-ghcup-" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
ghcupVer String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" > \"$HOME/.ghcup/bin/ghcup\""
                    String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String
"chmod a+x \"$HOME/.ghcup/bin/ghcup\""

                installGhcupCabal :: ShM ()
                installGhcupCabal :: ShM ()
installGhcupCabal =
                    String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String
"\"$HOME/.ghcup/bin/ghcup\" install cabal " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
cabalFullVer

            [Sh]
hvrppa <- ShM () -> ShM [Sh]
forall e (m :: * -> *).
(MonadErr e m, FromHsCiError e) =>
ShM () -> m [Sh]
runSh (ShM () -> ShM [Sh]) -> ShM () -> ShM [Sh]
forall a b. (a -> b) -> a -> b
$ do
                String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"apt-add-repository -y 'ppa:hvr/ghc'"
                Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
anyGHCJS (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ do
                    CompilerRange -> String -> ShM ()
sh_if CompilerRange
RangeGHCJS String
"apt-add-repository -y 'ppa:hvr/ghcjs'"
                    CompilerRange -> String -> ShM ()
sh_if CompilerRange
RangeGHCJS String
"curl -sSL \"https://deb.nodesource.com/gpgkey/nodesource.gpg.key\" | apt-key add -"
                    CompilerRange -> String -> ShM ()
sh_if CompilerRange
RangeGHCJS (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String
"apt-add-repository -y 'deb https://deb.nodesource.com/node_10.x " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
ubuntuVer String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" main'"
                String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"apt-get update"
                let basePackages :: [String]
basePackages  = [String
"\"$HCNAME\"" ] [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ [ String
"cabal-install-" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
cabalVer | Bool -> Bool
not Bool
cfgGhcupCabal ] [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ Set String -> [String]
forall a. Set a -> [a]
S.toList Set String
cfgApt
                    ghcjsPackages :: [String]
ghcjsPackages = [String
"ghc-8.4.4", String
"nodejs"]
                    baseInstall :: String
baseInstall   = String
"apt-get install -y " String -> String -> String
forall a. [a] -> [a] -> [a]
++ [String] -> String
unwords [String]
basePackages
                    ghcjsInstall :: String
ghcjsInstall  = String
"apt-get install -y " String -> String -> String
forall a. [a] -> [a] -> [a]
++ [String] -> String
unwords ([String]
basePackages [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ [String]
ghcjsPackages)
                if Bool
anyGHCJS
                    then CompilerRange -> String -> String -> ShM ()
if_then_else CompilerRange
RangeGHCJS String
ghcjsInstall String
baseInstall
                    else String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
baseInstall
                Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
cfgGhcupCabal (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ do
                    ShM ()
installGhcup
                    ShM ()
installGhcupCabal

            [Sh]
ghcup <- ShM () -> ShM [Sh]
forall e (m :: * -> *).
(MonadErr e m, FromHsCiError e) =>
ShM () -> m [Sh]
runSh (ShM () -> ShM [Sh]) -> ShM () -> ShM [Sh]
forall a b. (a -> b) -> a -> b
$ do
                ShM ()
installGhcup
                String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String
"\"$HOME/.ghcup/bin/ghcup\" install ghc \"$HCVER\""
                ShM ()
installGhcupCabal
                Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Set String -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null Set String
cfgApt) (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ do
                    String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"apt-get update"
                    String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String
"apt-get install -y " String -> String -> String
forall a. [a] -> [a] -> [a]
++ [String] -> String
unwords (Set String -> [String]
forall a. Set a -> [a]
S.toList Set String
cfgApt)

            [Sh] -> [Sh] -> ShM ()
setup [Sh]
hvrppa [Sh]
ghcup

        String
-> Map String String
-> ShM ()
-> ListBuilder (Either HsCiError GitHubStep) ()
githubRun' String
"Set PATH and environment variables" Map String String
envEnv (ShM () -> ListBuilder (Either HsCiError GitHubStep) ())
-> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ do
            String -> String -> ShM ()
echo_to String
"$GITHUB_PATH" String
"$HOME/.cabal/bin"

            -- Hack: happy needs ghc. Let's install version matching GHCJS.
            -- At the moment, there is only GHCJS-8.4, so we install GHC-8.4.4
            Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
anyGHCJS (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$
                CompilerRange -> String -> String -> ShM ()
echo_if_to CompilerRange
RangeGHCJS String
"$GITHUB_PATH" String
"/opt/ghc/8.4.4/bin"

            String -> String -> ShM ()
tell_env String
"LANG" String
"C.UTF-8"

            String -> String -> ShM ()
tell_env String
"CABAL_DIR"    String
"$HOME/.cabal"
            String -> String -> ShM ()
tell_env String
"CABAL_CONFIG" String
"$HOME/.cabal/config"

            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"HCDIR=/opt/$HCKIND/$HCVER"

            let ghcupCabalPath :: ShM ()
ghcupCabalPath = String -> String -> ShM ()
tell_env String
"CABAL" (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String
"$HOME/.ghcup/bin/cabal-" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
cabalFullVer String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" -vnormal+nowrap"

            [Sh]
hvrppa <- ShM () -> ShM [Sh]
forall e (m :: * -> *).
(MonadErr e m, FromHsCiError e) =>
ShM () -> m [Sh]
runSh (ShM () -> ShM [Sh]) -> ShM () -> ShM [Sh]
forall a b. (a -> b) -> a -> b
$ do
                let hc :: String
hc = String
"$HCDIR/bin/$HCKIND"
                String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String
"HC=" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
hc -- HC is an absolute path.
                String -> String -> ShM ()
tell_env String
"HC" String
"$HC"
                String -> String -> ShM ()
tell_env String
"HCPKG" (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String
hc String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"-pkg"
                String -> String -> ShM ()
tell_env String
"HADDOCK" String
"$HCDIR/bin/haddock"
                if Bool
cfgGhcupCabal
                then ShM ()
ghcupCabalPath
                else String -> String -> ShM ()
tell_env String
"CABAL" (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String
"/opt/cabal/" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
cabalVer String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"/bin/cabal -vnormal+nowrap"

            [Sh]
ghcup <- ShM () -> ShM [Sh]
forall e (m :: * -> *).
(MonadErr e m, FromHsCiError e) =>
ShM () -> m [Sh]
runSh (ShM () -> ShM [Sh]) -> ShM () -> ShM [Sh]
forall a b. (a -> b) -> a -> b
$ do
                let hc :: String
hc = String
"$HOME/.ghcup/bin/$HCKIND-$HCVER"
                String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String
"HC=" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
hc -- HC is an absolute path.
                String -> String -> ShM ()
tell_env String
"HC"      String
"$HC"
                String -> String -> ShM ()
tell_env String
"HCPKG" (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String
"$HOME/.ghcup/bin/$HCKIND-pkg-$HCVER"
                String -> String -> ShM ()
tell_env String
"HADDOCK" String
"$HOME/.ghcup/bin/haddock-$HCVER"
                ShM ()
ghcupCabalPath

            [Sh] -> [Sh] -> ShM ()
setup [Sh]
hvrppa [Sh]
ghcup

            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"HCNUMVER=$(${HC} --numeric-version|perl -ne '/^(\\d+)\\.(\\d+)\\.(\\d+)(\\.(\\d+))?$/; print(10000 * $1 + 100 * $2 + ($3 == 0 ? $5 != 1 : $3))')"
            String -> String -> ShM ()
tell_env String
"HCNUMVER" String
"$HCNUMVER"

            CompilerRange -> String -> String -> ShM ()
if_then_else (VersionRange -> CompilerRange
Range VersionRange
cfgTests)
                (String -> String -> String
tell_env' String
"ARG_TESTS" String
"--enable-tests")
                (String -> String -> String
tell_env' String
"ARG_TESTS" String
"--disable-tests")
            CompilerRange -> String -> String -> ShM ()
if_then_else (VersionRange -> CompilerRange
Range VersionRange
cfgBenchmarks)
                (String -> String -> String
tell_env' String
"ARG_BENCH" String
"--enable-benchmarks")
                (String -> String -> String
tell_env' String
"ARG_BENCH" String
"--disable-benchmarks")
            CompilerRange -> String -> String -> ShM ()
if_then_else (VersionRange -> CompilerRange
Range VersionRange
cfgHeadHackage CompilerRange -> CompilerRange -> CompilerRange
forall a. Lattice a => a -> a -> a
\/ Set CompilerVersion -> CompilerRange
RangePoints (CompilerVersion -> Set CompilerVersion
forall a. a -> Set a
S.singleton CompilerVersion
GHCHead))
                (String -> String -> String
tell_env' String
"HEADHACKAGE" String
"true")
                (String -> String -> String
tell_env' String
"HEADHACKAGE" String
"false")

            String -> String -> ShM ()
tell_env String
"ARG_COMPILER" String
"--$HCKIND --with-compiler=$HC"

            Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless Bool
anyGHCJS (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$
                String -> String -> ShM ()
tell_env String
"GHCJSARITH" String
"0"

        String -> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
githubRun String
"env" (ShM () -> ListBuilder (Either HsCiError GitHubStep) ())
-> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ do
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"env"

        String -> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
githubRun String
"write cabal config" (ShM () -> ListBuilder (Either HsCiError GitHubStep) ())
-> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ do
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"mkdir -p $CABAL_DIR"
            String -> String -> ShM ()
cat String
"$CABAL_CONFIG" (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ [String] -> String
unlines
                [ String
"remote-build-reporting: anonymous"
                , String
"write-ghc-environment-files: never"
                , String
"remote-repo-cache: $CABAL_DIR/packages"
                , String
"logs-dir:          $CABAL_DIR/logs"
                , String
"world-file:        $CABAL_DIR/world"
                , String
"extra-prog-path:   $CABAL_DIR/bin"
                , String
"symlink-bindir:    $CABAL_DIR/bin"
                , String
"installdir:        $CABAL_DIR/bin"
                , String
"build-summary:     $CABAL_DIR/logs/build.log"
                , String
"store-dir:         $CABAL_DIR/store"
                , String
"install-dirs user"
                , String
"  prefix: $CABAL_DIR"
                , String
"repository hackage.haskell.org"
                , String
"  url: http://hackage.haskell.org/"
                ]

            -- Add head.hackage repository to ~/.cabal/config
            -- (locally you want to add it to cabal.project)
            Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Set CompilerVersion -> Bool
forall a. Set a -> Bool
S.null Set CompilerVersion
headGhcVers) (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$
                [ String
"if $HEADHACKAGE; then\n"
                , String -> String -> String
catCmd String
"$CABAL_CONFIG" (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ [String] -> String
unlines [String]
headHackageRepoStanza
                , String
"\nfi"
                ]

            -- Cabal jobs
            Maybe Int -> (Int -> ShM ()) -> ShM ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ (Maybe Jobs
cfgJobs Maybe Jobs -> (Jobs -> Maybe Int) -> Maybe Int
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Jobs -> Maybe Int
cabalJobs) ((Int -> ShM ()) -> ShM ()) -> (Int -> ShM ()) -> ShM ()
forall a b. (a -> b) -> a -> b
$ \Int
n ->
                String -> String -> ShM ()
cat String
"$CABAL_CONFIG" (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ [String] -> String
unlines
                    [ String
"jobs: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
n
                    ]

            -- GHC jobs + ghc-options
            Maybe Int -> (Int -> ShM ()) -> ShM ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ (Maybe Jobs
cfgJobs Maybe Jobs -> (Jobs -> Maybe Int) -> Maybe Int
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Jobs -> Maybe Int
ghcJobs) ((Int -> ShM ()) -> ShM ()) -> (Int -> ShM ()) -> ShM ()
forall a b. (a -> b) -> a -> b
$ \Int
m -> do
                CompilerRange -> String -> ShM ()
sh_if (VersionRange -> CompilerRange
Range (VersionRange -> CompilerRange) -> VersionRange -> CompilerRange
forall a b. (a -> b) -> a -> b
$ Version -> VersionRange
C.orLaterVersion ([Int] -> Version
C.mkVersion [Int
7,Int
8])) (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String
"GHCJOBS=-j" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
m

            String -> String -> ShM ()
cat String
"$CABAL_CONFIG" (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ [String] -> String
unlines
                [ String
"program-default-options"
                , String
"  ghc-options: $GHCJOBS +RTS -M3G -RTS"
                ]

            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"cat $CABAL_CONFIG"

        String -> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
githubRun String
"versions" (ShM () -> ListBuilder (Either HsCiError GitHubStep) ())
-> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ do
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"$HC --version || true"
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"$HC --print-project-git-commit-id || true"
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"$CABAL --version || true"
            Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
anyGHCJS (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ do
                CompilerRange -> String -> ShM ()
sh_if CompilerRange
RangeGHCJS String
"node --version"
                CompilerRange -> String -> ShM ()
sh_if CompilerRange
RangeGHCJS String
"echo $GHCJS"

        String -> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
githubRun String
"update cabal index" (ShM () -> ListBuilder (Either HsCiError GitHubStep) ())
-> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ do
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"$CABAL v2-update -v"

        let toolsConfigHash :: String
            toolsConfigHash :: String
toolsConfigHash = Int -> String -> String
forall a. Int -> [a] -> [a]
take Int
8 (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ ByteString -> String
BS8.unpack (ByteString -> String) -> ByteString -> String
forall a b. (a -> b) -> a -> b
$ ByteString -> ByteString
Base16.encode (ByteString -> ByteString) -> ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$ ByteString -> ByteString
SHA256.hashlazy (ByteString -> ByteString) -> ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$ Put -> ByteString
Binary.runPut (Put -> ByteString) -> Put -> ByteString
forall a b. (a -> b) -> a -> b
$ do
                DoctestConfig -> Put
forall t. Binary t => t -> Put
Binary.put DoctestConfig
cfgDoctest
                HLintConfig -> Put
forall t. Binary t => t -> Put
Binary.put HLintConfig
cfgHLint

        Bool
-> ListBuilder (Either HsCiError GitHubStep) ()
-> ListBuilder (Either HsCiError GitHubStep) ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool
doctestEnabled Bool -> Bool -> Bool
|| HLintConfig -> Bool
cfgHLintEnabled HLintConfig
cfgHLint) (ListBuilder (Either HsCiError GitHubStep) ()
 -> ListBuilder (Either HsCiError GitHubStep) ())
-> ListBuilder (Either HsCiError GitHubStep) ()
-> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ String
-> String
-> [(String, String)]
-> ListBuilder (Either HsCiError GitHubStep) ()
githubUses String
"cache (tools)" String
"actions/cache@v2"
            [ (String
"key", String
"${{ runner.os }}-${{ matrix.compiler }}-tools-" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
toolsConfigHash)
            , (String
"path", String
"~/.haskell-ci-tools")
            ]

        String -> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
githubRun String
"install cabal-plan" (ShM () -> ListBuilder (Either HsCiError GitHubStep) ())
-> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ do
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"mkdir -p $HOME/.cabal/bin"
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"curl -sL https://github.com/haskell-hvr/cabal-plan/releases/download/v0.6.2.0/cabal-plan-0.6.2.0-x86_64-linux.xz > cabal-plan.xz"
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"echo 'de73600b1836d3f55e32d80385acc055fd97f60eaa0ab68a755302685f5d81bc  cabal-plan.xz' | sha256sum -c -"
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"xz -d < cabal-plan.xz > $HOME/.cabal/bin/cabal-plan"
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"rm -f cabal-plan.xz"
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"chmod a+x $HOME/.cabal/bin/cabal-plan"
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"cabal-plan --version"

        Bool
-> ListBuilder (Either HsCiError GitHubStep) ()
-> ListBuilder (Either HsCiError GitHubStep) ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
anyGHCJS (ListBuilder (Either HsCiError GitHubStep) ()
 -> ListBuilder (Either HsCiError GitHubStep) ())
-> ListBuilder (Either HsCiError GitHubStep) ()
-> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ String -> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
githubRun String
"install happy" (ShM () -> ListBuilder (Either HsCiError GitHubStep) ())
-> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ do
            [PackageName] -> (PackageName -> ShM ()) -> ShM ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ [PackageName]
cfgGhcjsTools ((PackageName -> ShM ()) -> ShM ())
-> (PackageName -> ShM ()) -> ShM ()
forall a b. (a -> b) -> a -> b
$ \PackageName
t ->
                CompilerRange -> String -> ShM ()
sh_if CompilerRange
RangeGHCJS (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String
"$CABAL v2-install -w ghc-8.4.4 --ignore-project -j2" String -> String -> String
forall a. [a] -> [a] -> [a]
++ PackageName -> String
forall a. Pretty a => a -> String
C.prettyShow PackageName
t

        Bool
-> ListBuilder (Either HsCiError GitHubStep) ()
-> ListBuilder (Either HsCiError GitHubStep) ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
docspecEnabled (ListBuilder (Either HsCiError GitHubStep) ()
 -> ListBuilder (Either HsCiError GitHubStep) ())
-> ListBuilder (Either HsCiError GitHubStep) ()
-> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ String -> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
githubRun String
"install cabal-docspec" (ShM () -> ListBuilder (Either HsCiError GitHubStep) ())
-> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ do
            let hash :: String
hash = DocspecConfig -> String
cfgDocspecHash DocspecConfig
cfgDocspec
                url :: String
url  = DocspecConfig -> String
cfgDocspecUrl DocspecConfig
cfgDocspec
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"mkdir -p $HOME/.cabal/bin"
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String
"curl -sL " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
url String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" > cabal-docspec.xz"
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String
"echo '" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
hash String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"  cabal-docspec.xz' | sha256sum -c -"
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"xz -d < cabal-docspec.xz > $HOME/.cabal/bin/cabal-docspec"
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"rm -f cabal-docspec.xz"
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"chmod a+x $HOME/.cabal/bin/cabal-docspec"
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"cabal-docspec --version"

        Bool
-> ListBuilder (Either HsCiError GitHubStep) ()
-> ListBuilder (Either HsCiError GitHubStep) ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
doctestEnabled (ListBuilder (Either HsCiError GitHubStep) ()
 -> ListBuilder (Either HsCiError GitHubStep) ())
-> ListBuilder (Either HsCiError GitHubStep) ()
-> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ String -> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
githubRun String
"install doctest" (ShM () -> ListBuilder (Either HsCiError GitHubStep) ())
-> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ do
            let range :: CompilerRange
range = VersionRange -> CompilerRange
Range (DoctestConfig -> VersionRange
cfgDoctestEnabled DoctestConfig
cfgDoctest) CompilerRange -> CompilerRange -> CompilerRange
forall a. Lattice a => a -> a -> a
/\ CompilerRange
doctestJobVersionRange
            CompilerRange -> String -> ShM ()
sh_if CompilerRange
range String
"$CABAL --store-dir=$HOME/.haskell-ci-tools/store v2-install $ARG_COMPILER --ignore-project -j2 doctest --constraint='doctest ^>=0.20'"
            CompilerRange -> String -> ShM ()
sh_if CompilerRange
range String
"doctest --version"

        let hlintVersionConstraint :: String
hlintVersionConstraint
                | VersionRange -> Bool
C.isAnyVersion (HLintConfig -> VersionRange
cfgHLintVersion HLintConfig
cfgHLint) = String
""
                | Bool
otherwise = String
" --constraint='hlint " String -> String -> String
forall a. [a] -> [a] -> [a]
++ VersionRange -> String
forall a. Pretty a => a -> String
prettyShow (HLintConfig -> VersionRange
cfgHLintVersion HLintConfig
cfgHLint) String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"'"
        Bool
-> ListBuilder (Either HsCiError GitHubStep) ()
-> ListBuilder (Either HsCiError GitHubStep) ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (HLintConfig -> Bool
cfgHLintEnabled HLintConfig
cfgHLint) (ListBuilder (Either HsCiError GitHubStep) ()
 -> ListBuilder (Either HsCiError GitHubStep) ())
-> ListBuilder (Either HsCiError GitHubStep) ()
-> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ String -> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
githubRun String
"install hlint" (ShM () -> ListBuilder (Either HsCiError GitHubStep) ())
-> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ do
            let forHLint :: String -> ShM ()
forHLint = CompilerRange -> String -> ShM ()
sh_if (Set CompilerVersion -> VersionRange -> HLintJob -> CompilerRange
hlintJobVersionRange Set CompilerVersion
allVersions VersionRange
cfgHeadHackage (HLintConfig -> HLintJob
cfgHLintJob HLintConfig
cfgHLint))
            if HLintConfig -> Bool
cfgHLintDownload HLintConfig
cfgHLint
            then do
                -- install --dry-run and use perl regex magic to find a hlint version
                -- -v is important
                String -> ShM ()
forHLint (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String
"HLINTVER=$(cd /tmp && (${CABAL} v2-install -v $ARG_COMPILER --dry-run hlint " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
hlintVersionConstraint String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" |  perl -ne 'if (/\\bhlint-(\\d+(\\.\\d+)*)\\b/) { print \"$1\"; last; }')); echo \"HLint version $HLINTVER\""
                String -> ShM ()
forHLint (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String
"if [ ! -e $HOME/.haskell-ci-tools/hlint-$HLINTVER/hlint ]; then " String -> String -> String
forall a. [a] -> [a] -> [a]
++ [String] -> String
unwords
                    [ String
"echo \"Downloading HLint version $HLINTVER\";"
                    , String
"mkdir -p $HOME/.haskell-ci-tools;"
                    , String
"curl --write-out 'Status Code: %{http_code} Redirects: %{num_redirects} Total time: %{time_total} Total Dsize: %{size_download}\\n' --silent --location --output $HOME/.haskell-ci-tools/hlint-$HLINTVER.tar.gz \"https://github.com/ndmitchell/hlint/releases/download/v$HLINTVER/hlint-$HLINTVER-x86_64-linux.tar.gz\";"
                    , String
"tar -xzv -f $HOME/.haskell-ci-tools/hlint-$HLINTVER.tar.gz -C $HOME/.haskell-ci-tools;"
                    , String
"fi"
                    ]
                String -> ShM ()
forHLint String
"mkdir -p $CABAL_DIR/bin && ln -sf \"$HOME/.haskell-ci-tools/hlint-$HLINTVER/hlint\" $CABAL_DIR/bin/hlint"
                String -> ShM ()
forHLint String
"hlint --version"

            else do
                String -> ShM ()
forHLint (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String
"$CABAL --store-dir=$HOME/.haskell-ci-tools/store v2-install $ARG_COMPILER --ignore-project -j2 hlint" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
hlintVersionConstraint
                String -> ShM ()
forHLint String
"hlint --version"

        String
-> String
-> [(String, String)]
-> ListBuilder (Either HsCiError GitHubStep) ()
githubUses String
"checkout" String
"actions/checkout@v2" ([(String, String)]
 -> ListBuilder (Either HsCiError GitHubStep) ())
-> [(String, String)]
-> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ ListBuilder (String, String) () -> [(String, String)]
forall x. ListBuilder x () -> [x]
buildList (ListBuilder (String, String) () -> [(String, String)])
-> ListBuilder (String, String) () -> [(String, String)]
forall a b. (a -> b) -> a -> b
$ do
            (String, String) -> ListBuilder (String, String) ()
forall x. x -> ListBuilder x ()
item (String
"path", String
"source")
            Bool
-> ListBuilder (String, String) ()
-> ListBuilder (String, String) ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
cfgSubmodules (ListBuilder (String, String) ()
 -> ListBuilder (String, String) ())
-> ListBuilder (String, String) ()
-> ListBuilder (String, String) ()
forall a b. (a -> b) -> a -> b
$
                (String, String) -> ListBuilder (String, String) ()
forall x. x -> ListBuilder x ()
item (String
"submodules", String
"true")

        String -> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
githubRun String
"initial cabal.project for sdist" (ShM () -> ListBuilder (Either HsCiError GitHubStep) ())
-> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ do
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"touch cabal.project"
            [Package] -> (Package -> ShM ()) -> ShM ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ [Package]
pkgs ((Package -> ShM ()) -> ShM ()) -> (Package -> ShM ()) -> ShM ()
forall a b. (a -> b) -> a -> b
$ \Package
pkg ->
                CompilerRange -> String -> String -> ShM ()
echo_if_to (Set CompilerVersion -> CompilerRange
RangePoints (Set CompilerVersion -> CompilerRange)
-> Set CompilerVersion -> CompilerRange
forall a b. (a -> b) -> a -> b
$ Package -> Set CompilerVersion
pkgJobs Package
pkg) String
"cabal.project" (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String
"packages: $GITHUB_WORKSPACE/source/" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Package -> String
pkgDir Package
pkg
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"cat cabal.project"

        String -> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
githubRun String
"sdist" (ShM () -> ListBuilder (Either HsCiError GitHubStep) ())
-> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ do
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"mkdir -p sdist"
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"$CABAL sdist all --output-dir $GITHUB_WORKSPACE/sdist"

        String -> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
githubRun String
"unpack" (ShM () -> ListBuilder (Either HsCiError GitHubStep) ())
-> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ do
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"mkdir -p unpacked"
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"find sdist -maxdepth 1 -type f -name '*.tar.gz' -exec tar -C $GITHUB_WORKSPACE/unpacked -xzvf {} \\;"

        String -> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
githubRun String
"generate cabal.project" (ShM () -> ListBuilder (Either HsCiError GitHubStep) ())
-> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ do
            [Package] -> (Package -> ShM ()) -> ShM ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ [Package]
pkgs ((Package -> ShM ()) -> ShM ()) -> (Package -> ShM ()) -> ShM ()
forall a b. (a -> b) -> a -> b
$ \Pkg{String
pkgName :: Package -> String
pkgName :: String
pkgName} -> do
                String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String -> String
pkgNameDirVariable' String
pkgName String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"=\"$(find \"$GITHUB_WORKSPACE/unpacked\" -maxdepth 1 -type d -regex '.*/" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
pkgName String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"-[0-9.]*')\""
                String -> String -> ShM ()
tell_env (String -> String
pkgNameDirVariable' String
pkgName) (String -> String
pkgNameDirVariable String
pkgName)

            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"rm -f cabal.project cabal.project.local"
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"touch cabal.project"
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"touch cabal.project.local"

            [Package] -> (Package -> ShM ()) -> ShM ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ [Package]
pkgs ((Package -> ShM ()) -> ShM ()) -> (Package -> ShM ()) -> ShM ()
forall a b. (a -> b) -> a -> b
$ \Package
pkg ->
                CompilerRange -> String -> String -> ShM ()
echo_if_to (Set CompilerVersion -> CompilerRange
RangePoints (Set CompilerVersion -> CompilerRange)
-> Set CompilerVersion -> CompilerRange
forall a b. (a -> b) -> a -> b
$ Package -> Set CompilerVersion
pkgJobs Package
pkg) String
"cabal.project" (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String
"packages: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> String
pkgNameDirVariable (Package -> String
pkgName Package
pkg)

            -- per package options
            case PackageScope
cfgErrorMissingMethods of
                PackageScope
PackageScopeNone  -> () -> ShM ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
                PackageScope
PackageScopeLocal -> [Package] -> (Package -> ShM ()) -> ShM ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ [Package]
pkgs ((Package -> ShM ()) -> ShM ()) -> (Package -> ShM ()) -> ShM ()
forall a b. (a -> b) -> a -> b
$ \Pkg{String
pkgName :: String
pkgName :: Package -> String
pkgName,Set CompilerVersion
pkgJobs :: Set CompilerVersion
pkgJobs :: Package -> Set CompilerVersion
pkgJobs} -> do
                    let range :: CompilerRange
range = VersionRange -> CompilerRange
Range (Version -> VersionRange
C.orLaterVersion ([Int] -> Version
C.mkVersion [Int
8,Int
2])) CompilerRange -> CompilerRange -> CompilerRange
forall a. Lattice a => a -> a -> a
/\ Set CompilerVersion -> CompilerRange
RangePoints Set CompilerVersion
pkgJobs
                    CompilerRange -> String -> String -> ShM ()
echo_if_to CompilerRange
range String
"cabal.project" (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String
"package " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
pkgName
                    CompilerRange -> String -> String -> ShM ()
echo_if_to CompilerRange
range String
"cabal.project" (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String
"    ghc-options: -Werror=missing-methods"
                PackageScope
PackageScopeAll   -> String -> String -> ShM ()
cat String
"cabal.project" (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ [String] -> String
unlines
                    [ String
"package *"
                    , String
"  ghc-options: -Werror=missing-methods"
                    ]

            -- extra cabal.project fields
            String -> String -> ShM ()
cat String
"cabal.project" (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ (() -> [String])
-> (() -> [String] -> [String])
-> Int
-> [PrettyField ()]
-> String
forall ann.
(ann -> [String])
-> (ann -> [String] -> [String])
-> Int
-> [PrettyField ann]
-> String
C.showFields' ([String] -> () -> [String]
forall a b. a -> b -> a
const []) (([String] -> [String]) -> () -> [String] -> [String]
forall a b. a -> b -> a
const [String] -> [String]
forall a. a -> a
id) Int
2 ([PrettyField ()] -> String) -> [PrettyField ()] -> String
forall a b. (a -> b) -> a -> b
$ String -> [PrettyField ()]
extraCabalProjectFields String
"$GITHUB_WORKSPACE/source/"

            -- If using head.hackage, allow building with newer versions of GHC boot libraries.
            -- Note that we put this in a cabal.project file, not ~/.cabal/config, in order to avoid
            -- https://github.com/haskell/cabal/issues/7291.
            Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Set CompilerVersion -> Bool
forall a. Set a -> Bool
S.null Set CompilerVersion
headGhcVers) (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$
                [ String
"if $HEADHACKAGE; then\n"
                , String
"echo \"allow-newer: $($HCPKG list --simple-output | sed -E 's/([a-zA-Z-]+)-[0-9.]+/*:\\1,/g')\" >> cabal.project\n"
                , String
"fi"
                ]

            -- also write cabal.project.local file with
            -- @
            -- constraints: base installed
            -- constraints: array installed
            -- ...
            --
            -- omitting any local package names
            case [Installed] -> InstalledNormalised
normaliseInstalled [Installed]
cfgInstalled of
                InstalledDiff Set PackageName
pns -> String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ [String] -> String
unwords
                    [ String
"$HCPKG list --simple-output --names-only"
                    , String
"| perl -ne 'for (split /\\s+/) { print \"constraints: $_ installed\\n\" unless /" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
re String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"/; }'"
                    , String
">> cabal.project.local"
                    ]
                  where
                    pns' :: Set String
pns' = (PackageName -> String) -> Set PackageName -> Set String
forall b a. Ord b => (a -> b) -> Set a -> Set b
S.map PackageName -> String
C.unPackageName Set PackageName
pns Set String -> Set String -> Set String
forall a. Ord a => Set a -> Set a -> Set a
`S.union` (Package -> Set String) -> [Package] -> Set String
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap (String -> Set String
forall a. a -> Set a
S.singleton (String -> Set String)
-> (Package -> String) -> Package -> Set String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Package -> String
pkgName) [Package]
pkgs
                    re :: String
re = String
"^(" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
"|" (Set String -> [String]
forall a. Set a -> [a]
S.toList Set String
pns') String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
")$"

                InstalledOnly Set PackageName
pns | Bool -> Bool
not (Set String -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null Set String
pns') -> String -> String -> ShM ()
cat String
"cabal.project.local" (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ [String] -> String
unlines
                    [ String
"constraints: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
pkg String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" installed"
                    | String
pkg <- Set String -> [String]
forall a. Set a -> [a]
S.toList Set String
pns'
                    ]
                  where
                    pns' :: Set String
pns' = (PackageName -> String) -> Set PackageName -> Set String
forall b a. Ord b => (a -> b) -> Set a -> Set b
S.map PackageName -> String
C.unPackageName Set PackageName
pns Set String -> Set String -> Set String
forall a. Ord a => Set a -> Set a -> Set a
`S.difference` (Package -> Set String) -> [Package] -> Set String
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap (String -> Set String
forall a. a -> Set a
S.singleton (String -> Set String)
-> (Package -> String) -> Package -> Set String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Package -> String
pkgName) [Package]
pkgs

                -- otherwise: nothing
                InstalledNormalised
_ -> () -> ShM ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()

            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"cat cabal.project"
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"cat cabal.project.local"

        String -> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
githubRun String
"dump install plan" (ShM () -> ListBuilder (Either HsCiError GitHubStep) ())
-> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ do
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"$CABAL v2-build $ARG_COMPILER $ARG_TESTS $ARG_BENCH --dry-run all"
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"cabal-plan"

        -- This a hack. https://github.com/actions/cache/issues/109
        -- Hashing Java - Maven style.
        String
-> String
-> [(String, String)]
-> ListBuilder (Either HsCiError GitHubStep) ()
githubUses String
"cache" String
"actions/cache@v2"
            [ (String
"key", String
"${{ runner.os }}-${{ matrix.compiler }}-${{ github.sha }}")
            , (String
"restore-keys", String
"${{ runner.os }}-${{ matrix.compiler }}-")
            , (String
"path", String
"~/.cabal/store")
            ]

        -- install dependencies
        Bool
-> ListBuilder (Either HsCiError GitHubStep) ()
-> ListBuilder (Either HsCiError GitHubStep) ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
cfgInstallDeps (ListBuilder (Either HsCiError GitHubStep) ()
 -> ListBuilder (Either HsCiError GitHubStep) ())
-> ListBuilder (Either HsCiError GitHubStep) ()
-> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ String -> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
githubRun String
"install dependencies" (ShM () -> ListBuilder (Either HsCiError GitHubStep) ())
-> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ do
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"$CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks --dependencies-only -j2 all"
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"$CABAL v2-build $ARG_COMPILER $ARG_TESTS $ARG_BENCH --dependencies-only -j2 all"

        -- build w/o tests benchs
        Bool
-> ListBuilder (Either HsCiError GitHubStep) ()
-> ListBuilder (Either HsCiError GitHubStep) ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (VersionRange -> VersionRange -> Bool
equivVersionRanges VersionRange
C.noVersion VersionRange
cfgNoTestsNoBench) (ListBuilder (Either HsCiError GitHubStep) ()
 -> ListBuilder (Either HsCiError GitHubStep) ())
-> ListBuilder (Either HsCiError GitHubStep) ()
-> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ String -> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
githubRun String
"build w/o tests" (ShM () -> ListBuilder (Either HsCiError GitHubStep) ())
-> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ do
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"$CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks all"

        -- build
        String -> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
githubRun String
"build" (ShM () -> ListBuilder (Either HsCiError GitHubStep) ())
-> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ do
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"$CABAL v2-build $ARG_COMPILER $ARG_TESTS $ARG_BENCH all --write-ghc-environment-files=always"

        -- tests
        String -> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
githubRun String
"tests" (ShM () -> ListBuilder (Either HsCiError GitHubStep) ())
-> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ do
            let range :: CompilerRange
range = CompilerRange
RangeGHC CompilerRange -> CompilerRange -> CompilerRange
forall a. Lattice a => a -> a -> a
/\ VersionRange -> CompilerRange
Range (VersionRange
cfgTests VersionRange -> VersionRange -> VersionRange
forall a. Lattice a => a -> a -> a
/\ VersionRange
cfgRunTests) CompilerRange -> CompilerRange -> CompilerRange
forall a. Lattice a => a -> a -> a
/\ CompilerRange
hasTests
            CompilerRange -> String -> ShM ()
sh_if CompilerRange
range (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String
"$CABAL v2-test $ARG_COMPILER $ARG_TESTS $ARG_BENCH all" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
testShowDetails

            Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool
anyGHCJS Bool -> Bool -> Bool
&& Bool
cfgGhcjsTests) (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ [String] -> String
unlines ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$
                [ String
"pkgdir() {"
                , String
"  case $1 in"
                ] [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++
                [ String
"    " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
pkgName String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
") echo " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> String
pkgNameDirVariable String
pkgName String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" ;;"
                | Pkg{String
pkgName :: String
pkgName :: Package -> String
pkgName} <- [Package]
pkgs
                ] [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++
                [ String
"  esac"
                , String
"}"
                ]

            Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
cfgGhcjsTests (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ CompilerRange -> String -> ShM ()
sh_if (CompilerRange
RangeGHCJS CompilerRange -> CompilerRange -> CompilerRange
forall a. Lattice a => a -> a -> a
/\ CompilerRange
hasTests) (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ [String] -> String
unwords
                [ String
"cabal-plan list-bins '*:test:*' | while read -r line; do"
                , String
"testpkg=$(echo \"$line\" | perl -pe 's/:.*//');"
                , String
"testexe=$(echo \"$line\" | awk '{ print $2 }');"
                , String
"echo \"testing $textexe in package $textpkg\";"
                , String
"(cd \"$(pkgdir $testpkg)\" && nodejs \"$testexe\".jsexe/all.js);"
                , String
"done"
                ]

        -- doctest
        Bool
-> ListBuilder (Either HsCiError GitHubStep) ()
-> ListBuilder (Either HsCiError GitHubStep) ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
doctestEnabled (ListBuilder (Either HsCiError GitHubStep) ()
 -> ListBuilder (Either HsCiError GitHubStep) ())
-> ListBuilder (Either HsCiError GitHubStep) ()
-> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ String -> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
githubRun String
"doctest" (ShM () -> ListBuilder (Either HsCiError GitHubStep) ())
-> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ do
            let doctestOptions :: String
doctestOptions = [String] -> String
unwords ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ DoctestConfig -> [String]
cfgDoctestOptions DoctestConfig
cfgDoctest

            Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless ([PackageName] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null ([PackageName] -> Bool) -> [PackageName] -> Bool
forall a b. (a -> b) -> a -> b
$ DoctestConfig -> [PackageName]
cfgDoctestFilterEnvPkgs DoctestConfig
cfgDoctest) (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ do
                -- cabal-install mangles unit ids on the OSX,
                -- removing the vowels to make filepaths shorter
                let manglePkgNames :: String -> [String]
                    manglePkgNames :: String -> [String]
manglePkgNames String
n
                        | Set CompilerVersion -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null Set CompilerVersion
macosVersions = [String
n]
                        | Bool
otherwise          = [String
n, (Char -> Bool) -> String -> String
forall a. (a -> Bool) -> [a] -> [a]
filter Char -> Bool
notVowel String
n]
                      where
                        notVowel :: Char -> Bool
notVowel Char
c = Char -> String -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
notElem Char
c (String
"aeiou" :: String)
                let filterPkgs :: String
filterPkgs = String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
"|" ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ (PackageName -> [String]) -> [PackageName] -> [String]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (String -> [String]
manglePkgNames (String -> [String])
-> (PackageName -> String) -> PackageName -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PackageName -> String
C.unPackageName) ([PackageName] -> [String]) -> [PackageName] -> [String]
forall a b. (a -> b) -> a -> b
$ DoctestConfig -> [PackageName]
cfgDoctestFilterEnvPkgs DoctestConfig
cfgDoctest
                String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String
"perl -i -e 'while (<ARGV>) { print unless /package-id\\s+(" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
filterPkgs String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
")-\\d+(\\.\\d+)*/; }' .ghc.environment.*"

            [Package] -> (Package -> ShM ()) -> ShM ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ [Package]
pkgs ((Package -> ShM ()) -> ShM ()) -> (Package -> ShM ()) -> ShM ()
forall a b. (a -> b) -> a -> b
$ \Pkg{String
pkgName :: String
pkgName :: Package -> String
pkgName,GenericPackageDescription
pkgGpd :: Package -> GenericPackageDescription
pkgGpd :: GenericPackageDescription
pkgGpd,Set CompilerVersion
pkgJobs :: Set CompilerVersion
pkgJobs :: Package -> Set CompilerVersion
pkgJobs} ->
                Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (String -> PackageName
C.mkPackageName String
pkgName PackageName -> [PackageName] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` DoctestConfig -> [PackageName]
cfgDoctestFilterSrcPkgs DoctestConfig
cfgDoctest) (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ do
                    [[String]] -> ([String] -> ShM ()) -> ShM ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ (GenericPackageDescription -> [[String]]
doctestArgs GenericPackageDescription
pkgGpd) (([String] -> ShM ()) -> ShM ()) -> ([String] -> ShM ()) -> ShM ()
forall a b. (a -> b) -> a -> b
$ \[String]
args -> do
                        let args' :: String
args' = [String] -> String
unwords [String]
args
                        let vr :: CompilerRange
vr = VersionRange -> CompilerRange
Range (DoctestConfig -> VersionRange
cfgDoctestEnabled DoctestConfig
cfgDoctest)
                              CompilerRange -> CompilerRange -> CompilerRange
forall a. Lattice a => a -> a -> a
/\ CompilerRange
doctestJobVersionRange
                              CompilerRange -> CompilerRange -> CompilerRange
forall a. Lattice a => a -> a -> a
/\ Set CompilerVersion -> CompilerRange
RangePoints Set CompilerVersion
pkgJobs

                        Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless ([String] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [String]
args) (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ do
                            CompilerRange -> String -> ShM ()
change_dir_if CompilerRange
vr (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String -> String
pkgNameDirVariable String
pkgName
                            CompilerRange -> String -> ShM ()
sh_if CompilerRange
vr (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String
"doctest " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
doctestOptions String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
args'

        -- docspec
        Bool
-> ListBuilder (Either HsCiError GitHubStep) ()
-> ListBuilder (Either HsCiError GitHubStep) ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
docspecEnabled (ListBuilder (Either HsCiError GitHubStep) ()
 -> ListBuilder (Either HsCiError GitHubStep) ())
-> ListBuilder (Either HsCiError GitHubStep) ()
-> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ String -> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
githubRun String
"docspec" (ShM () -> ListBuilder (Either HsCiError GitHubStep) ())
-> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ do
            -- docspec doesn't work with non-GHC (i.e. GHCJS)
            let docspecRange' :: CompilerRange
docspecRange' = CompilerRange
docspecRange CompilerRange -> CompilerRange -> CompilerRange
forall a. Lattice a => a -> a -> a
/\ CompilerRange
RangeGHC
            -- we need to rebuild, if tests screwed something.
            CompilerRange -> String -> ShM ()
sh_if CompilerRange
docspecRange' String
"$CABAL v2-build $ARG_COMPILER $ARG_TESTS $ARG_BENCH all"
            CompilerRange -> String -> ShM ()
sh_if CompilerRange
docspecRange' String
cabalDocspec

        -- hlint
        Bool
-> ListBuilder (Either HsCiError GitHubStep) ()
-> ListBuilder (Either HsCiError GitHubStep) ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (HLintConfig -> Bool
cfgHLintEnabled HLintConfig
cfgHLint) (ListBuilder (Either HsCiError GitHubStep) ()
 -> ListBuilder (Either HsCiError GitHubStep) ())
-> ListBuilder (Either HsCiError GitHubStep) ()
-> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ String -> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
githubRun String
"hlint" (ShM () -> ListBuilder (Either HsCiError GitHubStep) ())
-> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ do
            let String
"" <+> :: String -> String -> String
<+> String
ys = String
ys
                String
xs <+> String
"" = String
xs
                String
xs <+> String
ys = String
xs String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
ys

                prependSpace :: String -> String
prependSpace String
"" = String
""
                prependSpace String
xs = String
" " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
xs

            let hlintOptions :: String
hlintOptions = String -> String
prependSpace (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ String -> (String -> String) -> Maybe String -> String
forall b a. b -> (a -> b) -> Maybe a -> b
maybe String
"" (String
"-h ${GITHUB_WORKSPACE}/source/" String -> String -> String
forall a. [a] -> [a] -> [a]
++) (HLintConfig -> Maybe String
cfgHLintYaml HLintConfig
cfgHLint) String -> String -> String
<+> [String] -> String
unwords (HLintConfig -> [String]
cfgHLintOptions HLintConfig
cfgHLint)

            [Package] -> (Package -> ShM ()) -> ShM ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ [Package]
pkgs ((Package -> ShM ()) -> ShM ()) -> (Package -> ShM ()) -> ShM ()
forall a b. (a -> b) -> a -> b
$ \Pkg{String
pkgName :: String
pkgName :: Package -> String
pkgName,GenericPackageDescription
pkgGpd :: GenericPackageDescription
pkgGpd :: Package -> GenericPackageDescription
pkgGpd,Set CompilerVersion
pkgJobs :: Set CompilerVersion
pkgJobs :: Package -> Set CompilerVersion
pkgJobs} -> do
                [[String]] -> ([String] -> ShM ()) -> ShM ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ (GenericPackageDescription -> [[String]]
hlintArgs GenericPackageDescription
pkgGpd) (([String] -> ShM ()) -> ShM ()) -> ([String] -> ShM ()) -> ShM ()
forall a b. (a -> b) -> a -> b
$ \[String]
args -> do
                    let args' :: String
args' = [String] -> String
unwords [String]
args
                    Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless ([String] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [String]
args) (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$
                        CompilerRange -> String -> ShM ()
sh_if (Set CompilerVersion -> VersionRange -> HLintJob -> CompilerRange
hlintJobVersionRange Set CompilerVersion
allVersions VersionRange
cfgHeadHackage (HLintConfig -> HLintJob
cfgHLintJob HLintConfig
cfgHLint) CompilerRange -> CompilerRange -> CompilerRange
forall a. Lattice a => a -> a -> a
/\ Set CompilerVersion -> CompilerRange
RangePoints Set CompilerVersion
pkgJobs) (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$
                        String
"(cd " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> String
pkgNameDirVariable String
pkgName String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" && hlint" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
hlintOptions String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
args' String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
")"

        -- cabal check
        Bool
-> ListBuilder (Either HsCiError GitHubStep) ()
-> ListBuilder (Either HsCiError GitHubStep) ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
cfgCheck (ListBuilder (Either HsCiError GitHubStep) ()
 -> ListBuilder (Either HsCiError GitHubStep) ())
-> ListBuilder (Either HsCiError GitHubStep) ()
-> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ String -> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
githubRun String
"cabal check" (ShM () -> ListBuilder (Either HsCiError GitHubStep) ())
-> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ do
            [Package] -> (Package -> ShM ()) -> ShM ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ [Package]
pkgs ((Package -> ShM ()) -> ShM ()) -> (Package -> ShM ()) -> ShM ()
forall a b. (a -> b) -> a -> b
$ \Pkg{String
pkgName :: String
pkgName :: Package -> String
pkgName,Set CompilerVersion
pkgJobs :: Set CompilerVersion
pkgJobs :: Package -> Set CompilerVersion
pkgJobs} -> do
                let range :: CompilerRange
range = Set CompilerVersion -> CompilerRange
RangePoints Set CompilerVersion
pkgJobs
                CompilerRange -> String -> ShM ()
change_dir_if CompilerRange
range (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String -> String
pkgNameDirVariable String
pkgName
                CompilerRange -> String -> ShM ()
sh_if CompilerRange
range String
"${CABAL} -vnormal check"

        -- haddock
        Bool
-> ListBuilder (Either HsCiError GitHubStep) ()
-> ListBuilder (Either HsCiError GitHubStep) ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool
hasLibrary Bool -> Bool -> Bool
&& Bool -> Bool
not (VersionRange -> VersionRange -> Bool
equivVersionRanges VersionRange
C.noVersion VersionRange
cfgHaddock)) (ListBuilder (Either HsCiError GitHubStep) ()
 -> ListBuilder (Either HsCiError GitHubStep) ())
-> ListBuilder (Either HsCiError GitHubStep) ()
-> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ String -> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
githubRun String
"haddock" (ShM () -> ListBuilder (Either HsCiError GitHubStep) ())
-> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ do
            let range :: CompilerRange
range = CompilerRange
RangeGHC CompilerRange -> CompilerRange -> CompilerRange
forall a. Lattice a => a -> a -> a
/\ VersionRange -> CompilerRange
Range VersionRange
cfgHaddock
            CompilerRange -> String -> ShM ()
sh_if CompilerRange
range String
"$CABAL v2-haddock $ARG_COMPILER --with-haddock $HADDOCK $ARG_TESTS $ARG_BENCH all"

        -- unconstrained build
        Bool
-> ListBuilder (Either HsCiError GitHubStep) ()
-> ListBuilder (Either HsCiError GitHubStep) ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (VersionRange -> VersionRange -> Bool
equivVersionRanges VersionRange
C.noVersion VersionRange
cfgUnconstrainted) (ListBuilder (Either HsCiError GitHubStep) ()
 -> ListBuilder (Either HsCiError GitHubStep) ())
-> ListBuilder (Either HsCiError GitHubStep) ()
-> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ String -> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
githubRun String
"unconstrained build" (ShM () -> ListBuilder (Either HsCiError GitHubStep) ())
-> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ do
            let range :: CompilerRange
range = VersionRange -> CompilerRange
Range VersionRange
cfgUnconstrainted
            CompilerRange -> String -> ShM ()
sh_if CompilerRange
range String
"rm -f cabal.project.local"
            CompilerRange -> String -> ShM ()
sh_if CompilerRange
range String
"$CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks all"

        -- constraint sets
        Bool
-> ListBuilder (Either HsCiError GitHubStep) ()
-> ListBuilder (Either HsCiError GitHubStep) ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless ([ConstraintSet] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [ConstraintSet]
cfgConstraintSets) (ListBuilder (Either HsCiError GitHubStep) ()
 -> ListBuilder (Either HsCiError GitHubStep) ())
-> ListBuilder (Either HsCiError GitHubStep) ()
-> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ String -> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
githubRun String
"prepare for constraint sets" (ShM () -> ListBuilder (Either HsCiError GitHubStep) ())
-> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ do
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"rm -f cabal.project.local"

        [ConstraintSet]
-> (ConstraintSet -> ListBuilder (Either HsCiError GitHubStep) ())
-> ListBuilder (Either HsCiError GitHubStep) ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ [ConstraintSet]
cfgConstraintSets ((ConstraintSet -> ListBuilder (Either HsCiError GitHubStep) ())
 -> ListBuilder (Either HsCiError GitHubStep) ())
-> (ConstraintSet -> ListBuilder (Either HsCiError GitHubStep) ())
-> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ \ConstraintSet
cs -> String -> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
githubRun (String
"constraint set " String -> String -> String
forall a. [a] -> [a] -> [a]
++ ConstraintSet -> String
csName ConstraintSet
cs) (ShM () -> ListBuilder (Either HsCiError GitHubStep) ())
-> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ do
            let range :: CompilerRange
range
                  | ConstraintSet -> Bool
csGhcjs ConstraintSet
cs  = VersionRange -> CompilerRange
Range (ConstraintSet -> VersionRange
csGhcVersions ConstraintSet
cs)
                  | Bool
otherwise   = CompilerRange
RangeGHC CompilerRange -> CompilerRange -> CompilerRange
forall a. Lattice a => a -> a -> a
/\ VersionRange -> CompilerRange
Range (ConstraintSet -> VersionRange
csGhcVersions ConstraintSet
cs)

            let sh_cs :: String -> ShM ()
sh_cs           = CompilerRange -> String -> ShM ()
sh_if CompilerRange
range
            let sh_cs' :: CompilerRange -> String -> ShM ()
sh_cs' CompilerRange
r        = CompilerRange -> String -> ShM ()
sh_if (CompilerRange
range CompilerRange -> CompilerRange -> CompilerRange
forall a. Lattice a => a -> a -> a
/\ CompilerRange
r)
            let testFlag :: String
testFlag        = if ConstraintSet -> Bool
csTests ConstraintSet
cs then String
"--enable-tests" else String
"--disable-tests"
            let benchFlag :: String
benchFlag       = if ConstraintSet -> Bool
csBenchmarks ConstraintSet
cs then String
"--enable-benchmarks" else String
"--disable-benchmarks"
            let constraintFlags :: [String]
constraintFlags = (String -> String) -> [String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (\String
x ->  String
"--constraint='" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"'") (ConstraintSet -> [String]
csConstraints ConstraintSet
cs)
            let allFlags :: String
allFlags        = [String] -> String
unwords (String
testFlag String -> [String] -> [String]
forall a. a -> [a] -> [a]
: String
benchFlag String -> [String] -> [String]
forall a. a -> [a] -> [a]
: [String]
constraintFlags)

            Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
cfgInstallDeps (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ String -> ShM ()
sh_cs (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String
"$CABAL v2-build $ARG_COMPILER " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
allFlags String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" --dependencies-only -j2 all"
            String -> ShM ()
sh_cs (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String
"$CABAL v2-build $ARG_COMPILER " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
allFlags String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" all"
            Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool
docspecEnabled Bool -> Bool -> Bool
&& ConstraintSet -> Bool
csDocspec ConstraintSet
cs) (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$
                CompilerRange -> String -> ShM ()
sh_cs' CompilerRange
docspecRange String
cabalDocspec
            Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (ConstraintSet -> Bool
csRunTests ConstraintSet
cs) (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$
                CompilerRange -> String -> ShM ()
sh_cs' CompilerRange
hasTests (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String
"$CABAL v2-test $ARG_COMPILER " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
allFlags String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" all"
            Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool
hasLibrary Bool -> Bool -> Bool
&& ConstraintSet -> Bool
csHaddock ConstraintSet
cs) (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$
                String -> ShM ()
sh_cs (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String
"$CABAL v2-haddock $ARG_COMPILER " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
withHaddock String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
allFlags String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" all"

    -- assembling everything
    GitHub -> Either HsCiError GitHub
forall (m :: * -> *) a. Monad m => a -> m a
return GitHub :: String -> GitHubOn -> Map String GitHubJob -> GitHub
GitHub
        { ghName :: String
ghName = String
actionName
        , ghOn :: GitHubOn
ghOn = GitHubOn :: [String] -> GitHubOn
GitHubOn
            { ghBranches :: [String]
ghBranches = [String]
cfgOnlyBranches
            }
        , ghJobs :: Map String GitHubJob
ghJobs = [(String, GitHubJob)] -> Map String GitHubJob
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList ([(String, GitHubJob)] -> Map String GitHubJob)
-> [(String, GitHubJob)] -> Map String GitHubJob
forall a b. (a -> b) -> a -> b
$ ListBuilder (String, GitHubJob) () -> [(String, GitHubJob)]
forall x. ListBuilder x () -> [x]
buildList (ListBuilder (String, GitHubJob) () -> [(String, GitHubJob)])
-> ListBuilder (String, GitHubJob) () -> [(String, GitHubJob)]
forall a b. (a -> b) -> a -> b
$ do
            (String, GitHubJob) -> ListBuilder (String, GitHubJob) ()
forall x. x -> ListBuilder x ()
item (String
mainJobName, GitHubJob :: String
-> String
-> [String]
-> Maybe String
-> Maybe String
-> Map String GitHubService
-> Maybe String
-> [GitHubMatrixEntry]
-> [GitHubStep]
-> Natural
-> GitHubJob
GitHubJob
                { ghjName :: String
ghjName            = String
actionName String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" - Linux - ${{ matrix.compiler }}"
                  -- NB: The Ubuntu version used in `runs-on` isn't
                  -- particularly important since we use a Docker container.
                , ghjRunsOn :: String
ghjRunsOn          = String
"ubuntu-18.04"
                , ghjNeeds :: [String]
ghjNeeds           = []
                , ghjSteps :: [GitHubStep]
ghjSteps           = [GitHubStep]
steps
                , ghjIf :: Maybe String
ghjIf              = Maybe String
forall a. Maybe a
Nothing
                , ghjContainer :: Maybe String
ghjContainer       = String -> Maybe String
forall a. a -> Maybe a
Just (String -> Maybe String) -> String -> Maybe String
forall a b. (a -> b) -> a -> b
$ String
"buildpack-deps:" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
ubuntuVer
                , ghjContinueOnError :: Maybe String
ghjContinueOnError = String -> Maybe String
forall a. a -> Maybe a
Just String
"${{ matrix.allow-failure }}"
                , ghjServices :: Map String GitHubService
ghjServices        = [Map String GitHubService] -> Map String GitHubService
forall a. Monoid a => [a] -> a
mconcat
                    [ String -> GitHubService -> Map String GitHubService
forall k a. k -> a -> Map k a
Map.singleton String
"postgres" GitHubService
postgresService | Bool
cfgPostgres ]
                , ghjTimeout :: Natural
ghjTimeout         = Natural -> Natural -> Natural
forall a. Ord a => a -> a -> a
max Natural
10 Natural
cfgTimeoutMinutes
                , ghjMatrix :: [GitHubMatrixEntry]
ghjMatrix          =
                    [ GitHubMatrixEntry :: CompilerVersion -> Bool -> SetupMethod -> GitHubMatrixEntry
GitHubMatrixEntry
                        { ghmeCompiler :: CompilerVersion
ghmeCompiler     = CompilerVersion
compiler
                        , ghmeAllowFailure :: Bool
ghmeAllowFailure =
                               VersionRange -> CompilerVersion -> Bool
previewGHC VersionRange
cfgHeadHackage CompilerVersion
compiler
                            Bool -> Bool -> Bool
|| Bool -> (Version -> Bool) -> CompilerVersion -> Bool
forall a. a -> (Version -> a) -> CompilerVersion -> a
maybeGHC Bool
False (Version -> VersionRange -> Bool
`C.withinRange` VersionRange
cfgAllowFailures) CompilerVersion
compiler
                        , ghmeSetupMethod :: SetupMethod
ghmeSetupMethod = if CompilerVersion -> Bool
isGHCUP CompilerVersion
compiler then SetupMethod
GHCUP else SetupMethod
HVRPPA
                        }
                    | CompilerVersion
compiler <- [CompilerVersion] -> [CompilerVersion]
forall a. [a] -> [a]
reverse ([CompilerVersion] -> [CompilerVersion])
-> [CompilerVersion] -> [CompilerVersion]
forall a b. (a -> b) -> a -> b
$ Set CompilerVersion -> [CompilerVersion]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList Set CompilerVersion
linuxVersions
                    , CompilerVersion
compiler CompilerVersion -> CompilerVersion -> Bool
forall a. Eq a => a -> a -> Bool
/= CompilerVersion
GHCHead -- TODO: Make this work
                                          -- https://github.com/haskell-CI/haskell-ci/issues/458
                    ]
                })
            Bool
-> ListBuilder (String, GitHubJob) ()
-> ListBuilder (String, GitHubJob) ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless ([String] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [String]
cfgIrcChannels) (ListBuilder (String, GitHubJob) ()
 -> ListBuilder (String, GitHubJob) ())
-> ListBuilder (String, GitHubJob) ()
-> ListBuilder (String, GitHubJob) ()
forall a b. (a -> b) -> a -> b
$
                String
-> String
-> String
-> Config
-> GitConfig
-> ListBuilder (String, GitHubJob) ()
ircJob String
actionName String
mainJobName String
projectName Config
config GitConfig
gitconfig
        }
  where
    actionName :: String
actionName  = String -> Maybe String -> String
forall a. a -> Maybe a -> a
fromMaybe String
"Haskell-CI" Maybe String
cfgGitHubActionName
    mainJobName :: String
mainJobName = String
"linux"

    ubuntuVer :: String
ubuntuVer    = Ubuntu -> String
showUbuntu Ubuntu
cfgUbuntu
    cabalVer :: String
cabalVer     = Maybe Version -> String
dispCabalVersion Maybe Version
cfgCabalInstallVersion
    cabalFullVer :: String
cabalFullVer = Maybe Version -> String
dispCabalVersion (Maybe Version -> String) -> Maybe Version -> String
forall a b. (a -> b) -> a -> b
$ Maybe Version
cfgCabalInstallVersion Maybe Version -> (Version -> Version) -> Maybe Version
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> \Version
ver ->
        case Version -> [Int]
C.versionNumbers Version
ver of
            [Int
3,Int
6] -> [Int] -> Version
C.mkVersion [Int
3,Int
6,Int
2,Int
0]
            [Int
x,Int
y] -> [Int] -> Version
C.mkVersion [Int
x,Int
y,Int
0,Int
0]
            [Int]
_     -> Version
ver

    Auxiliary {Bool
String
[URI]
[Package]
CompilerRange
String -> [PrettyField ()]
testShowDetails :: Auxiliary -> String
extraCabalProjectFields :: Auxiliary -> String -> [PrettyField ()]
hasLibrary :: Auxiliary -> Bool
hasTests :: Auxiliary -> CompilerRange
docspecEnabled :: Auxiliary -> Bool
doctestEnabled :: Auxiliary -> Bool
projectName :: Auxiliary -> String
uris :: Auxiliary -> [URI]
pkgs :: Auxiliary -> [Package]
uris :: [URI]
projectName :: String
hasLibrary :: Bool
testShowDetails :: String
hasTests :: CompilerRange
extraCabalProjectFields :: String -> [PrettyField ()]
pkgs :: [Package]
docspecEnabled :: Bool
doctestEnabled :: Bool
..} = Config -> Project URI Void Package -> JobVersions -> Auxiliary
auxiliary Config
config Project URI Void Package
prj JobVersions
jobs

    anyGHCJS :: Bool
anyGHCJS = (CompilerVersion -> Bool) -> Set CompilerVersion -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any CompilerVersion -> Bool
isGHCJS Set CompilerVersion
allVersions
    anyGHCUP :: Bool
anyGHCUP = (CompilerVersion -> Bool) -> Set CompilerVersion -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any CompilerVersion -> Bool
isGHCUP Set CompilerVersion
allVersions
    allGHCUP :: Bool
allGHCUP = (CompilerVersion -> Bool) -> Set CompilerVersion -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all CompilerVersion -> Bool
isGHCUP Set CompilerVersion
allVersions

    -- Generate a setup block for hvr-ppa or ghcup, or both.
    setup :: [Sh] -> [Sh] -> ShM ()
    setup :: [Sh] -> [Sh] -> ShM ()
setup [Sh]
hvrppa [Sh]
ghcup
        | Bool
allGHCUP     = (Sh -> ShM ()) -> [Sh] -> ShM ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
(a -> f b) -> t a -> f ()
traverse_ Sh -> ShM ()
liftSh [Sh]
ghcup
        | Bool -> Bool
not Bool
anyGHCUP = (Sh -> ShM ()) -> [Sh] -> ShM ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
(a -> f b) -> t a -> f ()
traverse_ Sh -> ShM ()
liftSh [Sh]
hvrppa
        -- 2192: ${{ ...}} will match (ShellCheck think it doesn't)
        -- 2129: individual redirects
        | Bool
otherwise    = [Integer] -> String -> ShM ()
forall (m :: * -> *). MonadSh m => [Integer] -> String -> m ()
sh' [Integer
2193, Integer
2129] (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ [String] -> String
unlines ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$
            [ String
"if [ \"${{ matrix.setup-method }}\" = ghcup ]; then"
            ] [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++
            [ String
"  " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Sh -> String
shToString Sh
s
            | Sh
s <- [Sh]
ghcup
            ] [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++
            [ String
"else"
            ] [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++
            [ String
"  " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Sh -> String
shToString Sh
s
            | Sh
s <- [Sh]
hvrppa
            ] [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++
            [ String
"fi"
            ]

    -- job to be setup with ghcup
    isGHCUP :: CompilerVersion -> Bool
    isGHCUP :: CompilerVersion -> Bool
isGHCUP CompilerVersion
v = CompilerVersion -> CompilerRange -> Bool
compilerWithinRange CompilerVersion
v (CompilerRange
RangeGHC CompilerRange -> CompilerRange -> CompilerRange
forall a. Lattice a => a -> a -> a
/\ VersionRange -> CompilerRange
Range VersionRange
cfgGhcupJobs)

    -- GHC versions which need head.hackage
    headGhcVers :: Set CompilerVersion
    headGhcVers :: Set CompilerVersion
headGhcVers = (CompilerVersion -> Bool)
-> Set CompilerVersion -> Set CompilerVersion
forall a. (a -> Bool) -> Set a -> Set a
S.filter (VersionRange -> CompilerVersion -> Bool
previewGHC VersionRange
cfgHeadHackage) Set CompilerVersion
allVersions

    -- step primitives
    githubRun' :: String -> Map.Map String String ->  ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
    githubRun' :: String
-> Map String String
-> ShM ()
-> ListBuilder (Either HsCiError GitHubStep) ()
githubRun' String
name Map String String
env ShM ()
shm = Either HsCiError GitHubStep
-> ListBuilder (Either HsCiError GitHubStep) ()
forall x. x -> ListBuilder x ()
item (Either HsCiError GitHubStep
 -> ListBuilder (Either HsCiError GitHubStep) ())
-> Either HsCiError GitHubStep
-> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ do
        [Sh]
shs <- ShM () -> Either HsCiError [Sh]
forall e (m :: * -> *).
(MonadErr e m, FromHsCiError e) =>
ShM () -> m [Sh]
runSh ShM ()
shm
        GitHubStep -> Either HsCiError GitHubStep
forall (m :: * -> *) a. Monad m => a -> m a
return (GitHubStep -> Either HsCiError GitHubStep)
-> GitHubStep -> Either HsCiError GitHubStep
forall a b. (a -> b) -> a -> b
$ String -> Either GitHubRun GitHubUses -> GitHubStep
GitHubStep String
name (Either GitHubRun GitHubUses -> GitHubStep)
-> Either GitHubRun GitHubUses -> GitHubStep
forall a b. (a -> b) -> a -> b
$ GitHubRun -> Either GitHubRun GitHubUses
forall a b. a -> Either a b
Left (GitHubRun -> Either GitHubRun GitHubUses)
-> GitHubRun -> Either GitHubRun GitHubUses
forall a b. (a -> b) -> a -> b
$ [Sh] -> Map String String -> GitHubRun
GitHubRun [Sh]
shs Map String String
env

    githubRun :: String -> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
    githubRun :: String -> ShM () -> ListBuilder (Either HsCiError GitHubStep) ()
githubRun String
name = String
-> Map String String
-> ShM ()
-> ListBuilder (Either HsCiError GitHubStep) ()
githubRun' String
name Map String String
forall a. Monoid a => a
mempty

    githubUses :: String -> String -> [(String, String)] -> ListBuilder (Either HsCiError GitHubStep) ()
    githubUses :: String
-> String
-> [(String, String)]
-> ListBuilder (Either HsCiError GitHubStep) ()
githubUses String
name String
action [(String, String)]
with = Either HsCiError GitHubStep
-> ListBuilder (Either HsCiError GitHubStep) ()
forall x. x -> ListBuilder x ()
item (Either HsCiError GitHubStep
 -> ListBuilder (Either HsCiError GitHubStep) ())
-> Either HsCiError GitHubStep
-> ListBuilder (Either HsCiError GitHubStep) ()
forall a b. (a -> b) -> a -> b
$ GitHubStep -> Either HsCiError GitHubStep
forall (m :: * -> *) a. Monad m => a -> m a
return (GitHubStep -> Either HsCiError GitHubStep)
-> GitHubStep -> Either HsCiError GitHubStep
forall a b. (a -> b) -> a -> b
$
        String -> Either GitHubRun GitHubUses -> GitHubStep
GitHubStep String
name (Either GitHubRun GitHubUses -> GitHubStep)
-> Either GitHubRun GitHubUses -> GitHubStep
forall a b. (a -> b) -> a -> b
$ GitHubUses -> Either GitHubRun GitHubUses
forall a b. b -> Either a b
Right (GitHubUses -> Either GitHubRun GitHubUses)
-> GitHubUses -> Either GitHubRun GitHubUses
forall a b. (a -> b) -> a -> b
$ String -> Maybe String -> Map String String -> GitHubUses
GitHubUses String
action Maybe String
forall a. Maybe a
Nothing ([(String, String)] -> Map String String
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList [(String, String)]
with)

    -- shell primitives
    echo_to' :: FilePath -> String -> String
    echo_to' :: String -> String -> String
echo_to' String
fp String
s = String
"echo " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> String
forall a. Show a => a -> String
show String
s String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" >> " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
fp

    echo_to :: FilePath -> String -> ShM ()
    echo_to :: String -> String -> ShM ()
echo_to String
fp String
s = String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String -> String -> String
echo_to' String
fp String
s

    echo_if_to :: CompilerRange -> FilePath -> String -> ShM ()
    echo_if_to :: CompilerRange -> String -> String -> ShM ()
echo_if_to CompilerRange
range String
fp String
s = CompilerRange -> String -> ShM ()
sh_if CompilerRange
range (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String -> String -> String
echo_to' String
fp String
s

    change_dir_if :: CompilerRange -> String -> ShM ()
    change_dir_if :: CompilerRange -> String -> ShM ()
change_dir_if CompilerRange
range String
dir = CompilerRange -> String -> ShM ()
sh_if CompilerRange
range (String
"cd " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
dir String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" || false")

    tell_env' :: String -> String -> String
    tell_env' :: String -> String -> String
tell_env' String
k String
v = String
"echo " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> String
forall a. Show a => a -> String
show (String
k String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"=" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
v) String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" >> \"$GITHUB_ENV\""

    tell_env :: String -> String -> ShM ()
    tell_env :: String -> String -> ShM ()
tell_env String
k String
v = String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String -> String -> String
tell_env' String
k String
v

    if_then_else :: CompilerRange -> String -> String -> ShM ()
    if_then_else :: CompilerRange -> String -> String -> ShM ()
if_then_else CompilerRange
range String
con String
alt
        | (CompilerVersion -> Bool) -> Set CompilerVersion -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (CompilerVersion -> CompilerRange -> Bool
`compilerWithinRange` CompilerRange
range) Set CompilerVersion
allVersions       = String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
con
        | Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ (CompilerVersion -> Bool) -> Set CompilerVersion -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (CompilerVersion -> CompilerRange -> Bool
`compilerWithinRange` CompilerRange
range) Set CompilerVersion
allVersions = String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
alt
        | Bool
otherwise = String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ [String] -> String
unwords
        [ String
"if ["
        , Set CompilerVersion -> CompilerRange -> String
compilerVersionArithPredicate Set CompilerVersion
allVersions CompilerRange
range
        , String
"-ne 0 ]"
        , String
"; then"
        , String
con
        , String
";"
        , String
"else"
        , String
alt
        , String
";"
        , String
"fi"
        ]

    sh_if :: CompilerRange -> String -> ShM ()
    sh_if :: CompilerRange -> String -> ShM ()
sh_if CompilerRange
range String
con
        | (CompilerVersion -> Bool) -> Set CompilerVersion -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (CompilerVersion -> CompilerRange -> Bool
`compilerWithinRange` CompilerRange
range) Set CompilerVersion
allVersions       = String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
con
        | Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ (CompilerVersion -> Bool) -> Set CompilerVersion -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (CompilerVersion -> CompilerRange -> Bool
`compilerWithinRange` CompilerRange
range) Set CompilerVersion
allVersions = () -> ShM ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
        | Bool
otherwise = String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ [String] -> String
unwords
        [ String
"if ["
        , Set CompilerVersion -> CompilerRange -> String
compilerVersionArithPredicate Set CompilerVersion
allVersions CompilerRange
range
        , String
"-ne 0 ]"
        , String
"; then"
        , String
con
        , String
";"
        , String
"fi"
        ]

    -- Needed to work around haskell/cabal#6214
    withHaddock :: String
    withHaddock :: String
withHaddock = String
"--with-haddock $HADDOCK"

    cabalDocspec :: String
    cabalDocspec :: String
cabalDocspec =
      let docspecOptions :: [String]
docspecOptions = DocspecConfig -> [String]
cfgDocspecOptions DocspecConfig
cfgDocspec in
      [String] -> String
unwords ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ String
"cabal-docspec $ARG_COMPILER" String -> [String] -> [String]
forall a. a -> [a] -> [a]
: [String]
docspecOptions

    docspecRange :: CompilerRange
    docspecRange :: CompilerRange
docspecRange = VersionRange -> CompilerRange
Range (DocspecConfig -> VersionRange
cfgDocspecEnabled DocspecConfig
cfgDocspec)

postgresService :: GitHubService
postgresService :: GitHubService
postgresService = GitHubService :: String -> Map String String -> Maybe String -> GitHubService
GitHubService
    { ghServImage :: String
ghServImage   = String
"postgres:10"
    , ghServOptions :: Maybe String
ghServOptions = String -> Maybe String
forall a. a -> Maybe a
Just String
"--health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5"
    , ghServEnv :: Map String String
ghServEnv     = [(String, String)] -> Map String String
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList
          [ (String
"POSTGRES_PASSWORD", String
"postgres")
          ]
    }

ircJob :: String -> String -> String -> Config -> GitConfig -> ListBuilder (String, GitHubJob) ()
ircJob :: String
-> String
-> String
-> Config
-> GitConfig
-> ListBuilder (String, GitHubJob) ()
ircJob String
actionName String
mainJobName String
projectName Config
cfg GitConfig
gitconfig = (String, GitHubJob) -> ListBuilder (String, GitHubJob) ()
forall x. x -> ListBuilder x ()
item (String
"irc", GitHubJob :: String
-> String
-> [String]
-> Maybe String
-> Maybe String
-> Map String GitHubService
-> Maybe String
-> [GitHubMatrixEntry]
-> [GitHubStep]
-> Natural
-> GitHubJob
GitHubJob
    { ghjName :: String
ghjName            = String
actionName String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" (IRC notification)"
    , ghjRunsOn :: String
ghjRunsOn          = String
"ubuntu-18.04"
    , ghjNeeds :: [String]
ghjNeeds           = [String
mainJobName]
    , ghjIf :: Maybe String
ghjIf              = Maybe String
jobCondition
    , ghjContainer :: Maybe String
ghjContainer       = Maybe String
forall a. Maybe a
Nothing
    , ghjContinueOnError :: Maybe String
ghjContinueOnError = Maybe String
forall a. Maybe a
Nothing
    , ghjMatrix :: [GitHubMatrixEntry]
ghjMatrix          = []
    , ghjServices :: Map String GitHubService
ghjServices        = Map String GitHubService
forall a. Monoid a => a
mempty
    , ghjSteps :: [GitHubStep]
ghjSteps           = [ String -> Bool -> GitHubStep
ircStep String
serverChannelName Bool
success
                           | String
serverChannelName <- [String]
serverChannelNames
                           , Bool
success <- [Bool
True, Bool
False]
                           ]
    , ghjTimeout :: Natural
ghjTimeout         = Natural
10
    })
  where
    serverChannelNames :: [String]
serverChannelNames = Config -> [String]
cfgIrcChannels Config
cfg

    jobCondition :: Maybe String
    jobCondition :: Maybe String
jobCondition
        | Config -> Bool
cfgIrcIfInOriginRepo Config
cfg
        , Just Text
url <- Text -> Map Text Text -> Maybe Text
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Text
"origin" (GitConfig -> Map Text Text
gitCfgRemotes GitConfig
gitconfig)
        , Just Text
repo <- Text -> Maybe Text
parseGitHubRepo Text
url

        = String -> Maybe String
forall a. a -> Maybe a
Just
        (String -> Maybe String) -> String -> Maybe String
forall a b. (a -> b) -> a -> b
$ String
"${{ always() && (github.repository == '" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Text -> String
T.unpack Text
repo String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"') }}"

        | Bool
otherwise
        = String -> Maybe String
forall a. a -> Maybe a
Just String
"${{ always() }}"
        -- Use always() above to ensure that the IRC job will still run even if
        -- the build job itself fails (see #437).

    ircStep :: String -> Bool -> GitHubStep
    ircStep :: String -> Bool -> GitHubStep
ircStep String
serverChannelName Bool
success =
        let (String
serverName, String
channelName) = (Char -> Bool) -> String -> (String, String)
forall a. (a -> Bool) -> [a] -> ([a], [a])
break (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'#') String
serverChannelName

            result :: String
result | Bool
success   = String
"success"
                   | Bool
otherwise = String
"failure"

            resultPastTense :: String
resultPastTense | Bool
success   = String
"succeeded"
                            | Bool
otherwise = String
"failed"

            eqCheck :: String
eqCheck | Bool
success   = String
"=="
                    | Bool
otherwise = String
"!=" in

        String -> Either GitHubRun GitHubUses -> GitHubStep
GitHubStep (String
"IRC " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
result String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" notification (" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
serverChannelName String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
")") (Either GitHubRun GitHubUses -> GitHubStep)
-> Either GitHubRun GitHubUses -> GitHubStep
forall a b. (a -> b) -> a -> b
$ GitHubUses -> Either GitHubRun GitHubUses
forall a b. b -> Either a b
Right (GitHubUses -> Either GitHubRun GitHubUses)
-> GitHubUses -> Either GitHubRun GitHubUses
forall a b. (a -> b) -> a -> b
$
        String -> Maybe String -> Map String String -> GitHubUses
GitHubUses String
"Gottox/irc-message-action@v1.1"
                   (String -> Maybe String
forall a. a -> Maybe a
Just (String -> Maybe String) -> String -> Maybe String
forall a b. (a -> b) -> a -> b
$ String
"needs." String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
mainJobName String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
".result " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
eqCheck String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" 'success'") (Map String String -> GitHubUses)
-> Map String String -> GitHubUses
forall a b. (a -> b) -> a -> b
$
        [(String, String)] -> Map String String
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList ([(String, String)] -> Map String String)
-> [(String, String)] -> Map String String
forall a b. (a -> b) -> a -> b
$ ListBuilder (String, String) () -> [(String, String)]
forall x. ListBuilder x () -> [x]
buildList (ListBuilder (String, String) () -> [(String, String)])
-> ListBuilder (String, String) () -> [(String, String)]
forall a b. (a -> b) -> a -> b
$ do
            (String, String) -> ListBuilder (String, String) ()
forall x. x -> ListBuilder x ()
item (String
"server",   String
serverName)
            (String, String) -> ListBuilder (String, String) ()
forall x. x -> ListBuilder x ()
item (String
"channel",  String
channelName)
            (String, String) -> ListBuilder (String, String) ()
forall x. x -> ListBuilder x ()
item (String
"nickname", String -> Maybe String -> String
forall a. a -> Maybe a -> a
fromMaybe String
"github-actions" (Maybe String -> String) -> Maybe String -> String
forall a b. (a -> b) -> a -> b
$ Config -> Maybe String
cfgIrcNickname Config
cfg)
            Maybe String
-> (String -> ListBuilder (String, String) ())
-> ListBuilder (String, String) ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ (Config -> Maybe String
cfgIrcPassword Config
cfg) ((String -> ListBuilder (String, String) ())
 -> ListBuilder (String, String) ())
-> (String -> ListBuilder (String, String) ())
-> ListBuilder (String, String) ()
forall a b. (a -> b) -> a -> b
$ \String
p ->
                (String, String) -> ListBuilder (String, String) ()
forall x. x -> ListBuilder x ()
item (String
"sasl_password", String
p)
            (String, String) -> ListBuilder (String, String) ()
forall x. x -> ListBuilder x ()
item (String
"message",  String
"\x0313" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
projectName String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\x03/\x0306${{ github.ref }}\x03 "
                                       String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\x0314${{ github.sha }}\x03 "
                                       String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} "
                                       String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"The build " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
resultPastTense String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
".")

catCmd :: FilePath -> String -> String
catCmd :: String -> String -> String
catCmd String
path String
contents = [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
    [ String
"cat >> " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
path String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" <<EOF\n"
    , String
contents
    , String
"EOF"
    ]

cat :: FilePath -> String -> ShM ()
cat :: String -> String -> ShM ()
cat String
path String
contents = String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String -> String -> String
catCmd String
path String
contents

-- | GitHub is very lenient and undocumented. We accept something.
-- Please, write a patch, if you need an extra scheme to be accepted.
--
-- >>> parseGitHubRepo "git@github.com:haskell-CI/haskell-ci.git"
-- Just "haskell-CI/haskell-ci"
--
-- >>> parseGitHubRepo "git@github.com:haskell-CI/haskell-ci"
-- Just "haskell-CI/haskell-ci"
--
-- >>> parseGitHubRepo "https://github.com/haskell-CI/haskell-ci.git"
-- Just "haskell-CI/haskell-ci"
--
-- >>> parseGitHubRepo "https://github.com/haskell-CI/haskell-ci"
-- Just "haskell-CI/haskell-ci"
--
-- >>> parseGitHubRepo "git://github.com/haskell-CI/haskell-ci"
-- Just "haskell-CI/haskell-ci"
--
parseGitHubRepo :: Text -> Maybe Text
parseGitHubRepo :: Text -> Maybe Text
parseGitHubRepo Text
t =
    (String -> Maybe Text)
-> (Text -> Maybe Text) -> Either String Text -> Maybe Text
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (Maybe Text -> String -> Maybe Text
forall a b. a -> b -> a
const Maybe Text
forall a. Maybe a
Nothing) Text -> Maybe Text
forall a. a -> Maybe a
Just (Either String Text -> Maybe Text)
-> Either String Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Parser Text -> Text -> Either String Text
forall a. Parser a -> Text -> Either String a
Atto.parseOnly (Parser Text
parser Parser Text -> Parser Text () -> Parser Text
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser Text ()
forall t. Chunk t => Parser t ()
Atto.endOfInput) Text
t
  where
    parser :: Atto.Parser Text
    parser :: Parser Text
parser = Parser Text
sshP Parser Text -> Parser Text -> Parser Text
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Text
httpsP

    sshP :: Atto.Parser Text
    sshP :: Parser Text
sshP = do
        Maybe Text
_ <- Parser Text -> Parser Text (Maybe Text)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (Text -> Parser Text
Atto.string Text
"git://")
        Text
_ <- Text -> Parser Text
Atto.string Text
"git@github.com:"
        Text
repo <- (Char -> Bool) -> Parser Text
Atto.takeWhile (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'.')
        Maybe Text
_ <- Parser Text -> Parser Text (Maybe Text)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (Text -> Parser Text
Atto.string Text
".git")
        Text -> Parser Text
forall (m :: * -> *) a. Monad m => a -> m a
return Text
repo

    httpsP :: Atto.Parser Text
    httpsP :: Parser Text
httpsP = do
        Text
_ <- Text -> Parser Text
Atto.string Text
"https" Parser Text -> Parser Text -> Parser Text
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Text -> Parser Text
Atto.string Text
"git"
        Text
_ <- Text -> Parser Text
Atto.string Text
"://github.com/"
        Text
repo <- (Char -> Bool) -> Parser Text
Atto.takeWhile (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'.')
        Maybe Text
_ <- Parser Text -> Parser Text (Maybe Text)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (Text -> Parser Text
Atto.string Text
".git")
        Text -> Parser Text
forall (m :: * -> *) a. Monad m => a -> m a
return Text
repo