{"action":"created","comment":{"url":"https://api.github.com/repos/user-cont/colin/pulls/comments/205038929","pull_request_review_id":140228292,"id":205038929,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIwNTAzODkyOQ==","diff_hunk":"@@ -0,0 +1,287 @@\n+\"\"\"\n+This is a temporary module to support unpriv way of interacting with container images.\n+\n+It will be migrated to conu sooner or later.\n+\"\"\"\n+import json\n+import os\n+import logging\n+import shutil\n+import subprocess\n+from tempfile import mkdtemp\n+\n+from colin.core.exceptions import ColinException\n+\n+\n+logger = logging.getLogger(__name__)\n+\n+\n+def run_and_log(cmd, ostree_repo_path, error_msg, wd=None):\n+    \"\"\" run provided command and log all of its output; set path to ostree repo \"\"\"\n+    logger.debug(\"running command %s\", cmd)\n+    kwargs = {\n+        \"stderr\": subprocess.STDOUT,\n+        \"env\": os.environ.copy(),\n+    }\n+    if ostree_repo_path:\n+        # must not exist, ostree will create it\n+        kwargs[\"env\"][\"ATOMIC_OSTREE_REPO\"] = ostree_repo_path\n+    if wd:\n+        kwargs[\"cwd\"] = wd\n+    try:\n+        out = subprocess.check_output(cmd, **kwargs)\n+    except subprocess.CalledProcessError:\n+        logger.error(error_msg)\n+        raise\n+    else:\n+        if out:\n+            logger.debug(\"output of the command:\")\n+            logger.debug(out)\n+\n+\n+def extract_file_from_tarball(tarball_path, file_path, wd):\n+    \"\"\"\n+    Extract selected file (file_path) from tarball (tarball_path) within a selected\n+    directory (wd).\n+    \"\"\"\n+    tar_cmd = [\"tar\", \"-xf\", tarball_path, file_path]\n+    run_and_log(tar_cmd, None, \"Failed to extract selected tarball.\", wd)\n+\n+\n+class Image(object):\n+    \"\"\" Image representation using skopeo, ostree and atomic tool \"\"\"\n+\n+    def __init__(self, image_name, pull):\n+        \"\"\"\n+        :param image_name: str, name of the image to access\n+        :param pull: bool, pull the image from registry or from local dockerd\n+        \"\"\"\n+        self.image_name = image_name\n+        self.pull = pull\n+        self._tmpdir = None\n+        self._mount_point = None\n+        self._ostree_path = None\n+        self._layers_path = None\n+\n+        self.metadata = None\n+        self._labels = None\n+\n+        self._pull_image()\n+\n+\n+    @property\n+    def tmpdir(self):\n+        \"\"\" Temporary directory holding all the runtime data. \"\"\"\n+        if self._tmpdir is None:\n+            self._tmpdir = mkdtemp(prefix=\"colin-\", dir=\"/var/tmp\")\n+        return self._tmpdir\n+\n+    @property\n+    def ostree_path(self):\n+        \"\"\" ostree repository -- content \"\"\"\n+        if self._ostree_path is None:\n+            self._ostree_path = os.path.join(self.tmpdir, \"ostree-repo\")\n+        return self._ostree_path\n+\n+    @property\n+    def mount_point(self):\n+        \"\"\" ostree checkout -- real filesystem \"\"\"\n+        if self._mount_point is None:\n+            self._mount_point = os.path.join(self.tmpdir, \"checkout\")\n+            os.makedirs(self._mount_point)\n+            self._checkout()\n+        return self._mount_point\n+\n+    @property\n+    def layers_path(self):\n+        \"\"\" Directory with all the layers (docker save). \"\"\"\n+        if self._layers_path is None:\n+            self._layers_path = os.path.join(self.tmpdir, \"layers\")\n+        return self._layers_path\n+\n+    def _pull_image(self):\n+        \"\"\" pull the image using atomic --storage ostree \"\"\"\n+        image_name = ImageName.parse(self.image_name)\n+\n+        if self.pull:\n+            skopeo_source = \"docker://\" + image_name.name\n+            atomic_source = image_name.name\n+        else:\n+            skopeo_source = \"docker-daemon:\" + image_name.name\n+            atomic_source = \"docker:\" + image_name.name\n+\n+        cmd = [\"atomic\", \"pull\", \"--storage\", \"ostree\", atomic_source]\n+        run_and_log(cmd, self.ostree_path,\n+                    \"Failed to pull selected container image. Does it exist?\")\n+\n+        archive_file_name = \"archive.tar\"\n+        archive_path = os.path.join(self.tmpdir, archive_file_name)\n+        skopeo_target = \"docker-archive:\" + archive_path\n+        skopeo_cmd = [\"skopeo\", \"copy\", skopeo_source, skopeo_target]\n+        run_and_log(skopeo_cmd, None,\n+                    \"Failed to create tarball with layers from the selected image\")\n+\n+        manifest_file_name = \"manifest.json\"\n+\n+        # first extract manifest\n+        extract_file_from_tarball(archive_file_name, manifest_file_name, self.tmpdir)\n+        manifest_path = os.path.join(self.tmpdir, manifest_file_name)\n+        with open(manifest_path) as fd:\n+            j = json.load(fd)\n+\n+        # figure out name of the metadata file\n+        metadata_file_name = j[0][\"Config\"]\n+\n+        # then extract the metadata\n+        extract_file_from_tarball(archive_file_name, metadata_file_name, self.tmpdir)\n+        metadata_file_path = os.path.join(self.tmpdir, metadata_file_name)\n+        with open(metadata_file_path) as fd:\n+            self.metadata = json.load(fd)\n+\n+    def _checkout(self):\n+        \"\"\" check out the image filesystem on self.mount_point \"\"\"\n+        cmd = [\"atomic\", \"mount\", \"--storage\", \"ostree\", self.image_name, self.mount_point]\n+        # self.mount_point has to be created by us\n+        run_and_log(cmd, self.ostree_path, \"Failed to mount selected image as an ostree repo.\")\n+\n+    def clean_up(self):\n+        cmd = [\"atomic\", \"unmount\", self.mount_point]\n+        run_and_log(cmd, self.ostree_path, \"Failed to unmount ostree checkout.\")\n+        shutil.rmtree(self.tmpdir)\n+\n+    def cont_path(self, path):\n+        \"\"\"\n+        provide absolute path within the container\n+\n+        :param path: path with container\n+        :return: str\n+        \"\"\"\n+        if path.startswith(\"/\"):\n+            path = path[1:]\n+        p = os.path.join(self.mount_point, path)\n+        logger.debug(\"path = %s\", p)\n+        return p\n+\n+    def read_file(self, file_path):\n+        \"\"\"\n+        read file specified via 'file_path' and return its content - raises an ConuException if\n+        there is an issue accessing the file\n+        :param file_path: str, path to the file to read\n+        :return: str (not bytes), content of the file\n+        \"\"\"\n+        try:\n+            with open(self.cont_path(file_path)) as fd:\n+                return fd.read()\n+        except IOError as ex:\n+            logger.error(\"error while accessing file %s: %r\", file_path, ex)\n+            raise ColinException(\"There was an error while accessing file %s: %r\" % (file_path, ex))\n+\n+    def get_file(self, file_path, mode=\"r\"):\n+        \"\"\"\n+        provide File object specified via 'file_path'\n+        :param file_path: str, path to the file\n+        :param mode: str, mode used when opening the file\n+        :return: File instance\n+        \"\"\"\n+        return open(self.cont_path(file_path), mode=mode)\n+\n+    def file_is_present(self, file_path):\n+        \"\"\"\n+        check if file 'file_path' is present, raises IOError if file_path\n+        is not a file\n+        :param file_path: str, path to the file\n+        :return: True if file exists, False if file does not exist\n+        \"\"\"\n+        p = self.cont_path(file_path)","path":"colin/utils/cont.py","position":195,"original_position":195,"commit_id":"f67855fc900445e49666a75b32369298349600a3","original_commit_id":"f67855fc900445e49666a75b32369298349600a3","user":{"login":"codacy-bot","id":19940114,"node_id":"MDQ6VXNlcjE5OTQwMTE0","avatar_url":"https://avatars1.githubusercontent.com/u/19940114?v=4","gravatar_id":"","url":"https://api.github.com/users/codacy-bot","html_url":"https://github.com/codacy-bot","followers_url":"https://api.github.com/users/codacy-bot/followers","following_url":"https://api.github.com/users/codacy-bot/following{/other_user}","gists_url":"https://api.github.com/users/codacy-bot/gists{/gist_id}","starred_url":"https://api.github.com/users/codacy-bot/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/codacy-bot/subscriptions","organizations_url":"https://api.github.com/users/codacy-bot/orgs","repos_url":"https://api.github.com/users/codacy-bot/repos","events_url":"https://api.github.com/users/codacy-bot/events{/privacy}","received_events_url":"https://api.github.com/users/codacy-bot/received_events","type":"User","site_admin":false},"body":"![Codacy](https://app.codacy.com/assets/images/favicon.png) Issue found: [Variable name \"p\" doesn't conform to snake_case naming style](https://app.codacy.com/app/user-cont/colin/pullRequest?prid=1823877)","created_at":"2018-07-25T09:21:24Z","updated_at":"2018-07-25T09:21:24Z","html_url":"https://github.com/user-cont/colin/pull/151#discussion_r205038929","pull_request_url":"https://api.github.com/repos/user-cont/colin/pulls/151","author_association":"NONE","_links":{"self":{"href":"https://api.github.com/repos/user-cont/colin/pulls/comments/205038929"},"html":{"href":"https://github.com/user-cont/colin/pull/151#discussion_r205038929"},"pull_request":{"href":"https://api.github.com/repos/user-cont/colin/pulls/151"}}},"pull_request":{"url":"https://api.github.com/repos/user-cont/colin/pulls/151","id":197166874,"node_id":"MDExOlB1bGxSZXF1ZXN0MTk3MTY2ODc0","html_url":"https://github.com/user-cont/colin/pull/151","diff_url":"https://github.com/user-cont/colin/pull/151.diff","patch_url":"https://github.com/user-cont/colin/pull/151.patch","issue_url":"https://api.github.com/repos/user-cont/colin/issues/151","number":151,"state":"open","locked":false,"title":"use skopeo+tar to get image labels = no root","user":{"login":"TomasTomecek","id":1662493,"node_id":"MDQ6VXNlcjE2NjI0OTM=","avatar_url":"https://avatars0.githubusercontent.com/u/1662493?v=4","gravatar_id":"","url":"https://api.github.com/users/TomasTomecek","html_url":"https://github.com/TomasTomecek","followers_url":"https://api.github.com/users/TomasTomecek/followers","following_url":"https://api.github.com/users/TomasTomecek/following{/other_user}","gists_url":"https://api.github.com/users/TomasTomecek/gists{/gist_id}","starred_url":"https://api.github.com/users/TomasTomecek/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/TomasTomecek/subscriptions","organizations_url":"https://api.github.com/users/TomasTomecek/orgs","repos_url":"https://api.github.com/users/TomasTomecek/repos","events_url":"https://api.github.com/users/TomasTomecek/events{/privacy}","received_events_url":"https://api.github.com/users/TomasTomecek/received_events","type":"User","site_admin":false},"body":"...is required so it can run in openshift now\r\n\r\n    check images without docker\r\n\r\n    use skopeo+tar to get image labels = no root\r\n\r\n    The code is hideous. The plan is to give this a shot and if it works,\r\n    move the low level code to conu.\r\n\r\n    Also disabling dynamic checks: colin/issues/154\r\n\r\n    They are not being utilized yet anyway.\r\n\r\nFixes #150\r\n\r\nTODO:\r\n * [x] filesystem access via `ATOMIC_OSTREE_REPO=$PWD/c atomic pull --storage ostree registry.access.redhat.com/rhscl/mariadb && atomic mount`\r\n * [x] integration test that this can be run via unpriv user\r\n","created_at":"2018-06-25T16:20:45Z","updated_at":"2018-07-25T09:21:25Z","closed_at":null,"merged_at":null,"merge_commit_sha":"2c9026f105a7f98477368ea96072224e84185b76","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/user-cont/colin/pulls/151/commits","review_comments_url":"https://api.github.com/repos/user-cont/colin/pulls/151/comments","review_comment_url":"https://api.github.com/repos/user-cont/colin/pulls/comments{/number}","comments_url":"https://api.github.com/repos/user-cont/colin/issues/151/comments","statuses_url":"https://api.github.com/repos/user-cont/colin/statuses/f67855fc900445e49666a75b32369298349600a3","head":{"label":"TomasTomecek:fix-150","ref":"fix-150","sha":"f67855fc900445e49666a75b32369298349600a3","user":{"login":"TomasTomecek","id":1662493,"node_id":"MDQ6VXNlcjE2NjI0OTM=","avatar_url":"https://avatars0.githubusercontent.com/u/1662493?v=4","gravatar_id":"","url":"https://api.github.com/users/TomasTomecek","html_url":"https://github.com/TomasTomecek","followers_url":"https://api.github.com/users/TomasTomecek/followers","following_url":"https://api.github.com/users/TomasTomecek/following{/other_user}","gists_url":"https://api.github.com/users/TomasTomecek/gists{/gist_id}","starred_url":"https://api.github.com/users/TomasTomecek/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/TomasTomecek/subscriptions","organizations_url":"https://api.github.com/users/TomasTomecek/orgs","repos_url":"https://api.github.com/users/TomasTomecek/repos","events_url":"https://api.github.com/users/TomasTomecek/events{/privacy}","received_events_url":"https://api.github.com/users/TomasTomecek/received_events","type":"User","site_admin":false},"repo":{"id":126462798,"node_id":"MDEwOlJlcG9zaXRvcnkxMjY0NjI3OTg=","name":"colin","full_name":"TomasTomecek/colin","owner":{"login":"TomasTomecek","id":1662493,"node_id":"MDQ6VXNlcjE2NjI0OTM=","avatar_url":"https://avatars0.githubusercontent.com/u/1662493?v=4","gravatar_id":"","url":"https://api.github.com/users/TomasTomecek","html_url":"https://github.com/TomasTomecek","followers_url":"https://api.github.com/users/TomasTomecek/followers","following_url":"https://api.github.com/users/TomasTomecek/following{/other_user}","gists_url":"https://api.github.com/users/TomasTomecek/gists{/gist_id}","starred_url":"https://api.github.com/users/TomasTomecek/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/TomasTomecek/subscriptions","organizations_url":"https://api.github.com/users/TomasTomecek/orgs","repos_url":"https://api.github.com/users/TomasTomecek/repos","events_url":"https://api.github.com/users/TomasTomecek/events{/privacy}","received_events_url":"https://api.github.com/users/TomasTomecek/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/TomasTomecek/colin","description":"Tool to check generic rules/best-practices for containers/images/dockerfiles.","fork":true,"url":"https://api.github.com/repos/TomasTomecek/colin","forks_url":"https://api.github.com/repos/TomasTomecek/colin/forks","keys_url":"https://api.github.com/repos/TomasTomecek/colin/keys{/key_id}","collaborators_url":"https://api.github.com/repos/TomasTomecek/colin/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/TomasTomecek/colin/teams","hooks_url":"https://api.github.com/repos/TomasTomecek/colin/hooks","issue_events_url":"https://api.github.com/repos/TomasTomecek/colin/issues/events{/number}","events_url":"https://api.github.com/repos/TomasTomecek/colin/events","assignees_url":"https://api.github.com/repos/TomasTomecek/colin/assignees{/user}","branches_url":"https://api.github.com/repos/TomasTomecek/colin/branches{/branch}","tags_url":"https://api.github.com/repos/TomasTomecek/colin/tags","blobs_url":"https://api.github.com/repos/TomasTomecek/colin/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/TomasTomecek/colin/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/TomasTomecek/colin/git/refs{/sha}","trees_url":"https://api.github.com/repos/TomasTomecek/colin/git/trees{/sha}","statuses_url":"https://api.github.com/repos/TomasTomecek/colin/statuses/{sha}","languages_url":"https://api.github.com/repos/TomasTomecek/colin/languages","stargazers_url":"https://api.github.com/repos/TomasTomecek/colin/stargazers","contributors_url":"https://api.github.com/repos/TomasTomecek/colin/contributors","subscribers_url":"https://api.github.com/repos/TomasTomecek/colin/subscribers","subscription_url":"https://api.github.com/repos/TomasTomecek/colin/subscription","commits_url":"https://api.github.com/repos/TomasTomecek/colin/commits{/sha}","git_commits_url":"https://api.github.com/repos/TomasTomecek/colin/git/commits{/sha}","comments_url":"https://api.github.com/repos/TomasTomecek/colin/comments{/number}","issue_comment_url":"https://api.github.com/repos/TomasTomecek/colin/issues/comments{/number}","contents_url":"https://api.github.com/repos/TomasTomecek/colin/contents/{+path}","compare_url":"https://api.github.com/repos/TomasTomecek/colin/compare/{base}...{head}","merges_url":"https://api.github.com/repos/TomasTomecek/colin/merges","archive_url":"https://api.github.com/repos/TomasTomecek/colin/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/TomasTomecek/colin/downloads","issues_url":"https://api.github.com/repos/TomasTomecek/colin/issues{/number}","pulls_url":"https://api.github.com/repos/TomasTomecek/colin/pulls{/number}","milestones_url":"https://api.github.com/repos/TomasTomecek/colin/milestones{/number}","notifications_url":"https://api.github.com/repos/TomasTomecek/colin/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/TomasTomecek/colin/labels{/name}","releases_url":"https://api.github.com/repos/TomasTomecek/colin/releases{/id}","deployments_url":"https://api.github.com/repos/TomasTomecek/colin/deployments","created_at":"2018-03-23T09:29:00Z","updated_at":"2018-03-23T09:29:02Z","pushed_at":"2018-07-25T09:18:25Z","git_url":"git://github.com/TomasTomecek/colin.git","ssh_url":"git@github.com:TomasTomecek/colin.git","clone_url":"https://github.com/TomasTomecek/colin.git","svn_url":"https://github.com/TomasTomecek/colin","homepage":null,"size":5729,"stargazers_count":0,"watchers_count":0,"language":"Python","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":null,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"user-cont:master","ref":"master","sha":"bd8a499c03c722b7e264d5d4b1a8623d6eeae91e","user":{"login":"user-cont","id":35456931,"node_id":"MDEyOk9yZ2FuaXphdGlvbjM1NDU2OTMx","avatar_url":"https://avatars1.githubusercontent.com/u/35456931?v=4","gravatar_id":"","url":"https://api.github.com/users/user-cont","html_url":"https://github.com/user-cont","followers_url":"https://api.github.com/users/user-cont/followers","following_url":"https://api.github.com/users/user-cont/following{/other_user}","gists_url":"https://api.github.com/users/user-cont/gists{/gist_id}","starred_url":"https://api.github.com/users/user-cont/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/user-cont/subscriptions","organizations_url":"https://api.github.com/users/user-cont/orgs","repos_url":"https://api.github.com/users/user-cont/repos","events_url":"https://api.github.com/users/user-cont/events{/privacy}","received_events_url":"https://api.github.com/users/user-cont/received_events","type":"Organization","site_admin":false},"repo":{"id":124359252,"node_id":"MDEwOlJlcG9zaXRvcnkxMjQzNTkyNTI=","name":"colin","full_name":"user-cont/colin","owner":{"login":"user-cont","id":35456931,"node_id":"MDEyOk9yZ2FuaXphdGlvbjM1NDU2OTMx","avatar_url":"https://avatars1.githubusercontent.com/u/35456931?v=4","gravatar_id":"","url":"https://api.github.com/users/user-cont","html_url":"https://github.com/user-cont","followers_url":"https://api.github.com/users/user-cont/followers","following_url":"https://api.github.com/users/user-cont/following{/other_user}","gists_url":"https://api.github.com/users/user-cont/gists{/gist_id}","starred_url":"https://api.github.com/users/user-cont/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/user-cont/subscriptions","organizations_url":"https://api.github.com/users/user-cont/orgs","repos_url":"https://api.github.com/users/user-cont/repos","events_url":"https://api.github.com/users/user-cont/events{/privacy}","received_events_url":"https://api.github.com/users/user-cont/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/user-cont/colin","description":"Tool to check generic rules/best-practices for containers/images/dockerfiles.","fork":false,"url":"https://api.github.com/repos/user-cont/colin","forks_url":"https://api.github.com/repos/user-cont/colin/forks","keys_url":"https://api.github.com/repos/user-cont/colin/keys{/key_id}","collaborators_url":"https://api.github.com/repos/user-cont/colin/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/user-cont/colin/teams","hooks_url":"https://api.github.com/repos/user-cont/colin/hooks","issue_events_url":"https://api.github.com/repos/user-cont/colin/issues/events{/number}","events_url":"https://api.github.com/repos/user-cont/colin/events","assignees_url":"https://api.github.com/repos/user-cont/colin/assignees{/user}","branches_url":"https://api.github.com/repos/user-cont/colin/branches{/branch}","tags_url":"https://api.github.com/repos/user-cont/colin/tags","blobs_url":"https://api.github.com/repos/user-cont/colin/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/user-cont/colin/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/user-cont/colin/git/refs{/sha}","trees_url":"https://api.github.com/repos/user-cont/colin/git/trees{/sha}","statuses_url":"https://api.github.com/repos/user-cont/colin/statuses/{sha}","languages_url":"https://api.github.com/repos/user-cont/colin/languages","stargazers_url":"https://api.github.com/repos/user-cont/colin/stargazers","contributors_url":"https://api.github.com/repos/user-cont/colin/contributors","subscribers_url":"https://api.github.com/repos/user-cont/colin/subscribers","subscription_url":"https://api.github.com/repos/user-cont/colin/subscription","commits_url":"https://api.github.com/repos/user-cont/colin/commits{/sha}","git_commits_url":"https://api.github.com/repos/user-cont/colin/git/commits{/sha}","comments_url":"https://api.github.com/repos/user-cont/colin/comments{/number}","issue_comment_url":"https://api.github.com/repos/user-cont/colin/issues/comments{/number}","contents_url":"https://api.github.com/repos/user-cont/colin/contents/{+path}","compare_url":"https://api.github.com/repos/user-cont/colin/compare/{base}...{head}","merges_url":"https://api.github.com/repos/user-cont/colin/merges","archive_url":"https://api.github.com/repos/user-cont/colin/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/user-cont/colin/downloads","issues_url":"https://api.github.com/repos/user-cont/colin/issues{/number}","pulls_url":"https://api.github.com/repos/user-cont/colin/pulls{/number}","milestones_url":"https://api.github.com/repos/user-cont/colin/milestones{/number}","notifications_url":"https://api.github.com/repos/user-cont/colin/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/user-cont/colin/labels{/name}","releases_url":"https://api.github.com/repos/user-cont/colin/releases{/id}","deployments_url":"https://api.github.com/repos/user-cont/colin/deployments","created_at":"2018-03-08T08:15:35Z","updated_at":"2018-07-25T09:11:16Z","pushed_at":"2018-07-25T09:18:27Z","git_url":"git://github.com/user-cont/colin.git","ssh_url":"git@github.com:user-cont/colin.git","clone_url":"https://github.com/user-cont/colin.git","svn_url":"https://github.com/user-cont/colin","homepage":null,"size":5721,"stargazers_count":9,"watchers_count":9,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":7,"mirror_url":null,"archived":false,"open_issues_count":27,"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","node_id":"MDc6TGljZW5zZTk="},"forks":7,"open_issues":27,"watchers":9,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/user-cont/colin/pulls/151"},"html":{"href":"https://github.com/user-cont/colin/pull/151"},"issue":{"href":"https://api.github.com/repos/user-cont/colin/issues/151"},"comments":{"href":"https://api.github.com/repos/user-cont/colin/issues/151/comments"},"review_comments":{"href":"https://api.github.com/repos/user-cont/colin/pulls/151/comments"},"review_comment":{"href":"https://api.github.com/repos/user-cont/colin/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/user-cont/colin/pulls/151/commits"},"statuses":{"href":"https://api.github.com/repos/user-cont/colin/statuses/f67855fc900445e49666a75b32369298349600a3"}},"author_association":"MEMBER"}}
{"actor":{"display_login":"codacy-bot"}}