packages feed

gitlab-haskell 1.0.0.5 → 1.0.1.0

raw patch · 14 files changed

+74/−37 lines, 14 filesdep +data-default-classdep ~crypton-connectionPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: data-default-class

Dependency ranges changed: crypton-connection

API changes (from Hackage documentation)

- GitLab.Types: [timeout] :: GitLabServerConfig -> Int
+ GitLab.Types: AuthMethodOAuth :: Text -> AuthMethod
+ GitLab.Types: AuthMethodToken :: Text -> AuthMethod
+ GitLab.Types: data AuthMethod
- GitLab.Types: GitLabServerConfig :: Text -> Text -> Int -> Int -> Bool -> GitLabServerConfig
+ GitLab.Types: GitLabServerConfig :: Text -> AuthMethod -> Int -> Bool -> GitLabServerConfig
- GitLab.Types: [token] :: GitLabServerConfig -> Text
+ GitLab.Types: [token] :: GitLabServerConfig -> AuthMethod

Files

README.md view
@@ -22,6 +22,8 @@ * Notes * Boards +## gitlab-haskell API+ The library parses JSON results into Haskell data types in the `GitLab.Types` module, allowing you to work with statically typed GitLab data with data types and functions that the library@@ -30,6 +32,27 @@     searchUser     :: Text -> GitLab (Maybe User)     userProjects   :: User -> GitLab (Maybe [Project]) +## Server-side GitLab file hooks++This library can also be used to implement rule based GitLab file+system hooks that, when deployed a GitLab server, react in real time+to GitLab events like project creation, new users, merge requests etc.++The rule based API for implementing file hooks is:++    receive :: [Rule] -> GitLab ()++    class (FromJSON a) => SystemHook a where+      match   :: String -> (a -> GitLab ()) -> Rule+      matchIf :: String -> (a -> GitLab Bool) -> (a -> GitLab ()) -> Rule++For more details about the file system hooks support, see post:+[GitLab automation with file hook rules](https://www.macs.hw.ac.uk/~rs46/posts/2020-06-06-gitlab-system-hooks.html).++This library has almost 100% coverage of the GitLab REST API. For the complete+`gitlab-haskell` API, see the [hackage+documentation](https://hackage.haskell.org/package/gitlab-haskell).+ ## Example  Run all GitLab actions with `runGitLab`: @@ -46,25 +69,15 @@       runGitLab         (defaultGitLabServer            { url = "https://gitlab.example.com"-           , token="my_token"} )-        (searchUser "joe" >>= userProjects . fromJust)--This library can also be used to implement rule based GitLab file-system hooks that, when deployed a GitLab server, react in real time-to GitLab events like project creation, new users, merge requests etc.--The rule based API for implementing file hooks is:--    receive :: [Rule] -> GitLab ()--    class (FromJSON a) => SystemHook a where-      match   :: String -> (a -> GitLab ()) -> Rule-      matchIf :: String -> (a -> GitLab Bool) -> (a -> GitLab ()) -> Rule+           , token = AuthMethodToken "my_token"} )+        (searchUser "joe" >>=  \usr -> userProjects (fromJust usr) defaultProjectSearchAttrs) -For more details about the file system hooks support, see post:-[GitLab automation with file hook rules](https://www.macs.hw.ac.uk/~rs46/posts/2020-06-06-gitlab-system-hooks.html).+## Library use -For the complete `gitlab-haskell` API, see the [hackage documentation](https://hackage.haskell.org/package/gitlab-haskell).+It was initially developed to automate and support computer science+education. See our ICSE-SEET 2024 paper for the details: [_"Integrating Canvas+and GitLab to Enrich Learning+Processes"_](https://doi.org/10.1145/3639474.3640056).  An example of an application using this library is `gitlab-tools`, which is a command line tool for bulk GitLab transactions [link](https://gitlab.com/robstewart57/gitlab-tools).
gitlab-haskell.cabal view
@@ -1,7 +1,7 @@ cabal-version: 2.4 name:           gitlab-haskell category:       Git-version:        1.0.0.5+version:        1.0.1.0 synopsis:       A Haskell library for the GitLab web API description:             This library lifts the GitLab REST API into Haskell: <https://docs.gitlab.com/ee/api/>@@ -198,7 +198,7 @@   build-depends:                 base >=4.7 && <5               , http-conduit-              , crypton-connection+              , crypton-connection >= 0.4.1               , aeson >= 2.0.0.0               , bytestring               , text@@ -209,6 +209,7 @@               , temporary               , unix               , mtl+              , data-default-class   default-language: Haskell2010   ghc-options: -Wall                -- the following two for the stan static analysis tool
src/GitLab.hs view
@@ -39,6 +39,7 @@  import Control.Monad.IO.Class import Control.Monad.Trans.Reader+import Data.Default.Class import qualified Data.Text as T import GitLab.API.Boards import GitLab.API.Branches@@ -62,7 +63,6 @@ import GitLab.SystemHooks.Rules import GitLab.SystemHooks.Types import GitLab.Types-import Network.Connection (TLSSettings (..)) import Network.HTTP.Conduit import Network.HTTP.Types.Status import System.IO@@ -87,7 +87,7 @@ runGitLab :: GitLabServerConfig -> GitLab a -> IO a runGitLab cfg action = do   liftIO $ hSetBuffering stdout LineBuffering-  let settings = mkManagerSettings (TLSSettingsSimple True False False) Nothing+  let settings = mkManagerSettings def Nothing   manager <- liftIO $ newManager settings   runGitLabWithManager manager cfg action @@ -106,7 +106,7 @@   hostUrl <- getLine   liftIO (putStr "Enter GitLab access token\n> ")   pass <- getLine-  runGitLab (cfg {url = T.pack hostUrl, token = T.pack pass}) action+  runGitLab (cfg {url = T.pack hostUrl, token = AuthMethodToken (T.pack pass)}) action  -- | The same as 'runGitLab', except that it also takes a connection -- manager as an argument.@@ -130,4 +130,6 @@ runGitLabDbg :: GitLab a -> IO a runGitLabDbg (GitLabT action) = do   liftIO $ hSetBuffering stdout LineBuffering-  runReaderT action undefined+  manager <- liftIO $ newManager (mkManagerSettings def Nothing)+  let cfg = GitLabServerConfig {url = "", token = AuthMethodToken "", retries = 1, debugSystemHooks = False}+  runReaderT action (GitLabState cfg manager)
src/GitLab/API/Boards.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE StrictData #-}  -- | -- Module      : Boards
src/GitLab/API/Commits.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE StrictData #-}  -- | -- Module      : Commits
src/GitLab/API/Groups.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE StrictData #-}  -- | -- Module      : Groups
src/GitLab/API/Issues.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE StrictData #-} {-# LANGUAGE TemplateHaskell #-}  -- |
src/GitLab/API/MergeRequests.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE StrictData #-}  -- | -- Module      : MergeRequests@@ -227,7 +228,9 @@       ]     addr =       T.pack $-        "/projects/" <> show projectId <> "/merge_requests/"+        "/projects/"+          <> show projectId+          <> "/merge_requests/"           <> show mergeRequestIid           <> "/merge" @@ -252,7 +255,9 @@   where     addr =       T.pack $-        "/projects/" <> show projectId <> "/merge_requests/"+        "/projects/"+          <> show projectId+          <> "/merge_requests/"           <> show mergeRequestIid  -- | Attributes when searching for merge requests with the
src/GitLab/API/Projects.hs view
@@ -1,6 +1,7 @@ {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE StrictData #-}  -- | -- Module      : Projects@@ -586,12 +587,16 @@ -------------------- -- Additional functionality beyond the GitLab Projects API --- | Returns 'True' is a projecthas multiple email addresses+-- | Returns 'True' is a project has multiple email addresses -- associated with all commits in a project, 'False' otherwise. multipleCommitters :: Project -> GitLab Bool multipleCommitters prj = do   emailAddresses <- commitsEmailAddresses prj-  return (length (nub emailAddresses) > 1)+  return $+    case nub emailAddresses of+      [] -> False+      [_] -> False+      (_ : _) -> True  -- | gets the email addresses in the author information in all commit -- for a project.
src/GitLab/API/Todos.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE StrictData #-}  -- | -- Module      : Todos
src/GitLab/API/Users.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE StrictData #-}  -- | -- Module      : Users
src/GitLab/SystemHooks/GitLabSystemHooks.hs view
@@ -46,7 +46,7 @@  traceSystemHook :: Text -> GitLab () traceSystemHook eventContent = do-  cfg <- serverCfg <$> MR.ask+  cfg <- MR.asks serverCfg   liftIO $     E.catch       ( when (debugSystemHooks cfg) $ do
src/GitLab/Types.hs view
@@ -18,6 +18,7 @@     GitLabT (..),     GitLabState (..),     GitLabServerConfig (..),+    AuthMethod (..),     defaultGitLabServer,     ArchiveFormat (..),     AccessLevel (..),@@ -144,10 +145,7 @@ -- | configuration data specific to a GitLab server. data GitLabServerConfig = GitLabServerConfig   { url :: Text,-    -- | personal access token, see <https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html>-    token :: Text,-    -- | milliseconds-    timeout :: Int,+    token :: AuthMethod,     -- | how many times to retry a HTTP request before giving up and returning an error.     retries :: Int,     -- | write system hook events to files in the system temporary@@ -160,11 +158,15 @@ defaultGitLabServer =   GitLabServerConfig     { url = "https://gitlab.com",-      token = "",-      timeout = 15000000, -- 15 seconds+      token = AuthMethodToken "",       retries = 5,       debugSystemHooks = False     }++-- | personal access token, see <https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html>+data AuthMethod+  = AuthMethodToken Text+  | AuthMethodOAuth Text  -- https://docs.gitlab.com/ee/api/repositories.html#get-file-archive -- tar.gz, tar.bz2, tbz, tbz2, tb2, bz2, tar, and zip
src/GitLab/WebRequests/GitLabWebCalls.hs view
@@ -169,15 +169,18 @@   [GitLabParam] ->   GitLab (Response BSL.ByteString) gitlabHTTP httpMethod contentType urlPath urlParams contentParams = do-  cfg <- serverCfg <$> MR.ask-  manager <- httpManager <$> MR.ask+  cfg <- MR.asks serverCfg+  manager <- MR.asks httpManager   let url' = url cfg <> "/api/v4" <> urlPath <> T.decodeUtf8 (renderQuery True urlParams)+  let authHeader = case token cfg of+        AuthMethodToken t -> ("PRIVATE-TOKEN", T.encodeUtf8 t)+        AuthMethodOAuth t -> ("Authorization", "Bearer " <> T.encodeUtf8 t)   let request' = parseRequest_ (T.unpack url')       request =         request'           { method = httpMethod,             requestHeaders =-              [ ("PRIVATE-TOKEN", T.encodeUtf8 (token cfg)),+              [ authHeader,                 ("content-type", contentType)               ],             requestBody = RequestBodyBS (renderQuery False contentParams)