{"action":"created","comment":{"url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/pulls/comments/194272061","pull_request_review_id":127411599,"id":194272061,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDE5NDI3MjA2MQ==","diff_hunk":"@@ -0,0 +1,229 @@\n+<?php\n+\n+namespace BringYourOwnIdeas\\Maintenance\\Util;\n+\n+use BringYourOwnIdeas\\Maintenance\\Model\\Package;\n+use GuzzleHttp\\Client;\n+use GuzzleHttp\\Exception\\GuzzleException;\n+use GuzzleHttp\\Psr7\\Request;\n+use GuzzleHttp\\Psr7\\Response;\n+use Psr\\SimpleCache\\CacheInterface;\n+use RuntimeException;\n+use SilverStripe\\Core\\Convert;\n+use SilverStripe\\Core\\Extensible;\n+use SilverStripe\\Core\\Injector\\Injector;\n+\n+/**\n+ * Handles fetching supported addon details from addons.silverstripe.org\n+ */\n+abstract class ApiLoader\n+{\n+    use Extensible;\n+\n+    private static $dependencies = [\n+        'GuzzleClient' => '%$GuzzleHttp\\Client',\n+    ];\n+\n+    /**\n+     * @var Client\n+     */\n+    protected $guzzleClient;\n+\n+    /**\n+     * @var CacheInterface\n+     */\n+    protected $cache;\n+\n+    /**\n+     * Define a unique cache key for results to be saved for each request (subclass)\n+     *\n+     * @return string\n+     */\n+    abstract protected function getCacheKey();\n+\n+    /**\n+     * Perform an HTTP request for module health information\n+     *\n+     * @param string $endpoint API endpoint to check for results\n+     * @param callable $callback Function to return the result of after loading the API data\n+     * @return array\n+     * @throws RuntimeException When the API responds with something that's not module health information\n+     */\n+    public function doRequest($endpoint, callable $callback)\n+    {\n+        // Check for a cached value and return if one is available\n+        if ($result = $this->getFromCache()) {\n+            return $result;\n+        }\n+\n+        // Otherwise go and request data from the API\n+        $request = new Request('GET', $endpoint);\n+        $failureMessage = 'Could not obtain information about module. ';\n+\n+        try {\n+            /** @var Response $response */\n+            $response = $this->getGuzzleClient()->send($request, ['http_errors' => false]);\n+        } catch (GuzzleException $exception) {\n+            throw new RuntimeException($failureMessage);\n+        }\n+\n+        if ($response->getStatusCode() !== 200) {\n+            throw new RuntimeException($failureMessage . 'Error code ' . $response->getStatusCode());\n+        }\n+\n+        if (!in_array('application/json', $response->getHeader('Content-Type'))) {\n+            throw new RuntimeException($failureMessage . 'Response is not JSON');\n+        }\n+\n+        $responseBody = Convert::json2array($response->getBody()->getContents());\n+\n+        if (empty($responseBody)) {\n+            throw new RuntimeException($failureMessage . 'Response could not be parsed');\n+        }\n+\n+        if (!isset($responseBody['success']) || !$responseBody['success']) {\n+            throw new RuntimeException($failureMessage . 'Response returned unsuccessfully');\n+        }\n+\n+        // Allow callback to handle processing of the response body\n+        $result = $callback($responseBody);\n+\n+        // Setting the value to the cache for subsequent requests\n+        $this->handleCacheFromResponse($response, $result);\n+\n+        return $result;\n+    }\n+\n+    /**\n+     * @return Client\n+     */\n+    public function getGuzzleClient()\n+    {\n+        return $this->guzzleClient;\n+    }\n+\n+    /**\n+     * @param Client $guzzleClient\n+     * @return $this\n+     */\n+    public function setGuzzleClient(Client $guzzleClient)\n+    {\n+        $this->guzzleClient = $guzzleClient;\n+        return $this;\n+    }\n+\n+    /**\n+     * Attempts to load something from the cache and deserializes from JSON if successful\n+     *\n+     * @return array|bool\n+     * @throws \\Psr\\SimpleCache\\InvalidArgumentException\n+     */\n+    protected function getFromCache()\n+    {\n+        $cacheKey = $this->getCacheKey();\n+        $result = $this->getCache()->get($cacheKey, false);\n+        if ($result === false) {\n+            return false;\n+        }\n+\n+        // Deserialize JSON object and return as an array\n+        return Convert::json2array($result);\n+    }\n+\n+    /**\n+     * Given a value, set it to the cache with the given key after serializing the value as JSON\n+     *\n+     * @param string $cacheKey\n+     * @param mixed $value\n+     * @param int $ttl\n+     * @return bool\n+     * @throws \\Psr\\SimpleCache\\InvalidArgumentException\n+     */\n+    protected function setToCache($cacheKey, $value, $ttl = null)\n+    {\n+        // Seralize as JSON to ensure array etc can be stored\n+        $value = Convert::raw2json($value);\n+\n+        return $this->getCache()->set($cacheKey, $value, $ttl);\n+    }\n+\n+    /**\n+     * Check the API response for cache control headers and respect them internally in the SilverStripe\n+     * cache if found\n+     *\n+     * @param Response $response\n+     * @param array|string $result\n+     * @throws \\Psr\\SimpleCache\\InvalidArgumentException\n+     */\n+    protected function handleCacheFromResponse(Response $response, $result)\n+    {\n+        // Handle caching if requested\n+        if ($cacheControl = $response->getHeader('Cache-Control')) {\n+            // Combine separate header rows\n+            $cacheControl = implode(', ', $cacheControl);\n+\n+            if (strpos($cacheControl, 'no-store') === false\n+                && preg_match('/(?:max-age=)(\\d+)/i', $cacheControl, $matches)\n+            ) {\n+                $duration = (int) $matches[1];\n+\n+                $cacheKey = $this->getCacheKey();\n+                $this->setToCache($cacheKey, $result, $duration);\n+            }\n+        }\n+    }\n+\n+    /**\n+     * @return CacheInterface\n+     */\n+    public function getCache()\n+    {\n+        if (!$this->cache) {\n+            $this->cache = Injector::inst()->get(CacheInterface::class . '.supportedAddons');","path":"src/Util/ApiLoader.php","position":null,"original_position":182,"commit_id":"9f4b130c53c2043af73625b88b22c9e690b8e77f","original_commit_id":"b698be6e692e832ddc1957bea2d5c023b7928f94","user":{"login":"robbieaverill","id":5170590,"node_id":"MDQ6VXNlcjUxNzA1OTA=","avatar_url":"https://avatars1.githubusercontent.com/u/5170590?v=4","gravatar_id":"","url":"https://api.github.com/users/robbieaverill","html_url":"https://github.com/robbieaverill","followers_url":"https://api.github.com/users/robbieaverill/followers","following_url":"https://api.github.com/users/robbieaverill/following{/other_user}","gists_url":"https://api.github.com/users/robbieaverill/gists{/gist_id}","starred_url":"https://api.github.com/users/robbieaverill/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/robbieaverill/subscriptions","organizations_url":"https://api.github.com/users/robbieaverill/orgs","repos_url":"https://api.github.com/users/robbieaverill/repos","events_url":"https://api.github.com/users/robbieaverill/events{/privacy}","received_events_url":"https://api.github.com/users/robbieaverill/received_events","type":"User","site_admin":false},"body":"Yep! Updated","created_at":"2018-06-10T22:11:45Z","updated_at":"2018-06-10T22:11:45Z","html_url":"https://github.com/bringyourownideas/silverstripe-maintenance/pull/105#discussion_r194272061","pull_request_url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/pulls/105","author_association":"COLLABORATOR","_links":{"self":{"href":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/pulls/comments/194272061"},"html":{"href":"https://github.com/bringyourownideas/silverstripe-maintenance/pull/105#discussion_r194272061"},"pull_request":{"href":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/pulls/105"}},"in_reply_to_id":194270605},"pull_request":{"url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/pulls/105","id":193751435,"node_id":"MDExOlB1bGxSZXF1ZXN0MTkzNzUxNDM1","html_url":"https://github.com/bringyourownideas/silverstripe-maintenance/pull/105","diff_url":"https://github.com/bringyourownideas/silverstripe-maintenance/pull/105.diff","patch_url":"https://github.com/bringyourownideas/silverstripe-maintenance/pull/105.patch","issue_url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/issues/105","number":105,"state":"open","locked":false,"title":"Add module health indicator to popover","user":{"login":"raissanorth","id":14869519,"node_id":"MDQ6VXNlcjE0ODY5NTE5","avatar_url":"https://avatars3.githubusercontent.com/u/14869519?v=4","gravatar_id":"","url":"https://api.github.com/users/raissanorth","html_url":"https://github.com/raissanorth","followers_url":"https://api.github.com/users/raissanorth/followers","following_url":"https://api.github.com/users/raissanorth/following{/other_user}","gists_url":"https://api.github.com/users/raissanorth/gists{/gist_id}","starred_url":"https://api.github.com/users/raissanorth/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/raissanorth/subscriptions","organizations_url":"https://api.github.com/users/raissanorth/orgs","repos_url":"https://api.github.com/users/raissanorth/repos","events_url":"https://api.github.com/users/raissanorth/events{/privacy}","received_events_url":"https://api.github.com/users/raissanorth/received_events","type":"User","site_admin":false},"body":"This PR adds a health indicator to the popover for each module listed. It also ...\r\n\r\n- ... writes the rating data to the database.\r\n- ... refactors the loaders. ApiLoader is the base class - holding most of the logic - which SupportedAddonsLoader and the new ModuleHealthLoader extend from.\r\n- Tests were updated were necessary. As most of the logic resides in the ApiLoader, unit tests focus on this class. A few integration tests were added.\r\n- The rating data itself is retrieved from the new Addons API point introduced in https://github.com/silverstripe/addons.silverstripe.org/commit/67fbac68e936926ebf68a11483baa5136248a201\r\n- The module health indicator symbol is rendered as a diff; applied styling follows the BEM methodology\r\n- The module health information links out to the correlated section on addons.org, e.g. to https://addons.silverstripe.org/add-ons/bringyourownideas/silverstripe-maintenance#rating-breakdown\r\n\r\n\r\n![image](https://user-images.githubusercontent.com/14869519/41186180-292b0e70-6be6-11e8-9725-369849f940ba.png)\r\n*Module health rating above 70%*\r\n\r\n\r\n![image](https://user-images.githubusercontent.com/14869519/41186178-24d4da4a-6be6-11e8-9be4-cf2306c1114e.png)\r\n*Module health rating between 40% and 70%*\r\n\r\n![image](https://user-images.githubusercontent.com/14869519/41186177-2010cc1c-6be6-11e8-9ad1-bb33ae710ef5.png)\r\n*Module health rating below 40%*\r\n\r\n\r\nResolves #41","created_at":"2018-06-09T01:17:11Z","updated_at":"2018-06-10T22:11:45Z","closed_at":null,"merged_at":null,"merge_commit_sha":"dbc13a7621b5d47253ef671eabfbf13b17b483df","assignee":{"login":"robbieaverill","id":5170590,"node_id":"MDQ6VXNlcjUxNzA1OTA=","avatar_url":"https://avatars1.githubusercontent.com/u/5170590?v=4","gravatar_id":"","url":"https://api.github.com/users/robbieaverill","html_url":"https://github.com/robbieaverill","followers_url":"https://api.github.com/users/robbieaverill/followers","following_url":"https://api.github.com/users/robbieaverill/following{/other_user}","gists_url":"https://api.github.com/users/robbieaverill/gists{/gist_id}","starred_url":"https://api.github.com/users/robbieaverill/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/robbieaverill/subscriptions","organizations_url":"https://api.github.com/users/robbieaverill/orgs","repos_url":"https://api.github.com/users/robbieaverill/repos","events_url":"https://api.github.com/users/robbieaverill/events{/privacy}","received_events_url":"https://api.github.com/users/robbieaverill/received_events","type":"User","site_admin":false},"assignees":[{"login":"robbieaverill","id":5170590,"node_id":"MDQ6VXNlcjUxNzA1OTA=","avatar_url":"https://avatars1.githubusercontent.com/u/5170590?v=4","gravatar_id":"","url":"https://api.github.com/users/robbieaverill","html_url":"https://github.com/robbieaverill","followers_url":"https://api.github.com/users/robbieaverill/followers","following_url":"https://api.github.com/users/robbieaverill/following{/other_user}","gists_url":"https://api.github.com/users/robbieaverill/gists{/gist_id}","starred_url":"https://api.github.com/users/robbieaverill/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/robbieaverill/subscriptions","organizations_url":"https://api.github.com/users/robbieaverill/orgs","repos_url":"https://api.github.com/users/robbieaverill/repos","events_url":"https://api.github.com/users/robbieaverill/events{/privacy}","received_events_url":"https://api.github.com/users/robbieaverill/received_events","type":"User","site_admin":false}],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/pulls/105/commits","review_comments_url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/pulls/105/comments","review_comment_url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/pulls/comments{/number}","comments_url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/issues/105/comments","statuses_url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/statuses/9f4b130c53c2043af73625b88b22c9e690b8e77f","head":{"label":"creative-commoners:pulls/2.0/add-health-indicator","ref":"pulls/2.0/add-health-indicator","sha":"9f4b130c53c2043af73625b88b22c9e690b8e77f","user":{"login":"creative-commoners","id":28884460,"node_id":"MDEyOk9yZ2FuaXphdGlvbjI4ODg0NDYw","avatar_url":"https://avatars2.githubusercontent.com/u/28884460?v=4","gravatar_id":"","url":"https://api.github.com/users/creative-commoners","html_url":"https://github.com/creative-commoners","followers_url":"https://api.github.com/users/creative-commoners/followers","following_url":"https://api.github.com/users/creative-commoners/following{/other_user}","gists_url":"https://api.github.com/users/creative-commoners/gists{/gist_id}","starred_url":"https://api.github.com/users/creative-commoners/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/creative-commoners/subscriptions","organizations_url":"https://api.github.com/users/creative-commoners/orgs","repos_url":"https://api.github.com/users/creative-commoners/repos","events_url":"https://api.github.com/users/creative-commoners/events{/privacy}","received_events_url":"https://api.github.com/users/creative-commoners/received_events","type":"Organization","site_admin":false},"repo":{"id":132824151,"node_id":"MDEwOlJlcG9zaXRvcnkxMzI4MjQxNTE=","name":"silverstripe-maintenance","full_name":"creative-commoners/silverstripe-maintenance","owner":{"login":"creative-commoners","id":28884460,"node_id":"MDEyOk9yZ2FuaXphdGlvbjI4ODg0NDYw","avatar_url":"https://avatars2.githubusercontent.com/u/28884460?v=4","gravatar_id":"","url":"https://api.github.com/users/creative-commoners","html_url":"https://github.com/creative-commoners","followers_url":"https://api.github.com/users/creative-commoners/followers","following_url":"https://api.github.com/users/creative-commoners/following{/other_user}","gists_url":"https://api.github.com/users/creative-commoners/gists{/gist_id}","starred_url":"https://api.github.com/users/creative-commoners/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/creative-commoners/subscriptions","organizations_url":"https://api.github.com/users/creative-commoners/orgs","repos_url":"https://api.github.com/users/creative-commoners/repos","events_url":"https://api.github.com/users/creative-commoners/events{/privacy}","received_events_url":"https://api.github.com/users/creative-commoners/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/creative-commoners/silverstripe-maintenance","description":"Helps with the day by day work to run a SilverStripe application or website.","fork":true,"url":"https://api.github.com/repos/creative-commoners/silverstripe-maintenance","forks_url":"https://api.github.com/repos/creative-commoners/silverstripe-maintenance/forks","keys_url":"https://api.github.com/repos/creative-commoners/silverstripe-maintenance/keys{/key_id}","collaborators_url":"https://api.github.com/repos/creative-commoners/silverstripe-maintenance/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/creative-commoners/silverstripe-maintenance/teams","hooks_url":"https://api.github.com/repos/creative-commoners/silverstripe-maintenance/hooks","issue_events_url":"https://api.github.com/repos/creative-commoners/silverstripe-maintenance/issues/events{/number}","events_url":"https://api.github.com/repos/creative-commoners/silverstripe-maintenance/events","assignees_url":"https://api.github.com/repos/creative-commoners/silverstripe-maintenance/assignees{/user}","branches_url":"https://api.github.com/repos/creative-commoners/silverstripe-maintenance/branches{/branch}","tags_url":"https://api.github.com/repos/creative-commoners/silverstripe-maintenance/tags","blobs_url":"https://api.github.com/repos/creative-commoners/silverstripe-maintenance/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/creative-commoners/silverstripe-maintenance/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/creative-commoners/silverstripe-maintenance/git/refs{/sha}","trees_url":"https://api.github.com/repos/creative-commoners/silverstripe-maintenance/git/trees{/sha}","statuses_url":"https://api.github.com/repos/creative-commoners/silverstripe-maintenance/statuses/{sha}","languages_url":"https://api.github.com/repos/creative-commoners/silverstripe-maintenance/languages","stargazers_url":"https://api.github.com/repos/creative-commoners/silverstripe-maintenance/stargazers","contributors_url":"https://api.github.com/repos/creative-commoners/silverstripe-maintenance/contributors","subscribers_url":"https://api.github.com/repos/creative-commoners/silverstripe-maintenance/subscribers","subscription_url":"https://api.github.com/repos/creative-commoners/silverstripe-maintenance/subscription","commits_url":"https://api.github.com/repos/creative-commoners/silverstripe-maintenance/commits{/sha}","git_commits_url":"https://api.github.com/repos/creative-commoners/silverstripe-maintenance/git/commits{/sha}","comments_url":"https://api.github.com/repos/creative-commoners/silverstripe-maintenance/comments{/number}","issue_comment_url":"https://api.github.com/repos/creative-commoners/silverstripe-maintenance/issues/comments{/number}","contents_url":"https://api.github.com/repos/creative-commoners/silverstripe-maintenance/contents/{+path}","compare_url":"https://api.github.com/repos/creative-commoners/silverstripe-maintenance/compare/{base}...{head}","merges_url":"https://api.github.com/repos/creative-commoners/silverstripe-maintenance/merges","archive_url":"https://api.github.com/repos/creative-commoners/silverstripe-maintenance/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/creative-commoners/silverstripe-maintenance/downloads","issues_url":"https://api.github.com/repos/creative-commoners/silverstripe-maintenance/issues{/number}","pulls_url":"https://api.github.com/repos/creative-commoners/silverstripe-maintenance/pulls{/number}","milestones_url":"https://api.github.com/repos/creative-commoners/silverstripe-maintenance/milestones{/number}","notifications_url":"https://api.github.com/repos/creative-commoners/silverstripe-maintenance/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/creative-commoners/silverstripe-maintenance/labels{/name}","releases_url":"https://api.github.com/repos/creative-commoners/silverstripe-maintenance/releases{/id}","deployments_url":"https://api.github.com/repos/creative-commoners/silverstripe-maintenance/deployments","created_at":"2018-05-09T23:42:55Z","updated_at":"2018-05-09T23:42:57Z","pushed_at":"2018-06-10T22:11:32Z","git_url":"git://github.com/creative-commoners/silverstripe-maintenance.git","ssh_url":"git@github.com:creative-commoners/silverstripe-maintenance.git","clone_url":"https://github.com/creative-commoners/silverstripe-maintenance.git","svn_url":"https://github.com/creative-commoners/silverstripe-maintenance","homepage":"","size":402,"stargazers_count":0,"watchers_count":0,"language":"PHP","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":{"key":"bsd-3-clause","name":"BSD 3-Clause \"New\" or \"Revised\" License","spdx_id":"BSD-3-Clause","url":"https://api.github.com/licenses/bsd-3-clause","node_id":"MDc6TGljZW5zZTU="},"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"bringyourownideas:master","ref":"master","sha":"37f6b0e0494b030fa954a728de5bf8254c6b5663","user":{"login":"bringyourownideas","id":14135685,"node_id":"MDEyOk9yZ2FuaXphdGlvbjE0MTM1Njg1","avatar_url":"https://avatars1.githubusercontent.com/u/14135685?v=4","gravatar_id":"","url":"https://api.github.com/users/bringyourownideas","html_url":"https://github.com/bringyourownideas","followers_url":"https://api.github.com/users/bringyourownideas/followers","following_url":"https://api.github.com/users/bringyourownideas/following{/other_user}","gists_url":"https://api.github.com/users/bringyourownideas/gists{/gist_id}","starred_url":"https://api.github.com/users/bringyourownideas/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bringyourownideas/subscriptions","organizations_url":"https://api.github.com/users/bringyourownideas/orgs","repos_url":"https://api.github.com/users/bringyourownideas/repos","events_url":"https://api.github.com/users/bringyourownideas/events{/privacy}","received_events_url":"https://api.github.com/users/bringyourownideas/received_events","type":"Organization","site_admin":false},"repo":{"id":42240917,"node_id":"MDEwOlJlcG9zaXRvcnk0MjI0MDkxNw==","name":"silverstripe-maintenance","full_name":"bringyourownideas/silverstripe-maintenance","owner":{"login":"bringyourownideas","id":14135685,"node_id":"MDEyOk9yZ2FuaXphdGlvbjE0MTM1Njg1","avatar_url":"https://avatars1.githubusercontent.com/u/14135685?v=4","gravatar_id":"","url":"https://api.github.com/users/bringyourownideas","html_url":"https://github.com/bringyourownideas","followers_url":"https://api.github.com/users/bringyourownideas/followers","following_url":"https://api.github.com/users/bringyourownideas/following{/other_user}","gists_url":"https://api.github.com/users/bringyourownideas/gists{/gist_id}","starred_url":"https://api.github.com/users/bringyourownideas/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bringyourownideas/subscriptions","organizations_url":"https://api.github.com/users/bringyourownideas/orgs","repos_url":"https://api.github.com/users/bringyourownideas/repos","events_url":"https://api.github.com/users/bringyourownideas/events{/privacy}","received_events_url":"https://api.github.com/users/bringyourownideas/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/bringyourownideas/silverstripe-maintenance","description":"Helps with the day by day work to run a SilverStripe application or website.","fork":false,"url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance","forks_url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/forks","keys_url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/keys{/key_id}","collaborators_url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/teams","hooks_url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/hooks","issue_events_url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/issues/events{/number}","events_url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/events","assignees_url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/assignees{/user}","branches_url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/branches{/branch}","tags_url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/tags","blobs_url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/git/refs{/sha}","trees_url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/git/trees{/sha}","statuses_url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/statuses/{sha}","languages_url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/languages","stargazers_url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/stargazers","contributors_url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/contributors","subscribers_url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/subscribers","subscription_url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/subscription","commits_url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/commits{/sha}","git_commits_url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/git/commits{/sha}","comments_url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/comments{/number}","issue_comment_url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/issues/comments{/number}","contents_url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/contents/{+path}","compare_url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/compare/{base}...{head}","merges_url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/merges","archive_url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/downloads","issues_url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/issues{/number}","pulls_url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/pulls{/number}","milestones_url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/milestones{/number}","notifications_url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/labels{/name}","releases_url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/releases{/id}","deployments_url":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/deployments","created_at":"2015-09-10T11:37:42Z","updated_at":"2018-06-08T03:44:37Z","pushed_at":"2018-06-10T22:11:33Z","git_url":"git://github.com/bringyourownideas/silverstripe-maintenance.git","ssh_url":"git@github.com:bringyourownideas/silverstripe-maintenance.git","clone_url":"https://github.com/bringyourownideas/silverstripe-maintenance.git","svn_url":"https://github.com/bringyourownideas/silverstripe-maintenance","homepage":"","size":272,"stargazers_count":14,"watchers_count":14,"language":"PHP","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":3,"mirror_url":null,"archived":false,"open_issues_count":9,"license":{"key":"bsd-3-clause","name":"BSD 3-Clause \"New\" or \"Revised\" License","spdx_id":"BSD-3-Clause","url":"https://api.github.com/licenses/bsd-3-clause","node_id":"MDc6TGljZW5zZTU="},"forks":3,"open_issues":9,"watchers":14,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/pulls/105"},"html":{"href":"https://github.com/bringyourownideas/silverstripe-maintenance/pull/105"},"issue":{"href":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/issues/105"},"comments":{"href":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/issues/105/comments"},"review_comments":{"href":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/pulls/105/comments"},"review_comment":{"href":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/pulls/105/commits"},"statuses":{"href":"https://api.github.com/repos/bringyourownideas/silverstripe-maintenance/statuses/9f4b130c53c2043af73625b88b22c9e690b8e77f"}},"author_association":"COLLABORATOR"}}
{"actor":{"display_login":"robbieaverill"}}