{"action":"created","comment":{"url":"https://api.github.com/repos/awslabs/cfn-python-lint/pulls/comments/188825556","pull_request_review_id":120880757,"id":188825556,"diff_hunk":"@@ -0,0 +1,254 @@\n+\"\"\"\n+  Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.\n+\n+  Permission is hereby granted, free of charge, to any person obtaining a copy of this\n+  software and associated documentation files (the \"Software\"), to deal in the Software\n+  without restriction, including without limitation the rights to use, copy, modify,\n+  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n+  permit persons to whom the Software is furnished to do so.\n+\n+  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,\n+  INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A\n+  PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n+  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\n+  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n+  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n+\"\"\"\n+from cfnlint import CloudFormationLintRule\n+from cfnlint import RuleMatch\n+\n+\n+class CodepipelineStageActions(CloudFormationLintRule):\n+    \"\"\"Check if CodePipeline Stage Actions are set up properly.\"\"\"\n+    id = 'E2541'\n+    shortdesc = 'CodePipeline Stage Actions'\n+    description = 'See if CodePipeline stage actions are set correctly'\n+    tags = ['base', 'resources', 'codepipeline']\n+\n+    VALID_OWNER_STRINGS = {'AWS', 'ThirdParty', 'Custom'}\n+\n+    CONSTRAINTS = {\n+        'AWS': {\n+            'Source': {\n+                'S3': {\n+                    'InputArtifactRange': 0,\n+                    'OutputArtifactRange': 1,\n+                },\n+                'CodeCommit': {\n+                    'InputArtifactRange': 0,\n+                    'OutputArtifactRange': 1,\n+                }\n+            },\n+            'Build': {\n+                'CodeBuild': {\n+                    'InputArtifactRange': 1,\n+                    'OutputArtifactRange': (0, 1),\n+                },\n+            },\n+            'Test': {\n+                'CodeBuild': {\n+                    'InputArtifactRange': 1,\n+                    'OutputArtifactRange': (0, 1),\n+                }\n+            },\n+            'Approval': {\n+                'Manual': {\n+                    'InputArtifactRange': 0,\n+                    'OutputArtifactRange': 0,\n+                }\n+            },\n+            'Deploy': {\n+                'CloudFormation': {\n+                    'InputArtifactRange': (0, 10),\n+                    'OutputArtifactRange': (0, 1),\n+                },\n+                'CodeDeploy': {\n+                    'InputArtifactRange': 1,\n+                    'OutputArtifactRange': 0,\n+                },\n+                'ElasticBeanstalk': {\n+                    'InputArtifactRange': 1,\n+                    'OutputArtifactRange': 0,\n+                },\n+                'OpsWorks': {\n+                    'InputArtifactRange': 1,\n+                    'OutputArtifactRange': 0,\n+                },\n+                'ECS': {\n+                    'InputArtifactRange': 1,\n+                    'OutputArtifactRange': 0,\n+                },\n+            },\n+            'Invoke': {\n+                'Lambda': {\n+                    'InputArtifactRange': (0, 5),\n+                    'OutputArtifactRange': (0, 5),\n+                }\n+            }\n+        },\n+        'ThirdParty': {\n+            'Source': {\n+                'GitHub': {\n+                    'InputArtifactRange': 0,\n+                    'OutputArtifactRange': 1,\n+                }\n+            },\n+        },\n+    }\n+\n+    KEY_MAP = {\n+        'InputArtifacts': 'InputArtifactRange',\n+        'OutputArtifacts': 'OutputArtifactRange',\n+    }\n+\n+    def check_artifact_counts(self, action, artifact_type, path):\n+        \"\"\"Check that artifact counts are within valid ranges.\"\"\"\n+        matches = []\n+\n+        action_type_id = action.get('ActionTypeId')\n+        owner = action_type_id.get('Owner')\n+        category = action_type_id.get('Category')\n+        provider = action_type_id.get('Provider')\n+\n+        constraints = self.CONSTRAINTS.get(owner, {}).get(category, {}).get(provider, {})\n+        if not constraints:\n+            return matches\n+        artifact_count = len(action.get(artifact_type, []))\n+\n+        constraint_key = self.KEY_MAP[artifact_type]\n+        if isinstance(constraints[constraint_key], tuple):\n+            min_, max_ = constraints[constraint_key]\n+            if not (min_ <= artifact_count <= max_):\n+                message = (\n+                    'Action \"{action}\" declares {number} {artifact_type} which is not in '\n+                    'expected range [{a}, {b}].'\n+                ).format(\n+                    action=action['Name'],\n+                    number=artifact_count,\n+                    artifact_type=artifact_type,\n+                    a=min_,\n+                    b=max_\n+                )\n+                matches.append(RuleMatch(\n+                    path + [artifact_type],\n+                    message\n+                ))\n+        else:\n+            if artifact_count != constraints[constraint_key]:\n+                message = (\n+                    'Action \"{action}\" declares {number} {artifact_type} which is not the '\n+                    'expected number [{a}].'\n+                ).format(\n+                    action=action['Name'],\n+                    number=artifact_count,\n+                    artifact_type=artifact_type,\n+                    a=constraints[constraint_key]\n+                )\n+                matches.append(RuleMatch(\n+                    path + [artifact_type],\n+                    message\n+                ))\n+\n+        return matches\n+\n+    def check_action_keys(self, action, path):\n+        \"\"\"Check that action has required keys inside.\"\"\"\n+        matches = []\n+\n+        if 'Name' not in action:\n+            message = 'Expecting Name key in Action.'\n+            matches.append(RuleMatch(\n+                path,\n+                message\n+            ))\n+        if 'ActionTypeId' not in action:\n+            message = 'Expecting ActionTypeId key in Action.'\n+            matches.append(RuleMatch(\n+                path,\n+                message\n+            ))\n+\n+        return matches\n+\n+    def check_owner(self, action, path):\n+        \"\"\"Check that action type owner is valid.\"\"\"\n+        matches = []\n+\n+        owner = action.get('ActionTypeId').get('Owner')\n+        if owner not in self.VALID_OWNER_STRINGS:","path":"src/cfnlint/rules/resources/codepipeline/CodepipelineStageActions.py","position":178,"original_position":178,"commit_id":"8bb28e354d88d24212b85b601c6404d7bff232e3","original_commit_id":"8bb28e354d88d24212b85b601c6404d7bff232e3","user":{"login":"kddejong","id":36457093,"avatar_url":"https://avatars3.githubusercontent.com/u/36457093?v=4","gravatar_id":"","url":"https://api.github.com/users/kddejong","html_url":"https://github.com/kddejong","followers_url":"https://api.github.com/users/kddejong/followers","following_url":"https://api.github.com/users/kddejong/following{/other_user}","gists_url":"https://api.github.com/users/kddejong/gists{/gist_id}","starred_url":"https://api.github.com/users/kddejong/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kddejong/subscriptions","organizations_url":"https://api.github.com/users/kddejong/orgs","repos_url":"https://api.github.com/users/kddejong/repos","events_url":"https://api.github.com/users/kddejong/events{/privacy}","received_events_url":"https://api.github.com/users/kddejong/received_events","type":"User","site_admin":false},"body":"I'm debating if this should be.\r\n`if owner not in self.VALID_OWNER_STRINGS and owner is not None:` since the Owner check will be covered by the required properties check (E3003) if someone misses Owner with this version they will get double errors.\r\n\r\n```\r\nE3003 Property Owner missing from resource DeployPipeline\r\ntest/templates/quickstart/codepipeline.yaml:441:11\r\n\r\nE2541 For all currently supported action types, the only valid owner strings are AWS, Custom, ThirdParty\r\ntest/templates/quickstart/codepipeline.yaml:444:15\r\n```\r\n\r\nwhere as with the fix it would just be \r\n```\r\nE3003 Property Owner missing from resource DeployPipeline\r\ntest/templates/quickstart/codepipeline.yaml:441:11\r\n```\r\n","created_at":"2018-05-17T02:42:31Z","updated_at":"2018-05-17T02:47:36Z","html_url":"https://github.com/awslabs/cfn-python-lint/pull/30#discussion_r188825556","pull_request_url":"https://api.github.com/repos/awslabs/cfn-python-lint/pulls/30","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/awslabs/cfn-python-lint/pulls/comments/188825556"},"html":{"href":"https://github.com/awslabs/cfn-python-lint/pull/30#discussion_r188825556"},"pull_request":{"href":"https://api.github.com/repos/awslabs/cfn-python-lint/pulls/30"}}},"pull_request":{"url":"https://api.github.com/repos/awslabs/cfn-python-lint/pulls/30","id":185572576,"html_url":"https://github.com/awslabs/cfn-python-lint/pull/30","diff_url":"https://github.com/awslabs/cfn-python-lint/pull/30.diff","patch_url":"https://github.com/awslabs/cfn-python-lint/pull/30.patch","issue_url":"https://api.github.com/repos/awslabs/cfn-python-lint/issues/30","number":30,"state":"open","locked":false,"title":"PoC of simple CodePipeline rules","user":{"login":"seporaitis","id":141768,"avatar_url":"https://avatars1.githubusercontent.com/u/141768?v=4","gravatar_id":"","url":"https://api.github.com/users/seporaitis","html_url":"https://github.com/seporaitis","followers_url":"https://api.github.com/users/seporaitis/followers","following_url":"https://api.github.com/users/seporaitis/following{/other_user}","gists_url":"https://api.github.com/users/seporaitis/gists{/gist_id}","starred_url":"https://api.github.com/users/seporaitis/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/seporaitis/subscriptions","organizations_url":"https://api.github.com/users/seporaitis/orgs","repos_url":"https://api.github.com/users/seporaitis/repos","events_url":"https://api.github.com/users/seporaitis/events{/privacy}","received_events_url":"https://api.github.com/users/seporaitis/received_events","type":"User","site_admin":false},"body":"*Issue #:* #29 \r\n\r\n*Description of changes:*\r\n\r\nA proof of concept of two rules described in #29. If deemed worthy of adding to the project - I will tidy up the code and add test cases.\r\n\r\n\r\nBy submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.\r\n","created_at":"2018-05-02T21:59:53Z","updated_at":"2018-05-17T02:47:36Z","closed_at":null,"merged_at":null,"merge_commit_sha":"36645a044ddb2a425c5b7e2a1db3d3b87d311648","assignee":null,"assignees":[],"requested_reviewers":[{"login":"cmmeyer","id":5632125,"avatar_url":"https://avatars1.githubusercontent.com/u/5632125?v=4","gravatar_id":"","url":"https://api.github.com/users/cmmeyer","html_url":"https://github.com/cmmeyer","followers_url":"https://api.github.com/users/cmmeyer/followers","following_url":"https://api.github.com/users/cmmeyer/following{/other_user}","gists_url":"https://api.github.com/users/cmmeyer/gists{/gist_id}","starred_url":"https://api.github.com/users/cmmeyer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cmmeyer/subscriptions","organizations_url":"https://api.github.com/users/cmmeyer/orgs","repos_url":"https://api.github.com/users/cmmeyer/repos","events_url":"https://api.github.com/users/cmmeyer/events{/privacy}","received_events_url":"https://api.github.com/users/cmmeyer/received_events","type":"User","site_admin":false}],"requested_teams":[],"labels":[{"id":897505837,"url":"https://api.github.com/repos/awslabs/cfn-python-lint/labels/enhancement","name":"enhancement","color":"a2eeef","default":true}],"milestone":null,"commits_url":"https://api.github.com/repos/awslabs/cfn-python-lint/pulls/30/commits","review_comments_url":"https://api.github.com/repos/awslabs/cfn-python-lint/pulls/30/comments","review_comment_url":"https://api.github.com/repos/awslabs/cfn-python-lint/pulls/comments{/number}","comments_url":"https://api.github.com/repos/awslabs/cfn-python-lint/issues/30/comments","statuses_url":"https://api.github.com/repos/awslabs/cfn-python-lint/statuses/8bb28e354d88d24212b85b601c6404d7bff232e3","head":{"label":"seporaitis:codepipeline-rules","ref":"codepipeline-rules","sha":"8bb28e354d88d24212b85b601c6404d7bff232e3","user":{"login":"seporaitis","id":141768,"avatar_url":"https://avatars1.githubusercontent.com/u/141768?v=4","gravatar_id":"","url":"https://api.github.com/users/seporaitis","html_url":"https://github.com/seporaitis","followers_url":"https://api.github.com/users/seporaitis/followers","following_url":"https://api.github.com/users/seporaitis/following{/other_user}","gists_url":"https://api.github.com/users/seporaitis/gists{/gist_id}","starred_url":"https://api.github.com/users/seporaitis/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/seporaitis/subscriptions","organizations_url":"https://api.github.com/users/seporaitis/orgs","repos_url":"https://api.github.com/users/seporaitis/repos","events_url":"https://api.github.com/users/seporaitis/events{/privacy}","received_events_url":"https://api.github.com/users/seporaitis/received_events","type":"User","site_admin":false},"repo":{"id":131909899,"name":"cfn-python-lint","full_name":"seporaitis/cfn-python-lint","owner":{"login":"seporaitis","id":141768,"avatar_url":"https://avatars1.githubusercontent.com/u/141768?v=4","gravatar_id":"","url":"https://api.github.com/users/seporaitis","html_url":"https://github.com/seporaitis","followers_url":"https://api.github.com/users/seporaitis/followers","following_url":"https://api.github.com/users/seporaitis/following{/other_user}","gists_url":"https://api.github.com/users/seporaitis/gists{/gist_id}","starred_url":"https://api.github.com/users/seporaitis/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/seporaitis/subscriptions","organizations_url":"https://api.github.com/users/seporaitis/orgs","repos_url":"https://api.github.com/users/seporaitis/repos","events_url":"https://api.github.com/users/seporaitis/events{/privacy}","received_events_url":"https://api.github.com/users/seporaitis/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/seporaitis/cfn-python-lint","description":"CloudFormation Linter","fork":true,"url":"https://api.github.com/repos/seporaitis/cfn-python-lint","forks_url":"https://api.github.com/repos/seporaitis/cfn-python-lint/forks","keys_url":"https://api.github.com/repos/seporaitis/cfn-python-lint/keys{/key_id}","collaborators_url":"https://api.github.com/repos/seporaitis/cfn-python-lint/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/seporaitis/cfn-python-lint/teams","hooks_url":"https://api.github.com/repos/seporaitis/cfn-python-lint/hooks","issue_events_url":"https://api.github.com/repos/seporaitis/cfn-python-lint/issues/events{/number}","events_url":"https://api.github.com/repos/seporaitis/cfn-python-lint/events","assignees_url":"https://api.github.com/repos/seporaitis/cfn-python-lint/assignees{/user}","branches_url":"https://api.github.com/repos/seporaitis/cfn-python-lint/branches{/branch}","tags_url":"https://api.github.com/repos/seporaitis/cfn-python-lint/tags","blobs_url":"https://api.github.com/repos/seporaitis/cfn-python-lint/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/seporaitis/cfn-python-lint/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/seporaitis/cfn-python-lint/git/refs{/sha}","trees_url":"https://api.github.com/repos/seporaitis/cfn-python-lint/git/trees{/sha}","statuses_url":"https://api.github.com/repos/seporaitis/cfn-python-lint/statuses/{sha}","languages_url":"https://api.github.com/repos/seporaitis/cfn-python-lint/languages","stargazers_url":"https://api.github.com/repos/seporaitis/cfn-python-lint/stargazers","contributors_url":"https://api.github.com/repos/seporaitis/cfn-python-lint/contributors","subscribers_url":"https://api.github.com/repos/seporaitis/cfn-python-lint/subscribers","subscription_url":"https://api.github.com/repos/seporaitis/cfn-python-lint/subscription","commits_url":"https://api.github.com/repos/seporaitis/cfn-python-lint/commits{/sha}","git_commits_url":"https://api.github.com/repos/seporaitis/cfn-python-lint/git/commits{/sha}","comments_url":"https://api.github.com/repos/seporaitis/cfn-python-lint/comments{/number}","issue_comment_url":"https://api.github.com/repos/seporaitis/cfn-python-lint/issues/comments{/number}","contents_url":"https://api.github.com/repos/seporaitis/cfn-python-lint/contents/{+path}","compare_url":"https://api.github.com/repos/seporaitis/cfn-python-lint/compare/{base}...{head}","merges_url":"https://api.github.com/repos/seporaitis/cfn-python-lint/merges","archive_url":"https://api.github.com/repos/seporaitis/cfn-python-lint/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/seporaitis/cfn-python-lint/downloads","issues_url":"https://api.github.com/repos/seporaitis/cfn-python-lint/issues{/number}","pulls_url":"https://api.github.com/repos/seporaitis/cfn-python-lint/pulls{/number}","milestones_url":"https://api.github.com/repos/seporaitis/cfn-python-lint/milestones{/number}","notifications_url":"https://api.github.com/repos/seporaitis/cfn-python-lint/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/seporaitis/cfn-python-lint/labels{/name}","releases_url":"https://api.github.com/repos/seporaitis/cfn-python-lint/releases{/id}","deployments_url":"https://api.github.com/repos/seporaitis/cfn-python-lint/deployments","created_at":"2018-05-02T21:55:35Z","updated_at":"2018-05-02T21:55:37Z","pushed_at":"2018-05-16T19:43:13Z","git_url":"git://github.com/seporaitis/cfn-python-lint.git","ssh_url":"git@github.com:seporaitis/cfn-python-lint.git","clone_url":"https://github.com/seporaitis/cfn-python-lint.git","svn_url":"https://github.com/seporaitis/cfn-python-lint","homepage":null,"size":346,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":{"key":"other","name":"Other","spdx_id":null,"url":null},"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"awslabs:master","ref":"master","sha":"aefee9b6e567e5f50f5cff69c37d29a0be9f835e","user":{"login":"awslabs","id":3299148,"avatar_url":"https://avatars0.githubusercontent.com/u/3299148?v=4","gravatar_id":"","url":"https://api.github.com/users/awslabs","html_url":"https://github.com/awslabs","followers_url":"https://api.github.com/users/awslabs/followers","following_url":"https://api.github.com/users/awslabs/following{/other_user}","gists_url":"https://api.github.com/users/awslabs/gists{/gist_id}","starred_url":"https://api.github.com/users/awslabs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/awslabs/subscriptions","organizations_url":"https://api.github.com/users/awslabs/orgs","repos_url":"https://api.github.com/users/awslabs/repos","events_url":"https://api.github.com/users/awslabs/events{/privacy}","received_events_url":"https://api.github.com/users/awslabs/received_events","type":"Organization","site_admin":false},"repo":{"id":129005655,"name":"cfn-python-lint","full_name":"awslabs/cfn-python-lint","owner":{"login":"awslabs","id":3299148,"avatar_url":"https://avatars0.githubusercontent.com/u/3299148?v=4","gravatar_id":"","url":"https://api.github.com/users/awslabs","html_url":"https://github.com/awslabs","followers_url":"https://api.github.com/users/awslabs/followers","following_url":"https://api.github.com/users/awslabs/following{/other_user}","gists_url":"https://api.github.com/users/awslabs/gists{/gist_id}","starred_url":"https://api.github.com/users/awslabs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/awslabs/subscriptions","organizations_url":"https://api.github.com/users/awslabs/orgs","repos_url":"https://api.github.com/users/awslabs/repos","events_url":"https://api.github.com/users/awslabs/events{/privacy}","received_events_url":"https://api.github.com/users/awslabs/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/awslabs/cfn-python-lint","description":"CloudFormation Linter","fork":false,"url":"https://api.github.com/repos/awslabs/cfn-python-lint","forks_url":"https://api.github.com/repos/awslabs/cfn-python-lint/forks","keys_url":"https://api.github.com/repos/awslabs/cfn-python-lint/keys{/key_id}","collaborators_url":"https://api.github.com/repos/awslabs/cfn-python-lint/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/awslabs/cfn-python-lint/teams","hooks_url":"https://api.github.com/repos/awslabs/cfn-python-lint/hooks","issue_events_url":"https://api.github.com/repos/awslabs/cfn-python-lint/issues/events{/number}","events_url":"https://api.github.com/repos/awslabs/cfn-python-lint/events","assignees_url":"https://api.github.com/repos/awslabs/cfn-python-lint/assignees{/user}","branches_url":"https://api.github.com/repos/awslabs/cfn-python-lint/branches{/branch}","tags_url":"https://api.github.com/repos/awslabs/cfn-python-lint/tags","blobs_url":"https://api.github.com/repos/awslabs/cfn-python-lint/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/awslabs/cfn-python-lint/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/awslabs/cfn-python-lint/git/refs{/sha}","trees_url":"https://api.github.com/repos/awslabs/cfn-python-lint/git/trees{/sha}","statuses_url":"https://api.github.com/repos/awslabs/cfn-python-lint/statuses/{sha}","languages_url":"https://api.github.com/repos/awslabs/cfn-python-lint/languages","stargazers_url":"https://api.github.com/repos/awslabs/cfn-python-lint/stargazers","contributors_url":"https://api.github.com/repos/awslabs/cfn-python-lint/contributors","subscribers_url":"https://api.github.com/repos/awslabs/cfn-python-lint/subscribers","subscription_url":"https://api.github.com/repos/awslabs/cfn-python-lint/subscription","commits_url":"https://api.github.com/repos/awslabs/cfn-python-lint/commits{/sha}","git_commits_url":"https://api.github.com/repos/awslabs/cfn-python-lint/git/commits{/sha}","comments_url":"https://api.github.com/repos/awslabs/cfn-python-lint/comments{/number}","issue_comment_url":"https://api.github.com/repos/awslabs/cfn-python-lint/issues/comments{/number}","contents_url":"https://api.github.com/repos/awslabs/cfn-python-lint/contents/{+path}","compare_url":"https://api.github.com/repos/awslabs/cfn-python-lint/compare/{base}...{head}","merges_url":"https://api.github.com/repos/awslabs/cfn-python-lint/merges","archive_url":"https://api.github.com/repos/awslabs/cfn-python-lint/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/awslabs/cfn-python-lint/downloads","issues_url":"https://api.github.com/repos/awslabs/cfn-python-lint/issues{/number}","pulls_url":"https://api.github.com/repos/awslabs/cfn-python-lint/pulls{/number}","milestones_url":"https://api.github.com/repos/awslabs/cfn-python-lint/milestones{/number}","notifications_url":"https://api.github.com/repos/awslabs/cfn-python-lint/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/awslabs/cfn-python-lint/labels{/name}","releases_url":"https://api.github.com/repos/awslabs/cfn-python-lint/releases{/id}","deployments_url":"https://api.github.com/repos/awslabs/cfn-python-lint/deployments","created_at":"2018-04-10T23:16:16Z","updated_at":"2018-05-16T21:46:56Z","pushed_at":"2018-05-16T21:02:45Z","git_url":"git://github.com/awslabs/cfn-python-lint.git","ssh_url":"git@github.com:awslabs/cfn-python-lint.git","clone_url":"https://github.com/awslabs/cfn-python-lint.git","svn_url":"https://github.com/awslabs/cfn-python-lint","homepage":null,"size":455,"stargazers_count":37,"watchers_count":37,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":11,"mirror_url":null,"archived":false,"open_issues_count":13,"license":{"key":"other","name":"Other","spdx_id":null,"url":null},"forks":11,"open_issues":13,"watchers":37,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/awslabs/cfn-python-lint/pulls/30"},"html":{"href":"https://github.com/awslabs/cfn-python-lint/pull/30"},"issue":{"href":"https://api.github.com/repos/awslabs/cfn-python-lint/issues/30"},"comments":{"href":"https://api.github.com/repos/awslabs/cfn-python-lint/issues/30/comments"},"review_comments":{"href":"https://api.github.com/repos/awslabs/cfn-python-lint/pulls/30/comments"},"review_comment":{"href":"https://api.github.com/repos/awslabs/cfn-python-lint/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/awslabs/cfn-python-lint/pulls/30/commits"},"statuses":{"href":"https://api.github.com/repos/awslabs/cfn-python-lint/statuses/8bb28e354d88d24212b85b601c6404d7bff232e3"}},"author_association":"NONE"}}
{"actor":{"display_login":"kddejong"}}