From 58fd47246c36ac0191b3c246b36c2afdb710e2d9 Mon Sep 17 00:00:00 2001 From: Maxwell Swadling Date: Tue, 21 Jan 2014 22:15:12 +1100 Subject: [PATCH 01/37] Added hooks --- Github/Data.hs | 10 +++++++ Github/Data/Definitions.hs | 11 +++++++ Github/Repos/Hooks.hs | 59 ++++++++++++++++++++++++++++++++++++++ github.cabal | 1 + 4 files changed, 81 insertions(+) create mode 100644 Github/Repos/Hooks.hs diff --git a/Github/Data.hs b/Github/Data.hs index 353f06c4..f15bf542 100644 --- a/Github/Data.hs +++ b/Github/Data.hs @@ -521,6 +521,16 @@ instance FromJSON DetailedOwner where parseJSON _ = fail "Could not build a DetailedOwner" +instance FromJSON Hook where + parseJSON (Object o) = Hook <$> o .: "id" + <*> o .: "config" + <*> o .: "active" + <*> o .: "events" + <*> o .: "name" + <*> o .: "created_at" + <*> o .: "updated_at" + parseJSON _ = fail "Could not build a Hook" + -- | A slightly more generic version of Aeson's @(.:?)@, using `mzero' instead -- of `Nothing'. (.:<) :: (FromJSON a) => Object -> T.Text -> Parser [a] diff --git a/Github/Data/Definitions.hs b/Github/Data/Definitions.hs index ccf2add5..273e0270 100644 --- a/Github/Data/Definitions.hs +++ b/Github/Data/Definitions.hs @@ -5,6 +5,7 @@ module Github.Data.Definitions where import Data.Time import Data.Data import qualified Control.Exception as E +import qualified Data.Map as M -- | Errors have been tagged according to their source, so you can more easily -- dispatch and handle them. @@ -475,3 +476,13 @@ data DetailedOwner = DetailedUser { ,detailedOwnerHtmlUrl :: String ,detailedOwnerLogin :: String } deriving (Show, Data, Typeable, Eq, Ord) + +data Hook = Hook { + hookId :: Integer + ,hookConfig :: M.Map String String + ,hookActive :: Bool + ,hookEvents :: [String] + ,hookName :: String + ,hookCreatedAt :: GithubDate + ,hookUpdatedAt :: GithubDate +} deriving (Show, Data, Typeable, Eq, Ord) diff --git a/Github/Repos/Hooks.hs b/Github/Repos/Hooks.hs new file mode 100644 index 00000000..6f0bd95f --- /dev/null +++ b/Github/Repos/Hooks.hs @@ -0,0 +1,59 @@ +{-# LANGUAGE OverloadedStrings #-} +-- | The repo starring API as described on +-- . +module Github.Repos.Hooks ( + hooksFor +,singleHook +,createHook +,testHook +,module Github.Data +) where + +import Github.Data +import Github.Private + +import Data.Aeson (Value(String, Bool, Array), toJSON) +import qualified Data.Map as M +import Data.Text (pack, Text) +import qualified Data.Vector as V + +hooksFor :: GithubAuth -> String -> String -> IO (Either Error [Hook]) +hooksFor auth userName reqRepoName = + githubGet' (Just auth) ["repos", userName, reqRepoName, "hooks"] + +singleHook :: GithubAuth -> String -> String -> Integer -> IO (Either Error Hook) +singleHook auth userName reqRepoName hid = + githubGet' (Just auth) ["repos", userName, reqRepoName, "hooks", show hid] + +createHook :: GithubAuth -> String -> String -> String -> M.Map String String -> Maybe [String] -> Maybe Bool -> IO (Either Error Hook) +createHook auth userName reqRepoName hookName hookConfig hookEvents hookActive = + githubPost auth ["repos", userName, reqRepoName, "hooks"] + $ M.fromList $ ("name", String (pack hookName)) + : ("config", toJSON hookConfig) + : concat + [ jinA "events" hookEvents + , jinB "active" hookActive + ] + +-- Edit a hook: TODO + +testHook :: GithubAuth -> String -> String -> Integer -> IO (Either Error ()) +testHook auth userName reqRepoName hid = + githubPost auth ["repos", userName, reqRepoName, "hooks", show hid] () + +-- deleteHook :: GithubAuth -> String -> String -> Integer -> IO (Either Error ()) +-- deleteHook auth userName reqRepoName hid = +-- githubDelete auth ["repos", userName, reqRepoName, "hooks", show hid] () + +-- json kludge +jinA :: String -> Maybe [String] -> [(Text, Value)] +jinA k (Just x) = [(pack k, toJSON x)] +jinA _ Nothing = [] + +jinS :: String -> Maybe String -> [(Text, Value)] +jinS k (Just x) = [(pack k, String (pack x))] +jinS _ Nothing = [] + +jinB :: String -> Maybe Bool -> [(Text, Value)] +jinB k (Just x) = [(pack k, Bool x)] +jinB _ Nothing = [] \ No newline at end of file diff --git a/github.cabal b/github.cabal index 3ebabe5f..64dd16ab 100644 --- a/github.cabal +++ b/github.cabal @@ -133,6 +133,7 @@ Library Github.Repos.Collaborators, Github.Repos.Commits, Github.Repos.Forks, + Github.Repos.Hooks, Github.Repos.Watching, Github.Repos.Starring, Github.Users, From f6274fe63d4dafe481c75cd977f6222a12e6f926 Mon Sep 17 00:00:00 2001 From: Charles O'Farrell Date: Sun, 20 Jul 2014 00:13:49 +1000 Subject: [PATCH 02/37] Fix GitTree parsing on submodule paths --- Github/Data.hs | 2 +- Github/Data/Definitions.hs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Github/Data.hs b/Github/Data.hs index c429f529..a80bd994 100644 --- a/Github/Data.hs +++ b/Github/Data.hs @@ -48,7 +48,7 @@ instance FromJSON GitTree where parseJSON (Object o) = GitTree <$> o .: "type" <*> o .: "sha" - <*> o .: "url" + <*> o .:? "url" <*> o .:? "size" <*> o .: "path" <*> o .: "mode" diff --git a/Github/Data/Definitions.hs b/Github/Data/Definitions.hs index 244161a3..548828c3 100644 --- a/Github/Data/Definitions.hs +++ b/Github/Data/Definitions.hs @@ -40,7 +40,8 @@ data Tree = Tree { data GitTree = GitTree { gitTreeType :: String ,gitTreeSha :: String - ,gitTreeUrl :: String + -- Can be empty for submodule + ,gitTreeUrl :: Maybe String ,gitTreeSize :: Maybe Int ,gitTreePath :: String ,gitTreeMode :: String From abc7666304417ae2fb6b199176e74b917a1dfe85 Mon Sep 17 00:00:00 2001 From: Charles O'Farrell Date: Sun, 20 Jul 2014 00:14:04 +1000 Subject: [PATCH 03/37] Use GithubAuth for nestedTree --- Github/GitData/Trees.hs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Github/GitData/Trees.hs b/Github/GitData/Trees.hs index ce7d04c2..8ebe2052 100644 --- a/Github/GitData/Trees.hs +++ b/Github/GitData/Trees.hs @@ -19,7 +19,7 @@ tree user reqRepoName sha = -- | A recursively-nested tree for a SHA1. -- -- > nestedTree "thoughtbot" "paperclip" "fe114451f7d066d367a1646ca7ac10e689b46844" -nestedTree :: String -> String -> String -> IO (Either Error Tree) -nestedTree user reqRepoName sha = - githubGetWithQueryString ["repos", user, reqRepoName, "git", "trees", sha] +nestedTree :: Maybe GithubAuth -> String -> String -> String -> IO (Either Error Tree) +nestedTree auth user reqRepoName sha = + githubGetWithQueryString' auth ["repos", user, reqRepoName, "git", "trees", sha] "recursive=1" From 6013c67372bfc5c8e7353e5c23126e9631c1c878 Mon Sep 17 00:00:00 2001 From: Charles O'Farrell Date: Sat, 11 Apr 2015 14:54:02 +1000 Subject: [PATCH 04/37] Added membersOf' with auth --- Github/Organizations/Members.hs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Github/Organizations/Members.hs b/Github/Organizations/Members.hs index 1506d433..465af101 100644 --- a/Github/Organizations/Members.hs +++ b/Github/Organizations/Members.hs @@ -2,6 +2,7 @@ -- . module Github.Organizations.Members ( membersOf +,membersOf' ,module Github.Data ) where @@ -13,3 +14,6 @@ import Github.Private -- > membersOf "thoughtbot" membersOf :: String -> IO (Either Error [GithubOwner]) membersOf organization = githubGet ["orgs", organization, "members"] + +membersOf' :: Maybe GithubAuth -> String -> IO (Either Error [GithubOwner]) +membersOf' auth organization = githubGet' auth ["orgs", organization, "members"] From b69040ab96b72699d3e1c2fa3d035c6b09301c7b Mon Sep 17 00:00:00 2001 From: mth Date: Tue, 12 May 2015 22:49:48 +1000 Subject: [PATCH 05/37] Crude hack to expose pr list with state. --- Github/PullRequests.hs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Github/PullRequests.hs b/Github/PullRequests.hs index b3cf400d..567d485b 100644 --- a/Github/PullRequests.hs +++ b/Github/PullRequests.hs @@ -2,6 +2,7 @@ -- . module Github.PullRequests ( pullRequestsFor' +,pullRequestsWith' ,pullRequest' ,pullRequestCommits' ,pullRequestFiles' @@ -23,6 +24,14 @@ pullRequestsFor' :: Maybe GithubAuth -> String -> String -> IO (Either Error [Pu pullRequestsFor' auth userName reqRepoName = githubGet' auth ["repos", userName, reqRepoName, "pulls"] +-- | All pull requests for the repo, by owner and repo name. +-- | With authentification +-- +-- > pullRequestsWith' (Just ("github-username", "github-password")) "rails" "rails" +pullRequestsWith' :: Maybe GithubAuth -> String -> String -> String -> IO (Either Error [PullRequest]) +pullRequestsWith' auth userName reqRepoName state = + githubGetWithQueryString' auth ["repos", userName, reqRepoName, "pulls"] ("state=" ++ state) + -- | All pull requests for the repo, by owner and repo name. -- -- > pullRequestsFor "rails" "rails" From 2ea49dbef59a3b24cab4ffdb561795439f1765eb Mon Sep 17 00:00:00 2001 From: mth Date: Tue, 12 May 2015 23:13:03 +1000 Subject: [PATCH 06/37] Create organization repos with all fields. --- Github/Repos.hs | 47 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/Github/Repos.hs b/Github/Repos.hs index 704f6c08..e9e91db1 100644 --- a/Github/Repos.hs +++ b/Github/Repos.hs @@ -25,7 +25,9 @@ module Github.Repos ( ,createRepo ,createOrganizationRepo ,newRepo +,newOrgRepo ,NewRepo(..) +,NewOrgRepo(..) -- ** Edit ,editRepo @@ -187,9 +189,52 @@ instance ToJSON NewRepo where , "auto_init" .= autoInit ] +data NewOrgRepo = NewOrgRepo { + newOrgRepoName :: String +, newOrgRepoDescription :: (Maybe String) +, newOrgRepoHomepage :: (Maybe String) +, newOrgRepoPrivate :: (Maybe Bool) +, newOrgRepoHasIssues :: (Maybe Bool) +, newOrgRepoHasWiki :: (Maybe Bool) +, newOrgRepoHasDownloads :: (Maybe Bool) +, newOrgRepoTeamId :: (Maybe Integer) +, newOrgRepoAutoInit :: (Maybe Bool) +, newOrgRepoGitIgnore :: (Maybe String) +, newOrgRepoLicense :: (Maybe String) +} deriving Show + +instance ToJSON NewOrgRepo where + toJSON (NewOrgRepo { newOrgRepoName = name + , newOrgRepoDescription = description + , newOrgRepoHomepage = homepage + , newOrgRepoPrivate = private + , newOrgRepoHasIssues = hasIssues + , newOrgRepoHasWiki = hasWiki + , newOrgRepoHasDownloads = hasDownloads + , newOrgRepoTeamId = teamId + , newOrgRepoAutoInit = autoInit + , newOrgRepoGitIgnore = gitIgnore + , newOrgRepoLicense = license + }) = object + [ "name" .= name + , "description" .= description + , "homepage" .= homepage + , "private" .= private + , "has_issues" .= hasIssues + , "has_wiki" .= hasWiki + , "has_downloads" .= hasDownloads + , "team_id" .= teamId + , "auto_init" .= autoInit + , "gitignore_template" .= gitIgnore + , "license" .= license + ] + newRepo :: String -> NewRepo newRepo name = NewRepo name Nothing Nothing Nothing Nothing Nothing Nothing +newOrgRepo :: String -> NewOrgRepo +newOrgRepo name = NewOrgRepo name Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing + -- | -- Create a new repository. -- @@ -201,7 +246,7 @@ createRepo auth = githubPost auth ["user", "repos"] -- Create a new repository for an organization. -- -- > createOrganizationRepo (GithubUser (user, password)) "thoughtbot" (newRepo "some_repo") {newRepoHasIssues = Just False} -createOrganizationRepo :: GithubAuth -> String -> NewRepo -> IO (Either Error Repo) +createOrganizationRepo :: GithubAuth -> String -> NewOrgRepo -> IO (Either Error Repo) createOrganizationRepo auth org = githubPost auth ["orgs", org, "repos"] data Edit = Edit { From 08a212c2f6979b86ed788a401de258036ad3820c Mon Sep 17 00:00:00 2001 From: Michael Neale Date: Wed, 10 Jun 2015 13:05:37 +1000 Subject: [PATCH 07/37] small change to allow adding of a team to a repo --- Github/Organizations.hs | 5 +++++ Github/Private.hs | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/Github/Organizations.hs b/Github/Organizations.hs index db42dec3..65e113be 100644 --- a/Github/Organizations.hs +++ b/Github/Organizations.hs @@ -4,6 +4,7 @@ module Github.Organizations ( ,publicOrganizationsFor' ,publicOrganization ,publicOrganization' +,addTeamToRepo ,module Github.Data ) where @@ -33,3 +34,7 @@ publicOrganization' auth reqOrganizationName = githubGet' auth ["orgs", reqOrgan -- > publicOrganization "thoughtbot" publicOrganization :: String -> IO (Either Error Organization) publicOrganization = publicOrganization' Nothing + +-- PUT /teams/:id/repos/:org/:repo +addTeamToRepo auth teamId orgName projectName = do + githubPut auth ["teams", show teamId, "repos", orgName, projectName] diff --git a/Github/Private.hs b/Github/Private.hs index 97e515b4..57ed79b8 100644 --- a/Github/Private.hs +++ b/Github/Private.hs @@ -57,6 +57,10 @@ githubPatch auth paths body = (Just auth) (Just body) +githubPut auth paths = do + r <- doHttps "PUT" (buildUrl paths) auth Nothing + return r + buildUrl :: [String] -> String buildUrl paths = "https://api.github.com/" ++ intercalate "/" paths From 08a7fee16884ee892b15a46e43fb6986fc34ba99 Mon Sep 17 00:00:00 2001 From: Sharif Olorin Date: Wed, 30 Sep 2015 07:02:42 +0000 Subject: [PATCH 08/37] Add upper bound for aeson to avoid breaking changes in 0.10 aeson-0.10 changed `(.:?)` to give `empty` on nulls[0] (whereas it previously gave `Nothing` on both nulls and missing keys). Documented upstream[1] but no fix yet. [0] https://github.com/bos/aeson/issues/287 [1] https://github.com/jwiegley/github/issues/121 --- github.cabal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/github.cabal b/github.cabal index 5ad67333..b22fb56c 100644 --- a/github.cabal +++ b/github.cabal @@ -144,7 +144,7 @@ Library -- Packages needed in order to build this package. Build-depends: base >= 4.0 && < 5.0, time, - aeson >= 0.6.1.0, + aeson >= 0.6.1.0 && < 0.10, attoparsec >= 0.10.3.0, bytestring, case-insensitive >= 0.4.0.4, From d07d3c517c7b0b398f91b20fbb5570e8c3f106f8 Mon Sep 17 00:00:00 2001 From: Nick Hibberd Date: Tue, 8 Mar 2016 22:15:57 +1100 Subject: [PATCH 09/37] Adding support for setting permission when adding repoistory to team --- Github/Data.hs | 5 +++-- Github/Data/Teams.hs | 31 +++++++++++++++++++++++++++++++ Github/Organizations.hs | 5 +++-- Github/Private.hs | 7 ++++++- github.cabal | 1 + 5 files changed, 44 insertions(+), 5 deletions(-) create mode 100644 Github/Data/Teams.hs diff --git a/Github/Data.hs b/Github/Data.hs index a80bd994..ea818294 100644 --- a/Github/Data.hs +++ b/Github/Data.hs @@ -4,7 +4,7 @@ -- instances of @FromJSON@ to it. If you wish to use the data without the -- instances, use the @Github.Data.Definitions@ module instead. -module Github.Data (module Github.Data.Definitions) where +module Github.Data (module X) where import Data.Time import Control.Applicative @@ -16,7 +16,8 @@ import qualified Data.Vector as V import qualified Data.HashMap.Lazy as Map import Data.Hashable (Hashable) -import Github.Data.Definitions +import Github.Data.Definitions as X +import Github.Data.Teams as X instance FromJSON GithubDate where parseJSON (String t) = diff --git a/Github/Data/Teams.hs b/Github/Data/Teams.hs new file mode 100644 index 00000000..b6599df3 --- /dev/null +++ b/Github/Data/Teams.hs @@ -0,0 +1,31 @@ +{-# LANGUAGE OverloadedStrings #-} +module Github.Data.Teams ( + Permission (..) + ) where + +import Data.Aeson + +import Data.Text (Text) + +data Permission = + PermissionPull + | PermissionPush + | PermissionAdmin + deriving (Show, Enum, Bounded, Eq, Ord) + +-- https://developer.github.com/v3/orgs/teams/#add-or-update-team-repository +renderPermission :: Permission -> Text +renderPermission p = + case p of + PermissionPull -> + "pull" + PermissionPush -> + "push" + PermissionAdmin -> + "admin" + +instance ToJSON Permission where + toJSON p = + object [ + "permission" .= renderPermission p + ] diff --git a/Github/Organizations.hs b/Github/Organizations.hs index 65e113be..9e17435a 100644 --- a/Github/Organizations.hs +++ b/Github/Organizations.hs @@ -36,5 +36,6 @@ publicOrganization :: String -> IO (Either Error Organization) publicOrganization = publicOrganization' Nothing -- PUT /teams/:id/repos/:org/:repo -addTeamToRepo auth teamId orgName projectName = do - githubPut auth ["teams", show teamId, "repos", orgName, projectName] +--addTeamToRepo :: Int +addTeamToRepo auth teamId orgName projectName permission = do + githubPutBody auth ["teams", show teamId, "repos", orgName, projectName] permission diff --git a/Github/Private.hs b/Github/Private.hs index 57ed79b8..27fd6993 100644 --- a/Github/Private.hs +++ b/Github/Private.hs @@ -57,8 +57,13 @@ githubPatch auth paths body = (Just auth) (Just body) + githubPut auth paths = do - r <- doHttps "PUT" (buildUrl paths) auth Nothing + r <- doHttps "PUT" (buildUrl paths) (Just auth) Nothing + return r + +githubPutBody auth paths p = do + r <- doHttps "PUT" (buildUrl paths) (Just auth) $ fmap (RequestBodyLBS . encode) p return r buildUrl :: [String] -> String diff --git a/github.cabal b/github.cabal index b22fb56c..96329c15 100644 --- a/github.cabal +++ b/github.cabal @@ -116,6 +116,7 @@ Library Exposed-modules: Github.Auth, Github.Data, Github.Data.Definitions, + Github.Data.Teams, Github.Gists, Github.Gists.Comments, Github.GitData.Commits, From 8fe9d9dd130716dd52ff31d233d7dbe5775e1cf8 Mon Sep 17 00:00:00 2001 From: Nick Hibberd Date: Tue, 8 Mar 2016 23:07:44 +1100 Subject: [PATCH 10/37] Expose remove collaborator --- Github/Repos/Collaborators.hs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Github/Repos/Collaborators.hs b/Github/Repos/Collaborators.hs index 6cca521b..feb269c4 100644 --- a/Github/Repos/Collaborators.hs +++ b/Github/Repos/Collaborators.hs @@ -3,6 +3,7 @@ module Github.Repos.Collaborators ( collaboratorsOn ,isCollaboratorOn +,removeCollaborator ,module Github.Data ) where @@ -34,3 +35,14 @@ isCollaboratorOn userName repoOwnerName reqRepoName = do return $ either (Left . HTTPConnectionError) (Right . (204 ==) . T.statusCode . C.responseStatus) result + + +removeCollaborator :: String -> String -> String -> IO (Either Error Bool) +removeCollaborator userName repoOwnerName reqRepoName = do + result <- doHttps (pack "DELETE") + (buildUrl ["repos", repoOwnerName, reqRepoName, "collaborators", userName]) + Nothing + Nothing + return $ either (Left . HTTPConnectionError) + (Right . (204 ==) . T.statusCode . C.responseStatus) + result From 522019369962fcd80d64db23f53ef37c7bd9d844 Mon Sep 17 00:00:00 2001 From: Navin Keswani Date: Wed, 1 Jun 2016 14:37:13 +1000 Subject: [PATCH 11/37] Fix imports for 7.10 --- Github/Data.hs | 10 +++++----- Github/Issues.hs | 2 +- Github/Private.hs | 3 +-- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/Github/Data.hs b/Github/Data.hs index ea818294..5a3753fb 100644 --- a/Github/Data.hs +++ b/Github/Data.hs @@ -6,12 +6,12 @@ module Github.Data (module X) where -import Data.Time -import Control.Applicative +import Data.Time (parseTime, defaultTimeLocale) + import Control.Monad import qualified Data.Text as T import Data.Aeson.Types -import System.Locale (defaultTimeLocale) + import qualified Data.Vector as V import qualified Data.HashMap.Lazy as Map import Data.Hashable (Hashable) @@ -432,8 +432,8 @@ instance FromJSON Repo where <*> o .:? "has_wiki" <*> o .:? "has_issues" <*> o .:? "has_downloads" - <*> o .:? "parent" - <*> o .:? "source" + <*> o .:? "parent" + <*> o .:? "source" parseJSON _ = fail "Could not build a Repo" instance FromJSON RepoRef where diff --git a/Github/Issues.hs b/Github/Issues.hs index 88bea3fa..9934f004 100644 --- a/Github/Issues.hs +++ b/Github/Issues.hs @@ -16,8 +16,8 @@ module Github.Issues ( import Github.Data import Github.Private import Data.List (intercalate) +import Data.Time (defaultTimeLocale) import Data.Time.Format (formatTime) -import System.Locale (defaultTimeLocale) import Data.Time.Clock (UTCTime(..)) -- | A data structure for describing how to filter issues. This is used by diff --git a/Github/Private.hs b/Github/Private.hs index 27fd6993..fb02f236 100644 --- a/Github/Private.hs +++ b/Github/Private.hs @@ -1,4 +1,4 @@ -{-# LANGUAGE OverloadedStrings, StandaloneDeriving, DeriveDataTypeable #-} +{-# LANGUAGE OverloadedStrings, StandaloneDeriving, DeriveDataTypeable, FlexibleContexts #-} {-# LANGUAGE CPP #-} module Github.Private where @@ -7,7 +7,6 @@ import Data.Aeson import Data.Attoparsec.ByteString.Lazy import Data.Data import Data.Monoid -import Control.Applicative import Data.List import Data.CaseInsensitive (mk) import qualified Data.ByteString.Char8 as BS From c3aedddb6d29dafbd80a682495dc27264e933d44 Mon Sep 17 00:00:00 2001 From: Navin Keswani Date: Thu, 2 Jun 2016 11:40:06 +1000 Subject: [PATCH 12/37] Use time-locale-compat for 7.8 & 7.10 compatibility --- Github/Data.hs | 3 ++- Github/Issues.hs | 4 ++-- github.cabal | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Github/Data.hs b/Github/Data.hs index 5a3753fb..d57b6675 100644 --- a/Github/Data.hs +++ b/Github/Data.hs @@ -6,7 +6,8 @@ module Github.Data (module X) where -import Data.Time (parseTime, defaultTimeLocale) +import Data.Time (parseTime) +import Data.Time.Locale.Compat (defaultTimeLocale) import Control.Monad import qualified Data.Text as T diff --git a/Github/Issues.hs b/Github/Issues.hs index 9934f004..8875f906 100644 --- a/Github/Issues.hs +++ b/Github/Issues.hs @@ -16,9 +16,9 @@ module Github.Issues ( import Github.Data import Github.Private import Data.List (intercalate) -import Data.Time (defaultTimeLocale) -import Data.Time.Format (formatTime) import Data.Time.Clock (UTCTime(..)) +import Data.Time.Format (formatTime) +import Data.Time.Locale.Compat (defaultTimeLocale) -- | A data structure for describing how to filter issues. This is used by -- @issuesForRepo@. diff --git a/github.cabal b/github.cabal index 96329c15..3d9deba2 100644 --- a/github.cabal +++ b/github.cabal @@ -152,7 +152,7 @@ Library containers, hashable, text, - old-locale, + time-locale-compat == 0.1.*, HTTP, network, http-conduit >= 1.8, From 1b5d5a78bad13c8e67d44ba0f4854f62952f632b Mon Sep 17 00:00:00 2001 From: Navin Keswani Date: Fri, 3 Jun 2016 14:13:00 +1000 Subject: [PATCH 13/37] Fix breakages on 7.8 --- Github/Data.hs | 4 ++++ Github/Private.hs | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/Github/Data.hs b/Github/Data.hs index d57b6675..6857d8cb 100644 --- a/Github/Data.hs +++ b/Github/Data.hs @@ -6,6 +6,8 @@ module Github.Data (module X) where +import Control.Applicative + import Data.Time (parseTime) import Data.Time.Locale.Compat (defaultTimeLocale) @@ -20,6 +22,8 @@ import Data.Hashable (Hashable) import Github.Data.Definitions as X import Github.Data.Teams as X +import Prelude + instance FromJSON GithubDate where parseJSON (String t) = case parseTime defaultTimeLocale "%FT%T%Z" (T.unpack t) of diff --git a/Github/Private.hs b/Github/Private.hs index fb02f236..c0f4c9a0 100644 --- a/Github/Private.hs +++ b/Github/Private.hs @@ -3,6 +3,8 @@ module Github.Private where import Github.Data + +import Control.Applicative import Data.Aeson import Data.Attoparsec.ByteString.Lazy import Data.Data @@ -13,6 +15,9 @@ import qualified Data.ByteString.Char8 as BS import qualified Data.ByteString.Lazy.Char8 as LBS import Network.HTTP.Types (Status(..)) import Network.HTTP.Conduit + +import Prelude + -- import Data.Conduit (ResourceT) import qualified Control.Exception as E import Data.Maybe (fromMaybe) From 827718c67befcc8f228241d89ab7297b03b8073a Mon Sep 17 00:00:00 2001 From: Navin Keswani Date: Thu, 7 Jul 2016 16:55:20 +1000 Subject: [PATCH 14/37] Fix broken function for fetching a repo --- Github/Repos.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Github/Repos.hs b/Github/Repos.hs index e9e91db1..5fd702c9 100644 --- a/Github/Repos.hs +++ b/Github/Repos.hs @@ -104,7 +104,7 @@ organizationRepo = organizationRepo' Nothing -- -- > organizationRepo (Just (GithubUser (user, password))) "thoughtbot" "github" organizationRepo' :: Maybe GithubAuth -> String -> String -> IO (Either Error Repo) -organizationRepo' auth orgName reqRepoName = githubGet' auth ["orgs", orgName, reqRepoName] +organizationRepo' auth orgName reqRepoName = githubGet' auth ["repos", orgName, reqRepoName] -- | Details on a specific repo, given the owner and repo name. -- From fbd87c36b346af0b917de69f25a61e60f53d4ebf Mon Sep 17 00:00:00 2001 From: Nick Hibberd Date: Wed, 17 Aug 2016 23:38:18 +1000 Subject: [PATCH 15/37] Adding builds and lock file --- Github/Data.hs | 4 +- boris-git.toml | 8 +++ boris.toml | 8 +++ github.lock-7.10.2 | 68 +++++++++++++++++++++++++ mafia | 121 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 207 insertions(+), 2 deletions(-) create mode 100644 boris-git.toml create mode 100644 boris.toml create mode 100644 github.lock-7.10.2 create mode 100755 mafia diff --git a/Github/Data.hs b/Github/Data.hs index 6857d8cb..42121748 100644 --- a/Github/Data.hs +++ b/Github/Data.hs @@ -8,7 +8,7 @@ module Github.Data (module X) where import Control.Applicative -import Data.Time (parseTime) +import Data.Time.Format (parseTimeM) import Data.Time.Locale.Compat (defaultTimeLocale) import Control.Monad @@ -26,7 +26,7 @@ import Prelude instance FromJSON GithubDate where parseJSON (String t) = - case parseTime defaultTimeLocale "%FT%T%Z" (T.unpack t) of + case parseTimeM True defaultTimeLocale "%FT%T%Z" (T.unpack t) of Just d -> pure $ GithubDate d _ -> fail "could not parse Github datetime" parseJSON _ = fail "Given something besides a String" diff --git a/boris-git.toml b/boris-git.toml new file mode 100644 index 00000000..48994499 --- /dev/null +++ b/boris-git.toml @@ -0,0 +1,8 @@ +[boris] + version = 1 + +[build.dist] + git = "refs/heads/master" + +[build.branches] + git = "refs/heads/topic/*" diff --git a/boris.toml b/boris.toml new file mode 100644 index 00000000..a35c3b37 --- /dev/null +++ b/boris.toml @@ -0,0 +1,8 @@ +[boris] + version = 1 + +[build.dist] + command = [["./mafia", "build", "--", "-ghc-options=-Wall]] + +[build.branches] + command = [["./mafia", "build", "--", "-ghc-options=-Wall]] diff --git a/github.lock-7.10.2 b/github.lock-7.10.2 new file mode 100644 index 00000000..1d4da111 --- /dev/null +++ b/github.lock-7.10.2 @@ -0,0 +1,68 @@ +# mafia-lock-file-version: 0 +aeson == 0.9.0.1 +asn1-encoding == 0.9.4 +asn1-parse == 0.9.4 +asn1-types == 0.3.2 +async == 2.1.0 +attoparsec == 0.13.0.2 +base64-bytestring == 1.0.0.1 +blaze-builder == 0.4.0.2 +byteable == 0.1.1 +case-insensitive == 1.2.0.7 +cereal == 0.5.3.0 +conduit == 1.2.6.6 +conduit-extra == 1.1.13.2 +connection == 0.2.5 +cookie == 0.4.2.1 +cryptonite == 0.17 +data-default == 0.7.1.1 +data-default-class == 0.1.2.0 +data-default-instances-containers == 0.0.1 +data-default-instances-dlist == 0.0.1 +data-default-instances-old-locale == 0.0.1 +dlist == 0.8 +exceptions == 0.8.3 +fail == 4.9.0.0 +failure == 0.2.0.3 +hashable == 1.2.4.0 +hourglass == 0.2.10 +HTTP == 4000.3.3 +http-client == 0.4.31 +http-client-tls == 0.2.4.1 +http-conduit == 2.1.11 +http-types == 0.8.6 +lifted-base == 0.2.3.8 +memory == 0.13 +mime-types == 0.1.0.7 +mmorph == 1.0.6 +monad-control == 1.0.1.0 +mtl == 2.2.1 +network == 2.6.2.1 +network-uri == 2.6.1.0 +old-locale == 1.0.0.7 +parsec == 3.1.11 +pem == 0.2.2 +primitive == 0.6.1.0 +random == 1.1 +resourcet == 1.1.7.4 +scientific == 0.3.4.9 +semigroups == 0.18.2 +semigroups -bytestring-builder +socks == 0.5.5 +stm == 2.4.4.1 +streaming-commons == 0.1.15.5 +syb == 0.6 +tagged == 0.8.5 +text == 1.2.2.1 +time-locale-compat == 0.1.1.3 +time-locale-compat -old-locale +tls == 1.3.8 +transformers-base == 0.4.4 +transformers-compat == 0.5.1.4 +unordered-containers == 0.2.7.1 +vector == 0.11.0.0 +x509 == 1.6.3 +x509-store == 1.6.1 +x509-system == 1.6.3 +x509-validation == 1.6.3 +zlib == 0.6.1.1 diff --git a/mafia b/mafia new file mode 100755 index 00000000..de5e87fb --- /dev/null +++ b/mafia @@ -0,0 +1,121 @@ +#!/bin/sh -eu + +fetch_latest () { + if [ -z ${MAFIA_TEST_MODE+x} ]; then + TZ=$(date +"%T") + curl --silent "https://raw.githubusercontent.com/ambiata/mafia/master/script/mafia?$TZ" + else + cat ../script/mafia + fi +} + +latest_version () { + git ls-remote https://github.com/ambiata/mafia | grep refs/heads/master | cut -f 1 +} + +local_version () { + awk '/^# Version: / { print $3; exit 0; }' $0 +} + +run_upgrade () { + MAFIA_TEMP=$(mktemp 2>/dev/null || mktemp -t 'upgrade_mafia') + + clean_up () { + rm -f "$MAFIA_TEMP" + } + + trap clean_up EXIT + + MAFIA_CUR="$0" + + if [ -L "$MAFIA_CUR" ]; then + echo 'Refusing to overwrite a symlink; run `upgrade` from the canonical path.' >&2 + exit 1 + fi + + echo "Checking for a new version of mafia ..." + fetch_latest > $MAFIA_TEMP + + LATEST_VERSION=$(latest_version) + echo "# Version: $LATEST_VERSION" >> $MAFIA_TEMP + + if ! cmp $MAFIA_CUR $MAFIA_TEMP >/dev/null 2>&1; then + mv $MAFIA_TEMP $MAFIA_CUR + chmod +x $MAFIA_CUR + echo "New version found and upgraded. You can now commit it to your git repo." + else + echo "You have latest mafia." + fi +} + +exec_mafia () { + MAFIA_VERSION=$(local_version) + + if [ "x$MAFIA_VERSION" = "x" ]; then + # If we can't find the mafia version, then we need to upgrade the script. + run_upgrade + else + MAFIA_BIN=$HOME/.ambiata/mafia/bin + MAFIA_FILE=mafia-$MAFIA_VERSION + MAFIA_PATH=$MAFIA_BIN/$MAFIA_FILE + + [ -f "$MAFIA_PATH" ] || { + # Create a temporary directory which will be deleted when the script + # terminates. Unfortunately `mktemp` doesn't behave the same on + # Linux and OS/X so we need to try two different approaches. + MAFIA_TEMP=$(mktemp -d 2>/dev/null || mktemp -d -t 'exec_mafia') + + # Create a temporary file in MAFIA_BIN so we can do an atomic copy/move dance. + mkdir -p $MAFIA_BIN + + clean_up () { + rm -rf "$MAFIA_TEMP" + } + + trap clean_up EXIT + + echo "Building $MAFIA_FILE in $MAFIA_TEMP" + + ( cd "$MAFIA_TEMP" + + git clone https://github.com/ambiata/mafia + cd mafia + + git reset --hard $MAFIA_VERSION + + bin/bootstrap ) || exit $? + + MAFIA_PATH_TEMP=$(mktemp --tmpdir=$MAFIA_BIN $MAFIA_FILE-XXXXXX 2>/dev/null || TMPDIR=$MAFIA_BIN mktemp -t $MAFIA_FILE) + + clean_up_temp () { + clean_up + rm -f "$MAFIA_PATH_TEMP" + } + trap clean_up_temp EXIT + + cp "$MAFIA_TEMP/mafia/.cabal-sandbox/bin/mafia" "$MAFIA_PATH_TEMP" + chmod 755 "$MAFIA_PATH_TEMP" + mv "$MAFIA_PATH_TEMP" "$MAFIA_PATH" + + clean_up_temp + } + + exec $MAFIA_PATH "$@" + fi +} + +# +# The actual start of the script..... +# + +if [ $# -gt 0 ]; then + MODE="$1" +else + MODE="" +fi + +case "$MODE" in +upgrade) shift; run_upgrade "$@" ;; +*) exec_mafia "$@" +esac +# Version: de245376fd86c1ec9a5a451f096cb79bc8ae68f7 From 3ec51ec7c7bd61aaa8232839edac423232a7b875 Mon Sep 17 00:00:00 2001 From: Nick Hibberd Date: Wed, 17 Aug 2016 23:39:36 +1000 Subject: [PATCH 16/37] toml --- boris.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/boris.toml b/boris.toml index a35c3b37..7ab0eb46 100644 --- a/boris.toml +++ b/boris.toml @@ -2,7 +2,7 @@ version = 1 [build.dist] - command = [["./mafia", "build", "--", "-ghc-options=-Wall]] + command = [["./mafia", "build", "--", "-ghc-options=-Wall"]] [build.branches] - command = [["./mafia", "build", "--", "-ghc-options=-Wall]] + command = [["./mafia", "build", "--", "-ghc-options=-Wall"]] From 46a08531399d59f8e097480cf0dd4f876fc317e1 Mon Sep 17 00:00:00 2001 From: Nick Hibberd Date: Wed, 17 Aug 2016 23:44:19 +1000 Subject: [PATCH 17/37] Updating build --- bin/build | 12 ++++++++++++ boris.toml | 4 ++-- 2 files changed, 14 insertions(+), 2 deletions(-) create mode 100755 bin/build diff --git a/bin/build b/bin/build new file mode 100755 index 00000000..7915766f --- /dev/null +++ b/bin/build @@ -0,0 +1,12 @@ +#!/bin/sh -euvx + +export GHC_VERSION="7.10.2" +export CABAL_VERSION = "1.22.4.0" + + +GHC_PATH=$(ghc-path) +export PATH=$GHC_PATH:$PATH +CABAL_PATH=$(cabal-path) +export PATH=$CABAL_PATH:$PATH + +./mafia build -- --ghc-options=-Wall diff --git a/boris.toml b/boris.toml index 7ab0eb46..eff6ba6e 100644 --- a/boris.toml +++ b/boris.toml @@ -2,7 +2,7 @@ version = 1 [build.dist] - command = [["./mafia", "build", "--", "-ghc-options=-Wall"]] + command = [["bin/build"]] [build.branches] - command = [["./mafia", "build", "--", "-ghc-options=-Wall"]] + command = [["bin/build"]] From b5691411bd2b3f69d195eaed8b0751eed5c118ef Mon Sep 17 00:00:00 2001 From: Nick Hibberd Date: Wed, 17 Aug 2016 23:45:41 +1000 Subject: [PATCH 18/37] toml --- bin/build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/build b/bin/build index 7915766f..2c477fb1 100755 --- a/bin/build +++ b/bin/build @@ -1,7 +1,7 @@ #!/bin/sh -euvx export GHC_VERSION="7.10.2" -export CABAL_VERSION = "1.22.4.0" +export CABAL_VERSION="1.22.4.0" GHC_PATH=$(ghc-path) From f73c098add3951e3fc61a3f9a2eedb69866a48a6 Mon Sep 17 00:00:00 2001 From: Nick Hibberd Date: Wed, 17 Aug 2016 23:51:23 +1000 Subject: [PATCH 19/37] -w --- bin/build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/build b/bin/build index 2c477fb1..96a989e3 100755 --- a/bin/build +++ b/bin/build @@ -9,4 +9,4 @@ export PATH=$GHC_PATH:$PATH CABAL_PATH=$(cabal-path) export PATH=$CABAL_PATH:$PATH -./mafia build -- --ghc-options=-Wall +./mafia build -w From 2629dc1245e1103e6372a00e693391bed332a682 Mon Sep 17 00:00:00 2001 From: Nick Hibberd Date: Wed, 17 Aug 2016 23:48:42 +1000 Subject: [PATCH 20/37] Drop CPP --- Github/Private.hs | 9 --------- Github/Repos.hs | 3 --- github.cabal | 2 +- 3 files changed, 1 insertion(+), 13 deletions(-) diff --git a/Github/Private.hs b/Github/Private.hs index c0f4c9a0..5bcca84c 100644 --- a/Github/Private.hs +++ b/Github/Private.hs @@ -1,5 +1,4 @@ {-# LANGUAGE OverloadedStrings, StandaloneDeriving, DeriveDataTypeable, FlexibleContexts #-} -{-# LANGUAGE CPP #-} module Github.Private where import Github.Data @@ -151,17 +150,9 @@ doHttps reqMethod url auth body = do BS.pack ("token " ++ token))] getOAuth _ = [] getResponse request = withManager $ \manager -> httpLbs request manager -#if MIN_VERSION_http_conduit(1, 9, 0) successOrMissing s@(Status sci _) hs cookiejar -#else - successOrMissing s@(Status sci _) hs -#endif | (200 <= sci && sci < 300) || sci == 404 = Nothing -#if MIN_VERSION_http_conduit(1, 9, 0) | otherwise = Just $ E.toException $ StatusCodeException s hs cookiejar -#else - | otherwise = Just $ E.toException $ StatusCodeException s hs -#endif parseJsonRaw :: LBS.ByteString -> Either Error Value parseJsonRaw jsonString = diff --git a/Github/Repos.hs b/Github/Repos.hs index 5fd702c9..9aaade84 100644 --- a/Github/Repos.hs +++ b/Github/Repos.hs @@ -1,5 +1,4 @@ {-# LANGUAGE OverloadedStrings #-} -{-# LANGUAGE CPP #-} -- | The Github Repos API, as documented at -- module Github.Repos ( @@ -316,9 +315,7 @@ deleteRepo auth owner repo = do then return (Left (HTTPConnectionError (E.toException (StatusCodeException status headers -#if MIN_VERSION_http_conduit(1, 9, 0) (responseCookieJar resp) -#endif )))) else return (Right ()) where diff --git a/github.cabal b/github.cabal index 3d9deba2..dab04cb3 100644 --- a/github.cabal +++ b/github.cabal @@ -155,7 +155,7 @@ Library time-locale-compat == 0.1.*, HTTP, network, - http-conduit >= 1.8, + http-conduit >= 1.9, conduit, failure, http-types, From 1604fd73b462f723b2fa211f6c0a96032eca1448 Mon Sep 17 00:00:00 2001 From: Nick Hibberd Date: Wed, 1 Jun 2016 11:43:26 +1000 Subject: [PATCH 21/37] Adding branch protections --- Github/Data/Definitions.hs | 34 ++++++++++++++++++++++++- Github/Private.hs | 24 ++++++++++-------- Github/Repos.hs | 2 +- Github/Repos/Branches.hs | 47 +++++++++++++++++++++++++++++++++++ Github/Repos/Collaborators.hs | 2 ++ Github/Repos/Hooks.hs | 2 +- github.cabal | 1 + 7 files changed, 99 insertions(+), 13 deletions(-) create mode 100644 Github/Repos/Branches.hs diff --git a/Github/Data/Definitions.hs b/Github/Data/Definitions.hs index 548828c3..04b76aae 100644 --- a/Github/Data/Definitions.hs +++ b/Github/Data/Definitions.hs @@ -265,7 +265,7 @@ data EventType = | Referenced -- ^ The issue was referenced from a commit message. The commit_id attribute is the commit SHA1 of where that happened. | Merged -- ^ The issue was merged by the actor. The commit_id attribute is the SHA1 of the HEAD commit that was merged. | Assigned -- ^ The issue was assigned to the actor. - | Closed -- ^ The issue was closed by the actor. When the commit_id is present, it identifies the commit that closed the issue using “closes / fixes #NN” syntax. + | Closed -- ^ The issue was closed by the actor. When the commit_id is present, it identifies the commit that closed the issue using “closes / fixes #NN” syntax. | Reopened -- ^ The issue was reopened by the actor. deriving (Show, Data, Typeable, Eq, Ord) @@ -487,3 +487,35 @@ data Hook = Hook { ,hookCreatedAt :: GithubDate ,hookUpdatedAt :: GithubDate } deriving (Show, Data, Typeable, Eq, Ord) + +data Protection = + Protection { + requiredStatusChecks :: Maybe RequiredStatusChecks + , pushRestrictions :: Maybe PushRestrictions + } deriving (Show, Data, Typeable, Eq, Ord) + +data RequiredStatusChecks = + RequiredStatusChecks { + enforcementLevel :: EnforcementLevel + , strict :: Bool + , context :: [String] + } deriving (Show, Data, Typeable, Eq, Ord) + +data EnforcementLevel = + Everyone + | NotAdmins + deriving (Show, Data, Typeable, Eq, Ord) + +data PushRestrictions = + PushRestrictions [User] [Team] + deriving (Show, Data, Typeable, Eq, Ord) + +newtype User = + User { + user :: String + } deriving (Show, Data, Typeable, Eq, Ord) + +newtype Team = + Team { + team :: String + } deriving (Show, Data, Typeable, Eq, Ord) diff --git a/Github/Private.hs b/Github/Private.hs index 5bcca84c..a3a000fd 100644 --- a/Github/Private.hs +++ b/Github/Private.hs @@ -32,6 +32,7 @@ githubGet = githubGet' Nothing githubGet' :: (FromJSON b, Show b) => Maybe GithubAuth -> [String] -> IO (Either Error b) githubGet' auth paths = githubAPI (BS.pack "GET") + Nothing (buildUrl paths) auth (Nothing :: Maybe Value) @@ -42,6 +43,7 @@ githubGetWithQueryString = githubGetWithQueryString' Nothing githubGetWithQueryString' :: (FromJSON b, Show b) => Maybe GithubAuth -> [String] -> String -> IO (Either Error b) githubGetWithQueryString' auth paths qs = githubAPI (BS.pack "GET") + Nothing (buildUrl paths ++ "?" ++ qs) auth (Nothing :: Maybe Value) @@ -49,6 +51,7 @@ githubGetWithQueryString' auth paths qs = githubPost :: (ToJSON a, Show a, FromJSON b, Show b) => GithubAuth -> [String] -> a -> IO (Either Error b) githubPost auth paths body = githubAPI (BS.pack "POST") + Nothing (buildUrl paths) (Just auth) (Just body) @@ -56,26 +59,26 @@ githubPost auth paths body = githubPatch :: (ToJSON a, Show a, FromJSON b, Show b) => GithubAuth -> [String] -> a -> IO (Either Error b) githubPatch auth paths body = githubAPI (BS.pack "PATCH") + Nothing (buildUrl paths) (Just auth) (Just body) - githubPut auth paths = do - r <- doHttps "PUT" (buildUrl paths) (Just auth) Nothing + r <- doHttps "PUT" Nothing (buildUrl paths) (Just auth) Nothing return r githubPutBody auth paths p = do - r <- doHttps "PUT" (buildUrl paths) (Just auth) $ fmap (RequestBodyLBS . encode) p + r <- doHttps "PUT" Nothing (buildUrl paths) (Just auth) $ fmap (RequestBodyLBS . encode) p return r buildUrl :: [String] -> String buildUrl paths = "https://api.github.com/" ++ intercalate "/" paths -githubAPI :: (ToJSON a, Show a, FromJSON b, Show b) => BS.ByteString -> String +githubAPI :: (ToJSON a, Show a, FromJSON b, Show b) => BS.ByteString -> Maybe BS.ByteString -> String -> Maybe GithubAuth -> Maybe a -> IO (Either Error b) -githubAPI apimethod url auth body = do - result <- doHttps apimethod url auth (encodeBody body) +githubAPI apimethod mversion url auth body = do + result <- doHttps apimethod mversion url auth (encodeBody body) case result of Left e -> return (Left (HTTPConnectionError e)) Right resp -> either Left (\x -> jsonResultToE (LBS.pack (show x)) @@ -106,7 +109,7 @@ githubAPI apimethod url auth body = do nextJson <- handleBody nextResp return $ (\(Array x) -> Array (ary <> x)) <$> nextJson) - =<< doHttps apimethod nu auth Nothing + =<< doHttps apimethod mversion nu auth Nothing handleJson _ gotjson = return (Right gotjson) getNextUrl l = @@ -116,13 +119,14 @@ githubAPI apimethod url auth body = do in Just (Data.List.takeWhile (/= '>') s') else Nothing --- doHttps :: Method -> String -> Maybe GithubAuth +-- doHttps :: Method -> Maybe ByteString -> String -> Maybe GithubAuth -- -> Maybe (RequestBody (ResourceT IO)) -- -> IO (Either E.SomeException (Response LBS.ByteString)) -doHttps reqMethod url auth body = do +doHttps reqMethod mversion url auth body = do let reqBody = fromMaybe (RequestBodyBS $ BS.pack "") body reqHeaders = maybe [] getOAuth auth Just uri = parseUrl url + version = maybe "application/vnd.github.preview" id mversion request = uri { method = reqMethod , secure = True , port = 443 @@ -130,7 +134,7 @@ doHttps reqMethod url auth body = do , responseTimeout = Just 20000000 , requestHeaders = reqHeaders <> [("User-Agent", "github.hs/0.7.4")] - <> [("Accept", "application/vnd.github.preview")] + <> [("Accept", version)] , checkStatus = successOrMissing } authRequest = getAuthRequest auth request diff --git a/Github/Repos.hs b/Github/Repos.hs index 9aaade84..0963d196 100644 --- a/Github/Repos.hs +++ b/Github/Repos.hs @@ -302,7 +302,7 @@ deleteRepo :: GithubAuth -> String -- ^ repository name -> IO (Either Error ()) deleteRepo auth owner repo = do - result <- doHttps "DELETE" url (Just auth) Nothing + result <- doHttps "DELETE" Nothing url (Just auth) Nothing case result of Left e -> return (Left (HTTPConnectionError e)) Right resp -> diff --git a/Github/Repos/Branches.hs b/Github/Repos/Branches.hs new file mode 100644 index 00000000..e1d6b590 --- /dev/null +++ b/Github/Repos/Branches.hs @@ -0,0 +1,47 @@ +{-# LANGUAGE OverloadedStrings #-} +-- | The repo starring API as described on +-- . +module Github.Repos.Branches ( + ) where + +import Data.Aeson +import qualified Data.ByteString.Char8 as BS + +import Github.Data +import Github.Private + +import qualified Network.HTTP.Conduit as C (responseStatus) +import qualified Network.HTTP.Types as T (statusCode) + + +-- https://developer.github.com/v3/repos/branches/#update-branch-protection +--protect :: GithubAuth -> String -> String -> String -> Protection -> IO (Either SomeException ()) +protect auth userName reqRepoName branch protection = do + githubPutBody + auth + ["repos", userName, reqRepoName, "branches", branch, "protection"] + protection + +instance ToJSON Protection where + toJSON (Protection r p) = + object [ + ("required_status_checks", maybeOrNull r $ \(RequiredStatusChecks e s c) -> + object [ + "include_admins" .= case e of { Everyone -> True; NotAdmins -> False } + , "strict" .= s + , "contexts" .= toJSON c + ]) + , ("restrictions", maybeOrNull p $ \(PushRestrictions us ts) -> + object [ + "users" .= toJSON (fmap user us) + , "teams" .= toJSON (fmap team ts) + ]) + ] + +maybeOrNull :: Maybe a -> (a -> Value) -> Value +maybeOrNull m f = + case m of + Nothing -> + Null + Just a -> + f a diff --git a/Github/Repos/Collaborators.hs b/Github/Repos/Collaborators.hs index feb269c4..4e93143c 100644 --- a/Github/Repos/Collaborators.hs +++ b/Github/Repos/Collaborators.hs @@ -29,6 +29,7 @@ collaboratorsOn userName reqRepoName = isCollaboratorOn :: String -> String -> String -> IO (Either Error Bool) isCollaboratorOn userName repoOwnerName reqRepoName = do result <- doHttps (pack "GET") + Nothing (buildUrl ["repos", repoOwnerName, reqRepoName, "collaborators", userName]) Nothing Nothing @@ -40,6 +41,7 @@ isCollaboratorOn userName repoOwnerName reqRepoName = do removeCollaborator :: String -> String -> String -> IO (Either Error Bool) removeCollaborator userName repoOwnerName reqRepoName = do result <- doHttps (pack "DELETE") + Nothing (buildUrl ["repos", repoOwnerName, reqRepoName, "collaborators", userName]) Nothing Nothing diff --git a/Github/Repos/Hooks.hs b/Github/Repos/Hooks.hs index 6f0bd95f..92d62abc 100644 --- a/Github/Repos/Hooks.hs +++ b/Github/Repos/Hooks.hs @@ -56,4 +56,4 @@ jinS _ Nothing = [] jinB :: String -> Maybe Bool -> [(Text, Value)] jinB k (Just x) = [(pack k, Bool x)] -jinB _ Nothing = [] \ No newline at end of file +jinB _ Nothing = [] diff --git a/github.cabal b/github.cabal index dab04cb3..f7ffdc13 100644 --- a/github.cabal +++ b/github.cabal @@ -132,6 +132,7 @@ Library Github.Organizations.Members, Github.PullRequests, Github.Repos, + Github.Repos.Branches, Github.Repos.Collaborators, Github.Repos.Commits, Github.Repos.Forks, From 5ece7405f72b92f14508c82d8b274554836da498 Mon Sep 17 00:00:00 2001 From: Nick Hibberd Date: Thu, 18 Aug 2016 12:38:26 +1000 Subject: [PATCH 22/37] Fixing naming conflict --- Github/Data/Definitions.hs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Github/Data/Definitions.hs b/Github/Data/Definitions.hs index 04b76aae..c9f82c69 100644 --- a/Github/Data/Definitions.hs +++ b/Github/Data/Definitions.hs @@ -507,7 +507,7 @@ data EnforcementLevel = deriving (Show, Data, Typeable, Eq, Ord) data PushRestrictions = - PushRestrictions [User] [Team] + PushRestrictions [User] [TeamName] deriving (Show, Data, Typeable, Eq, Ord) newtype User = @@ -515,7 +515,7 @@ newtype User = user :: String } deriving (Show, Data, Typeable, Eq, Ord) -newtype Team = - Team { +newtype TeamName = + TeamName { team :: String } deriving (Show, Data, Typeable, Eq, Ord) From fcc7c6c9d14a0b461a704ec333d0dc6c916a5bff Mon Sep 17 00:00:00 2001 From: Nick Hibberd Date: Thu, 18 Aug 2016 12:48:16 +1000 Subject: [PATCH 23/37] Export protect from branches --- Github/Repos/Branches.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/Github/Repos/Branches.hs b/Github/Repos/Branches.hs index e1d6b590..1865c31b 100644 --- a/Github/Repos/Branches.hs +++ b/Github/Repos/Branches.hs @@ -2,6 +2,7 @@ -- | The repo starring API as described on -- . module Github.Repos.Branches ( + protect ) where import Data.Aeson From 1e95b3f0a91926b7f1f8f319e5b1b01219d5a61a Mon Sep 17 00:00:00 2001 From: Nick Hibberd Date: Thu, 18 Aug 2016 14:50:05 +1000 Subject: [PATCH 24/37] Add custom media type to accept header for branch protection --- Github/Private.hs | 4 ++++ Github/Repos/Branches.hs | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Github/Private.hs b/Github/Private.hs index a3a000fd..402a3f2e 100644 --- a/Github/Private.hs +++ b/Github/Private.hs @@ -72,6 +72,10 @@ githubPutBody auth paths p = do r <- doHttps "PUT" Nothing (buildUrl paths) (Just auth) $ fmap (RequestBodyLBS . encode) p return r +githubPutBodyMedia auth paths m p = do + r <- doHttps "PUT" m (buildUrl paths) (Just auth) $ fmap (RequestBodyLBS . encode) p + return r + buildUrl :: [String] -> String buildUrl paths = "https://api.github.com/" ++ intercalate "/" paths diff --git a/Github/Repos/Branches.hs b/Github/Repos/Branches.hs index 1865c31b..b4cd01c3 100644 --- a/Github/Repos/Branches.hs +++ b/Github/Repos/Branches.hs @@ -18,11 +18,13 @@ import qualified Network.HTTP.Types as T (statusCode) -- https://developer.github.com/v3/repos/branches/#update-branch-protection --protect :: GithubAuth -> String -> String -> String -> Protection -> IO (Either SomeException ()) protect auth userName reqRepoName branch protection = do - githubPutBody + githubPutBodyMedia auth ["repos", userName, reqRepoName, "branches", branch, "protection"] + (Just "application/vnd.github.loki-preview+json") protection + instance ToJSON Protection where toJSON (Protection r p) = object [ From 432e1fb59c9c11494c279c57a082d9faf6659ef8 Mon Sep 17 00:00:00 2001 From: Russell Aronson Date: Wed, 24 Aug 2016 17:28:51 +1000 Subject: [PATCH 25/37] Add issue search --- Github/Data.hs | 6 ++++++ Github/Data/Definitions.hs | 5 +++++ Github/Search.hs | 18 +++++++++++++++++- 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/Github/Data.hs b/Github/Data.hs index 42121748..9614f165 100644 --- a/Github/Data.hs +++ b/Github/Data.hs @@ -410,6 +410,12 @@ instance FromJSON SearchReposResult where <*> o .:< "items" parseJSON _ = fail "Could not build a SearchReposResult" +instance FromJSON SearchIssuesResult where + parseJSON (Object o) = + SearchIssuesResult <$> o .: "total_count" + <*> o .:< "items" + parseJSON _ = fail "Could not build a SearchIssuesResult" + instance FromJSON Repo where parseJSON (Object o) = Repo <$> o .: "ssh_url" diff --git a/Github/Data/Definitions.hs b/Github/Data/Definitions.hs index c9f82c69..57ffe2e3 100644 --- a/Github/Data/Definitions.hs +++ b/Github/Data/Definitions.hs @@ -371,6 +371,11 @@ data SearchReposResult = SearchReposResult { ,searchReposRepos :: [ Repo ] } deriving (Show, Data, Typeable, Eq, Ord) +data SearchIssuesResult = SearchIssuesResult { + searchIssuesTotalCount :: Int + ,searchIssuesIssues :: [ Issue ] +} deriving (Show, Data, Typeable, Eq, Ord) + data Repo = Repo { repoSshUrl :: String ,repoDescription :: Maybe String diff --git a/Github/Search.hs b/Github/Search.hs index 41fe84a3..79791c70 100644 --- a/Github/Search.hs +++ b/Github/Search.hs @@ -1,7 +1,9 @@ -- | The Github Search API, as described at -- . module Github.Search( - searchRepos' + searchIssues' +,searchIssues +,searchRepos' ,searchRepos ,module Github.Data ) where @@ -23,3 +25,17 @@ searchRepos' auth queryString = githubGetWithQueryString' auth ["search/reposito searchRepos :: String -> IO (Either Error SearchReposResult) searchRepos = searchRepos' Nothing +-- | Perform an issue search. +-- | With authentication. +-- +-- > searchIssues' (Just $ GithubBasicAuth "github-username" "github-password') "q=is%3Aopen" +searchIssues' :: Maybe GithubAuth -> String -> IO (Either Error SearchIssuesResult) +searchIssues' auth queryString = githubGetWithQueryString' auth ["search/issues"] queryString + +-- | Perform an issue search. +-- | Without authentication. +-- +-- > searchIssues "q=is%3Aopen" +searchIssues :: String -> IO (Either Error SearchIssuesResult) +searchIssues = searchIssues' Nothing + From 07d5da34ed05231b5cc2afcf19ebedbb2e6e24a8 Mon Sep 17 00:00:00 2001 From: Sharif Olorin Date: Thu, 25 Aug 2016 23:03:25 +0000 Subject: [PATCH 26/37] Add upper bound on http-conduit To avoid breakage with exported http-client types - the package uses a constructor which was removed in http-client 0.5 (checkStatus). --- github.cabal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/github.cabal b/github.cabal index f7ffdc13..3c3c5b41 100644 --- a/github.cabal +++ b/github.cabal @@ -156,7 +156,7 @@ Library time-locale-compat == 0.1.*, HTTP, network, - http-conduit >= 1.9, + http-conduit >= 1.9 && < 2.2, conduit, failure, http-types, From fa9baee311c60e3be6412fef65041c0ccdb40e2d Mon Sep 17 00:00:00 2001 From: Nick Hibberd Date: Fri, 2 Sep 2016 14:18:29 +1000 Subject: [PATCH 27/37] Adding issue label commands --- Github/Data.hs | 7 +++++++ Github/Data/Definitions.hs | 7 +++++++ Github/Issues/Labels.hs | 23 +++++++++++++++++++++++ Github/Private.hs | 4 ++++ 4 files changed, 41 insertions(+) diff --git a/Github/Data.hs b/Github/Data.hs index 9614f165..cab50a7a 100644 --- a/Github/Data.hs +++ b/Github/Data.hs @@ -134,6 +134,13 @@ instance ToJSON NewComment where instance ToJSON EditComment where toJSON (EditComment b) = object [ "body" .= b ] +instance ToJSON NewLabel where + toJSON (NewLabel n c) = + object [ + "name" .= n + , "color" .= c + ] + instance FromJSON Diff where parseJSON (Object o) = Diff <$> o .: "status" diff --git a/Github/Data/Definitions.hs b/Github/Data/Definitions.hs index 57ffe2e3..c0c2e0ff 100644 --- a/Github/Data/Definitions.hs +++ b/Github/Data/Definitions.hs @@ -524,3 +524,10 @@ newtype TeamName = TeamName { team :: String } deriving (Show, Data, Typeable, Eq, Ord) + +-- https://developer.github.com/v3/issues/labels/#create-a-label +data NewLabel = + NewLabel { + newLabelName :: String + , newLabelColor :: String + } deriving (Show, Data, Typeable, Eq, Ord) diff --git a/Github/Issues/Labels.hs b/Github/Issues/Labels.hs index 44db680e..036a800f 100644 --- a/Github/Issues/Labels.hs +++ b/Github/Issues/Labels.hs @@ -37,3 +37,26 @@ labelsOnMilestone user reqRepoName milestoneId = label :: String -> String -> String -> IO (Either Error IssueLabel) label user reqRepoName reqLabelName = githubGet ["repos", user, reqRepoName, "labels", reqLabelName] + +-- https://developer.github.com/v3/issues/labels/#create-a-label +createLabel :: GithubAuth -> String -> String -> NewLabel -> IO (Either Error IssueLabel) +createLabel auth user reqRepoName label = + githubPost auth ["repos", user, reqRepoName, "labels"] label + +-- https://developer.github.com/v3/issues/labels/#add-labels-to-an-issue +applyLabels :: GithubAuth -> String -> String -> String -> [String] -> IO (Either Error [IssueLabel]) +applyLabels auth user reqRepoName issueNumber l = + githubPost auth ["repos", user, reqRepoName, "issues", issueNumber, "labels"] l + +listLabels :: GithubAuth -> String -> String -> String -> String -> IO (Either Error [IssueLabel]) +listLabels auth user reqRepoName issueNumber l = + githubGet' (Just auth) ["repos", user, reqRepoName, "issues", issueNumber, "labels"] + +-- https://developer.github.com/v3/issues/labels/#remove-a-label-from-an-issue +--removeLabels :: GithubAuth -> String -> String -> String -> String -> IO (Either SomeException (Response LBS.ByteString)) +removeLabels auth user reqRepoName issueNumber l = + githubDelete auth ["repos", user, reqRepoName, "issues", issueNumber, "labels", l] + +--removeAllLabels :: GithubAuth -> String -> String -> String -> IO (Either SomeException (Response LBS.ByteString)) +removeAllLabels auth user reqRepoName issueNumber = + githubDelete auth ["repos", user, reqRepoName, "issues", issueNumber, "labels"] diff --git a/Github/Private.hs b/Github/Private.hs index 402a3f2e..a4a2ee95 100644 --- a/Github/Private.hs +++ b/Github/Private.hs @@ -56,6 +56,10 @@ githubPost auth paths body = (Just auth) (Just body) +githubDelete auth paths = do + r <- doHttps "DELETE" Nothing (buildUrl paths) (Just auth) Nothing + return r + githubPatch :: (ToJSON a, Show a, FromJSON b, Show b) => GithubAuth -> [String] -> a -> IO (Either Error b) githubPatch auth paths body = githubAPI (BS.pack "PATCH") From c9844790be56baec0b11b177af4c9faf8dc448e0 Mon Sep 17 00:00:00 2001 From: Nick Hibberd Date: Fri, 2 Sep 2016 14:32:43 +1000 Subject: [PATCH 28/37] Assignees --- Github/Data.hs | 11 +++++++++++ Github/Data/Definitions.hs | 10 ++++++++++ Github/Issues/Assignees.hs | 23 +++++++++++++++++++++++ Github/Private.hs | 8 ++++++++ 4 files changed, 52 insertions(+) create mode 100644 Github/Issues/Assignees.hs diff --git a/Github/Data.hs b/Github/Data.hs index cab50a7a..a5488fa0 100644 --- a/Github/Data.hs +++ b/Github/Data.hs @@ -141,6 +141,17 @@ instance ToJSON NewLabel where , "color" .= c ] +instance ToJSON Assignees where + toJSON (Assignees as) = + object [ + "assignees" .= toJSON as + ] + +instance FromJSON Assignee where + parseJSON (Object o) = + Assignee + <$> o .: "login" + instance FromJSON Diff where parseJSON (Object o) = Diff <$> o .: "status" diff --git a/Github/Data/Definitions.hs b/Github/Data/Definitions.hs index c0c2e0ff..939202ec 100644 --- a/Github/Data/Definitions.hs +++ b/Github/Data/Definitions.hs @@ -531,3 +531,13 @@ data NewLabel = newLabelName :: String , newLabelColor :: String } deriving (Show, Data, Typeable, Eq, Ord) + +newtype Assignees = + Assignees { + assignees :: [String] + } deriving (Show, Data, Typeable, Eq, Ord) + +newtype Assignee = + Assignee { + assigneeLogin :: String + } deriving (Show, Data, Typeable, Eq, Ord) diff --git a/Github/Issues/Assignees.hs b/Github/Issues/Assignees.hs new file mode 100644 index 00000000..357b03ac --- /dev/null +++ b/Github/Issues/Assignees.hs @@ -0,0 +1,23 @@ +-- | The Github issues assignees events API, which is described on +-- +module Github.Issues.Assignees ( + listAssignees +,addAssignee +,removeAssignee +,module Github.Data +) where + +import Github.Data +import Github.Private + +listAssignees :: GithubAuth -> String -> String -> IO (Either Error [Assignee]) +listAssignees auth user reqRepoName = + githubGet' (Just auth) ["repos", user, reqRepoName, "assignees"] + +addAssignee :: GithubAuth -> String -> String -> String -> Assignees -> IO (Either Error ()) +addAssignee auth user reqRepoName issueNumber assignees = + githubPost auth ["repos", user, reqRepoName, "issues", issueNumber, "assignees"] assignees + +removeAssignee :: GithubAuth -> String -> String -> String -> Assignees -> IO (Either Error ()) +removeAssignee auth user reqRepoName issueNumber assignees = + githubDeleteBody auth ["repos", user, reqRepoName, "issues", issueNumber, "assignees"] assignees diff --git a/Github/Private.hs b/Github/Private.hs index a4a2ee95..e002e66b 100644 --- a/Github/Private.hs +++ b/Github/Private.hs @@ -60,6 +60,14 @@ githubDelete auth paths = do r <- doHttps "DELETE" Nothing (buildUrl paths) (Just auth) Nothing return r +githubDeleteBody :: (ToJSON a, Show a, FromJSON b, Show b) => GithubAuth -> [String] -> a -> IO (Either Error b) +githubDeleteBody auth paths body = do + githubAPI (BS.pack "DELETE") + Nothing + (buildUrl paths) + (Just auth) + (Just body) + githubPatch :: (ToJSON a, Show a, FromJSON b, Show b) => GithubAuth -> [String] -> a -> IO (Either Error b) githubPatch auth paths body = githubAPI (BS.pack "PATCH") From ded6302114c47d99980b7fd7ec0d86eea324f3c2 Mon Sep 17 00:00:00 2001 From: Nick Hibberd Date: Fri, 2 Sep 2016 15:27:58 +1000 Subject: [PATCH 29/37] Adding lables on repo with auth --- Github/Issues/Labels.hs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Github/Issues/Labels.hs b/Github/Issues/Labels.hs index 036a800f..ad3072bf 100644 --- a/Github/Issues/Labels.hs +++ b/Github/Issues/Labels.hs @@ -17,6 +17,10 @@ import Github.Private labelsOnRepo :: String -> String -> IO (Either Error [IssueLabel]) labelsOnRepo user reqRepoName = githubGet ["repos", user, reqRepoName, "labels"] +labelsOnRepo' :: GithubAuth -> String -> String -> IO (Either Error [IssueLabel]) +labelsOnRepo' auth user reqRepoName = + githubGet' (Just auth) ["repos", user, reqRepoName, "labels"] + -- | The labels on an issue in a repo. -- -- > labelsOnIssue "thoughtbot" "paperclip" 585 From 54949da9252ae565c6d43410370b017994c89fb1 Mon Sep 17 00:00:00 2001 From: Nick Hibberd Date: Fri, 2 Sep 2016 15:36:18 +1000 Subject: [PATCH 30/37] Adding lables on repo with auth --- Github/Issues/Labels.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/Github/Issues/Labels.hs b/Github/Issues/Labels.hs index ad3072bf..b08eb2db 100644 --- a/Github/Issues/Labels.hs +++ b/Github/Issues/Labels.hs @@ -3,6 +3,7 @@ module Github.Issues.Labels ( label ,labelsOnRepo +,labelsOnRepo' ,labelsOnIssue ,labelsOnMilestone ,module Github.Data From 8c38d5c38af5c40c523f309ef59ec59fa0471838 Mon Sep 17 00:00:00 2001 From: Nick Hibberd Date: Fri, 2 Sep 2016 15:39:58 +1000 Subject: [PATCH 31/37] export --- Github/Issues/Labels.hs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Github/Issues/Labels.hs b/Github/Issues/Labels.hs index b08eb2db..c774e795 100644 --- a/Github/Issues/Labels.hs +++ b/Github/Issues/Labels.hs @@ -6,6 +6,11 @@ module Github.Issues.Labels ( ,labelsOnRepo' ,labelsOnIssue ,labelsOnMilestone +,createLabel +,applyLabels +,listLabels +,removeLabels +,removeAllLabels ,module Github.Data ) where From 35ccba62462c2b5a20db6767627af58ff94621ff Mon Sep 17 00:00:00 2001 From: Nick Hibberd Date: Fri, 2 Sep 2016 16:13:06 +1000 Subject: [PATCH 32/37] Export assignees --- github.cabal | 1 + 1 file changed, 1 insertion(+) diff --git a/github.cabal b/github.cabal index 3c3c5b41..613637a7 100644 --- a/github.cabal +++ b/github.cabal @@ -124,6 +124,7 @@ Library Github.GitData.Trees, Github.GitData.Blobs, Github.Issues, + Github.Issues.Assignees, Github.Issues.Comments, Github.Issues.Events, Github.Issues.Labels, From 00edccd3bfda0745bfeb6fa129acfba788d8b524 Mon Sep 17 00:00:00 2001 From: Nick Hibberd Date: Fri, 2 Sep 2016 16:50:56 +1000 Subject: [PATCH 33/37] Removing extra type --- Github/Issues/Labels.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Github/Issues/Labels.hs b/Github/Issues/Labels.hs index c774e795..48726b78 100644 --- a/Github/Issues/Labels.hs +++ b/Github/Issues/Labels.hs @@ -58,8 +58,8 @@ applyLabels :: GithubAuth -> String -> String -> String -> [String] -> IO (Eithe applyLabels auth user reqRepoName issueNumber l = githubPost auth ["repos", user, reqRepoName, "issues", issueNumber, "labels"] l -listLabels :: GithubAuth -> String -> String -> String -> String -> IO (Either Error [IssueLabel]) -listLabels auth user reqRepoName issueNumber l = +listLabels :: GithubAuth -> String -> String -> String -> IO (Either Error [IssueLabel]) +listLabels auth user reqRepoName issueNumber = githubGet' (Just auth) ["repos", user, reqRepoName, "issues", issueNumber, "labels"] -- https://developer.github.com/v3/issues/labels/#remove-a-label-from-an-issue From 32c0531cde1c3c5359b319457525866979a8a3ac Mon Sep 17 00:00:00 2001 From: Charles O'Farrell Date: Mon, 5 Sep 2016 12:18:06 +1000 Subject: [PATCH 34/37] Return Issue from add/remove assignee to fix parsing errors --- Github/Issues/Assignees.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Github/Issues/Assignees.hs b/Github/Issues/Assignees.hs index 357b03ac..9b3836f8 100644 --- a/Github/Issues/Assignees.hs +++ b/Github/Issues/Assignees.hs @@ -14,10 +14,10 @@ listAssignees :: GithubAuth -> String -> String -> IO (Either Error [Assignee]) listAssignees auth user reqRepoName = githubGet' (Just auth) ["repos", user, reqRepoName, "assignees"] -addAssignee :: GithubAuth -> String -> String -> String -> Assignees -> IO (Either Error ()) +addAssignee :: GithubAuth -> String -> String -> String -> Assignees -> IO (Either Error Issue) addAssignee auth user reqRepoName issueNumber assignees = githubPost auth ["repos", user, reqRepoName, "issues", issueNumber, "assignees"] assignees -removeAssignee :: GithubAuth -> String -> String -> String -> Assignees -> IO (Either Error ()) +removeAssignee :: GithubAuth -> String -> String -> String -> Assignees -> IO (Either Error Issue) removeAssignee auth user reqRepoName issueNumber assignees = githubDeleteBody auth ["repos", user, reqRepoName, "issues", issueNumber, "assignees"] assignees From 2e2f060292db75d21fa2877059021e9107ef4007 Mon Sep 17 00:00:00 2001 From: Charles O'Farrell Date: Wed, 7 Sep 2016 10:10:13 +1000 Subject: [PATCH 35/37] Github issues now support multiple assignees --- Github/Data.hs | 2 +- Github/Data/Definitions.hs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Github/Data.hs b/Github/Data.hs index a5488fa0..4def9b64 100644 --- a/Github/Data.hs +++ b/Github/Data.hs @@ -235,7 +235,7 @@ instance FromJSON Issue where <*> o .:? "closed_by" <*> o .: "labels" <*> o .: "number" - <*> o .:? "assignee" + <*> o .: "assignees" <*> o .: "user" <*> o .: "title" <*> o .:? "pull_request" diff --git a/Github/Data/Definitions.hs b/Github/Data/Definitions.hs index 939202ec..b757ce2f 100644 --- a/Github/Data/Definitions.hs +++ b/Github/Data/Definitions.hs @@ -192,7 +192,7 @@ data Issue = Issue { ,issueClosedBy :: Maybe GithubOwner ,issueLabels :: [IssueLabel] ,issueNumber :: Int - ,issueAssignee :: Maybe GithubOwner + ,issueAssignee :: [GithubOwner] ,issueUser :: GithubOwner ,issueTitle :: String ,issuePullRequest :: Maybe PullRequestReference From cbc8d269133edcefb51671171b042a1a643f43bf Mon Sep 17 00:00:00 2001 From: Charles O'Farrell Date: Fri, 9 Sep 2016 08:36:55 +1000 Subject: [PATCH 36/37] Add support for organisation teams --- Github/Data.hs | 8 ++++++++ Github/Data/Definitions.hs | 6 ++++++ Github/Organizations/Teams.hs | 18 ++++++++++++++++++ github.cabal | 1 + 4 files changed, 33 insertions(+) create mode 100644 Github/Organizations/Teams.hs diff --git a/Github/Data.hs b/Github/Data.hs index 4def9b64..74f9115c 100644 --- a/Github/Data.hs +++ b/Github/Data.hs @@ -560,6 +560,14 @@ instance FromJSON Hook where <*> o .: "updated_at" parseJSON _ = fail "Could not build a Hook" +instance FromJSON Team where + parseJSON (Object o) = + Team + <$> (TeamName <$> o .: "name") + <*> o .: "id" + parseJSON _ = + fail "Could not build a Team" + -- | A slightly more generic version of Aeson's @(.:?)@, using `mzero' instead -- of `Nothing'. (.:<) :: (FromJSON a) => Object -> T.Text -> Parser [a] diff --git a/Github/Data/Definitions.hs b/Github/Data/Definitions.hs index b757ce2f..ea0acf98 100644 --- a/Github/Data/Definitions.hs +++ b/Github/Data/Definitions.hs @@ -520,6 +520,12 @@ newtype User = user :: String } deriving (Show, Data, Typeable, Eq, Ord) +data Team = + Team { + teamName :: TeamName + , teamId :: Integer + } deriving (Show, Data, Typeable, Eq, Ord) + newtype TeamName = TeamName { team :: String diff --git a/Github/Organizations/Teams.hs b/Github/Organizations/Teams.hs new file mode 100644 index 00000000..fa874e0e --- /dev/null +++ b/Github/Organizations/Teams.hs @@ -0,0 +1,18 @@ +-- | The organization members API as described on +-- . +module Github.Organizations.Teams ( + listTeams' +,listTeamMembers' +,module Github.Data +) where + +import Github.Data +import Github.Private + +listTeams' :: Maybe GithubAuth -> String -> IO (Either Error [Team]) +listTeams' auth organization = + githubGet' auth ["orgs", organization, "teams"] + +listTeamMembers' :: Maybe GithubAuth -> Integer -> IO (Either Error [GithubOwner]) +listTeamMembers' auth teamId = + githubGet' auth ["teams", show teamId, "members"] diff --git a/github.cabal b/github.cabal index 613637a7..5707c889 100644 --- a/github.cabal +++ b/github.cabal @@ -131,6 +131,7 @@ Library Github.Issues.Milestones, Github.Organizations, Github.Organizations.Members, + Github.Organizations.Teams, Github.PullRequests, Github.Repos, Github.Repos.Branches, From f0720d905d5449b9a9e48bac98e0326bde8450bc Mon Sep 17 00:00:00 2001 From: Charles O'Farrell Date: Wed, 14 Feb 2018 10:51:54 +1100 Subject: [PATCH 37/37] Fix getNextUrl to parse link correctly --- Github/Private.hs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/Github/Private.hs b/Github/Private.hs index e002e66b..c8624684 100644 --- a/Github/Private.hs +++ b/Github/Private.hs @@ -9,6 +9,8 @@ import Data.Attoparsec.ByteString.Lazy import Data.Data import Data.Monoid import Data.List +import qualified Data.Text as T +import Data.Tuple (swap) import Data.CaseInsensitive (mk) import qualified Data.ByteString.Char8 as BS import qualified Data.ByteString.Lazy.Char8 as LBS @@ -128,12 +130,13 @@ githubAPI apimethod mversion url auth body = do =<< doHttps apimethod mversion nu auth Nothing handleJson _ gotjson = return (Right gotjson) - getNextUrl l = - if "rel=\"next\"" `isInfixOf` l - then let s = l - s' = Data.List.tail $ Data.List.dropWhile (/= '<') s - in Just (Data.List.takeWhile (/= '>') s') - else Nothing +getNextUrl :: String -> Maybe String +getNextUrl = + let + p = + T.takeWhile (/= '>') . T.tail . T.dropWhile (/= '<') + in + fmap (T.unpack . p) . lookup "rel=\"next\"" . fmap (swap . fmap (T.strip . T.drop 1) . T.breakOn ";") . T.splitOn "," . T.pack -- doHttps :: Method -> Maybe ByteString -> String -> Maybe GithubAuth -- -> Maybe (RequestBody (ResourceT IO))