{"action":"created","comment":{"url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/pulls/comments/88514055","pull_request_review_id":9083673,"id":88514055,"diff_hunk":"@@ -0,0 +1,281 @@\n+# Copyright 2016 Google Inc.\n+#\n+# Licensed under the Apache License, Version 2.0 (the \"License\");\n+# you may not use this file except in compliance with the License.\n+# You may obtain a copy of the License at\n+#\n+#     http://www.apache.org/licenses/LICENSE-2.0\n+#\n+# Unless required by applicable law or agreed to in writing, software\n+# distributed under the License is distributed on an \"AS IS\" BASIS,\n+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n+# See the License for the specific language governing permissions and\n+# limitations under the License.\n+\n+# Set up the gsutil environment and create buckets and folders that hold\n+# the baseline policies for projects.\n+#\n+# This has been tested with python 2.7.\n+\n+import json\n+import re\n+\n+from distutils.spawn import find_executable\n+from gcloud_env import GcloudEnvironment\n+from subprocess import PIPE, Popen, call\n+\n+class GsutilEnvironment(object):\n+    \"\"\"\n+    A class that encapsulates the environment for gsutil and sets up\n+    the buckets and base policy files.\n+    \"\"\"\n+\n+    DEFAULT_BUCKETNAME_POLICIES = 'gs://{}_policies'\n+    DEFAULT_BUCKETNAME_OUTPUT = 'gs://{}.appspot.com'\n+    GCS_LS_ERROR_REGEX = re.compile('^(.*Exception): (\\d{3})', re.MULTILINE)\n+\n+    def __init__(self, projects_filename=None):\n+        self.gcloud_config = GcloudEnvironment()\n+        self.policy_bucket = None\n+        self.output_bucket = None\n+        self.projects_filename = projects_filename\n+\n+    def __repr__(self):\n+        return ('GsutilEnvironment:\\n'\n+                '  {}\\n'\n+                '  Policy bucket: {}\\n'\n+                '  Output bucket: {}\\n'\n+                .format(self.gcloud_config,\n+                        self.policy_bucket,\n+                        self.output_bucket))\n+\n+    def ensure_environment(self):\n+        \"\"\"\n+        Check the following:\n+        1. gsutil tool is installed\n+        2. gcloud tool/environment is logged in (gcloud auth login)\n+        3. A project_id has been set on the environment\n+        \"\"\"\n+        gsutil_cmd = find_executable('gsutil')\n+        if gsutil_cmd:\n+            print 'Found gsutil tool!'\n+        else:\n+            raise EnvironmentError(\n+                'Could not find gsutil. '\n+                'Have you installed the Google Cloud SDK?\\n'\n+                'You can get it here: https://cloud.google.com/sdk/')\n+        p = Popen(['gcloud', 'info', '--format=json'], stdout=PIPE, stderr=PIPE)\n+        output, err = p.communicate()\n+        try:\n+            gcloud_info = json.JSONDecoder().decode(output)\n+            if 'config' in gcloud_info:\n+                self.gcloud_config.auth_account = gcloud_info['config']['account']\n+                self.gcloud_config.project_id = gcloud_info['config']['project']\n+        except ValueError:\n+            print 'Failed to get gcloud info, will initialize gcloud'\n+\n+        if not self.gcloud_config.auth_account:\n+            self.gcloud_config.auth_login()\n+\n+        if not self.gcloud_config.project_id:\n+            self.gcloud_config.create_or_use_project()\n+\n+        print self.gcloud_config\n+\n+    def choose_bucket(self, object_type):\n+        \"\"\"\n+        Create or use a specified GCS bucket to store the specified object.\n+        Also turn on object versioning on the bucket if it stores policy\n+        objects.\n+        \"\"\"\n+        p = Popen(['gsutil', 'ls'], stdout=PIPE, stderr=PIPE)\n+        output, err = p.communicate()\n+        if p.returncode:\n+            print err\n+            from sys import exit\n+            exit(p.returncode)\n+\n+        prompt_templ = ('+----------------------+\\n'\n+                        '| Set up {} bucket |\\n'\n+                        '+----------------------+\\n'\n+                        'Specify a bucket for {}:')\n+        prompt_header = ''\n+        if object_type == ScannerBucketObject.POLICY:\n+            prompt_header = prompt_templ.format('POLICY', 'your policies')\n+        elif object_type == ScannerBucketObject.OUTPUT:\n+            prompt_header = prompt_templ.format('OUTPUT', 'the scanner output')\n+\n+        while True:\n+            bucket_choice = raw_input(\n+                ('{}\\n'\n+                 '[1] Enter bucket name\\n'\n+                 '[2] Choose from list\\n'\n+                 'Enter your numeric choice: '\n+                 .format(prompt_header))).strip()\n+\n+            bucket = None\n+            if bucket_choice == '1':\n+                bucket = self._create_or_reuse_bucket(object_type)\n+            elif bucket_choice == '2':\n+                bucket = self._choose_bucket(output)\n+            else:\n+                continue\n+\n+            if bucket:\n+                if not bucket.endswith('/'):\n+                    bucket = bucket + '/'\n+\n+                if object_type == ScannerBucketObject.POLICY:\n+                    # if policy bucket, enable versioning\n+                    self.policy_bucket = bucket\n+                    self._enable_object_versioning(bucket)\n+                elif object_type == ScannerBucketObject.OUTPUT:\n+                    # warn if using same buckets, prefer not to version\n+                    # output and temp files\n+                    if bucket == self.policy_bucket:\n+                        same_bucket = raw_input(\n+                            'I don\\'t recommend using the same bucket for '\n+                            'both your known-good policies AND output files!\\n'\n+                            'Continue anyway? y/N ').strip().lower()\n+                        if same_bucket != 'y':\n+                            continue\n+                    self.output_bucket = bucket\n+\n+                print 'Using bucket: {}\\n'.format(bucket)\n+                break\n+\n+    def _create_or_reuse_bucket(self, object_type):\n+        \"\"\"\n+        Give the user the option to either create or re-use a bucket.\n+\n+        This method can be used for either the POLICY or the OUTPUT\n+        bucket types.\n+        \"\"\"\n+        bucket_name = None\n+\n+        default_bucket = ''\n+        if object_type == ScannerBucketObject.POLICY:\n+            default_bucket = self.DEFAULT_BUCKETNAME_POLICIES\n+        elif object_type == ScannerBucketObject.OUTPUT:\n+            default_bucket = self.DEFAULT_BUCKETNAME_OUTPUT\n+\n+        default_bucket = default_bucket.format(self.gcloud_config.project_id)\n+\n+        while True:\n+          bucket_name = raw_input('Enter a bucket name (default: {}): '\n+                                  .format(default_bucket)).strip()\n+          if not bucket_name:\n+              bucket_name = default_bucket\n+\n+          if not bucket_name.startswith('gs://'):\n+              bucket_name = 'gs://{}'.format(bucket_name)\n+\n+          p = Popen(['gsutil', 'mb', bucket_name], stdout=PIPE, stderr=PIPE)\n+          out, err = p.communicate()\n+          if p.returncode:\n+              print err\n+              if self._force_use_bucket(bucket_name, err):\n+                  break\n+\n+        return bucket_name\n+\n+    def _force_use_bucket(self, bucket_name, mb_error_text):\n+        \"\"\"\n+        Parse the error text from gsutil mb and check what the\n+        exception is. If it's a 409, confirm with the user whether\n+        they actually want to use that bucket name.\n+        \"\"\"\n+        exceptions = self.GCS_LS_ERROR_REGEX.findall(mb_error_text)\n+        if len(exceptions):\n+          try:\n+              mb_exception, res_code_mb = exceptions[0]\n+              if mb_exception == 'ServiceException' and int(res_code_mb) == 409:\n+                  p = Popen(['gsutil', 'ls', bucket_name],\n+                            stdout=PIPE, stderr=PIPE)\n+                  ls_out, ls_err = p.communicate()\n+                  ls_exceptions = self.GCS_LS_ERROR_REGEX.findall(ls_err)\n+                  if p.returncode:\n+                      print ls_err\n+\n+                  if len(ls_exceptions):\n+                      ls_exception, res_code_ls = ls_exceptions[0]\n+                      if int(res_code_ls) == 403:\n+                          print 'You can\\'t use this bucket.'\n+                          return False\n+\n+              while True:\n+                should_use = raw_input(\n+                    'Re-use the bucket \"{}\"? (y/N) '\n+                    .format(bucket_name)).strip().lower()\n+\n+                if should_use == 'y':\n+                    return True\n+                elif should_use == 'n':\n+                    break\n+          except:\n+              print 'Ok, then let\\'s try another bucket.'\n+\n+        return False\n+\n+    def _choose_bucket(self, gsls_output):\n+        \"\"\"\n+        Present a list of the buckets (from gsutil ls).\n+        \"\"\"\n+        bucket = None\n+        buckets = []\n+        print 'Which bucket do you want to use?'\n+        for i, line in enumerate(gsls_output.split('\\n')):\n+            line = line.strip()\n+            if len(line):\n+                print '[{}] {}'.format(i+1, line)\n+                buckets.append(line)\n+\n+        while True:\n+            entry = raw_input(('Enter your numeric choice '\n+                               '(press ENTER to return): ')).strip()\n+            if not entry:\n+                return None\n+            try:\n+                entry_idx = int(entry)\n+                if entry_idx-1 < 0 or entry_idx+1 > len(buckets):\n+                    raise IndexError\n+\n+                bucket = buckets[entry_idx-1]\n+                break\n+            except ValueError:\n+                print 'Expected a number'\n+            except IndexError:\n+                print 'Expected a numeric choice from above'\n+        return bucket\n+\n+    def _enable_object_versioning(self, bucket):\n+        \"\"\"\n+        Enable object versioning on the bucket level.\n+        \"\"\"\n+        p = Popen(['gsutil', 'versioning', 'set', 'on', bucket],\n+                  stdout=PIPE, stderr=PIPE)\n+        out, err = p.communicate()\n+        print err\n+        if p.returncode:\n+            raise InvalidBucketException(\n+                'Abort operation, the bucket is invalid')\n+\n+    def setup_project_policies(self):\n+        \"\"\"\n+        Read in an input file (optional) of specific project ids or read in all\n+        projects in organization and create folders (with the project id as the\n+        name) for each one.\n+\n+        For each project, get its IAM policy and save as a json file in its\n+        respective GCS bucket.\n+        \"\"\"\n+        pass","path":"scripts/environment/gsutil_env.py","position":272,"original_position":272,"commit_id":"92a12e8e18080d03c9e778b077b6680b59f9ef36","original_commit_id":"92a12e8e18080d03c9e778b077b6680b59f9ef36","user":{"login":"blueandgold","id":6977544,"avatar_url":"https://avatars.githubusercontent.com/u/6977544?v=3","gravatar_id":"","url":"https://api.github.com/users/blueandgold","html_url":"https://github.com/blueandgold","followers_url":"https://api.github.com/users/blueandgold/followers","following_url":"https://api.github.com/users/blueandgold/following{/other_user}","gists_url":"https://api.github.com/users/blueandgold/gists{/gist_id}","starred_url":"https://api.github.com/users/blueandgold/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/blueandgold/subscriptions","organizations_url":"https://api.github.com/users/blueandgold/orgs","repos_url":"https://api.github.com/users/blueandgold/repos","events_url":"https://api.github.com/users/blueandgold/events{/privacy}","received_events_url":"https://api.github.com/users/blueandgold/received_events","type":"User","site_admin":false},"body":"if this is still to be done, please tag with TODO","created_at":"2016-11-17T18:23:20Z","updated_at":"2016-11-17T18:23:20Z","html_url":"https://github.com/GoogleCloudPlatform/policyscanner/pull/22#discussion_r88514055","pull_request_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/pulls/22","_links":{"self":{"href":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/pulls/comments/88514055"},"html":{"href":"https://github.com/GoogleCloudPlatform/policyscanner/pull/22#discussion_r88514055"},"pull_request":{"href":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/pulls/22"}}},"pull_request":{"url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/pulls/22","id":93433718,"html_url":"https://github.com/GoogleCloudPlatform/policyscanner/pull/22","diff_url":"https://github.com/GoogleCloudPlatform/policyscanner/pull/22.diff","patch_url":"https://github.com/GoogleCloudPlatform/policyscanner/pull/22.patch","issue_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/issues/22","number":22,"state":"open","locked":false,"title":"Automate setup script","user":{"login":"carise","id":14340,"avatar_url":"https://avatars.githubusercontent.com/u/14340?v=3","gravatar_id":"","url":"https://api.github.com/users/carise","html_url":"https://github.com/carise","followers_url":"https://api.github.com/users/carise/followers","following_url":"https://api.github.com/users/carise/following{/other_user}","gists_url":"https://api.github.com/users/carise/gists{/gist_id}","starred_url":"https://api.github.com/users/carise/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/carise/subscriptions","organizations_url":"https://api.github.com/users/carise/orgs","repos_url":"https://api.github.com/users/carise/repos","events_url":"https://api.github.com/users/carise/events{/privacy}","received_events_url":"https://api.github.com/users/carise/received_events","type":"User","site_admin":false},"body":"I'm creating the PR so we can start doing code review","created_at":"2016-11-12T09:27:09Z","updated_at":"2016-11-17T18:33:04Z","closed_at":null,"merged_at":null,"merge_commit_sha":"b52920d1aeb81c0c85c9c469a2a469a26762a6f9","assignee":{"login":"blueandgold","id":6977544,"avatar_url":"https://avatars.githubusercontent.com/u/6977544?v=3","gravatar_id":"","url":"https://api.github.com/users/blueandgold","html_url":"https://github.com/blueandgold","followers_url":"https://api.github.com/users/blueandgold/followers","following_url":"https://api.github.com/users/blueandgold/following{/other_user}","gists_url":"https://api.github.com/users/blueandgold/gists{/gist_id}","starred_url":"https://api.github.com/users/blueandgold/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/blueandgold/subscriptions","organizations_url":"https://api.github.com/users/blueandgold/orgs","repos_url":"https://api.github.com/users/blueandgold/repos","events_url":"https://api.github.com/users/blueandgold/events{/privacy}","received_events_url":"https://api.github.com/users/blueandgold/received_events","type":"User","site_admin":false},"assignees":[{"login":"blueandgold","id":6977544,"avatar_url":"https://avatars.githubusercontent.com/u/6977544?v=3","gravatar_id":"","url":"https://api.github.com/users/blueandgold","html_url":"https://github.com/blueandgold","followers_url":"https://api.github.com/users/blueandgold/followers","following_url":"https://api.github.com/users/blueandgold/following{/other_user}","gists_url":"https://api.github.com/users/blueandgold/gists{/gist_id}","starred_url":"https://api.github.com/users/blueandgold/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/blueandgold/subscriptions","organizations_url":"https://api.github.com/users/blueandgold/orgs","repos_url":"https://api.github.com/users/blueandgold/repos","events_url":"https://api.github.com/users/blueandgold/events{/privacy}","received_events_url":"https://api.github.com/users/blueandgold/received_events","type":"User","site_admin":false}],"milestone":null,"commits_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/pulls/22/commits","review_comments_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/pulls/22/comments","review_comment_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/pulls/comments{/number}","comments_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/issues/22/comments","statuses_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/statuses/92a12e8e18080d03c9e778b077b6680b59f9ef36","head":{"label":"GoogleCloudPlatform:automate-setup","ref":"automate-setup","sha":"92a12e8e18080d03c9e778b077b6680b59f9ef36","user":{"login":"GoogleCloudPlatform","id":2810941,"avatar_url":"https://avatars.githubusercontent.com/u/2810941?v=3","gravatar_id":"","url":"https://api.github.com/users/GoogleCloudPlatform","html_url":"https://github.com/GoogleCloudPlatform","followers_url":"https://api.github.com/users/GoogleCloudPlatform/followers","following_url":"https://api.github.com/users/GoogleCloudPlatform/following{/other_user}","gists_url":"https://api.github.com/users/GoogleCloudPlatform/gists{/gist_id}","starred_url":"https://api.github.com/users/GoogleCloudPlatform/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/GoogleCloudPlatform/subscriptions","organizations_url":"https://api.github.com/users/GoogleCloudPlatform/orgs","repos_url":"https://api.github.com/users/GoogleCloudPlatform/repos","events_url":"https://api.github.com/users/GoogleCloudPlatform/events{/privacy}","received_events_url":"https://api.github.com/users/GoogleCloudPlatform/received_events","type":"Organization","site_admin":false},"repo":{"id":70102883,"name":"policyscanner","full_name":"GoogleCloudPlatform/policyscanner","owner":{"login":"GoogleCloudPlatform","id":2810941,"avatar_url":"https://avatars.githubusercontent.com/u/2810941?v=3","gravatar_id":"","url":"https://api.github.com/users/GoogleCloudPlatform","html_url":"https://github.com/GoogleCloudPlatform","followers_url":"https://api.github.com/users/GoogleCloudPlatform/followers","following_url":"https://api.github.com/users/GoogleCloudPlatform/following{/other_user}","gists_url":"https://api.github.com/users/GoogleCloudPlatform/gists{/gist_id}","starred_url":"https://api.github.com/users/GoogleCloudPlatform/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/GoogleCloudPlatform/subscriptions","organizations_url":"https://api.github.com/users/GoogleCloudPlatform/orgs","repos_url":"https://api.github.com/users/GoogleCloudPlatform/repos","events_url":"https://api.github.com/users/GoogleCloudPlatform/events{/privacy}","received_events_url":"https://api.github.com/users/GoogleCloudPlatform/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/GoogleCloudPlatform/policyscanner","description":null,"fork":false,"url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner","forks_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/forks","keys_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/keys{/key_id}","collaborators_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/teams","hooks_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/hooks","issue_events_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/issues/events{/number}","events_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/events","assignees_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/assignees{/user}","branches_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/branches{/branch}","tags_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/tags","blobs_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/git/refs{/sha}","trees_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/git/trees{/sha}","statuses_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/statuses/{sha}","languages_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/languages","stargazers_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/stargazers","contributors_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/contributors","subscribers_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/subscribers","subscription_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/subscription","commits_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/commits{/sha}","git_commits_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/git/commits{/sha}","comments_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/comments{/number}","issue_comment_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/issues/comments{/number}","contents_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/contents/{+path}","compare_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/compare/{base}...{head}","merges_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/merges","archive_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/downloads","issues_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/issues{/number}","pulls_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/pulls{/number}","milestones_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/milestones{/number}","notifications_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/labels{/name}","releases_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/releases{/id}","deployments_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/deployments","created_at":"2016-10-05T22:01:44Z","updated_at":"2016-11-17T14:22:46Z","pushed_at":"2016-11-17T07:46:25Z","git_url":"git://github.com/GoogleCloudPlatform/policyscanner.git","ssh_url":"git@github.com:GoogleCloudPlatform/policyscanner.git","clone_url":"https://github.com/GoogleCloudPlatform/policyscanner.git","svn_url":"https://github.com/GoogleCloudPlatform/policyscanner","homepage":null,"size":150,"stargazers_count":13,"watchers_count":13,"language":"Java","has_issues":true,"has_downloads":false,"has_wiki":true,"has_pages":false,"forks_count":4,"mirror_url":null,"open_issues_count":2,"forks":4,"open_issues":2,"watchers":13,"default_branch":"master"}},"base":{"label":"GoogleCloudPlatform:master","ref":"master","sha":"7a94ec028a0109cd13ac205bdc5af52baa94022d","user":{"login":"GoogleCloudPlatform","id":2810941,"avatar_url":"https://avatars.githubusercontent.com/u/2810941?v=3","gravatar_id":"","url":"https://api.github.com/users/GoogleCloudPlatform","html_url":"https://github.com/GoogleCloudPlatform","followers_url":"https://api.github.com/users/GoogleCloudPlatform/followers","following_url":"https://api.github.com/users/GoogleCloudPlatform/following{/other_user}","gists_url":"https://api.github.com/users/GoogleCloudPlatform/gists{/gist_id}","starred_url":"https://api.github.com/users/GoogleCloudPlatform/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/GoogleCloudPlatform/subscriptions","organizations_url":"https://api.github.com/users/GoogleCloudPlatform/orgs","repos_url":"https://api.github.com/users/GoogleCloudPlatform/repos","events_url":"https://api.github.com/users/GoogleCloudPlatform/events{/privacy}","received_events_url":"https://api.github.com/users/GoogleCloudPlatform/received_events","type":"Organization","site_admin":false},"repo":{"id":70102883,"name":"policyscanner","full_name":"GoogleCloudPlatform/policyscanner","owner":{"login":"GoogleCloudPlatform","id":2810941,"avatar_url":"https://avatars.githubusercontent.com/u/2810941?v=3","gravatar_id":"","url":"https://api.github.com/users/GoogleCloudPlatform","html_url":"https://github.com/GoogleCloudPlatform","followers_url":"https://api.github.com/users/GoogleCloudPlatform/followers","following_url":"https://api.github.com/users/GoogleCloudPlatform/following{/other_user}","gists_url":"https://api.github.com/users/GoogleCloudPlatform/gists{/gist_id}","starred_url":"https://api.github.com/users/GoogleCloudPlatform/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/GoogleCloudPlatform/subscriptions","organizations_url":"https://api.github.com/users/GoogleCloudPlatform/orgs","repos_url":"https://api.github.com/users/GoogleCloudPlatform/repos","events_url":"https://api.github.com/users/GoogleCloudPlatform/events{/privacy}","received_events_url":"https://api.github.com/users/GoogleCloudPlatform/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/GoogleCloudPlatform/policyscanner","description":null,"fork":false,"url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner","forks_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/forks","keys_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/keys{/key_id}","collaborators_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/teams","hooks_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/hooks","issue_events_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/issues/events{/number}","events_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/events","assignees_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/assignees{/user}","branches_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/branches{/branch}","tags_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/tags","blobs_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/git/refs{/sha}","trees_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/git/trees{/sha}","statuses_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/statuses/{sha}","languages_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/languages","stargazers_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/stargazers","contributors_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/contributors","subscribers_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/subscribers","subscription_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/subscription","commits_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/commits{/sha}","git_commits_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/git/commits{/sha}","comments_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/comments{/number}","issue_comment_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/issues/comments{/number}","contents_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/contents/{+path}","compare_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/compare/{base}...{head}","merges_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/merges","archive_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/downloads","issues_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/issues{/number}","pulls_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/pulls{/number}","milestones_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/milestones{/number}","notifications_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/labels{/name}","releases_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/releases{/id}","deployments_url":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/deployments","created_at":"2016-10-05T22:01:44Z","updated_at":"2016-11-17T14:22:46Z","pushed_at":"2016-11-17T07:46:25Z","git_url":"git://github.com/GoogleCloudPlatform/policyscanner.git","ssh_url":"git@github.com:GoogleCloudPlatform/policyscanner.git","clone_url":"https://github.com/GoogleCloudPlatform/policyscanner.git","svn_url":"https://github.com/GoogleCloudPlatform/policyscanner","homepage":null,"size":150,"stargazers_count":13,"watchers_count":13,"language":"Java","has_issues":true,"has_downloads":false,"has_wiki":true,"has_pages":false,"forks_count":4,"mirror_url":null,"open_issues_count":2,"forks":4,"open_issues":2,"watchers":13,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/pulls/22"},"html":{"href":"https://github.com/GoogleCloudPlatform/policyscanner/pull/22"},"issue":{"href":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/issues/22"},"comments":{"href":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/issues/22/comments"},"review_comments":{"href":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/pulls/22/comments"},"review_comment":{"href":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/pulls/22/commits"},"statuses":{"href":"https://api.github.com/repos/GoogleCloudPlatform/policyscanner/statuses/92a12e8e18080d03c9e778b077b6680b59f9ef36"}}}}
{"actor":{"display_login":"blueandgold"}}