packages feed

gitlab-haskell 0.2.3 → 0.2.4

raw patch · 16 files changed

+409/−166 lines, 16 filesdep +temporarydep +unixPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: temporary, unix

API changes (from Hackage documentation)

- GitLab.API.Projects: shareProjectWithGroup :: Int -> Int -> AccessLevel -> GitLab (Either Status GroupShare)
+ GitLab.API.MergeRequests: deleteMergeRequest :: Project -> Int -> GitLab (Either Status ())
+ GitLab.API.MergeRequests: deleteMergeRequest' :: Int -> Int -> GitLab (Either Status ())
+ GitLab.API.Notes: createMergeRequestNote :: Project -> Int -> Text -> GitLab (Either Status (Maybe ()))
+ GitLab.API.Notes: createMergeRequestNote' :: Int -> Int -> Text -> GitLab (Either Status (Maybe ()))
+ GitLab.API.Projects: addGroupToProject :: Int -> Int -> AccessLevel -> GitLab (Either Status (Maybe GroupShare))
+ GitLab.API.Users: userId :: Int -> GitLab (Maybe User)
+ GitLab.SystemHooks.Types: MergeRequestChange :: Maybe a -> Maybe a -> MergeRequestChange a
+ GitLab.SystemHooks.Types: MergeRequestChanges :: MergeRequestChange Int -> MergeRequestChange Text -> MergeRequestChange Text -> MergeRequestChange Int -> MergeRequestChange Int -> MergeRequestChange Text -> MergeRequestChange Int -> MergeRequestChange Text -> MergeRequestChange Int -> MergeRequestChange Text -> MergeRequestChange Text -> MergeRequestChanges
+ GitLab.SystemHooks.Types: [$sel:mergeRequestChange_current:MergeRequestChange] :: MergeRequestChange a -> Maybe a
+ GitLab.SystemHooks.Types: [$sel:mergeRequestChange_previous:MergeRequestChange] :: MergeRequestChange a -> Maybe a
+ GitLab.SystemHooks.Types: [$sel:mergeRequestChanges_author_id:MergeRequestChanges] :: MergeRequestChanges -> MergeRequestChange Int
+ GitLab.SystemHooks.Types: [$sel:mergeRequestChanges_created_at:MergeRequestChanges] :: MergeRequestChanges -> MergeRequestChange Text
+ GitLab.SystemHooks.Types: [$sel:mergeRequestChanges_description:MergeRequestChanges] :: MergeRequestChanges -> MergeRequestChange Text
+ GitLab.SystemHooks.Types: [$sel:mergeRequestChanges_id:MergeRequestChanges] :: MergeRequestChanges -> MergeRequestChange Int
+ GitLab.SystemHooks.Types: [$sel:mergeRequestChanges_iid:MergeRequestChanges] :: MergeRequestChanges -> MergeRequestChange Int
+ GitLab.SystemHooks.Types: [$sel:mergeRequestChanges_source_branch:MergeRequestChanges] :: MergeRequestChanges -> MergeRequestChange Text
+ GitLab.SystemHooks.Types: [$sel:mergeRequestChanges_source_project_id:MergeRequestChanges] :: MergeRequestChanges -> MergeRequestChange Int
+ GitLab.SystemHooks.Types: [$sel:mergeRequestChanges_target_branch:MergeRequestChanges] :: MergeRequestChanges -> MergeRequestChange Text
+ GitLab.SystemHooks.Types: [$sel:mergeRequestChanges_target_project_id:MergeRequestChanges] :: MergeRequestChanges -> MergeRequestChange Int
+ GitLab.SystemHooks.Types: [$sel:mergeRequestChanges_title:MergeRequestChanges] :: MergeRequestChanges -> MergeRequestChange Text
+ GitLab.SystemHooks.Types: [$sel:mergeRequestChanges_updated_at:MergeRequestChanges] :: MergeRequestChanges -> MergeRequestChange Text
+ GitLab.SystemHooks.Types: [$sel:mergeRequest_changes:MergeRequestEvent] :: MergeRequestEvent -> MergeRequestChanges
+ GitLab.SystemHooks.Types: [$sel:mergeRequest_event_type:MergeRequestEvent] :: MergeRequestEvent -> Text
+ GitLab.SystemHooks.Types: [$sel:objectAttributes_action:ObjectAttributes] :: ObjectAttributes -> Maybe Text
+ GitLab.SystemHooks.Types: [$sel:objectAttributes_assignee_ids:ObjectAttributes] :: ObjectAttributes -> Maybe [Int]
+ GitLab.SystemHooks.Types: [$sel:objectAttributes_state_id:ObjectAttributes] :: ObjectAttributes -> Maybe Int
+ GitLab.SystemHooks.Types: data MergeRequestChange a
+ GitLab.SystemHooks.Types: data MergeRequestChanges
+ GitLab.SystemHooks.Types: instance Data.Aeson.Types.FromJSON.FromJSON GitLab.SystemHooks.Types.MergeRequestChanges
+ GitLab.SystemHooks.Types: instance Data.Aeson.Types.FromJSON.FromJSON a => Data.Aeson.Types.FromJSON.FromJSON (GitLab.SystemHooks.Types.MergeRequestChange a)
+ GitLab.SystemHooks.Types: instance GHC.Classes.Eq GitLab.SystemHooks.Types.MergeRequestChanges
+ GitLab.SystemHooks.Types: instance GHC.Classes.Eq a => GHC.Classes.Eq (GitLab.SystemHooks.Types.MergeRequestChange a)
+ GitLab.SystemHooks.Types: instance GHC.Generics.Generic (GitLab.SystemHooks.Types.MergeRequestChange a)
+ GitLab.SystemHooks.Types: instance GHC.Generics.Generic GitLab.SystemHooks.Types.MergeRequestChanges
+ GitLab.SystemHooks.Types: instance GHC.Show.Show GitLab.SystemHooks.Types.MergeRequestChanges
+ GitLab.SystemHooks.Types: instance GHC.Show.Show a => GHC.Show.Show (GitLab.SystemHooks.Types.MergeRequestChange a)
+ GitLab.Types: [debugSystemHooks] :: GitLabServerConfig -> Bool
- GitLab.API.Groups: addAllUsersToGroup :: Text -> AccessLevel -> GitLab [Either Status Member]
+ GitLab.API.Groups: addAllUsersToGroup :: Text -> AccessLevel -> GitLab [Either Status (Maybe Member)]
- GitLab.API.Groups: addUserToGroup :: Text -> AccessLevel -> User -> GitLab (Either Status Member)
+ GitLab.API.Groups: addUserToGroup :: Text -> AccessLevel -> User -> GitLab (Either Status (Maybe Member))
- GitLab.API.Groups: addUserToGroup' :: Text -> AccessLevel -> Int -> GitLab (Either Status Member)
+ GitLab.API.Groups: addUserToGroup' :: Text -> AccessLevel -> Int -> GitLab (Either Status (Maybe Member))
- GitLab.API.Groups: addUsersToGroup :: Text -> AccessLevel -> [User] -> GitLab [Either Status Member]
+ GitLab.API.Groups: addUsersToGroup :: Text -> AccessLevel -> [User] -> GitLab [Either Status (Maybe Member)]
- GitLab.API.Groups: addUsersToGroup' :: Text -> AccessLevel -> [Text] -> GitLab [Either Status Member]
+ GitLab.API.Groups: addUsersToGroup' :: Text -> AccessLevel -> [Text] -> GitLab [Either Status (Maybe Member)]
- GitLab.API.Issues: newIssue :: Project -> Text -> Text -> GitLab (Either Status Issue)
+ GitLab.API.Issues: newIssue :: Project -> Text -> Text -> GitLab (Either Status (Maybe Issue))
- GitLab.API.Issues: newIssue' :: Int -> Text -> Text -> GitLab (Either Status Issue)
+ GitLab.API.Issues: newIssue' :: Int -> Text -> Text -> GitLab (Either Status (Maybe Issue))
- GitLab.API.Members: addMemberToProject :: Project -> AccessLevel -> User -> GitLab (Either Status Member)
+ GitLab.API.Members: addMemberToProject :: Project -> AccessLevel -> User -> GitLab (Either Status (Maybe Member))
- GitLab.API.Members: addMemberToProject' :: Int -> AccessLevel -> Int -> GitLab (Either Status Member)
+ GitLab.API.Members: addMemberToProject' :: Int -> AccessLevel -> Int -> GitLab (Either Status (Maybe Member))
- GitLab.API.Members: addMembersToProject :: Project -> AccessLevel -> [User] -> GitLab [Either Status Member]
+ GitLab.API.Members: addMembersToProject :: Project -> AccessLevel -> [User] -> GitLab [Either Status (Maybe Member)]
- GitLab.API.Members: addMembersToProject' :: Int -> AccessLevel -> [Int] -> GitLab [Either Status Member]
+ GitLab.API.Members: addMembersToProject' :: Int -> AccessLevel -> [Int] -> GitLab [Either Status (Maybe Member)]
- GitLab.API.MergeRequests: acceptMergeRequest :: Project -> Int -> GitLab (Either Status MergeRequest)
+ GitLab.API.MergeRequests: acceptMergeRequest :: Project -> Int -> GitLab (Either Status (Maybe MergeRequest))
- GitLab.API.MergeRequests: acceptMergeRequest' :: Int -> Int -> GitLab (Either Status MergeRequest)
+ GitLab.API.MergeRequests: acceptMergeRequest' :: Int -> Int -> GitLab (Either Status (Maybe MergeRequest))
- GitLab.API.MergeRequests: createMergeRequest :: Project -> Text -> Text -> Int -> Text -> Text -> GitLab (Either Status MergeRequest)
+ GitLab.API.MergeRequests: createMergeRequest :: Project -> Text -> Text -> Int -> Text -> Text -> GitLab (Either Status (Maybe MergeRequest))
- GitLab.API.MergeRequests: createMergeRequest' :: Int -> Text -> Text -> Int -> Text -> Text -> GitLab (Either Status MergeRequest)
+ GitLab.API.MergeRequests: createMergeRequest' :: Int -> Text -> Text -> Int -> Text -> Text -> GitLab (Either Status (Maybe MergeRequest))
- GitLab.SystemHooks.Types: MergeParams :: Text -> MergeParams
+ GitLab.SystemHooks.Types: MergeParams :: Maybe Text -> MergeParams
- GitLab.SystemHooks.Types: MergeRequestEvent :: Text -> UserEvent -> ProjectEvent -> ObjectAttributes -> Maybe Text -> RepositoryEvent -> MergeRequestEvent
+ GitLab.SystemHooks.Types: MergeRequestEvent :: Text -> Text -> UserEvent -> ProjectEvent -> ObjectAttributes -> Maybe [Text] -> MergeRequestChanges -> RepositoryEvent -> MergeRequestEvent
- GitLab.SystemHooks.Types: ObjectAttributes :: Int -> Text -> Text -> Int -> Int -> Int -> Text -> Text -> Text -> Maybe Int -> Text -> Text -> Int -> Int -> Text -> Maybe Int -> Maybe Text -> MergeParams -> Bool -> Maybe Int -> Maybe Text -> Maybe Text -> Maybe Text -> Maybe Int -> Int -> Text -> Int -> Int -> Bool -> Maybe Int -> ProjectEvent -> ProjectEvent -> CommitEvent -> Bool -> Int -> Maybe Int -> Maybe Int -> ObjectAttributes
+ GitLab.SystemHooks.Types: ObjectAttributes :: Int -> Text -> Text -> Int -> Int -> Maybe Int -> Maybe [Int] -> Text -> Text -> Text -> Maybe Int -> Text -> Maybe Int -> Text -> Int -> Int -> Text -> Maybe Int -> Maybe Text -> MergeParams -> Bool -> Maybe Int -> Maybe Text -> Maybe Text -> Maybe Text -> Maybe Int -> Int -> Maybe Text -> Maybe Int -> Maybe Int -> Maybe Bool -> Maybe Int -> ProjectEvent -> ProjectEvent -> CommitEvent -> Bool -> Int -> Maybe Int -> Maybe Int -> Maybe Text -> ObjectAttributes
- GitLab.SystemHooks.Types: [$sel:mergeParams_force_remove_source_branch:MergeParams] :: MergeParams -> Text
+ GitLab.SystemHooks.Types: [$sel:mergeParams_force_remove_source_branch:MergeParams] :: MergeParams -> Maybe Text
- GitLab.SystemHooks.Types: [$sel:mergeRequest_labels:MergeRequestEvent] :: MergeRequestEvent -> Maybe Text
+ GitLab.SystemHooks.Types: [$sel:mergeRequest_labels:MergeRequestEvent] :: MergeRequestEvent -> Maybe [Text]
- GitLab.SystemHooks.Types: [$sel:objectAttributes_assignee_id:ObjectAttributes] :: ObjectAttributes -> Int
+ GitLab.SystemHooks.Types: [$sel:objectAttributes_assignee_id:ObjectAttributes] :: ObjectAttributes -> Maybe Int
- GitLab.SystemHooks.Types: [$sel:objectAttributes_head_pipeline_id:ObjectAttributes] :: ObjectAttributes -> Int
+ GitLab.SystemHooks.Types: [$sel:objectAttributes_head_pipeline_id:ObjectAttributes] :: ObjectAttributes -> Maybe Int
- GitLab.SystemHooks.Types: [$sel:objectAttributes_last_edited_at:ObjectAttributes] :: ObjectAttributes -> Text
+ GitLab.SystemHooks.Types: [$sel:objectAttributes_last_edited_at:ObjectAttributes] :: ObjectAttributes -> Maybe Text
- GitLab.SystemHooks.Types: [$sel:objectAttributes_last_edited_by_id:ObjectAttributes] :: ObjectAttributes -> Int
+ GitLab.SystemHooks.Types: [$sel:objectAttributes_last_edited_by_id:ObjectAttributes] :: ObjectAttributes -> Maybe Int
- GitLab.SystemHooks.Types: [$sel:objectAttributes_ref_fetched:ObjectAttributes] :: ObjectAttributes -> Bool
+ GitLab.SystemHooks.Types: [$sel:objectAttributes_ref_fetched:ObjectAttributes] :: ObjectAttributes -> Maybe Bool
- GitLab.Types: GitLabServerConfig :: Text -> Text -> Int -> Int -> GitLabServerConfig
+ GitLab.Types: GitLabServerConfig :: Text -> Text -> Int -> Int -> Bool -> GitLabServerConfig
- GitLab.Types: Links :: Text -> Text -> Text -> Text -> Text -> Text -> Text -> Links
+ GitLab.Types: Links :: Text -> Maybe Text -> Text -> Text -> Text -> Text -> Text -> Links
- GitLab.Types: [issues] :: Links -> Text
+ GitLab.Types: [issues] :: Links -> Maybe Text

