{"action":"created","comment":{"url":"https://api.github.com/repos/badges/shields/pulls/comments/234359763","pull_request_review_id":175995937,"id":234359763,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIzNDM1OTc2Mw==","diff_hunk":"@@ -1,78 +1,82 @@\n 'use strict'\n \n-const queryString = require('query-string')\n-const LegacyService = require('../legacy-service')\n-const { makeBadgeData: getBadgeData } = require('../../lib/badge-data')\n-const { fetchFromSvg } = require('../../lib/svg-badge-parser')\n+const Joi = require('joi')\n const {\n   coveragePercentage: coveragePercentageColor,\n } = require('../../lib/color-formatters')\n+const BaseSvgScrapingService = require('../base-svg-scraping')\n+const { NotFound } = require('../errors')\n \n-module.exports = class CodacyCoverage extends LegacyService {\n+const schema = Joi.object({\n+  message: Joi.alternatives()\n+    .try([Joi.string().regex(/^[0-9]+%$/), Joi.equal('!')])\n+    .required(),\n+}).required()\n+\n+module.exports = class CodacyCoverage extends BaseSvgScrapingService {\n   static get category() {\n     return 'build'\n   }\n \n   static get route() {\n     return {\n-      base: 'codacy',\n+      base: 'codacy/coverage',\n+      format: '(?!grade/)([^/]+)(?:/(.+))?',\n+      capture: ['projectId', 'branch'],\n     }\n   }\n \n   static get examples() {\n     return [\n       {\n         title: 'Codacy coverage',\n-        previewUrl: 'coverage/59d607d0e311408885e418004068ea58',\n+        urlPattern: ':projectId',\n+        staticExample: this.render({ percentage: 90 }),\n+        exampleUrl: '59d607d0e311408885e418004068ea58',\n       },\n       {\n         title: 'Codacy branch coverage',\n-        previewUrl: 'coverage/59d607d0e311408885e418004068ea58/master',\n+        urlPattern: ':projectId/:branch',\n+        staticExample: this.render({ percentage: 90 }),\n+        exampleUrl: '59d607d0e311408885e418004068ea58/master',\n       },\n     ]\n   }\n \n-  static registerLegacyRouteHandler({ camp, cache }) {\n-    camp.route(\n-      /^\\/codacy\\/coverage\\/(?!grade\\/)([^/]+)(?:\\/(.+))?\\.(svg|png|gif|jpg|json)$/,\n-      cache((data, match, sendBadge, request) => {\n-        const projectId = match[1] // eg. e27821fb6289410b8f58338c7e0bc686\n-        const branch = match[2]\n-        const format = match[3]\n+  static get defaultBadgeData() {\n+    return {\n+      label: 'coverage',\n+    }\n+  }\n \n-        const queryParams = {}\n-        if (branch) {\n-          queryParams.branch = branch\n-        }\n-        const query = queryString.stringify(queryParams)\n-        const url = `https://api.codacy.com/project/badge/coverage/${projectId}?${query}`\n-        const badgeData = getBadgeData('coverage', data)\n-        fetchFromSvg(\n-          request,\n-          url,\n-          /text-anchor=\"middle\">([^<>]+)<\\/text>/,\n-          (err, res) => {\n-            if (err != null) {\n-              badgeData.text[1] = 'inaccessible'\n-              sendBadge(format, badgeData)\n-              return\n-            }\n-            try {\n-              const coverage = parseInt(res)\n-              if (Number.isNaN(coverage)) {\n-                badgeData.text[1] = 'unknown'\n-              } else {\n-                badgeData.text[1] = res\n-                badgeData.colorscheme = coveragePercentageColor(coverage)\n-              }\n-              sendBadge(format, badgeData)\n-            } catch (e) {\n-              badgeData.text[1] = 'invalid'\n-              sendBadge(format, badgeData)\n-            }\n-          }\n-        )\n+  static render({ percentage }) {\n+    return {\n+      message: `${percentage}%`,\n+      color: coveragePercentageColor(percentage),\n+    }\n+  }\n+\n+  static transform({ coverageString }) {\n+    return {\n+      percentage: parseFloat(coverageString.replace(/%$/, '')),\n+    }\n+  }\n+\n+  async handle({ projectId, branch }) {\n+    const { message: coverageString } = await this._requestSvg({\n+      schema,\n+      url: `https://api.codacy.com/project/badge/coverage/${encodeURIComponent(\n+        projectId\n+      )}`,\n+      options: { qs: { branch } },\n+      valueMatcher: /text-anchor=\"middle\">([^<>]+)<\\/text>/,\n+    })\n+    if (coverageString === '!') {","path":"services/codacy/codacy-coverage.service.js","position":121,"original_position":121,"commit_id":"82e8d7ad1e7c5ca5c3cce9faf1c10619f0710d7b","original_commit_id":"28210965bdd237dac4d5839e5a5ce91ae06575e0","user":{"login":"paulmelnikow","id":1487036,"node_id":"MDQ6VXNlcjE0ODcwMzY=","avatar_url":"https://avatars2.githubusercontent.com/u/1487036?v=4","gravatar_id":"","url":"https://api.github.com/users/paulmelnikow","html_url":"https://github.com/paulmelnikow","followers_url":"https://api.github.com/users/paulmelnikow/followers","following_url":"https://api.github.com/users/paulmelnikow/following{/other_user}","gists_url":"https://api.github.com/users/paulmelnikow/gists{/gist_id}","starred_url":"https://api.github.com/users/paulmelnikow/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/paulmelnikow/subscriptions","organizations_url":"https://api.github.com/users/paulmelnikow/orgs","repos_url":"https://api.github.com/users/paulmelnikow/repos","events_url":"https://api.github.com/users/paulmelnikow/events{/privacy}","received_events_url":"https://api.github.com/users/paulmelnikow/received_events","type":"User","site_admin":false},"body":"Thanks for digging into that. I'll see if I can't get a separate \"project not found\" test case working here.","created_at":"2018-11-16T21:55:49Z","updated_at":"2018-11-16T21:55:57Z","html_url":"https://github.com/badges/shields/pull/2275#discussion_r234359763","pull_request_url":"https://api.github.com/repos/badges/shields/pulls/2275","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/badges/shields/pulls/comments/234359763"},"html":{"href":"https://github.com/badges/shields/pull/2275#discussion_r234359763"},"pull_request":{"href":"https://api.github.com/repos/badges/shields/pulls/2275"}},"in_reply_to_id":234350088},"pull_request":{"url":"https://api.github.com/repos/badges/shields/pulls/2275","id":228517467,"node_id":"MDExOlB1bGxSZXF1ZXN0MjI4NTE3NDY3","html_url":"https://github.com/badges/shields/pull/2275","diff_url":"https://github.com/badges/shields/pull/2275.diff","patch_url":"https://github.com/badges/shields/pull/2275.patch","issue_url":"https://api.github.com/repos/badges/shields/issues/2275","number":2275,"state":"open","locked":false,"title":"Rewrite [codacy] badges; rm unused svg helpers","user":{"login":"paulmelnikow","id":1487036,"node_id":"MDQ6VXNlcjE0ODcwMzY=","avatar_url":"https://avatars2.githubusercontent.com/u/1487036?v=4","gravatar_id":"","url":"https://api.github.com/users/paulmelnikow","html_url":"https://github.com/paulmelnikow","followers_url":"https://api.github.com/users/paulmelnikow/followers","following_url":"https://api.github.com/users/paulmelnikow/following{/other_user}","gists_url":"https://api.github.com/users/paulmelnikow/gists{/gist_id}","starred_url":"https://api.github.com/users/paulmelnikow/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/paulmelnikow/subscriptions","organizations_url":"https://api.github.com/users/paulmelnikow/orgs","repos_url":"https://api.github.com/users/paulmelnikow/repos","events_url":"https://api.github.com/users/paulmelnikow/events{/privacy}","received_events_url":"https://api.github.com/users/paulmelnikow/received_events","type":"User","site_admin":false},"body":"","created_at":"2018-11-05T22:47:20Z","updated_at":"2018-11-16T21:55:57Z","closed_at":null,"merged_at":null,"merge_commit_sha":"4e3037f87d364c81507df883aa0d94cc46ddfc85","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[{"id":585616182,"node_id":"MDU6TGFiZWw1ODU2MTYxODI=","url":"https://api.github.com/repos/badges/shields/labels/core","name":"core","color":"c5def5","default":false},{"id":316395868,"node_id":"MDU6TGFiZWwzMTYzOTU4Njg=","url":"https://api.github.com/repos/badges/shields/labels/service-badge","name":"service-badge","color":"fbca04","default":false}],"milestone":null,"commits_url":"https://api.github.com/repos/badges/shields/pulls/2275/commits","review_comments_url":"https://api.github.com/repos/badges/shields/pulls/2275/comments","review_comment_url":"https://api.github.com/repos/badges/shields/pulls/comments{/number}","comments_url":"https://api.github.com/repos/badges/shields/issues/2275/comments","statuses_url":"https://api.github.com/repos/badges/shields/statuses/82e8d7ad1e7c5ca5c3cce9faf1c10619f0710d7b","head":{"label":"badges:rewrite-codacy","ref":"rewrite-codacy","sha":"82e8d7ad1e7c5ca5c3cce9faf1c10619f0710d7b","user":{"login":"badges","id":6254238,"node_id":"MDEyOk9yZ2FuaXphdGlvbjYyNTQyMzg=","avatar_url":"https://avatars2.githubusercontent.com/u/6254238?v=4","gravatar_id":"","url":"https://api.github.com/users/badges","html_url":"https://github.com/badges","followers_url":"https://api.github.com/users/badges/followers","following_url":"https://api.github.com/users/badges/following{/other_user}","gists_url":"https://api.github.com/users/badges/gists{/gist_id}","starred_url":"https://api.github.com/users/badges/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/badges/subscriptions","organizations_url":"https://api.github.com/users/badges/orgs","repos_url":"https://api.github.com/users/badges/repos","events_url":"https://api.github.com/users/badges/events{/privacy}","received_events_url":"https://api.github.com/users/badges/received_events","type":"Organization","site_admin":false},"repo":{"id":7910045,"node_id":"MDEwOlJlcG9zaXRvcnk3OTEwMDQ1","name":"shields","full_name":"badges/shields","private":false,"owner":{"login":"badges","id":6254238,"node_id":"MDEyOk9yZ2FuaXphdGlvbjYyNTQyMzg=","avatar_url":"https://avatars2.githubusercontent.com/u/6254238?v=4","gravatar_id":"","url":"https://api.github.com/users/badges","html_url":"https://github.com/badges","followers_url":"https://api.github.com/users/badges/followers","following_url":"https://api.github.com/users/badges/following{/other_user}","gists_url":"https://api.github.com/users/badges/gists{/gist_id}","starred_url":"https://api.github.com/users/badges/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/badges/subscriptions","organizations_url":"https://api.github.com/users/badges/orgs","repos_url":"https://api.github.com/users/badges/repos","events_url":"https://api.github.com/users/badges/events{/privacy}","received_events_url":"https://api.github.com/users/badges/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/badges/shields","description":"Concise, consistent, and legible badges in SVG and raster format","fork":false,"url":"https://api.github.com/repos/badges/shields","forks_url":"https://api.github.com/repos/badges/shields/forks","keys_url":"https://api.github.com/repos/badges/shields/keys{/key_id}","collaborators_url":"https://api.github.com/repos/badges/shields/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/badges/shields/teams","hooks_url":"https://api.github.com/repos/badges/shields/hooks","issue_events_url":"https://api.github.com/repos/badges/shields/issues/events{/number}","events_url":"https://api.github.com/repos/badges/shields/events","assignees_url":"https://api.github.com/repos/badges/shields/assignees{/user}","branches_url":"https://api.github.com/repos/badges/shields/branches{/branch}","tags_url":"https://api.github.com/repos/badges/shields/tags","blobs_url":"https://api.github.com/repos/badges/shields/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/badges/shields/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/badges/shields/git/refs{/sha}","trees_url":"https://api.github.com/repos/badges/shields/git/trees{/sha}","statuses_url":"https://api.github.com/repos/badges/shields/statuses/{sha}","languages_url":"https://api.github.com/repos/badges/shields/languages","stargazers_url":"https://api.github.com/repos/badges/shields/stargazers","contributors_url":"https://api.github.com/repos/badges/shields/contributors","subscribers_url":"https://api.github.com/repos/badges/shields/subscribers","subscription_url":"https://api.github.com/repos/badges/shields/subscription","commits_url":"https://api.github.com/repos/badges/shields/commits{/sha}","git_commits_url":"https://api.github.com/repos/badges/shields/git/commits{/sha}","comments_url":"https://api.github.com/repos/badges/shields/comments{/number}","issue_comment_url":"https://api.github.com/repos/badges/shields/issues/comments{/number}","contents_url":"https://api.github.com/repos/badges/shields/contents/{+path}","compare_url":"https://api.github.com/repos/badges/shields/compare/{base}...{head}","merges_url":"https://api.github.com/repos/badges/shields/merges","archive_url":"https://api.github.com/repos/badges/shields/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/badges/shields/downloads","issues_url":"https://api.github.com/repos/badges/shields/issues{/number}","pulls_url":"https://api.github.com/repos/badges/shields/pulls{/number}","milestones_url":"https://api.github.com/repos/badges/shields/milestones{/number}","notifications_url":"https://api.github.com/repos/badges/shields/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/badges/shields/labels{/name}","releases_url":"https://api.github.com/repos/badges/shields/releases{/id}","deployments_url":"https://api.github.com/repos/badges/shields/deployments","created_at":"2013-01-30T07:41:54Z","updated_at":"2018-11-16T21:52:56Z","pushed_at":"2018-11-16T21:53:08Z","git_url":"git://github.com/badges/shields.git","ssh_url":"git@github.com:badges/shields.git","clone_url":"https://github.com/badges/shields.git","svn_url":"https://github.com/badges/shields","homepage":"https://shields.io","size":14583,"stargazers_count":6592,"watchers_count":6592,"language":"JavaScript","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":1510,"mirror_url":null,"archived":false,"open_issues_count":198,"license":{"key":"cc0-1.0","name":"Creative Commons Zero v1.0 Universal","spdx_id":"CC0-1.0","url":"https://api.github.com/licenses/cc0-1.0","node_id":"MDc6TGljZW5zZTY="},"forks":1510,"open_issues":198,"watchers":6592,"default_branch":"master"}},"base":{"label":"badges:master","ref":"master","sha":"6aa45e756bbaaee37a20147b18ab2a4bea3786aa","user":{"login":"badges","id":6254238,"node_id":"MDEyOk9yZ2FuaXphdGlvbjYyNTQyMzg=","avatar_url":"https://avatars2.githubusercontent.com/u/6254238?v=4","gravatar_id":"","url":"https://api.github.com/users/badges","html_url":"https://github.com/badges","followers_url":"https://api.github.com/users/badges/followers","following_url":"https://api.github.com/users/badges/following{/other_user}","gists_url":"https://api.github.com/users/badges/gists{/gist_id}","starred_url":"https://api.github.com/users/badges/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/badges/subscriptions","organizations_url":"https://api.github.com/users/badges/orgs","repos_url":"https://api.github.com/users/badges/repos","events_url":"https://api.github.com/users/badges/events{/privacy}","received_events_url":"https://api.github.com/users/badges/received_events","type":"Organization","site_admin":false},"repo":{"id":7910045,"node_id":"MDEwOlJlcG9zaXRvcnk3OTEwMDQ1","name":"shields","full_name":"badges/shields","private":false,"owner":{"login":"badges","id":6254238,"node_id":"MDEyOk9yZ2FuaXphdGlvbjYyNTQyMzg=","avatar_url":"https://avatars2.githubusercontent.com/u/6254238?v=4","gravatar_id":"","url":"https://api.github.com/users/badges","html_url":"https://github.com/badges","followers_url":"https://api.github.com/users/badges/followers","following_url":"https://api.github.com/users/badges/following{/other_user}","gists_url":"https://api.github.com/users/badges/gists{/gist_id}","starred_url":"https://api.github.com/users/badges/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/badges/subscriptions","organizations_url":"https://api.github.com/users/badges/orgs","repos_url":"https://api.github.com/users/badges/repos","events_url":"https://api.github.com/users/badges/events{/privacy}","received_events_url":"https://api.github.com/users/badges/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/badges/shields","description":"Concise, consistent, and legible badges in SVG and raster format","fork":false,"url":"https://api.github.com/repos/badges/shields","forks_url":"https://api.github.com/repos/badges/shields/forks","keys_url":"https://api.github.com/repos/badges/shields/keys{/key_id}","collaborators_url":"https://api.github.com/repos/badges/shields/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/badges/shields/teams","hooks_url":"https://api.github.com/repos/badges/shields/hooks","issue_events_url":"https://api.github.com/repos/badges/shields/issues/events{/number}","events_url":"https://api.github.com/repos/badges/shields/events","assignees_url":"https://api.github.com/repos/badges/shields/assignees{/user}","branches_url":"https://api.github.com/repos/badges/shields/branches{/branch}","tags_url":"https://api.github.com/repos/badges/shields/tags","blobs_url":"https://api.github.com/repos/badges/shields/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/badges/shields/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/badges/shields/git/refs{/sha}","trees_url":"https://api.github.com/repos/badges/shields/git/trees{/sha}","statuses_url":"https://api.github.com/repos/badges/shields/statuses/{sha}","languages_url":"https://api.github.com/repos/badges/shields/languages","stargazers_url":"https://api.github.com/repos/badges/shields/stargazers","contributors_url":"https://api.github.com/repos/badges/shields/contributors","subscribers_url":"https://api.github.com/repos/badges/shields/subscribers","subscription_url":"https://api.github.com/repos/badges/shields/subscription","commits_url":"https://api.github.com/repos/badges/shields/commits{/sha}","git_commits_url":"https://api.github.com/repos/badges/shields/git/commits{/sha}","comments_url":"https://api.github.com/repos/badges/shields/comments{/number}","issue_comment_url":"https://api.github.com/repos/badges/shields/issues/comments{/number}","contents_url":"https://api.github.com/repos/badges/shields/contents/{+path}","compare_url":"https://api.github.com/repos/badges/shields/compare/{base}...{head}","merges_url":"https://api.github.com/repos/badges/shields/merges","archive_url":"https://api.github.com/repos/badges/shields/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/badges/shields/downloads","issues_url":"https://api.github.com/repos/badges/shields/issues{/number}","pulls_url":"https://api.github.com/repos/badges/shields/pulls{/number}","milestones_url":"https://api.github.com/repos/badges/shields/milestones{/number}","notifications_url":"https://api.github.com/repos/badges/shields/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/badges/shields/labels{/name}","releases_url":"https://api.github.com/repos/badges/shields/releases{/id}","deployments_url":"https://api.github.com/repos/badges/shields/deployments","created_at":"2013-01-30T07:41:54Z","updated_at":"2018-11-16T21:52:56Z","pushed_at":"2018-11-16T21:53:08Z","git_url":"git://github.com/badges/shields.git","ssh_url":"git@github.com:badges/shields.git","clone_url":"https://github.com/badges/shields.git","svn_url":"https://github.com/badges/shields","homepage":"https://shields.io","size":14583,"stargazers_count":6592,"watchers_count":6592,"language":"JavaScript","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":1510,"mirror_url":null,"archived":false,"open_issues_count":198,"license":{"key":"cc0-1.0","name":"Creative Commons Zero v1.0 Universal","spdx_id":"CC0-1.0","url":"https://api.github.com/licenses/cc0-1.0","node_id":"MDc6TGljZW5zZTY="},"forks":1510,"open_issues":198,"watchers":6592,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/badges/shields/pulls/2275"},"html":{"href":"https://github.com/badges/shields/pull/2275"},"issue":{"href":"https://api.github.com/repos/badges/shields/issues/2275"},"comments":{"href":"https://api.github.com/repos/badges/shields/issues/2275/comments"},"review_comments":{"href":"https://api.github.com/repos/badges/shields/pulls/2275/comments"},"review_comment":{"href":"https://api.github.com/repos/badges/shields/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/badges/shields/pulls/2275/commits"},"statuses":{"href":"https://api.github.com/repos/badges/shields/statuses/82e8d7ad1e7c5ca5c3cce9faf1c10619f0710d7b"}},"author_association":"MEMBER"}}
{"actor":{"display_login":"paulmelnikow"}}