github-tools-0.1.2: src/GitHub/Tools/AutoMerge.hs
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
module GitHub.Tools.AutoMerge
( autoMergePullRequest
, autoMergeAll
, trustedAuthors
) where
import qualified Data.ByteString.Char8 as BS8
import Data.Text (Text)
import qualified Data.Text as Text
import qualified Data.Vector as V
import qualified GitHub
import Network.HTTP.Client (newManager)
import Network.HTTP.Client.TLS (tlsManagerSettings)
import System.Directory (setCurrentDirectory)
import System.Process (callProcess)
import GitHub.Tools.PullRequestInfo (PullRequestInfo (..))
import GitHub.Tools.PullStatus (getPrInfos, getPullInfos,
makePullRequestInfo)
import GitHub.Tools.Requests (request)
trustedAuthors :: [Text]
trustedAuthors =
[ "JFreegman"
, "TokTok"
, "iphydf"
, "nurupo"
, "robinlinden"
, "sudden6"
, "zugz"
]
workDir :: FilePath
workDir = "/tmp/automerge"
autoMerge
:: String
-> GitHub.Name GitHub.Owner
-> PullRequestInfo
-> IO ()
autoMerge _ _ PullRequestInfo{prOrigin = Nothing} = return ()
autoMerge token ownerName PullRequestInfo{prRepoName, prUser, prBranch, prOrigin = Just prOrigin} = do
let clonePath = workDir <> "/" <> Text.unpack prRepoName
callProcess "rm" ["-rf", clonePath]
callProcess "git"
[ "clone", "--depth=6" -- 6 so we can merge up to 5 commits on top of the master HEAD commit
, "--branch=" <> Text.unpack prBranch
, "https://github.com/" <> Text.unpack prUser <> "/" <> Text.unpack prOrigin
, clonePath
]
setCurrentDirectory clonePath
callProcess "git"
[ "remote", "add", "upstream"
, "https://" <> token <> "@github.com/" <> Text.unpack (GitHub.untagName ownerName) <> "/" <> Text.unpack prRepoName
]
callProcess "git"
[ "push", "upstream", Text.unpack prBranch <> ":master" ]
-- Go back to a directory that will definitely exist even when next time
-- we "rm -rf" the git repo cloned above.
setCurrentDirectory workDir
mergeable :: PullRequestInfo -> Bool
mergeable PullRequestInfo{prState, prTrustworthy, prUser} =
prState == "clean" && (prTrustworthy || prUser `elem` trustedAuthors)
autoMergePullRequest
:: String
-> GitHub.Name GitHub.Owner
-> GitHub.Name GitHub.Repo
-> IO ()
autoMergePullRequest token ownerName repoName = do
let auth = Just . GitHub.OAuth . BS8.pack $ token
mgr <- newManager tlsManagerSettings
pulls <- (V.toList <$>
request auth mgr (GitHub.pullRequestsForR ownerName repoName GitHub.stateOpen GitHub.FetchAll))
>>= fmap (map $ makePullRequestInfo repoName) . getPrInfos auth mgr ownerName repoName
putStrLn $ "found " <> show (length pulls) <> " pulls"
let mergeablePulls = filter mergeable pulls
putStrLn $ "selected " <> show (length mergeablePulls) <> " mergeable pulls:"
mapM_ print mergeablePulls
mapM_ (autoMerge token ownerName) mergeablePulls
autoMergeAll
:: GitHub.Name GitHub.Organization
-> GitHub.Name GitHub.Owner
-> String
-> IO ()
autoMergeAll orgName ownerName token = do
let auth = Just . GitHub.OAuth . BS8.pack $ token
pulls <- filter mergeable . concat <$> getPullInfos orgName ownerName auth
mapM_ (autoMerge token ownerName) pulls