Files

README.md view
@@ -24,10 +24,9 @@ Run all GitLab actions with `runGitLab`:       runGitLab ::-      (MonadUnliftIO m, MonadIO m)        => GitLabServerConfig-       -> GitLab m a-       -> m a+       -> GitLab a+       -> IO a  For example: @@ -40,8 +39,26 @@  Which uses the functions: -    searchUser   :: Text -> GitLab m (Maybe User)-    userProjects :: User -> GitLab m (Maybe [Project])+    searchUser     :: Text -> GitLab (Maybe User)+    userProjects   :: User -> GitLab (Maybe [Project])+    projectCommits :: Project -> GitLab [Commit]++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).++For the complete `gitlab-haskell` API, see the [hackage documentation](https://hackage.haskell.org/package/gitlab-haskell).  The `gitlab-tools` command line tool for bulk GitLab transactions uses this library [link](https://gitlab.com/robstewart57/gitlab-tools).
data/system-hooks/merge-request.json view
@@ -1,114 +1,125 @@-{-  "object_kind": "merge_request",-  "user": {-    "name": "Administrator",-    "username": "root",-    "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon"-  },-  "project": {-    "name": "Example",-    "description": "",-    "web_url": "http://example.com/jsmith/example",-    "avatar_url": null,-    "git_ssh_url": "git@example.com:jsmith/example.git",-    "git_http_url": "http://example.com/jsmith/example.git",-    "namespace": "Jsmith",-    "visibility_level": 0,-    "path_with_namespace": "jsmith/example",-    "default_branch": "master",-    "ci_config_path": "",-    "homepage": "http://example.com/jsmith/example",-    "url": "git@example.com:jsmith/example.git",-    "ssh_url": "git@example.com:jsmith/example.git",-    "http_url": "http://example.com/jsmith/example.git"-  },-  "object_attributes": {-    "id": 90,-    "target_branch": "master",-    "source_branch": "ms-viewport",-    "source_project_id": 14,-    "author_id": 51,-    "assignee_id": 6,-    "title": "MS-Viewport",-    "created_at": "2017-09-20T08:31:45.944Z",-    "updated_at": "2017-09-28T12:23:42.365Z",-    "milestone_id": null,-    "state": "opened",-    "merge_status": "unchecked",-    "target_project_id": 14,-    "iid": 1,-    "description": "",-    "updated_by_id": 1,-    "merge_error": null,-    "merge_params": {-      "force_remove_source_branch": "0"-    },-    "merge_when_pipeline_succeeds": false,-    "merge_user_id": null,-    "merge_commit_sha": null,-    "deleted_at": null,-    "in_progress_merge_commit_sha": null,-    "lock_version": 5,-    "time_estimate": 0,-    "last_edited_at": "2017-09-27T12:43:37.558Z",-    "last_edited_by_id": 1,-    "head_pipeline_id": 61,-    "ref_fetched": true,-    "merge_jid": null,-    "source": {-      "name": "Awesome Project",-      "description": "",-      "web_url": "http://example.com/awesome_space/awesome_project",-      "avatar_url": null,-      "git_ssh_url": "git@example.com:awesome_space/awesome_project.git",-      "git_http_url": "http://example.com/awesome_space/awesome_project.git",-      "namespace": "root",-      "visibility_level": 0,-      "path_with_namespace": "awesome_space/awesome_project",-      "default_branch": "master",-      "ci_config_path": "",-      "homepage": "http://example.com/awesome_space/awesome_project",-      "url": "http://example.com/awesome_space/awesome_project.git",-      "ssh_url": "git@example.com:awesome_space/awesome_project.git",-      "http_url": "http://example.com/awesome_space/awesome_project.git"-    },-    "target": {-      "name": "Awesome Project",-      "description": "Aut reprehenderit ut est.",-      "web_url": "http://example.com/awesome_space/awesome_project",-      "avatar_url": null,-      "git_ssh_url": "git@example.com:awesome_space/awesome_project.git",-      "git_http_url": "http://example.com/awesome_space/awesome_project.git",-      "namespace": "Awesome Space",-      "visibility_level": 0,-      "path_with_namespace": "awesome_space/awesome_project",-      "default_branch": "master",-      "ci_config_path": "",-      "homepage": "http://example.com/awesome_space/awesome_project",-      "url": "http://example.com/awesome_space/awesome_project.git",-      "ssh_url": "git@example.com:awesome_space/awesome_project.git",-      "http_url": "http://example.com/awesome_space/awesome_project.git"-    },-    "last_commit": {-      "id": "ba3e0d8ff79c80d5b0bbb4f3e2e343e0aaa662b7",-      "message": "fixed readme",-      "timestamp": "2017-09-26T16:12:57Z",-      "url": "http://example.com/awesome_space/awesome_project/commits/da1560886d4f094c3e6c9ef40349f7d38b5d27d7",-      "author": {-        "name": "GitLab dev user",-        "email": "gitlabdev@dv6700.(none)"-      }-    },-    "work_in_progress": false,-    "total_time_spent": 0,-    "human_total_time_spent": null,-    "human_time_estimate": null-  },-  "labels": null,-  "repository": {-    "name": "git-gpg-test",-    "url": "git@example.com:awesome_space/awesome_project.git",-    "description": "",-    "homepage": "http://example.com/awesome_space/awesome_project"-  }+{"object_kind":"merge_request",+ "event_type":"merge_request",+  "user":+ {"name":"Rob", "username":"abc123",+  "avatar_url":"",+  "email":""+ },+  "project": {"id":8879,+              "name":"",+              "description":"",+             "web_url":"",+             "avatar_url":null,"git_ssh_url":"",+             "git_http_url":"",+             "namespace":"",+             "visibility_level":0,"path_with_namespace":"",+             "default_branch":"master", "ci_config_path":null,+             "homepage":"",+             "url":"",+             "ssh_url":"",+             "http_url":""+             },+ "object_attributes":{"assignee_id":null,+                      "author_id":5,+                      "created_at":"2020-12-21 22:56:31 UTC",+                      "description":"",+                      "head_pipeline_id":null,+                      "id":1567,+                      "iid":7,+                      "last_edited_at":null,+                      "last_edited_by_id":null,+                      "merge_commit_sha":null,+                      "merge_error":null,+                      "merge_params":{},+                      "merge_status":"unchecked",+                      "merge_user_id":null,+                      "merge_when_pipeline_succeeds":false,+                      "milestone_id":null,+                      "source_branch":"master",+                      "source_project_id":8987,+                      "state_id":1,+                      "target_branch":"master",+                      "target_project_id":8879,+                      "time_estimate":0,+                      "title":"Master",+                      "updated_at":"2020-12-21 22:56:31 UTC",+                      "updated_by_id":null,+                      "url":"",+                      "source":{"id":8987, "name":"",+                                "description":"",+                                "web_url":"",+                                "avatar_url":null,+                                "git_ssh_url":"",+                                "git_http_url":"",+                                "namespace":"Rob", "visibility_level":0,+                                "path_with_namespace":"",+                                "default_branch":"master", "ci_config_path":null,+                                "homepage":"",+                                "url":"",+                                "ssh_url":"",+                                "http_url":""+                               },+                      "target":{"id":8879, "name":"",+                                "description":"",+                                "web_url":"",+                                "avatar_url":null,+                                "git_ssh_url":"",+                                "git_http_url":"",+                                "namespace":"", "visibility_level":0,+                                "path_with_namespace":"",+                                "default_branch":"master", "ci_config_path":null,+                                "homepage":"",+                                "url":"",+                                "ssh_url":"",+                                "http_url":""+                               },+                      "last_commit":{"id":"",+                                     "message":"",+                                     "title":"",+                                     "timestamp":"2020-09-28T16:13:42+01:00",+                                     "url":"",+                                     "author":{+                                        "name":"Rob",+                                        "email":""+                                        }+                                     },+                      "work_in_progress":false,+                      "total_time_spent":0,+                      "human_total_time_spent":null,+                      "human_time_estimate":null,+                      "assignee_ids":[],+                      "state":"opened",+                      "action":"open"+                     },+ "labels":[],+ "changes":{"author_id":+            {"previous":null,+             "current":5+            },+            "created_at":+            {"previous":null,+             "current":"2020-12-21 22:56:31 UTC"+            },+            "description":+            {"previous":null,+             "current":""+            },+            "id":+            {"previous":null,+             "current":1567+            },+            "iid":{"previous":null, "current":7},+            "source_branch":{"previous":null, "current":"master"},+            "source_project_id":{"previous":null, "current":8987},+            "target_branch":{"previous":null, "current":"master"},+            "target_project_id":{"previous":null, "current":8879},+            "title":{"previous":null, "current":"Master"},+            "updated_at":{"previous":null, "current":"2020-12-21 22:56:31 UTC"}+           },+  "repository": { "name":"",+                  "url":"",+                  "description":"",+                  "homepage":""+                }+ }
gitlab-haskell.cabal view
@@ -1,7 +1,7 @@ cabal-version: 2.4 name:           gitlab-haskell category:       Git-version:        0.2.3+version:        0.2.4 synopsis:       A Haskell library for the GitLab web API description:             This Haskell library queries and updates the database of a GitLab instance using the GitLab web API: <https://docs.gitlab.com/ee/api/>@@ -10,10 +10,10 @@             .             Run all GitLab actions with `runGitLab`:             .-            > runGitLab :: (MonadUnliftIO m, MonadIO m)+            > runGitLab ::             >  => GitLabServerConfig -- ^ the GitLab server details-            >  -> GitLab m a         -- ^ the GitLab action-            >  -> m a+            >  -> GitLab a           -- ^ the GitLab action+            >  -> IO a             .             For example:             .@@ -25,8 +25,9 @@             .             Which uses the functions:             .-            > searchUser   :: Text -> GitLab m (Maybe User)-            > userProjects :: User -> GitLab m (Maybe [Project])+            > searchUser   :: Text -> GitLab (Maybe User)+            > userProjects :: User -> GitLab (Maybe [Project])+            > projectCommits :: Project -> GitLab [Commit]             .             This library can also be used to develop rule based GitLab file hooks that react in real time to GitLab events with:             .@@ -75,6 +76,7 @@                 , GitLab.API.RepositoryFiles                 , GitLab.API.Todos                 , GitLab.API.Version+                , GitLab.API.Notes                 , GitLab.SystemHooks.Types                 , GitLab.SystemHooks.GitLabSystemHooks                 , GitLab.SystemHooks.Rules@@ -94,6 +96,8 @@               , unliftio               , unliftio-core               , time+              , temporary+              , unix   default-language: Haskell2010   ghc-options: -Wall                -- the following two for the stan static analysis tool
src/GitLab.hs view
@@ -26,6 +26,7 @@     module GitLab.API.RepositoryFiles,     module GitLab.API.Todos,     module GitLab.API.Version,+    module GitLab.API.Notes,     module GitLab.SystemHooks.GitLabSystemHooks,     module GitLab.SystemHooks.Types,     module GitLab.SystemHooks.Rules,@@ -41,6 +42,7 @@ import GitLab.API.Jobs import GitLab.API.Members import GitLab.API.MergeRequests+import GitLab.API.Notes import GitLab.API.Pipelines import GitLab.API.Projects import GitLab.API.Repositories
src/GitLab/API/Groups.hs view
@@ -49,7 +49,7 @@   Text ->   -- | level of access granted   AccessLevel ->-  GitLab [Either Status Member]+  GitLab [Either Status (Maybe Member)] addAllUsersToGroup groupName access = do   allRegisteredUsers <- allUsers   let allUserIds = map user_username allRegisteredUsers@@ -63,7 +63,7 @@   AccessLevel ->   -- | the user   User ->-  GitLab (Either Status Member)+  GitLab (Either Status (Maybe Member)) addUserToGroup groupName access usr =   addUserToGroup' groupName access (user_id usr) @@ -75,7 +75,7 @@   AccessLevel ->   -- | user ID   Int ->-  GitLab (Either Status Member)+  GitLab (Either Status (Maybe Member)) addUserToGroup' groupName access userId = do   attempt <- groupsWithNameOrPath groupName   case attempt of@@ -103,7 +103,7 @@   AccessLevel ->   -- | list of usernames to be added to the group   [User] ->-  GitLab [Either Status Member]+  GitLab [Either Status (Maybe Member)] addUsersToGroup groupName access =   mapM (addUserToGroup groupName access) @@ -115,7 +115,7 @@   AccessLevel ->   -- | list of usernames to be added to the group   [Text] ->-  GitLab [Either Status Member]+  GitLab [Either Status (Maybe Member)] addUsersToGroup' groupName access usernames = do   users <- catMaybes <$> mapM searchUser usernames   mapM (addUserToGroup' groupName access . user_id) users
src/GitLab/API/Issues.hs view
@@ -63,7 +63,7 @@   Text ->   -- | issue description   Text ->-  GitLab (Either Status Issue)+  GitLab (Either Status (Maybe Issue)) newIssue project =   newIssue' (project_id project) @@ -75,7 +75,7 @@   Text ->   -- | issue description   Text ->-  GitLab (Either Status Issue)+  GitLab (Either Status (Maybe Issue)) newIssue' projectId issueTitle issueDescription =   gitlabPost addr dataBody   where
src/GitLab/API/Members.hs view
@@ -56,7 +56,7 @@   AccessLevel ->   -- | the user   User ->-  GitLab (Either Status Member)+  GitLab (Either Status (Maybe Member)) addMemberToProject project access usr =   addMemberToProject' (project_id project) access (user_id usr) @@ -70,7 +70,7 @@   AccessLevel ->   -- | user ID   Int ->-  GitLab (Either Status Member)+  GitLab (Either Status (Maybe Member)) addMemberToProject' projectId access userId =   gitlabPost addr dataBody   where@@ -90,7 +90,7 @@   AccessLevel ->   -- | users to add to the project   [User] ->-  GitLab [Either Status Member]+  GitLab [Either Status (Maybe Member)] addMembersToProject project access =   mapM (addMemberToProject project access) @@ -104,6 +104,6 @@   AccessLevel ->   -- | IDs of users to add to the project   [Int] ->-  GitLab [Either Status Member]+  GitLab [Either Status (Maybe Member)] addMembersToProject' projectId access =   mapM (addMemberToProject' projectId access)
src/GitLab/API/MergeRequests.hs view
@@ -52,7 +52,7 @@   Text ->   -- | merge request description   Text ->-  GitLab (Either Status MergeRequest)+  GitLab (Either Status (Maybe MergeRequest)) createMergeRequest project =   createMergeRequest' (project_id project) @@ -70,7 +70,7 @@   Text ->   -- | merge request description   Text ->-  GitLab (Either Status MergeRequest)+  GitLab (Either Status (Maybe MergeRequest)) createMergeRequest' projectId sourceBranch targetBranch targetProjectId mrTitle mrDescription =   gitlabPost addr dataBody   where@@ -91,7 +91,7 @@   Project ->   -- | merge request IID   Int ->-  GitLab (Either Status MergeRequest)+  GitLab (Either Status (Maybe MergeRequest)) acceptMergeRequest project =   acceptMergeRequest' (project_id project) @@ -101,7 +101,7 @@   Int ->   -- | merge request IID   Int ->-  GitLab (Either Status MergeRequest)+  GitLab (Either Status (Maybe MergeRequest)) acceptMergeRequest' projectId mergeRequestIid = gitlabPost addr dataBody   where     dataBody :: Text@@ -113,3 +113,27 @@         "/projects/" <> show projectId <> "/merge_requests/"           <> show mergeRequestIid           <> "/merge"++-- | Deletes a merge request. Only for admins and project owners.+deleteMergeRequest ::+  -- | project+  Project ->+  -- | merge request IID+  Int ->+  GitLab (Either Status ())+deleteMergeRequest project =+  deleteMergeRequest' (project_id project)++-- | Deletes a merge request. Only for admins and project owners.+deleteMergeRequest' ::+  -- | project ID+  Int ->+  -- | merge request IID+  Int ->+  GitLab (Either Status ())+deleteMergeRequest' projectId mergeRequestIid = gitlabDelete addr+  where+    addr =+      T.pack $+        "/projects/" <> show projectId <> "/merge_requests/"+          <> show mergeRequestIid
+ src/GitLab/API/Notes.hs view
@@ -0,0 +1,53 @@+{-# LANGUAGE OverloadedStrings #-}++-- |+-- Module      : Notes+-- Description : Notes on issues, snippets, merge requests and epics.+-- Copyright   : (c) Rob Stewart, Heriot-Watt University, 2020+-- License     : BSD3+-- Maintainer  : robstewart57@gmail.com+-- Stability   : stable+module GitLab.API.Notes where++import Data.Text (Text)+import qualified Data.Text as T+import GitLab.Types+import GitLab.WebRequests.GitLabWebCalls+import Network.HTTP.Types.Status++createMergeRequestNote ::+  -- | project+  Project ->+  -- | merge request IID+  Int ->+  -- | the note+  Text ->+  GitLab (Either Status (Maybe ()))+createMergeRequestNote project =+  createMergeRequestNote' (project_id project)++createMergeRequestNote' ::+  -- | project ID+  Int ->+  -- | merge request IID+  Int ->+  -- | the note+  Text ->+  GitLab (Either Status (Maybe ()))+createMergeRequestNote' projectId mergeRequestIID comment =+  gitlabPost addr dataBody+  where+    dataBody :: Text+    dataBody =+      T.pack $+        "id="+          <> show projectId+          <> "&merge_request_iid="+          <> show mergeRequestIID+          <> "&body="+          <> T.unpack comment+    addr =+      T.pack $+        "/projects/" <> show projectId <> "/merge_requests/"+          <> show mergeRequestIID+          <> "/notes"
src/GitLab/API/Projects.hs view
@@ -226,16 +226,16 @@         <> "/diff/"     ) --- | share a project with a group.-shareProjectWithGroup ::+-- | add a group to a project.+addGroupToProject ::   -- | group ID   Int ->   -- | project ID   Int ->   -- | level of access granted   AccessLevel ->-  GitLab (Either Status GroupShare)-shareProjectWithGroup groupId projectId access =+  GitLab (Either Status (Maybe GroupShare))+addGroupToProject groupId projectId access =   gitlabPost addr dataBody   where     dataBody :: Text
src/GitLab/API/Users.hs view
@@ -13,6 +13,7 @@ import Data.List import Data.Maybe import Data.Text (Text)+import qualified Data.Text as T import GitLab.Types import GitLab.WebRequests.GitLabWebCalls @@ -21,6 +22,22 @@ allUsers = do   let path = "/users"   gitlabUnsafe path++-- | searches for a user given a user ID. Returns @Just User@ if the+-- user is found, otherwise @Nothing@.+userId ::+  -- | username to search for+  Int ->+  GitLab (Maybe User)+userId usrId = do+  let path =+        "/users/"+          <> T.pack (show usrId)+  res <- gitlabOne path+  case res of+    Left _err -> return Nothing+    Right Nothing -> return Nothing+    Right (Just user) -> return (Just user)  -- | searches for a user given a username. Returns @Just User@ if the -- user is found, otherwise @Nothing@.
src/GitLab/SystemHooks/GitLabSystemHooks.hs view
@@ -17,11 +17,15 @@   ) where +import qualified Control.Exception as E import Control.Monad import Control.Monad.IO.Class+import Control.Monad.Trans.Reader import Data.Typeable import GitLab.SystemHooks.Types import GitLab.Types+import System.IO.Temp+import System.Posix.Files  -- | Attempts to fire each rule in sequence. Reads the JSON data -- received from the GitLab server from standard input.@@ -34,7 +38,20 @@ -- received from a function argument. receiveString :: String -> [Rule] -> GitLab () receiveString eventContent rules = do+  traceSystemHook eventContent   mapM_ (fire eventContent) rules++traceSystemHook :: String -> GitLab ()+traceSystemHook eventContent = do+  cfg <- serverCfg <$> ask+  liftIO $+    E.catch+      ( when (debugSystemHooks cfg) $ do+          fpath <- writeSystemTempFile "gitlab-system-hook-" eventContent+          void $ setFileMode fpath otherReadMode+      )+      -- runGitLabDbg must have been used, which doesn't define a GitLabServerConfig+      (\(_exception :: E.ErrorCall) -> return ())  orElse :: GitLab Bool -> GitLab Bool -> GitLab Bool orElse f g = do
src/GitLab/SystemHooks/Types.hs view
@@ -46,6 +46,8 @@     CommitAuthorEvent (..),     Visibility (..),     MergeRequestEvent (..),+    MergeRequestChanges (..),+    MergeRequestChange (..),     ObjectAttributes (..),     MergeParams (..),     UserEvent (..),@@ -582,26 +584,51 @@ -- in GitLab.Types. data MergeRequestEvent = MergeRequestEvent   { mergeRequest_object_kind :: Text,+    mergeRequest_event_type :: Text,     mergeRequest_user :: UserEvent,     mergeRequest_project :: ProjectEvent,     mergeRequest_object_attributes :: ObjectAttributes,-    mergeRequest_labels :: Maybe Text,+    mergeRequest_labels :: Maybe [Text],+    mergeRequest_changes :: MergeRequestChanges,     mergeRequest_repository :: RepositoryEvent   }   deriving (Typeable, Show, Eq, Generic) +data MergeRequestChanges = MergeRequestChanges+  { mergeRequestChanges_author_id :: MergeRequestChange Int,+    mergeRequestChanges_created_at :: MergeRequestChange Text,+    mergeRequestChanges_description :: MergeRequestChange Text,+    mergeRequestChanges_id :: MergeRequestChange Int,+    mergeRequestChanges_iid :: MergeRequestChange Int,+    mergeRequestChanges_source_branch :: MergeRequestChange Text,+    mergeRequestChanges_source_project_id :: MergeRequestChange Int,+    mergeRequestChanges_target_branch :: MergeRequestChange Text,+    mergeRequestChanges_target_project_id :: MergeRequestChange Int,+    mergeRequestChanges_title :: MergeRequestChange Text,+    mergeRequestChanges_updated_at :: MergeRequestChange Text+  }+  deriving (Typeable, Show, Eq, Generic)++data MergeRequestChange a = MergeRequestChange+  { mergeRequestChange_previous :: Maybe a,+    mergeRequestChange_current :: Maybe a+  }+  deriving (Typeable, Show, Eq, Generic)+ data ObjectAttributes = ObjectAttributes   { objectAttributes_id :: Int,     objectAttributes_target_branch :: Text,     objectAttributes_source_branch :: Text,     objectAttributes_source_project_id :: Int,     objectAttributes_author_id :: Int,-    objectAttributes_assignee_id :: Int,+    objectAttributes_assignee_id :: Maybe Int,+    objectAttributes_assignee_ids :: Maybe [Int],     objectAttributes_title :: Text,     objectAttributes_created_at :: Text,     objectAttributes_updated_at :: Text,     objectAttributes_milestone_id :: Maybe Int,     objectAttributes_state :: Text,+    objectAttributes_state_id :: Maybe Int,     objectAttributes_merge_status :: Text,     objectAttributes_target_project_id :: Int,     objectAttributes_iid :: Int,@@ -616,10 +643,10 @@     objectAttributes_in_progress_merge_commit_sha :: Maybe Text,     objectAttributes_lock_version :: Maybe Int,     objectAttributes_time_estimate :: Int,-    objectAttributes_last_edited_at :: Text,-    objectAttributes_last_edited_by_id :: Int,-    objectAttributes_head_pipeline_id :: Int,-    objectAttributes_ref_fetched :: Bool,+    objectAttributes_last_edited_at :: Maybe Text,+    objectAttributes_last_edited_by_id :: Maybe Int,+    objectAttributes_head_pipeline_id :: Maybe Int,+    objectAttributes_ref_fetched :: Maybe Bool,     objectAttributes_merge_jid :: Maybe Int,     objectAttributes_source :: ProjectEvent,     objectAttributes_target :: ProjectEvent,@@ -627,12 +654,13 @@     objectAttributes_work_in_progress :: Bool,     objectAttributes_total_time_spent :: Int,     objectAttributes_human_total_time_spent :: Maybe Int,-    objectAttributes_human_time_estimate :: Maybe Int+    objectAttributes_human_time_estimate :: Maybe Int,+    objectAttributes_action :: Maybe Text   }   deriving (Typeable, Show, Eq, Generic)  data MergeParams = MergeParams-  { mergeParams_force_remove_source_branch :: Text+  { mergeParams_force_remove_source_branch :: Maybe Text   }   deriving (Typeable, Show, Eq, Generic) @@ -1185,7 +1213,11 @@ instance FromJSON MergeRequestEvent where   parseJSON =     withObject "MergeRequestEvent" $ \v -> do-      -- Note: it's `event_name` in all other examples.+      -- Note: it's `event_name` in all other examples, but the GitLab+      -- documentation for MergeRequests says `object_kind`.+      --+      -- `object_kind` has been tried.+      --       -- Bug in GitLab system hooks documentation?       isProjectEvent <- v .:? "object_kind"       case isProjectEvent of@@ -1194,10 +1226,12 @@             MergeRequested ->               MergeRequestEvent                 <$> v .: "object_kind"+                <*> v .: "event_type"                 <*> v .: "user"                 <*> v .: "project"                 <*> v .: "object_attributes"                 <*> v .: "labels"+                <*> v .: "changes"                 <*> v .: "repository"             _unexpected -> fail "merge_request parsing failed"         _unexpected -> fail "merge_request parsing failed"@@ -1245,11 +1279,13 @@ bodyNoPrefix "objectAttributes_source_project_id" = "source_project_id" bodyNoPrefix "objectAttributes_author_id" = "author_id" bodyNoPrefix "objectAttributes_assignee_id" = "assignee_id"+bodyNoPrefix "objectAttributes_assignee_ids" = "assignee_ids" bodyNoPrefix "objectAttributes_title" = "title" bodyNoPrefix "objectAttributes_created_at" = "created_at" bodyNoPrefix "objectAttributes_updated_at" = "updated_at" bodyNoPrefix "objectAttributes_milestone_id" = "milestone_id" bodyNoPrefix "objectAttributes_state" = "state"+bodyNoPrefix "objectAttributes_state_id" = "state_id" bodyNoPrefix "objectAttributes_merge_status" = "merge_status" bodyNoPrefix "objectAttributes_target_project_id" = "target_project_id" bodyNoPrefix "objectAttributes_iid" = "iid"@@ -1276,6 +1312,20 @@ bodyNoPrefix "objectAttributes_total_time_spent" = "total_time_spent" bodyNoPrefix "objectAttributes_human_total_time_spent" = "human_total_time_spent" bodyNoPrefix "objectAttributes_human_time_estimate" = "human_time_estimate"+bodyNoPrefix "objectAttributes_action" = "action"+bodyNoPrefix "mergeRequestChanges_author_id" = "author_id"+bodyNoPrefix "mergeRequestChanges_created_at" = "created_at"+bodyNoPrefix "mergeRequestChanges_description" = "description"+bodyNoPrefix "mergeRequestChanges_id" = "id"+bodyNoPrefix "mergeRequestChanges_iid" = "iid"+bodyNoPrefix "mergeRequestChanges_source_branch" = "source_branch"+bodyNoPrefix "mergeRequestChanges_source_project_id" = "source_project_id"+bodyNoPrefix "mergeRequestChanges_target_branch" = "target_branch"+bodyNoPrefix "mergeRequestChanges_target_project_id" = "target_project_id"+bodyNoPrefix "mergeRequestChanges_title" = "title"+bodyNoPrefix "mergeRequestChanges_updated_at" = "updated_at"+bodyNoPrefix "mergeRequestChange_previous" = "previous"+bodyNoPrefix "mergeRequestChange_current" = "current" bodyNoPrefix s = error ("uexpected JSON field prefix: " <> s)  instance FromJSON ProjectEvent where@@ -1335,6 +1385,22 @@       )  instance FromJSON UserEvent where+  parseJSON =+    genericParseJSON+      ( defaultOptions+          { fieldLabelModifier = bodyNoPrefix+          }+      )++instance FromJSON MergeRequestChanges where+  parseJSON =+    genericParseJSON+      ( defaultOptions+          { fieldLabelModifier = bodyNoPrefix+          }+      )++instance (FromJSON a) => FromJSON (MergeRequestChange a) where   parseJSON =     genericParseJSON       ( defaultOptions
src/GitLab/Types.hs view
@@ -81,7 +81,10 @@     -- | milliseconds     timeout :: Int,     -- | how many times to retry a HTTP request before giving up and returning an error.-    retries :: Int+    retries :: Int,+    -- | write system hook events to files in the system temporary+    -- directory.+    debugSystemHooks :: Bool   }  -- | default settings, the 'url' and 'token' values will need to be overwritten.@@ -91,7 +94,8 @@     { url = "https://gitlab.com",       token = "",       timeout = 15000000, -- 15 seconds-      retries = 5+      retries = 5,+      debugSystemHooks = False     }  -- https://docs.gitlab.com/ee/api/repositories.html#get-file-archive@@ -154,7 +158,7 @@ -- | links. data Links = Links   { self :: Text,-    issues :: Text,+    issues :: Maybe Text,     merge_requests :: Text,     repo_branches :: Text,     link_labels :: Text,
src/GitLab/WebRequests/GitLabWebCalls.hs view
@@ -14,6 +14,7 @@     -- gitlabWithAttrsOneUnsafe,     gitlabPost,     gitlabPut,+    gitlabDelete,     gitlabReqText,     gitlabReqByteString,   )@@ -23,6 +24,7 @@ import Control.Monad.IO.Class import Control.Monad.Trans.Reader import Data.Aeson+import qualified Data.ByteString as BS import qualified Data.ByteString.Lazy as BSL import Data.ByteString.Lazy.Char8 as C import Data.Either@@ -49,7 +51,7 @@   Text ->   -- | the data to post   Text ->-  GitLab (Either Status b)+  GitLab (Either Status (Maybe b)) gitlabPost urlPath dataBody = do   cfg <- serverCfg <$> ask   manager <- httpManager <$> ask@@ -67,10 +69,11 @@     then       return         ( case parseBSOne (responseBody resp) of-            Just x -> Right x-            Nothing ->-              Left $-                mkStatus 409 "unable to parse POST response"+            Just x -> Right (Just x)+            Nothing -> Right Nothing+            -- Nothing ->+            --   Left $+            --     mkStatus 409 "unable to parse POST response"         )     else return (Left (responseStatus resp)) @@ -105,6 +108,29 @@               Left $                 mkStatus 409 "unable to parse PUT response"         )+    else return (Left (responseStatus resp))++gitlabDelete ::+  -- | the URL to post to+  Text ->+  GitLab (Either Status ())+gitlabDelete urlPath = do+  cfg <- serverCfg <$> ask+  manager <- httpManager <$> ask+  let url' = url cfg <> "/api/v4" <> urlPath+  let request' = parseRequest_ (T.unpack url')+      request =+        request'+          { method = "DELETE",+            requestHeaders =+              [ ("PRIVATE-TOKEN", T.encodeUtf8 (token cfg)),+                ("content-type", "application/json")+              ],+            requestBody = RequestBodyBS BS.empty+          }+  resp <- liftIO $ tryGitLab 0 request (retries cfg) manager Nothing+  if successStatus (responseStatus resp)+    then return (Right ())     else return (Left (responseStatus resp))  tryGitLab ::
tests/SystemHookTests.hs view
@@ -1108,7 +1108,7 @@   matchIf     "mergeRequest rule-if yes"     ( \event@MergeRequestEvent {} -> do-        return (userEvent_name (mergeRequest_user event) == "Administrator")+        return (userEvent_name (mergeRequest_user event) == "Rob")     )     ( \MergeRequestEvent {} -> do         return ()@@ -1473,9 +1473,11 @@ mergeRequestHaskell =   MergeRequestEvent     { mergeRequest_object_kind = "merge_request",-      mergeRequest_user = UserEvent {userEvent_name = "Administrator", userEvent_username = "root", userEvent_avatar_url = "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon"},-      mergeRequest_project = ProjectEvent {projectEvent_name = "Example", projectEvent_description = "", projectEvent_web_url = "http://example.com/jsmith/example", projectEvent_avatar_url = Nothing, projectEvent_git_ssh_url = "git@example.com:jsmith/example.git", projectEvent_git_http_url = "http://example.com/jsmith/example.git", projectEvent_namespace = "Jsmith", projectEvent_visibility_level = Private, projectEvent_path_with_namespace = "jsmith/example", projectEvent_default_branch = "master", projectEvent_homepage = Just "http://example.com/jsmith/example", projectEvent_url = "git@example.com:jsmith/example.git", projectEvent_ssh_url = "git@example.com:jsmith/example.git", projectEvent_http_url = "http://example.com/jsmith/example.git"},-      mergeRequest_object_attributes = ObjectAttributes {objectAttributes_id = 90, objectAttributes_target_branch = "master", objectAttributes_source_branch = "ms-viewport", objectAttributes_source_project_id = 14, objectAttributes_author_id = 51, objectAttributes_assignee_id = 6, objectAttributes_title = "MS-Viewport", objectAttributes_created_at = "2017-09-20T08:31:45.944Z", objectAttributes_updated_at = "2017-09-28T12:23:42.365Z", objectAttributes_milestone_id = Nothing, objectAttributes_state = "opened", objectAttributes_merge_status = "unchecked", objectAttributes_target_project_id = 14, objectAttributes_iid = 1, objectAttributes_description = "", objectAttributes_updated_by_id = Just 1, objectAttributes_merge_error = Nothing, objectAttributes_merge_params = MergeParams {mergeParams_force_remove_source_branch = "0"}, objectAttributes_merge_when_pipeline_succeeds = False, objectAttributes_merge_user_id = Nothing, objectAttributes_merge_commit_sha = Nothing, objectAttributes_deleted_at = Nothing, objectAttributes_in_progress_merge_commit_sha = Nothing, objectAttributes_lock_version = Just 5, objectAttributes_time_estimate = 0, objectAttributes_last_edited_at = "2017-09-27T12:43:37.558Z", objectAttributes_last_edited_by_id = 1, objectAttributes_head_pipeline_id = 61, objectAttributes_ref_fetched = True, objectAttributes_merge_jid = Nothing, objectAttributes_source = ProjectEvent {projectEvent_name = "Awesome Project", projectEvent_description = "", projectEvent_web_url = "http://example.com/awesome_space/awesome_project", projectEvent_avatar_url = Nothing, projectEvent_git_ssh_url = "git@example.com:awesome_space/awesome_project.git", projectEvent_git_http_url = "http://example.com/awesome_space/awesome_project.git", projectEvent_namespace = "root", projectEvent_visibility_level = Private, projectEvent_path_with_namespace = "awesome_space/awesome_project", projectEvent_default_branch = "master", projectEvent_homepage = Just "http://example.com/awesome_space/awesome_project", projectEvent_url = "http://example.com/awesome_space/awesome_project.git", projectEvent_ssh_url = "git@example.com:awesome_space/awesome_project.git", projectEvent_http_url = "http://example.com/awesome_space/awesome_project.git"}, objectAttributes_target = ProjectEvent {projectEvent_name = "Awesome Project", projectEvent_description = "Aut reprehenderit ut est.", projectEvent_web_url = "http://example.com/awesome_space/awesome_project", projectEvent_avatar_url = Nothing, projectEvent_git_ssh_url = "git@example.com:awesome_space/awesome_project.git", projectEvent_git_http_url = "http://example.com/awesome_space/awesome_project.git", projectEvent_namespace = "Awesome Space", projectEvent_visibility_level = Private, projectEvent_path_with_namespace = "awesome_space/awesome_project", projectEvent_default_branch = "master", projectEvent_homepage = Just "http://example.com/awesome_space/awesome_project", projectEvent_url = "http://example.com/awesome_space/awesome_project.git", projectEvent_ssh_url = "git@example.com:awesome_space/awesome_project.git", projectEvent_http_url = "http://example.com/awesome_space/awesome_project.git"}, objectAttributes_last_commit = CommitEvent {commitEvent_id = "ba3e0d8ff79c80d5b0bbb4f3e2e343e0aaa662b7", commitEvent_message = "fixed readme", commitEvent_timestamp = "2017-09-26T16:12:57Z", commitEvent_url = "http://example.com/awesome_space/awesome_project/commits/da1560886d4f094c3e6c9ef40349f7d38b5d27d7", commitEvent_author = CommitAuthorEvent {commitAuthorEvent_name = "GitLab dev user", commitAuthorEvent_email = "gitlabdev@dv6700.(none)"}}, objectAttributes_work_in_progress = False, objectAttributes_total_time_spent = 0, objectAttributes_human_total_time_spent = Nothing, objectAttributes_human_time_estimate = Nothing},-      mergeRequest_labels = Nothing,-      mergeRequest_repository = RepositoryEvent {repositoryEvent_name = "git-gpg-test", repositoryEvent_url = "git@example.com:awesome_space/awesome_project.git", repositoryEvent_description = "", repositoryEvent_homepage = Just "http://example.com/awesome_space/awesome_project", repositoryEvent_git_http_url = Nothing, repositoryEvent_git_ssh_url = Nothing, repositoryEvent_visibility_level = Nothing}+      mergeRequest_event_type = "merge_request",+      mergeRequest_user = UserEvent {userEvent_name = "Rob", userEvent_username = "abc123", userEvent_avatar_url = ""},+      mergeRequest_project = ProjectEvent {projectEvent_name = "", projectEvent_description = "", projectEvent_web_url = "", projectEvent_avatar_url = Nothing, projectEvent_git_ssh_url = "", projectEvent_git_http_url = "", projectEvent_namespace = "", projectEvent_visibility_level = Private, projectEvent_path_with_namespace = "", projectEvent_default_branch = "master", projectEvent_homepage = Just "", projectEvent_url = "", projectEvent_ssh_url = "", projectEvent_http_url = ""},+      mergeRequest_object_attributes = ObjectAttributes {objectAttributes_id = 1567, objectAttributes_target_branch = "master", objectAttributes_source_branch = "master", objectAttributes_source_project_id = 8987, objectAttributes_author_id = 5, objectAttributes_assignee_id = Nothing, objectAttributes_assignee_ids = Just [], objectAttributes_title = "Master", objectAttributes_created_at = "2020-12-21 22:56:31 UTC", objectAttributes_updated_at = "2020-12-21 22:56:31 UTC", objectAttributes_milestone_id = Nothing, objectAttributes_state = "opened", objectAttributes_state_id = Just 1, objectAttributes_merge_status = "unchecked", objectAttributes_target_project_id = 8879, objectAttributes_iid = 7, objectAttributes_description = "", objectAttributes_updated_by_id = Nothing, objectAttributes_merge_error = Nothing, objectAttributes_merge_params = MergeParams {mergeParams_force_remove_source_branch = Nothing}, objectAttributes_merge_when_pipeline_succeeds = False, objectAttributes_merge_user_id = Nothing, objectAttributes_merge_commit_sha = Nothing, objectAttributes_deleted_at = Nothing, objectAttributes_in_progress_merge_commit_sha = Nothing, objectAttributes_lock_version = Nothing, objectAttributes_time_estimate = 0, objectAttributes_last_edited_at = Nothing, objectAttributes_last_edited_by_id = Nothing, objectAttributes_head_pipeline_id = Nothing, objectAttributes_ref_fetched = Nothing, objectAttributes_merge_jid = Nothing, objectAttributes_source = ProjectEvent {projectEvent_name = "", projectEvent_description = "", projectEvent_web_url = "", projectEvent_avatar_url = Nothing, projectEvent_git_ssh_url = "", projectEvent_git_http_url = "", projectEvent_namespace = "Rob", projectEvent_visibility_level = Private, projectEvent_path_with_namespace = "", projectEvent_default_branch = "master", projectEvent_homepage = Just "", projectEvent_url = "", projectEvent_ssh_url = "", projectEvent_http_url = ""}, objectAttributes_target = ProjectEvent {projectEvent_name = "", projectEvent_description = "", projectEvent_web_url = "", projectEvent_avatar_url = Nothing, projectEvent_git_ssh_url = "", projectEvent_git_http_url = "", projectEvent_namespace = "", projectEvent_visibility_level = Private, projectEvent_path_with_namespace = "", projectEvent_default_branch = "master", projectEvent_homepage = Just "", projectEvent_url = "", projectEvent_ssh_url = "", projectEvent_http_url = ""}, objectAttributes_last_commit = CommitEvent {commitEvent_id = "", commitEvent_message = "", commitEvent_timestamp = "2020-09-28T16:13:42+01:00", commitEvent_url = "", commitEvent_author = CommitAuthorEvent {commitAuthorEvent_name = "Rob", commitAuthorEvent_email = ""}}, objectAttributes_work_in_progress = False, objectAttributes_total_time_spent = 0, objectAttributes_human_total_time_spent = Nothing, objectAttributes_human_time_estimate = Nothing, objectAttributes_action = Just "open"},+      mergeRequest_labels = Just [],+      mergeRequest_changes = MergeRequestChanges {mergeRequestChanges_author_id = MergeRequestChange {mergeRequestChange_previous = Nothing, mergeRequestChange_current = Just 5}, mergeRequestChanges_created_at = MergeRequestChange {mergeRequestChange_previous = Nothing, mergeRequestChange_current = Just "2020-12-21 22:56:31 UTC"}, mergeRequestChanges_description = MergeRequestChange {mergeRequestChange_previous = Nothing, mergeRequestChange_current = Just ""}, mergeRequestChanges_id = MergeRequestChange {mergeRequestChange_previous = Nothing, mergeRequestChange_current = Just 1567}, mergeRequestChanges_iid = MergeRequestChange {mergeRequestChange_previous = Nothing, mergeRequestChange_current = Just 7}, mergeRequestChanges_source_branch = MergeRequestChange {mergeRequestChange_previous = Nothing, mergeRequestChange_current = Just "master"}, mergeRequestChanges_source_project_id = MergeRequestChange {mergeRequestChange_previous = Nothing, mergeRequestChange_current = Just 8987}, mergeRequestChanges_target_branch = MergeRequestChange {mergeRequestChange_previous = Nothing, mergeRequestChange_current = Just "master"}, mergeRequestChanges_target_project_id = MergeRequestChange {mergeRequestChange_previous = Nothing, mergeRequestChange_current = Just 8879}, mergeRequestChanges_title = MergeRequestChange {mergeRequestChange_previous = Nothing, mergeRequestChange_current = Just "Master"}, mergeRequestChanges_updated_at = MergeRequestChange {mergeRequestChange_previous = Nothing, mergeRequestChange_current = Just "2020-12-21 22:56:31 UTC"}},+      mergeRequest_repository = RepositoryEvent {repositoryEvent_name = "", repositoryEvent_url = "", repositoryEvent_description = "", repositoryEvent_homepage = Just "", repositoryEvent_git_http_url = Nothing, repositoryEvent_git_ssh_url = Nothing, repositoryEvent_visibility_level = Nothing}     }