{"action":"created","comment":{"url":"https://api.github.com/repos/ansible/ansible/pulls/comments/172022618","pull_request_review_id":100980902,"id":172022618,"diff_hunk":"@@ -0,0 +1,203 @@\n+# This file is part of Ansible\n+#\n+# Ansible is free software: you can redistribute it and/or modify\n+# it under the terms of the GNU General Public License as published by\n+# the Free Software Foundation, either version 3 of the License, or\n+# (at your option) any later version.\n+#\n+# Ansible is distributed in the hope that it will be useful,\n+# but WITHOUT ANY WARRANTY; without even the implied warranty of\n+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n+# GNU General Public License for more details.\n+#\n+# You should have received a copy of the GNU General Public License\n+# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.\n+\n+from __future__ import (absolute_import, division, print_function)\n+__metaclass__ = type\n+\n+DOCUMENTATION = '''\n+    callback: grafana_annotations\n+    type: notification\n+    short_description: Sends events to Grafana HTTP API\n+    description:\n+      - This callback will report start, failed and stats events to Grafana as annotations (https://grafana.com)\n+    version_added: \"2.5\"\n+    requirements:\n+      - whitelisting in configuration\n+    options:\n+      server:\n+        description: Address of the Logstash server\n+        env:\n+          - name: GRAFANA_SERVER\n+        default: localhost\n+      port:\n+        description: Port on which Grafana is listening\n+        env:\n+            - name: GRAFANA_PORT\n+        default: 3000\n+      secure:\n+        description: Boolean specifying if HTTPS should be used. (0=HTTP, 1=HTTPS)\n+        env:\n+          - name: GRAFANA_SECURE\n+        default: 0\n+      token:\n+        description: Grafana API Token, allowing to authenticate when posting on the HTTP API.\n+                     If not provided, the callback will be disabled.\n+        env:\n+          - name: GRAFANA_API_TOKEN\n+'''\n+\n+import os\n+import json\n+import socket\n+import getpass\n+from datetime import datetime\n+\n+try:\n+    import httplib\n+except ImportError:\n+    # Python 3\n+    import http.client as httplib\n+\n+from ansible.plugins.callback import CallbackBase\n+\n+\n+PLAYBOOK_START_TXT = \"\"\"\\\n+Started playbook {playbook}\n+\n+From '{hostname}'\n+By user '{username}'\n+\"\"\"\n+\n+PLAYBOOK_ERROR_TXT = \"\"\"\\\n+Playbook {playbook} Failure !\n+\n+From '{hostname}'\n+By user '{username}'\n+\n+'{task}' failed on {host}\n+\n+debug: {result}\n+\"\"\"\n+\n+PLAYBOOK_STATS_TXT = \"\"\"\\\n+Playbook {playbook}\n+Duration: {duration}\n+Status: {status}\n+\n+From '{hostname}'\n+By user '{username}'\n+\n+Result:\n+{summary}\n+\"\"\"\n+\n+\n+def to_millis(dt):\n+    return int(dt.strftime('%s')) * 1000\n+\n+\n+class CallbackModule(CallbackBase):\n+    \"\"\"\n+    ansible grafana callback plugin\n+    ansible.cfg:\n+        callback_plugins   = <path_to_callback_plugins_folder>\n+        callback_whitelist = grafana\n+    and put the plugin in <path_to_callback_plugins_folder>\n+\n+    This plugin makes use of the following environment variables:\n+        GRAFANA_SERVER   (optional): defaults to localhost\n+        GRAFANA_PORT     (optional): defaults to 3000\n+        GRAFANA_SECURE   (optional): Set to 1 if HTTPs is implemented on Grafana.\n+                                     defaults to 0 (false)\n+        GRAFANA_API_TOKEN          : Grafana API authentication token\n+    \"\"\"\n+\n+    CALLBACK_VERSION = 1.0\n+    CALLBACK_TYPE = 'aggregate'\n+    CALLBACK_NAME = 'grafana'\n+    CALLBACK_NEEDS_WHITELIST = True\n+\n+    def __init__(self):\n+        super(CallbackModule, self).__init__()\n+\n+        token = os.getenv('GRAFANA_API_TOKEN')\n+        self.secure = int(os.getenv('GRAFANA_SECURE', 0))\n+        if self.secure not in [0, 1]:\n+            self.secure = 0\n+        if token is None:\n+            self.disabled = True\n+            self._display.warning(\"GRAFANA_API_TOKEN not defined in the environment\")\n+        self.grafana_server = os.getenv('GRAFANA_SERVER', 'localhost')\n+        self.grafana_port = int(os.getenv('GRAFANA_PORT', 3000))\n+        self.headers = {'Content-Type': 'application/json',\n+                        'Authorization': 'Bearer %s' % token}\n+        self.errors = 0\n+        self.hostname = socket.gethostname()\n+        self.username = getpass.getuser()\n+        self.start_time = datetime.now()\n+\n+    def v2_playbook_on_start(self, playbook):\n+        self.playbook = playbook._file_name\n+        text = PLAYBOOK_START_TXT.format(playbook=self.playbook,\n+                                         hostname=self.hostname, username=self.username)\n+        data = {\n+            'time': to_millis(self.start_time),","path":"lib/ansible/plugins/callback/grafana_annotations.py","position":146,"original_position":146,"commit_id":"0527541cf6980ed372b23f58533cda7c921e8593","original_commit_id":"0527541cf6980ed372b23f58533cda7c921e8593","user":{"login":"rrey","id":2752379,"avatar_url":"https://avatars1.githubusercontent.com/u/2752379?v=4","gravatar_id":"","url":"https://api.github.com/users/rrey","html_url":"https://github.com/rrey","followers_url":"https://api.github.com/users/rrey/followers","following_url":"https://api.github.com/users/rrey/following{/other_user}","gists_url":"https://api.github.com/users/rrey/gists{/gist_id}","starred_url":"https://api.github.com/users/rrey/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rrey/subscriptions","organizations_url":"https://api.github.com/users/rrey/orgs","repos_url":"https://api.github.com/users/rrey/repos","events_url":"https://api.github.com/users/rrey/events{/privacy}","received_events_url":"https://api.github.com/users/rrey/received_events","type":"User","site_admin":false},"body":"I did not put it on purpose because I felt that the annotations needs to be globals to allow one to display them on any dashboard.\r\nBut I can still add the feature allowing to provide a dashboard id.","created_at":"2018-03-03T17:16:27Z","updated_at":"2018-03-03T17:16:27Z","html_url":"https://github.com/ansible/ansible/pull/34246#discussion_r172022618","pull_request_url":"https://api.github.com/repos/ansible/ansible/pulls/34246","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/ansible/ansible/pulls/comments/172022618"},"html":{"href":"https://github.com/ansible/ansible/pull/34246#discussion_r172022618"},"pull_request":{"href":"https://api.github.com/repos/ansible/ansible/pulls/34246"}},"in_reply_to_id":171955725},"pull_request":{"url":"https://api.github.com/repos/ansible/ansible/pulls/34246","id":160157060,"html_url":"https://github.com/ansible/ansible/pull/34246","diff_url":"https://github.com/ansible/ansible/pull/34246.diff","patch_url":"https://github.com/ansible/ansible/pull/34246.patch","issue_url":"https://api.github.com/repos/ansible/ansible/issues/34246","number":34246,"state":"open","locked":false,"title":"Introduce grafana callback plugin.","user":{"login":"rrey","id":2752379,"avatar_url":"https://avatars1.githubusercontent.com/u/2752379?v=4","gravatar_id":"","url":"https://api.github.com/users/rrey","html_url":"https://github.com/rrey","followers_url":"https://api.github.com/users/rrey/followers","following_url":"https://api.github.com/users/rrey/following{/other_user}","gists_url":"https://api.github.com/users/rrey/gists{/gist_id}","starred_url":"https://api.github.com/users/rrey/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rrey/subscriptions","organizations_url":"https://api.github.com/users/rrey/orgs","repos_url":"https://api.github.com/users/rrey/repos","events_url":"https://api.github.com/users/rrey/events{/privacy}","received_events_url":"https://api.github.com/users/rrey/received_events","type":"User","site_admin":false},"body":"##### SUMMARY\r\n\r\nThe grafana plugin plublishes annotations to the HTTP API available in\r\nGrafana 4.6+\r\n\r\nThe callback publishes:\r\n* An annotation on playbook start, tagged with \"ansible\",\r\n \"ansible_event_start\" and playbook name, example:\r\n\r\n```\r\n{\r\n    \"text\": \"Started playbook test.yml\\n\\nFrom 'pc45.home'\\nBy user 'remirey'\\n\",\r\n    \"tags\": [\"ansible\", \"ansible_event_start\", \"test.yml\"],\r\n    \"time\": 1514291163000\r\n}\r\n```\r\n\r\n* An annotation on error containing the host and task who failed and\r\n  tagged with \"ansible\", \"ansible_event_failure\" and playbook name, example:\r\n\r\n```\r\n{\r\n    \"text\": \"Playbook test.yml Failure !\\n\\nFrom 'pc45.home'\\nBy user 'remirey'\\n\\n'TASK: simulate failure' failed on localhost\\n\\ndebug: {\\\"changed\\\": false, \\\"msg\\\": \\\"Some random failure\\\"}\\n\",\r\n    \"tags\": [\"ansible\", \"ansible_event_failure\", \"test.yml\"],\r\n    \"time\": 1514291165000\r\n}\r\n```\r\n\r\n* A region annotation emitted on playbook stats, tagged with \"ansible\",\r\n  \"ansible_report\" and playbook name, example:\r\n\r\n```\r\n{\r\n    \"text\": \"Playbook test.yml\\nDuration: 1.641703\\nStatus: FAILED\\n\\nFrom 'pc45.home'\\nBy user 'remirey'\\n\\nResult:\\n{\\\"localhost\\\": {\\\"unreachable\\\": 0, \\\"skipped\\\": 0, \\\"ok\\\": 2, \\\"changed\\\": 1, \\\"failures\\\": 1}}\\n\",\r\n    \"tags\": [\"ansible\", \"ansible_report\", \"test.yml\"],\r\n    \"isRegion\": true,\r\n    \"timeEnd\": 1514291165000,\r\n    \"time\": 1514291163000\r\n}\r\n```\r\n\r\n##### ISSUE TYPE\r\n\r\n - Feature Pull Request\r\n\r\n##### COMPONENT NAME\r\n\r\nplugins/callback/grafana.py\r\n\r\n##### ANSIBLE VERSION\r\nN/A\r\n\r\n##### ADDITIONAL INFORMATION\r\n\r\nFixes #34225","created_at":"2017-12-26T18:45:02Z","updated_at":"2018-03-03T17:16:27Z","closed_at":null,"merged_at":null,"merge_commit_sha":"7dcc43fd2e9cbb915eb664075f61bacdb2065d14","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[{"id":686214011,"url":"https://api.github.com/repos/ansible/ansible/labels/affects_2.5","name":"affects_2.5","color":"ededed","default":false},{"id":852590921,"url":"https://api.github.com/repos/ansible/ansible/labels/feature","name":"feature","color":"006b75","default":false},{"id":61436281,"url":"https://api.github.com/repos/ansible/ansible/labels/needs_revision","name":"needs_revision","color":"eb6450","default":false},{"id":581543918,"url":"https://api.github.com/repos/ansible/ansible/labels/stale_ci","name":"stale_ci","color":"fef2c0","default":false},{"id":636352796,"url":"https://api.github.com/repos/ansible/ansible/labels/support:core","name":"support:core","color":"ededed","default":false}],"milestone":null,"commits_url":"https://api.github.com/repos/ansible/ansible/pulls/34246/commits","review_comments_url":"https://api.github.com/repos/ansible/ansible/pulls/34246/comments","review_comment_url":"https://api.github.com/repos/ansible/ansible/pulls/comments{/number}","comments_url":"https://api.github.com/repos/ansible/ansible/issues/34246/comments","statuses_url":"https://api.github.com/repos/ansible/ansible/statuses/0527541cf6980ed372b23f58533cda7c921e8593","head":{"label":"rrey:grafana_callback","ref":"grafana_callback","sha":"0527541cf6980ed372b23f58533cda7c921e8593","user":{"login":"rrey","id":2752379,"avatar_url":"https://avatars1.githubusercontent.com/u/2752379?v=4","gravatar_id":"","url":"https://api.github.com/users/rrey","html_url":"https://github.com/rrey","followers_url":"https://api.github.com/users/rrey/followers","following_url":"https://api.github.com/users/rrey/following{/other_user}","gists_url":"https://api.github.com/users/rrey/gists{/gist_id}","starred_url":"https://api.github.com/users/rrey/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rrey/subscriptions","organizations_url":"https://api.github.com/users/rrey/orgs","repos_url":"https://api.github.com/users/rrey/repos","events_url":"https://api.github.com/users/rrey/events{/privacy}","received_events_url":"https://api.github.com/users/rrey/received_events","type":"User","site_admin":false},"repo":{"id":94525925,"name":"ansible","full_name":"rrey/ansible","owner":{"login":"rrey","id":2752379,"avatar_url":"https://avatars1.githubusercontent.com/u/2752379?v=4","gravatar_id":"","url":"https://api.github.com/users/rrey","html_url":"https://github.com/rrey","followers_url":"https://api.github.com/users/rrey/followers","following_url":"https://api.github.com/users/rrey/following{/other_user}","gists_url":"https://api.github.com/users/rrey/gists{/gist_id}","starred_url":"https://api.github.com/users/rrey/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rrey/subscriptions","organizations_url":"https://api.github.com/users/rrey/orgs","repos_url":"https://api.github.com/users/rrey/repos","events_url":"https://api.github.com/users/rrey/events{/privacy}","received_events_url":"https://api.github.com/users/rrey/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/rrey/ansible","description":"Ansible is a radically simple IT automation platform that makes your applications and systems easier to deploy. Avoid writing scripts or custom code to deploy and update your applications— automate in a language that approaches plain English, using SSH, with no agents to install on remote systems.","fork":true,"url":"https://api.github.com/repos/rrey/ansible","forks_url":"https://api.github.com/repos/rrey/ansible/forks","keys_url":"https://api.github.com/repos/rrey/ansible/keys{/key_id}","collaborators_url":"https://api.github.com/repos/rrey/ansible/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/rrey/ansible/teams","hooks_url":"https://api.github.com/repos/rrey/ansible/hooks","issue_events_url":"https://api.github.com/repos/rrey/ansible/issues/events{/number}","events_url":"https://api.github.com/repos/rrey/ansible/events","assignees_url":"https://api.github.com/repos/rrey/ansible/assignees{/user}","branches_url":"https://api.github.com/repos/rrey/ansible/branches{/branch}","tags_url":"https://api.github.com/repos/rrey/ansible/tags","blobs_url":"https://api.github.com/repos/rrey/ansible/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/rrey/ansible/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/rrey/ansible/git/refs{/sha}","trees_url":"https://api.github.com/repos/rrey/ansible/git/trees{/sha}","statuses_url":"https://api.github.com/repos/rrey/ansible/statuses/{sha}","languages_url":"https://api.github.com/repos/rrey/ansible/languages","stargazers_url":"https://api.github.com/repos/rrey/ansible/stargazers","contributors_url":"https://api.github.com/repos/rrey/ansible/contributors","subscribers_url":"https://api.github.com/repos/rrey/ansible/subscribers","subscription_url":"https://api.github.com/repos/rrey/ansible/subscription","commits_url":"https://api.github.com/repos/rrey/ansible/commits{/sha}","git_commits_url":"https://api.github.com/repos/rrey/ansible/git/commits{/sha}","comments_url":"https://api.github.com/repos/rrey/ansible/comments{/number}","issue_comment_url":"https://api.github.com/repos/rrey/ansible/issues/comments{/number}","contents_url":"https://api.github.com/repos/rrey/ansible/contents/{+path}","compare_url":"https://api.github.com/repos/rrey/ansible/compare/{base}...{head}","merges_url":"https://api.github.com/repos/rrey/ansible/merges","archive_url":"https://api.github.com/repos/rrey/ansible/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/rrey/ansible/downloads","issues_url":"https://api.github.com/repos/rrey/ansible/issues{/number}","pulls_url":"https://api.github.com/repos/rrey/ansible/pulls{/number}","milestones_url":"https://api.github.com/repos/rrey/ansible/milestones{/number}","notifications_url":"https://api.github.com/repos/rrey/ansible/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/rrey/ansible/labels{/name}","releases_url":"https://api.github.com/repos/rrey/ansible/releases{/id}","deployments_url":"https://api.github.com/repos/rrey/ansible/deployments","created_at":"2017-06-16T09:01:11Z","updated_at":"2017-06-16T09:01:36Z","pushed_at":"2018-01-18T21:24:16Z","git_url":"git://github.com/rrey/ansible.git","ssh_url":"git@github.com:rrey/ansible.git","clone_url":"https://github.com/rrey/ansible.git","svn_url":"https://github.com/rrey/ansible","homepage":"http://ansible.com/","size":100624,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":null,"forks":0,"open_issues":0,"watchers":0,"default_branch":"devel"}},"base":{"label":"ansible:devel","ref":"devel","sha":"3a4b69096f68cf73ed8fc45cbd4b8be429871170","user":{"login":"ansible","id":1507452,"avatar_url":"https://avatars2.githubusercontent.com/u/1507452?v=4","gravatar_id":"","url":"https://api.github.com/users/ansible","html_url":"https://github.com/ansible","followers_url":"https://api.github.com/users/ansible/followers","following_url":"https://api.github.com/users/ansible/following{/other_user}","gists_url":"https://api.github.com/users/ansible/gists{/gist_id}","starred_url":"https://api.github.com/users/ansible/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ansible/subscriptions","organizations_url":"https://api.github.com/users/ansible/orgs","repos_url":"https://api.github.com/users/ansible/repos","events_url":"https://api.github.com/users/ansible/events{/privacy}","received_events_url":"https://api.github.com/users/ansible/received_events","type":"Organization","site_admin":false},"repo":{"id":3638964,"name":"ansible","full_name":"ansible/ansible","owner":{"login":"ansible","id":1507452,"avatar_url":"https://avatars2.githubusercontent.com/u/1507452?v=4","gravatar_id":"","url":"https://api.github.com/users/ansible","html_url":"https://github.com/ansible","followers_url":"https://api.github.com/users/ansible/followers","following_url":"https://api.github.com/users/ansible/following{/other_user}","gists_url":"https://api.github.com/users/ansible/gists{/gist_id}","starred_url":"https://api.github.com/users/ansible/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ansible/subscriptions","organizations_url":"https://api.github.com/users/ansible/orgs","repos_url":"https://api.github.com/users/ansible/repos","events_url":"https://api.github.com/users/ansible/events{/privacy}","received_events_url":"https://api.github.com/users/ansible/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/ansible/ansible","description":"Ansible is a radically simple IT automation platform that makes your applications and systems easier to deploy. Avoid writing scripts or custom code to deploy and update your applications— automate in a language that approaches plain English, using SSH, with no agents to install on remote systems.","fork":false,"url":"https://api.github.com/repos/ansible/ansible","forks_url":"https://api.github.com/repos/ansible/ansible/forks","keys_url":"https://api.github.com/repos/ansible/ansible/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ansible/ansible/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ansible/ansible/teams","hooks_url":"https://api.github.com/repos/ansible/ansible/hooks","issue_events_url":"https://api.github.com/repos/ansible/ansible/issues/events{/number}","events_url":"https://api.github.com/repos/ansible/ansible/events","assignees_url":"https://api.github.com/repos/ansible/ansible/assignees{/user}","branches_url":"https://api.github.com/repos/ansible/ansible/branches{/branch}","tags_url":"https://api.github.com/repos/ansible/ansible/tags","blobs_url":"https://api.github.com/repos/ansible/ansible/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ansible/ansible/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ansible/ansible/git/refs{/sha}","trees_url":"https://api.github.com/repos/ansible/ansible/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ansible/ansible/statuses/{sha}","languages_url":"https://api.github.com/repos/ansible/ansible/languages","stargazers_url":"https://api.github.com/repos/ansible/ansible/stargazers","contributors_url":"https://api.github.com/repos/ansible/ansible/contributors","subscribers_url":"https://api.github.com/repos/ansible/ansible/subscribers","subscription_url":"https://api.github.com/repos/ansible/ansible/subscription","commits_url":"https://api.github.com/repos/ansible/ansible/commits{/sha}","git_commits_url":"https://api.github.com/repos/ansible/ansible/git/commits{/sha}","comments_url":"https://api.github.com/repos/ansible/ansible/comments{/number}","issue_comment_url":"https://api.github.com/repos/ansible/ansible/issues/comments{/number}","contents_url":"https://api.github.com/repos/ansible/ansible/contents/{+path}","compare_url":"https://api.github.com/repos/ansible/ansible/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ansible/ansible/merges","archive_url":"https://api.github.com/repos/ansible/ansible/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ansible/ansible/downloads","issues_url":"https://api.github.com/repos/ansible/ansible/issues{/number}","pulls_url":"https://api.github.com/repos/ansible/ansible/pulls{/number}","milestones_url":"https://api.github.com/repos/ansible/ansible/milestones{/number}","notifications_url":"https://api.github.com/repos/ansible/ansible/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ansible/ansible/labels{/name}","releases_url":"https://api.github.com/repos/ansible/ansible/releases{/id}","deployments_url":"https://api.github.com/repos/ansible/ansible/deployments","created_at":"2012-03-06T14:58:02Z","updated_at":"2018-03-03T16:05:27Z","pushed_at":"2018-03-03T16:41:00Z","git_url":"git://github.com/ansible/ansible.git","ssh_url":"git@github.com:ansible/ansible.git","clone_url":"https://github.com/ansible/ansible.git","svn_url":"https://github.com/ansible/ansible","homepage":"https://www.ansible.com/","size":120091,"stargazers_count":28752,"watchers_count":28752,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":10389,"mirror_url":null,"archived":false,"open_issues_count":4833,"license":{"key":"gpl-3.0","name":"GNU General Public License v3.0","spdx_id":"GPL-3.0","url":"https://api.github.com/licenses/gpl-3.0"},"forks":10389,"open_issues":4833,"watchers":28752,"default_branch":"devel"}},"_links":{"self":{"href":"https://api.github.com/repos/ansible/ansible/pulls/34246"},"html":{"href":"https://github.com/ansible/ansible/pull/34246"},"issue":{"href":"https://api.github.com/repos/ansible/ansible/issues/34246"},"comments":{"href":"https://api.github.com/repos/ansible/ansible/issues/34246/comments"},"review_comments":{"href":"https://api.github.com/repos/ansible/ansible/pulls/34246/comments"},"review_comment":{"href":"https://api.github.com/repos/ansible/ansible/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/ansible/ansible/pulls/34246/commits"},"statuses":{"href":"https://api.github.com/repos/ansible/ansible/statuses/0527541cf6980ed372b23f58533cda7c921e8593"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"rrey"}}