{"action":"created","comment":{"url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/pulls/comments/51403190","id":51403190,"diff_hunk":"@@ -0,0 +1,471 @@\n+import json\n+\n+import mock\n+from ..helpers import BaseApplicationTest\n+\n+from dmapiclient.audit import AuditTypes\n+from app import db\n+from app.models import Framework\n+\n+\n+class TestBriefs(BaseApplicationTest):\n+    def setup(self):\n+        super(TestBriefs, self).setup()\n+        self.user_id = self.setup_dummy_user(role='buyer')\n+\n+        with self.app.app_context():\n+            framework = Framework.query.filter(Framework.slug == 'digital-outcomes-and-specialists').first()\n+            self._original_framework_status = framework.status\n+            framework.status = 'live'\n+\n+            db.session.add(framework)\n+            db.session.commit()\n+\n+    def teardown(self):\n+        with self.app.app_context():\n+            framework = Framework.query.filter(Framework.slug == 'digital-outcomes-and-specialists').first()\n+            framework.status = self._original_framework_status\n+\n+            db.session.add(framework)\n+            db.session.commit()\n+        super(TestBriefs, self).teardown()\n+\n+    def test_create_brief_with_no_data(self):\n+        res = self.client.post(\n+            '/briefs',\n+            content_type='application/json')\n+\n+        assert res.status_code == 400\n+\n+    def test_create_brief(self):\n+        res = self.client.post(\n+            '/briefs',\n+            data=json.dumps({\n+                'briefs': {\n+                    'userId': self.user_id,\n+                    'frameworkSlug': 'digital-outcomes-and-specialists',\n+                    'lot': 'digital-specialists',\n+                    'title': 'the title',\n+                },\n+                'update_details': {\n+                    'updated_by': 'example'\n+                }\n+            }),\n+            content_type='application/json')\n+        data = json.loads(res.get_data(as_text=True))\n+\n+        assert res.status_code == 201\n+        assert data['briefs']['frameworkSlug'] == 'digital-outcomes-and-specialists'\n+        assert data['briefs']['title'] == 'the title'\n+\n+    def test_create_fails_if_lot_does_not_require_briefs(self):\n+        res = self.client.post(\n+            '/briefs',\n+            data=json.dumps({\n+                'briefs': {\n+                    'userId': self.user_id,\n+                    'frameworkSlug': 'digital-outcomes-and-specialists',\n+                    'lot': 'user-research-studios',\n+                    'title': 'the title',\n+                },\n+                'update_details': {\n+                    'updated_by': 'example'\n+                }\n+            }),\n+            content_type='application/json')\n+        data = json.loads(res.get_data(as_text=True))\n+\n+        assert res.status_code == 400\n+        assert data['error'] == \"Lot 'User research studios' does not require a brief\"\n+\n+    def test_create_fails_if_required_field_is_not_provided(self):\n+        res = self.client.post(\n+            '/briefs',\n+            data=json.dumps({\n+                'briefs': {\n+                    'userId': self.user_id,\n+                    'frameworkSlug': 'digital-outcomes-and-specialists',\n+                    'lot': 'digital-specialists',\n+                },\n+                'update_details': {\n+                    'updated_by': 'example'\n+                },\n+                'page_questions': ['title'],\n+            }),\n+            content_type='application/json')\n+        data = json.loads(res.get_data(as_text=True))\n+\n+        assert res.status_code == 400\n+        assert data['error'] == {'title': 'answer_required'}\n+\n+    def test_can_only_create_briefs_on_live_frameworks(self):\n+        with self.app.app_context():\n+            framework = Framework.query.filter(Framework.slug == 'digital-outcomes-and-specialists').first()\n+            self._original_framework_status = framework.status\n+            framework.status = 'open'\n+\n+            db.session.add(framework)\n+            db.session.commit()\n+\n+        res = self.client.post(\n+            '/briefs',\n+            data=json.dumps({\n+                'briefs': {\n+                    'userId': self.user_id,\n+                    'frameworkSlug': 'digital-outcomes-and-specialists',\n+                    'lot': 'digital-specialists',\n+                    'title': 'the title',\n+                },\n+                'update_details': {\n+                    'updated_by': 'example'\n+                }\n+            }),\n+            content_type='application/json')\n+\n+        assert res.status_code == 400\n+\n+    def test_create_brief_creates_audit_event(self):\n+        self.client.post(\n+            '/briefs',\n+            data=json.dumps({\n+                'briefs': {\n+                    'userId': self.user_id,\n+                    'frameworkSlug': 'digital-outcomes-and-specialists',\n+                    'lot': 'digital-specialists',\n+                    'title': 'my title',\n+                },\n+                'update_details': {'updated_by': 'example'}\n+            }),\n+            content_type='application/json')\n+\n+        audit_response = self.client.get('/audit-events')\n+        assert audit_response.status_code == 200\n+        data = json.loads(audit_response.get_data(as_text=True))\n+\n+        brief_audits = [event for event in data['auditEvents'] if event['type'] == AuditTypes.create_brief.value]\n+        assert len(brief_audits) == 1\n+        assert brief_audits[0]['data'] == {\n+            'briefId': mock.ANY,\n+            'briefJson': {\n+                'frameworkSlug': 'digital-outcomes-and-specialists',\n+                'lot': 'digital-specialists',\n+                'title': 'my title'\n+            }\n+        }\n+\n+    def test_create_brief_fails_if_schema_validation_fails(self):\n+        res = self.client.post(\n+            '/briefs',\n+            data=json.dumps({\n+                'briefs': {\n+                    'userId': self.user_id,\n+                    'frameworkSlug': 'digital-outcomes-and-specialists',\n+                    'lot': 'digital-specialists',\n+                    'title': 'my title' * 30,\n+                },\n+                'update_details': {'updated_by': 'example'}\n+            }),\n+            content_type='application/json')\n+        data = json.loads(res.get_data(as_text=True))\n+\n+        assert res.status_code == 400\n+        assert data['error'] == {'title': 'under_character_limit'}\n+\n+    def test_create_brief_fails_if_user_does_not_exist(self):\n+        res = self.client.post(\n+            '/briefs',\n+            data=json.dumps({\n+                'briefs': {\n+                    'userId': 999,\n+                    'frameworkSlug': 'digital-outcomes-and-specialists',\n+                    'lot': 'digital-specialists',\n+                },\n+                'update_details': {'updated_by': 'example'}\n+            }),\n+            content_type='application/json')\n+\n+        assert res.status_code == 400\n+        assert json.loads(res.get_data(as_text=True))['error'] == 'User ID does not exist'\n+\n+    def test_create_brief_fails_if_framework_does_not_exist(self):\n+        res = self.client.post(\n+            '/briefs',\n+            data=json.dumps({\n+                'briefs': {\n+                    'userId': self.user_id,\n+                    'frameworkSlug': 'not-exists',\n+                    'lot': 'digital-specialists',\n+                },\n+                'update_details': {'updated_by': 'example'}\n+            }),\n+            content_type='application/json')\n+\n+        assert res.status_code == 400\n+        assert json.loads(res.get_data(as_text=True))['error'] == \"Framework 'not-exists' does not exist\"\n+\n+    def test_create_brief_fails_if_lot_does_not_exist(self):\n+        res = self.client.post(\n+            '/briefs',\n+            data=json.dumps({\n+                'briefs': {\n+                    'userId': self.user_id,\n+                    'frameworkSlug': 'digital-outcomes-and-specialists',\n+                    'lot': 'not-exists',\n+                },\n+                'update_details': {'updated_by': 'example'}\n+            }),\n+            content_type='application/json')\n+\n+        assert res.status_code == 400\n+        assert json.loads(res.get_data(as_text=True))['error'] == \\\n+            \"Incorrect lot 'not-exists' for framework 'digital-outcomes-and-specialists'\"\n+\n+    def test_update_brief(self):\n+        self.setup_dummy_briefs(1)\n+\n+        res = self.client.post(\n+            '/briefs/1',\n+            data=json.dumps({\n+                'briefs': {'title': 'my title'},\n+                'update_details': {'updated_by': 'example'},\n+            }),\n+            content_type='application/json')\n+        data = json.loads(res.get_data(as_text=True))\n+\n+        assert res.status_code == 200\n+        assert data['briefs']['title'] == 'my title'\n+\n+    def test_update_fails_if_required_field_is_not_provided(self):\n+        self.setup_dummy_briefs(1)\n+\n+        res = self.client.post(\n+            '/briefs/1',\n+            data=json.dumps({\n+                'briefs': {},\n+                'update_details': {'updated_by': 'example'},\n+                'page_questions': ['title'],\n+            }),\n+            content_type='application/json')\n+        data = json.loads(res.get_data(as_text=True))\n+\n+        assert res.status_code == 400\n+        assert data['error'] == {'title': 'answer_required'}\n+\n+    def test_update_fails_if_status_is_live(self):\n+        self.setup_dummy_briefs(1, status='live')\n+\n+        res = self.client.post(\n+            '/briefs/1',\n+            data=json.dumps({\n+                'briefs': {'title': 'my title'},\n+                'update_details': {'updated_by': 'example'},\n+            }),\n+            content_type='application/json')\n+        data = json.loads(res.get_data(as_text=True))\n+\n+        assert res.status_code == 400\n+        assert data['error'] == 'Cannot update a live brief'\n+\n+    def test_update_brief_creates_audit_event(self):\n+        self.setup_dummy_briefs(1)\n+\n+        self.client.post(\n+            '/briefs/1',\n+            data=json.dumps({\n+                'briefs': {'title': 'my title'},\n+                'update_details': {'updated_by': 'example'}\n+            }),\n+            content_type='application/json')\n+\n+        audit_response = self.client.get('/audit-events')\n+        assert audit_response.status_code == 200\n+        data = json.loads(audit_response.get_data(as_text=True))\n+\n+        brief_audits = [event for event in data['auditEvents'] if event['type'] == AuditTypes.update_brief.value]\n+        assert len(brief_audits) == 1\n+        assert brief_audits[0]['data'] == {'briefId': 1, 'briefJson': {'title': 'my title'}}\n+\n+    def test_update_brief_fails_if_schema_validation_fails(self):\n+        self.setup_dummy_briefs(1)\n+\n+        res = self.client.post(\n+            '/briefs/1',\n+            data=json.dumps({\n+                'briefs': {\n+                    'title': 'my title' * 30,\n+                },\n+                'update_details': {'updated_by': 'example'}\n+            }),\n+            content_type='application/json')\n+        data = json.loads(res.get_data(as_text=True))\n+\n+        assert res.status_code == 400\n+        assert data['error'] == {'title': 'under_character_limit'}\n+\n+    def test_update_brief_returns_404_if_not_found(self):\n+        res = self.client.post(\n+            '/briefs/1',\n+            data=json.dumps({\n+                'briefs': {},\n+                'update_details': {'updated_by': 'example'},\n+            }),\n+            content_type='application/json')\n+\n+        assert res.status_code == 404\n+\n+    def test_get_brief(self):\n+        self.setup_dummy_briefs(1)\n+        res = self.client.get('/briefs/1')\n+\n+        assert res.status_code == 200\n+        assert json.loads(res.get_data(as_text=True)) == {\n+            'briefs': {\n+                'id': 1,\n+                'status': 'draft',\n+                'frameworkSlug': 'digital-outcomes-and-specialists',\n+                'frameworkName': 'Digital Outcomes and Specialists',\n+                'frameworkStatus': 'live',\n+                'lot': 'digital-specialists',\n+                'lotName': 'Digital specialists',\n+                'createdAt': mock.ANY,\n+                'updatedAt': mock.ANY,\n+                'links': {\n+                    'framework': 'http://localhost/frameworks/digital-outcomes-and-specialists',\n+                    'self': 'http://localhost/briefs/1',\n+                },\n+            }\n+        }\n+\n+    def test_get_brief_returns_404_if_not_found(self):\n+        res = self.client.get('/briefs/1')\n+\n+        assert res.status_code == 404\n+\n+    def test_list_briefs(self):\n+        self.setup_dummy_briefs(3)\n+\n+        res = self.client.get('/briefs')\n+        data = json.loads(res.get_data(as_text=True))\n+\n+        assert res.status_code == 200\n+        assert len(data['briefs']) == 3\n+\n+    def test_list_briefs_pagination_page_one(self):\n+        self.setup_dummy_briefs(7)\n+\n+        res = self.client.get('/briefs')\n+        data = json.loads(res.get_data(as_text=True))\n+\n+        assert res.status_code == 200\n+\n+        assert len(data['briefs']) == 5\n+        assert data['links']['next'] == 'http://localhost/briefs?page=2'\n+        assert data['links']['last'] == 'http://localhost/briefs?page=2'\n+\n+    def test_list_briefs_pagination_page_two(self):\n+        self.setup_dummy_briefs(7)\n+\n+        res = self.client.get('/briefs?page=2')\n+        data = json.loads(res.get_data(as_text=True))\n+\n+        assert res.status_code == 200\n+\n+        assert len(data['briefs']) == 2\n+        assert data['links']['prev'] == 'http://localhost/briefs?page=1'\n+\n+    def test_make_a_brief_live(self):\n+        self.setup_dummy_briefs(1, title='The Title')\n+\n+        res = self.client.put(\n+            '/briefs/1/status',\n+            data=json.dumps({\n+                'briefs': {'status': 'live'},\n+                'update_details': {'updated_by': 'example'}\n+            }),\n+            content_type='application/json')\n+        data = json.loads(res.get_data(as_text=True))\n+\n+        assert res.status_code == 200\n+        assert data['briefs']['status'] == 'live'\n+\n+    def test_cannot_make_a_brief_live_if_is_not_complete(self):\n+        self.setup_dummy_briefs(1)\n+\n+        res = self.client.put(\n+            '/briefs/1/status',\n+            data=json.dumps({\n+                'briefs': {'status': 'live'},\n+                'update_details': {'updated_by': 'example'}\n+            }),\n+            content_type='application/json')\n+        data = json.loads(res.get_data(as_text=True))\n+\n+        assert res.status_code == 400\n+        assert data['error'] == {'title': 'answer_required'}\n+\n+    def test_cannot_make_a_brief_live_if_it_is_already_live(self):\n+        self.setup_dummy_briefs(1, status='live')\n+\n+        res = self.client.put(\n+            '/briefs/1/status',\n+            data=json.dumps({\n+                'briefs': {'status': 'live'},\n+                'update_details': {'updated_by': 'example'}\n+            }),\n+            content_type='application/json')\n+        data = json.loads(res.get_data(as_text=True))\n+\n+        assert res.status_code == 400\n+        assert data['error'] == 'Brief is already live'\n+\n+    def test_cannot_make_a_live_brief_pending(self):","path":"tests/app/views/test_briefs.py","position":null,"original_position":421,"commit_id":"1c22840503c2842124fcaf3fe118e4a6531b3969","original_commit_id":"fec7cdaa93b17b0ff314ac2c5e2c446ccf50c80a","user":{"login":"TheDoubleK","id":6525554,"avatar_url":"https://avatars.githubusercontent.com/u/6525554?v=3","gravatar_id":"","url":"https://api.github.com/users/TheDoubleK","html_url":"https://github.com/TheDoubleK","followers_url":"https://api.github.com/users/TheDoubleK/followers","following_url":"https://api.github.com/users/TheDoubleK/following{/other_user}","gists_url":"https://api.github.com/users/TheDoubleK/gists{/gist_id}","starred_url":"https://api.github.com/users/TheDoubleK/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/TheDoubleK/subscriptions","organizations_url":"https://api.github.com/users/TheDoubleK/orgs","repos_url":"https://api.github.com/users/TheDoubleK/repos","events_url":"https://api.github.com/users/TheDoubleK/events{/privacy}","received_events_url":"https://api.github.com/users/TheDoubleK/received_events","type":"User","site_admin":false},"body":"`cannot_make_a_live_brief_draft`? Or `cannot_return_a_live_brief_to_draft`?","created_at":"2016-02-01T10:48:08Z","updated_at":"2016-02-01T10:48:08Z","html_url":"https://github.com/alphagov/digitalmarketplace-api/pull/335#discussion_r51403190","pull_request_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/pulls/335","_links":{"self":{"href":"https://api.github.com/repos/alphagov/digitalmarketplace-api/pulls/comments/51403190"},"html":{"href":"https://github.com/alphagov/digitalmarketplace-api/pull/335#discussion_r51403190"},"pull_request":{"href":"https://api.github.com/repos/alphagov/digitalmarketplace-api/pulls/335"}}},"pull_request":{"url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/pulls/335","id":57637420,"html_url":"https://github.com/alphagov/digitalmarketplace-api/pull/335","diff_url":"https://github.com/alphagov/digitalmarketplace-api/pull/335.diff","patch_url":"https://github.com/alphagov/digitalmarketplace-api/pull/335.patch","issue_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/issues/335","number":335,"state":"open","locked":false,"title":"Buyer should be able to write a brief","user":{"login":"robyoung","id":14287,"avatar_url":"https://avatars.githubusercontent.com/u/14287?v=3","gravatar_id":"","url":"https://api.github.com/users/robyoung","html_url":"https://github.com/robyoung","followers_url":"https://api.github.com/users/robyoung/followers","following_url":"https://api.github.com/users/robyoung/following{/other_user}","gists_url":"https://api.github.com/users/robyoung/gists{/gist_id}","starred_url":"https://api.github.com/users/robyoung/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/robyoung/subscriptions","organizations_url":"https://api.github.com/users/robyoung/orgs","repos_url":"https://api.github.com/users/robyoung/repos","events_url":"https://api.github.com/users/robyoung/events{/privacy}","received_events_url":"https://api.github.com/users/robyoung/received_events","type":"User","site_admin":false},"body":"[#111139752](https://www.pivotaltracker.com/story/show/111139752)\r\n\r\nAdds a `Brief` model and routes to create, update, list, get and update the status.\r\n\r\nThere are various constraints around brief creation and modification.\r\n- There is a composite foreign key to `FrameworkLot` to ensure that a brief isn't created for a lot on a different framework.\r\n- Only 'buyer' users can be associated with a brief\r\n- Status must be 'draft' or 'live' and 'live' briefs cannot be turned into 'draft' briefs.\r\n- Briefs can only be created for lots that require briefs (ie. not for G-Cloud lots or studios)\r\n\r\nI have created stub JSON schemas just to allow their integration.\r\n\r\n## depends on\r\n- [x] https://github.com/alphagov/digitalmarketplace-apiclient/pull/6\r\n\r\n","created_at":"2016-01-29T11:41:48Z","updated_at":"2016-02-01T10:48:08Z","closed_at":null,"merged_at":null,"merge_commit_sha":"bd7f3991625b263c26d0357e7962854322ac9923","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/pulls/335/commits","review_comments_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/pulls/335/comments","review_comment_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/pulls/comments{/number}","comments_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/issues/335/comments","statuses_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/statuses/1c22840503c2842124fcaf3fe118e4a6531b3969","head":{"label":"alphagov:buyer-should-be-able-to-write-a-brief","ref":"buyer-should-be-able-to-write-a-brief","sha":"1c22840503c2842124fcaf3fe118e4a6531b3969","user":{"login":"alphagov","id":596977,"avatar_url":"https://avatars.githubusercontent.com/u/596977?v=3","gravatar_id":"","url":"https://api.github.com/users/alphagov","html_url":"https://github.com/alphagov","followers_url":"https://api.github.com/users/alphagov/followers","following_url":"https://api.github.com/users/alphagov/following{/other_user}","gists_url":"https://api.github.com/users/alphagov/gists{/gist_id}","starred_url":"https://api.github.com/users/alphagov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alphagov/subscriptions","organizations_url":"https://api.github.com/users/alphagov/orgs","repos_url":"https://api.github.com/users/alphagov/repos","events_url":"https://api.github.com/users/alphagov/events{/privacy}","received_events_url":"https://api.github.com/users/alphagov/received_events","type":"Organization","site_admin":false},"repo":{"id":26963583,"name":"digitalmarketplace-api","full_name":"alphagov/digitalmarketplace-api","owner":{"login":"alphagov","id":596977,"avatar_url":"https://avatars.githubusercontent.com/u/596977?v=3","gravatar_id":"","url":"https://api.github.com/users/alphagov","html_url":"https://github.com/alphagov","followers_url":"https://api.github.com/users/alphagov/followers","following_url":"https://api.github.com/users/alphagov/following{/other_user}","gists_url":"https://api.github.com/users/alphagov/gists{/gist_id}","starred_url":"https://api.github.com/users/alphagov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alphagov/subscriptions","organizations_url":"https://api.github.com/users/alphagov/orgs","repos_url":"https://api.github.com/users/alphagov/repos","events_url":"https://api.github.com/users/alphagov/events{/privacy}","received_events_url":"https://api.github.com/users/alphagov/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/alphagov/digitalmarketplace-api","description":"Digital Marketplace API.","fork":false,"url":"https://api.github.com/repos/alphagov/digitalmarketplace-api","forks_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/forks","keys_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/keys{/key_id}","collaborators_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/teams","hooks_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/hooks","issue_events_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/issues/events{/number}","events_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/events","assignees_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/assignees{/user}","branches_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/branches{/branch}","tags_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/tags","blobs_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/git/refs{/sha}","trees_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/git/trees{/sha}","statuses_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/statuses/{sha}","languages_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/languages","stargazers_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/stargazers","contributors_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/contributors","subscribers_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/subscribers","subscription_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/subscription","commits_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/commits{/sha}","git_commits_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/git/commits{/sha}","comments_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/comments{/number}","issue_comment_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/issues/comments{/number}","contents_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/contents/{+path}","compare_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/compare/{base}...{head}","merges_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/merges","archive_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/downloads","issues_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/issues{/number}","pulls_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/pulls{/number}","milestones_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/milestones{/number}","notifications_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/labels{/name}","releases_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/releases{/id}","deployments_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/deployments","created_at":"2014-11-21T14:41:36Z","updated_at":"2016-01-12T14:14:23Z","pushed_at":"2016-02-01T10:28:15Z","git_url":"git://github.com/alphagov/digitalmarketplace-api.git","ssh_url":"git@github.com:alphagov/digitalmarketplace-api.git","clone_url":"https://github.com/alphagov/digitalmarketplace-api.git","svn_url":"https://github.com/alphagov/digitalmarketplace-api","homepage":null,"size":1849,"stargazers_count":6,"watchers_count":6,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":5,"mirror_url":null,"open_issues_count":2,"forks":5,"open_issues":2,"watchers":6,"default_branch":"master"}},"base":{"label":"alphagov:master","ref":"master","sha":"696d7b9abfd88d6b5a59b782ef3765759b8b77f2","user":{"login":"alphagov","id":596977,"avatar_url":"https://avatars.githubusercontent.com/u/596977?v=3","gravatar_id":"","url":"https://api.github.com/users/alphagov","html_url":"https://github.com/alphagov","followers_url":"https://api.github.com/users/alphagov/followers","following_url":"https://api.github.com/users/alphagov/following{/other_user}","gists_url":"https://api.github.com/users/alphagov/gists{/gist_id}","starred_url":"https://api.github.com/users/alphagov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alphagov/subscriptions","organizations_url":"https://api.github.com/users/alphagov/orgs","repos_url":"https://api.github.com/users/alphagov/repos","events_url":"https://api.github.com/users/alphagov/events{/privacy}","received_events_url":"https://api.github.com/users/alphagov/received_events","type":"Organization","site_admin":false},"repo":{"id":26963583,"name":"digitalmarketplace-api","full_name":"alphagov/digitalmarketplace-api","owner":{"login":"alphagov","id":596977,"avatar_url":"https://avatars.githubusercontent.com/u/596977?v=3","gravatar_id":"","url":"https://api.github.com/users/alphagov","html_url":"https://github.com/alphagov","followers_url":"https://api.github.com/users/alphagov/followers","following_url":"https://api.github.com/users/alphagov/following{/other_user}","gists_url":"https://api.github.com/users/alphagov/gists{/gist_id}","starred_url":"https://api.github.com/users/alphagov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alphagov/subscriptions","organizations_url":"https://api.github.com/users/alphagov/orgs","repos_url":"https://api.github.com/users/alphagov/repos","events_url":"https://api.github.com/users/alphagov/events{/privacy}","received_events_url":"https://api.github.com/users/alphagov/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/alphagov/digitalmarketplace-api","description":"Digital Marketplace API.","fork":false,"url":"https://api.github.com/repos/alphagov/digitalmarketplace-api","forks_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/forks","keys_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/keys{/key_id}","collaborators_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/teams","hooks_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/hooks","issue_events_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/issues/events{/number}","events_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/events","assignees_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/assignees{/user}","branches_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/branches{/branch}","tags_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/tags","blobs_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/git/refs{/sha}","trees_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/git/trees{/sha}","statuses_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/statuses/{sha}","languages_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/languages","stargazers_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/stargazers","contributors_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/contributors","subscribers_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/subscribers","subscription_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/subscription","commits_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/commits{/sha}","git_commits_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/git/commits{/sha}","comments_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/comments{/number}","issue_comment_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/issues/comments{/number}","contents_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/contents/{+path}","compare_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/compare/{base}...{head}","merges_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/merges","archive_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/downloads","issues_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/issues{/number}","pulls_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/pulls{/number}","milestones_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/milestones{/number}","notifications_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/labels{/name}","releases_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/releases{/id}","deployments_url":"https://api.github.com/repos/alphagov/digitalmarketplace-api/deployments","created_at":"2014-11-21T14:41:36Z","updated_at":"2016-01-12T14:14:23Z","pushed_at":"2016-02-01T10:28:15Z","git_url":"git://github.com/alphagov/digitalmarketplace-api.git","ssh_url":"git@github.com:alphagov/digitalmarketplace-api.git","clone_url":"https://github.com/alphagov/digitalmarketplace-api.git","svn_url":"https://github.com/alphagov/digitalmarketplace-api","homepage":null,"size":1849,"stargazers_count":6,"watchers_count":6,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":5,"mirror_url":null,"open_issues_count":2,"forks":5,"open_issues":2,"watchers":6,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/alphagov/digitalmarketplace-api/pulls/335"},"html":{"href":"https://github.com/alphagov/digitalmarketplace-api/pull/335"},"issue":{"href":"https://api.github.com/repos/alphagov/digitalmarketplace-api/issues/335"},"comments":{"href":"https://api.github.com/repos/alphagov/digitalmarketplace-api/issues/335/comments"},"review_comments":{"href":"https://api.github.com/repos/alphagov/digitalmarketplace-api/pulls/335/comments"},"review_comment":{"href":"https://api.github.com/repos/alphagov/digitalmarketplace-api/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/alphagov/digitalmarketplace-api/pulls/335/commits"},"statuses":{"href":"https://api.github.com/repos/alphagov/digitalmarketplace-api/statuses/1c22840503c2842124fcaf3fe118e4a6531b3969"}}}}