{"action":"created","comment":{"url":"https://api.github.com/repos/edx/edx-video-pipeline/pulls/comments/152020461","pull_request_review_id":77818118,"id":152020461,"diff_hunk":"@@ -125,162 +127,199 @@ def about_video_validate(self, meta, key):\n \n         reset_queries()\n \n-    def studio_s3_ingest(self):\n+    def move(self, key, destination_dir):\n         \"\"\"\n-        Ingest files from studio upload endpoint\n+        Moves an S3 key file to destination directory.\n+\n+        Arguments:\n+            key: An S3 file key.\n+            destination_dir: target directory where the key will be moved eventually.\n         \"\"\"\n-        if self.node_work_directory is None:\n-            ErrorObject().print_error(\n-                message='No Workdir'\n-            )\n-            return\n+        new_key_name = os.path.join(destination_dir, os.path.basename(key.name))\n+        key.copy(self.bucket, new_key_name)\n+        key.delete()\n \n-        conn = boto.connect_s3()\n-        try:\n-            self.bucket = conn.get_bucket(self.auth_dict['edx_s3_ingest_bucket'])\n-        except S3ResponseError:\n-            print 'S3: Ingest Conn Failure'\n-            return\n+    def reject_file_and_update_val(self, key, s3_filename, client_title, course_id):\n+        \"\"\"\n+        Moves a video file to rejected videos, update edx-val to 'invalid_token'.\n+        \"\"\"\n+        video_proto = VideoProto(\n+            s3_filename=s3_filename,\n+            client_title=client_title,\n+            file_extension='',\n+            platform_course_url=course_id\n+        )\n+        # Update val status to 'invalid_token'\n+        VALAPICall(video_proto=video_proto, val_status=u'invalid_token').call()\n+        # Move the video file to 'edx-prod/rejected' directory.\n+        self.move(key, destination_dir=self.auth_dict['edx_s3_rejected_prefix'])\n \n-        for key in self.bucket.list(self.auth_dict['edx_s3_ingest_prefix'], '/'):\n-            meta = self.bucket.get_key(key.name)\n-            self.studio_s3_validate(\n-                meta=meta,\n-                key=key\n-            )\n+    def get_course(self, course_id, course_hex=None):\n+        \"\"\"\n+        Retrieves a course associated with course_hex, course_id or a creates new one.\n \n-    def studio_s3_validate(self, meta, key):\n-        if meta.get_metadata('course_video_upload_token') is None:\n-            return None\n+        Arguments:\n+            course_id: course id identifying a course run\n+            course_hex: studio_hex identifying course runs\n \n-        client_title = meta.get_metadata('client_video_id')\n-        course_hex = meta.get_metadata('course_video_upload_token')\n-        course_url = meta.get_metadata('course_key')\n-        transcript_preferences = meta.get_metadata('transcript_preferences')\n-        edx_filename = key.name[::-1].split('/')[0][::-1]\n+        Details:\n+         - if course_hex is there, try getting course with course_hex.\n+         - else try making use of course_id to get the associated course\n+           and if no course is associated with the course_id, try creating\n+           a new course with course_name, institution, edx_classid and\n+           local_storedir.\n \n-        if len(course_hex) == 0:\n-            return None\n+        \"\"\"\n+        if not course_hex:\n+            try:\n+                course_key = CourseKey.from_string(course_id)\n+            except InvalidKeyError:\n+                return\n+\n+            course_set = Course.objects.filter(institution=course_key.org, edx_classid=course_key.course)\n+            if course_set.exists():\n+                course = course_set.first()\n+                course_runs = course.course_runs\n+                if course_id not in course_runs:\n+                    course_runs.append(course_id)\n+                    course.local_storedir = ','.join(course_runs)\n+                    course.save()\n+            else:\n+                course_name = '{org} {number}'.format(org=course_key.org, number=course_key.course)\n+                course = Course.objects.create(\n+                    course_name=course_name,\n+                    institution=course_key.org,\n+                    edx_classid=course_key.course,\n+                    local_storedir=course_id,\n+                )\n+        else:\n+            try:\n+                course = Course.objects.get(studio_hex=course_hex)\n+            except Course.DoesNotExist:\n+                return\n \n-        course_query = Course.objects.filter(studio_hex=course_hex)\n-        if len(course_query) == 0:\n-            V = VideoProto(\n-                s3_filename=edx_filename,\n-                client_title=client_title,\n-                file_extension='',\n-                platform_course_url=course_url\n-            )\n+        return course\n \n-            \"\"\"\n-            Call VAL Api\n-            \"\"\"\n-            val_status = 'invalid_token'\n-            VAC = VALAPICall(\n-                video_proto=V,\n-                val_status=val_status\n-            )\n-            VAC.call()\n+    def download_video_to_working_directory(self, key, file_name, file_extension):\n+        \"\"\"\n+        Downloads the video to working directory from S3 and\n+        returns whether its successfully downloaded or not.\n+        \"\"\"\n+        if len(file_extension) == 3:\n+            file_name = u'{file_name}.{ext}'.format(file_name=file_name, ext=file_extension)\n \n-            new_key = 'prod-edx/rejected/' + key.name[::-1].split('/')[0][::-1]\n-            key.copy(self.bucket, new_key)\n-            key.delete()\n-            return\n+        try:\n+            key.get_contents_to_filename(os.path.join(self.node_work_directory, file_name))\n+            file_ingested = True\n+        except S3DataError:\n+            file_ingested = False\n+            LOGGER.exception('[File Ingest] Error downloading the file into node working directory.')\n \n-        file_extension = client_title[::-1].split('.')[0][::-1]\n+        return file_ingested\n \n+    def parse_transcript_preferences(self, course_id, transcript_preferences):\n         \"\"\"\n-        download file\n-        \"\"\"\n-        if len(file_extension) == 3:\n-            try:\n-                meta.get_contents_to_filename(\n-                    os.path.join(\n-                        self.node_work_directory,\n-                        edx_filename + '.' + file_extension\n-                    )\n-                )\n-                file_ingested = True\n-            except S3DataError:\n-                print 'File Copy Fail: Studio S3 Ingest'\n-                file_ingested = False\n-        else:\n-            try:\n-                meta.get_contents_to_filename(\n-                    os.path.join(\n-                        self.node_work_directory,\n-                        edx_filename\n-                    )\n-                )\n-                file_ingested = True\n-            except S3DataError:\n-                print 'File Copy Fail: Studio S3 Ingest'\n-                file_ingested = False\n-                file_extension = ''\n-\n-        if file_ingested is not True:\n-            # 's3 Bucket ingest Fail'\n-            new_key = 'prod-edx/rejected/' + key.name[::-1].split('/')[0][::-1]\n-            key.copy(self.bucket, new_key)\n-            key.delete()\n-            return\n+        Parses and validates transcript preferences.\n \n-        # Make decision if this video needs the transcription as well.\n+        Arguments:\n+            course_id: course id identifying a course run.\n+            transcript_preferences: A serialized dict containing third party transcript preferences.\n+        \"\"\"\n         try:\n             transcript_preferences = json.loads(transcript_preferences)\n             TranscriptCredentials.objects.get(\n-                org=extract_course_org(course_url),\n+                org=extract_course_org(course_id),\n                 provider=transcript_preferences.get('provider')\n             )\n-            process_transcription = True\n         except (TypeError, TranscriptCredentials.DoesNotExist):\n             # when the preferences are not set OR these are set to some data in invalid format OR these don't\n             # have associated 3rd party transcription provider API keys.\n-            process_transcription = False\n+            transcript_preferences = None\n         except ValueError:\n-            LOGGER.error('[VIDEO-PIPELINE] File Discovery - Invalid transcripts preferences=%s', transcript_preferences)\n-            process_transcription = False\n+            LOGGER.exception('[File Discovery] Invalid transcripts preferences=%s', transcript_preferences)\n+            transcript_preferences = None\n \n-        # Trigger Ingest Process\n-        video_metadata = dict(\n-            s3_filename=edx_filename,\n-            client_title=client_title,\n-            file_extension=file_extension,\n-            platform_course_url=course_url,\n-        )\n-        if process_transcription:\n-            video_metadata.update({\n-                'process_transcription': process_transcription,\n-                'provider': transcript_preferences.get('provider'),\n-                'three_play_turnaround': transcript_preferences.get('three_play_turnaround'),\n-                'cielo24_turnaround': transcript_preferences.get('cielo24_turnaround'),\n-                'cielo24_fidelity': transcript_preferences.get('cielo24_fidelity'),\n-                'preferred_languages': transcript_preferences.get('preferred_languages'),\n-                'source_language': transcript_preferences.get('video_source_language'),\n-            })\n-\n-        ingest = VedaIngest(\n-            course_object=course_query[0],\n-            video_proto=VideoProto(**video_metadata),\n-            node_work_directory=self.node_work_directory\n-        )\n-        ingest.insert()\n-\n-        if ingest.complete is False:\n-            return\n+        return transcript_preferences\n \n+    def discover_studio_ingested_videos(self):\n         \"\"\"\n-        Delete Original After Copy\n+        Discovers studio ingested videos, for further validations and processes.\n         \"\"\"\n-        if self.auth_dict['edx_s3_ingest_prefix'] is not None:\n-            new_key = 'prod-edx/processed/' + key.name[::-1].split('/')[0][::-1]\n-            key.copy(self.bucket, new_key)\n+        if self.node_work_directory:\n+            try:\n+                connection = boto.connect_s3()\n+                self.bucket = connection.get_bucket(self.auth_dict['edx_s3_ingest_bucket'])\n+                for video_s3_key in self.bucket.list(self.auth_dict['edx_s3_ingest_prefix'], '/'):\n+                    self.validate_and_feed_to_ingest(video_s3_key=self.bucket.get_key(video_s3_key.name))\n+            except S3ResponseError:\n+                ErrorObject.print_error(message='[File Ingest] S3 Ingest Connection Failure')\n+        else:\n+            ErrorObject.print_error(message='[File Ingest] No Working Node directory')\n \n-        key.delete()\n+    def validate_and_feed_to_ingest(self, video_s3_key):\n+        \"\"\"\n+        Validates the video key and feed it to ingestion phase.","path":"control/veda_file_discovery.py","position":276,"original_position":276,"commit_id":"3883ab11ef466ff6ebc9e68ea610dd02827d0a18","original_commit_id":"3883ab11ef466ff6ebc9e68ea610dd02827d0a18","user":{"login":"yro","id":7050866,"avatar_url":"https://avatars1.githubusercontent.com/u/7050866?v=4","gravatar_id":"","url":"https://api.github.com/users/yro","html_url":"https://github.com/yro","followers_url":"https://api.github.com/users/yro/followers","following_url":"https://api.github.com/users/yro/following{/other_user}","gists_url":"https://api.github.com/users/yro/gists{/gist_id}","starred_url":"https://api.github.com/users/yro/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/yro/subscriptions","organizations_url":"https://api.github.com/users/yro/orgs","repos_url":"https://api.github.com/users/yro/repos","events_url":"https://api.github.com/users/yro/events{/privacy}","received_events_url":"https://api.github.com/users/yro/received_events","type":"User","site_admin":false},"body":"Can we rename 'validate' to something else? Usually 'validate' refers to the video file's corruptibility in this repo.","created_at":"2017-11-20T15:24:12Z","updated_at":"2017-11-20T15:24:12Z","html_url":"https://github.com/edx/edx-video-pipeline/pull/69#discussion_r152020461","pull_request_url":"https://api.github.com/repos/edx/edx-video-pipeline/pulls/69","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/edx/edx-video-pipeline/pulls/comments/152020461"},"html":{"href":"https://github.com/edx/edx-video-pipeline/pull/69#discussion_r152020461"},"pull_request":{"href":"https://api.github.com/repos/edx/edx-video-pipeline/pulls/69"}}},"pull_request":{"url":"https://api.github.com/repos/edx/edx-video-pipeline/pulls/69","id":153327167,"html_url":"https://github.com/edx/edx-video-pipeline/pull/69","diff_url":"https://github.com/edx/edx-video-pipeline/pull/69.diff","patch_url":"https://github.com/edx/edx-video-pipeline/pull/69.patch","issue_url":"https://api.github.com/repos/edx/edx-video-pipeline/issues/69","number":69,"state":"open","locked":false,"title":"[File Discovery]  Course can be fetched/created without a course_hex","user":{"login":"Qubad786","id":7848408,"avatar_url":"https://avatars3.githubusercontent.com/u/7848408?v=4","gravatar_id":"","url":"https://api.github.com/users/Qubad786","html_url":"https://github.com/Qubad786","followers_url":"https://api.github.com/users/Qubad786/followers","following_url":"https://api.github.com/users/Qubad786/following{/other_user}","gists_url":"https://api.github.com/users/Qubad786/gists{/gist_id}","starred_url":"https://api.github.com/users/Qubad786/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Qubad786/subscriptions","organizations_url":"https://api.github.com/users/Qubad786/orgs","repos_url":"https://api.github.com/users/Qubad786/repos","events_url":"https://api.github.com/users/Qubad786/events{/privacy}","received_events_url":"https://api.github.com/users/Qubad786/received_events","type":"User","site_admin":false},"body":" - Course retrieval/creation can be done via `course_id` alone. No hard and fast dependency for `course_hex` except for the courses with youtube dependency.\r\n -  This rewrites File Discovery phase related to Studio along with relevant tests.","created_at":"2017-11-17T15:39:15Z","updated_at":"2017-11-20T15:24:12Z","closed_at":null,"merged_at":null,"merge_commit_sha":"81437b80f0cad51414f34a07b2ff82febf79acfd","assignee":null,"assignees":[],"requested_reviewers":[],"milestone":null,"commits_url":"https://api.github.com/repos/edx/edx-video-pipeline/pulls/69/commits","review_comments_url":"https://api.github.com/repos/edx/edx-video-pipeline/pulls/69/comments","review_comment_url":"https://api.github.com/repos/edx/edx-video-pipeline/pulls/comments{/number}","comments_url":"https://api.github.com/repos/edx/edx-video-pipeline/issues/69/comments","statuses_url":"https://api.github.com/repos/edx/edx-video-pipeline/statuses/3883ab11ef466ff6ebc9e68ea610dd02827d0a18","head":{"label":"edx:mrehan/course-hex-dependency","ref":"mrehan/course-hex-dependency","sha":"3883ab11ef466ff6ebc9e68ea610dd02827d0a18","user":{"login":"edx","id":3179841,"avatar_url":"https://avatars3.githubusercontent.com/u/3179841?v=4","gravatar_id":"","url":"https://api.github.com/users/edx","html_url":"https://github.com/edx","followers_url":"https://api.github.com/users/edx/followers","following_url":"https://api.github.com/users/edx/following{/other_user}","gists_url":"https://api.github.com/users/edx/gists{/gist_id}","starred_url":"https://api.github.com/users/edx/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/edx/subscriptions","organizations_url":"https://api.github.com/users/edx/orgs","repos_url":"https://api.github.com/users/edx/repos","events_url":"https://api.github.com/users/edx/events{/privacy}","received_events_url":"https://api.github.com/users/edx/received_events","type":"Organization","site_admin":false},"repo":{"id":96140633,"name":"edx-video-pipeline","full_name":"edx/edx-video-pipeline","owner":{"login":"edx","id":3179841,"avatar_url":"https://avatars3.githubusercontent.com/u/3179841?v=4","gravatar_id":"","url":"https://api.github.com/users/edx","html_url":"https://github.com/edx","followers_url":"https://api.github.com/users/edx/followers","following_url":"https://api.github.com/users/edx/following{/other_user}","gists_url":"https://api.github.com/users/edx/gists{/gist_id}","starred_url":"https://api.github.com/users/edx/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/edx/subscriptions","organizations_url":"https://api.github.com/users/edx/orgs","repos_url":"https://api.github.com/users/edx/repos","events_url":"https://api.github.com/users/edx/events{/privacy}","received_events_url":"https://api.github.com/users/edx/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/edx/edx-video-pipeline","description":"Video encode automation for edx-platform","fork":false,"url":"https://api.github.com/repos/edx/edx-video-pipeline","forks_url":"https://api.github.com/repos/edx/edx-video-pipeline/forks","keys_url":"https://api.github.com/repos/edx/edx-video-pipeline/keys{/key_id}","collaborators_url":"https://api.github.com/repos/edx/edx-video-pipeline/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/edx/edx-video-pipeline/teams","hooks_url":"https://api.github.com/repos/edx/edx-video-pipeline/hooks","issue_events_url":"https://api.github.com/repos/edx/edx-video-pipeline/issues/events{/number}","events_url":"https://api.github.com/repos/edx/edx-video-pipeline/events","assignees_url":"https://api.github.com/repos/edx/edx-video-pipeline/assignees{/user}","branches_url":"https://api.github.com/repos/edx/edx-video-pipeline/branches{/branch}","tags_url":"https://api.github.com/repos/edx/edx-video-pipeline/tags","blobs_url":"https://api.github.com/repos/edx/edx-video-pipeline/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/edx/edx-video-pipeline/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/edx/edx-video-pipeline/git/refs{/sha}","trees_url":"https://api.github.com/repos/edx/edx-video-pipeline/git/trees{/sha}","statuses_url":"https://api.github.com/repos/edx/edx-video-pipeline/statuses/{sha}","languages_url":"https://api.github.com/repos/edx/edx-video-pipeline/languages","stargazers_url":"https://api.github.com/repos/edx/edx-video-pipeline/stargazers","contributors_url":"https://api.github.com/repos/edx/edx-video-pipeline/contributors","subscribers_url":"https://api.github.com/repos/edx/edx-video-pipeline/subscribers","subscription_url":"https://api.github.com/repos/edx/edx-video-pipeline/subscription","commits_url":"https://api.github.com/repos/edx/edx-video-pipeline/commits{/sha}","git_commits_url":"https://api.github.com/repos/edx/edx-video-pipeline/git/commits{/sha}","comments_url":"https://api.github.com/repos/edx/edx-video-pipeline/comments{/number}","issue_comment_url":"https://api.github.com/repos/edx/edx-video-pipeline/issues/comments{/number}","contents_url":"https://api.github.com/repos/edx/edx-video-pipeline/contents/{+path}","compare_url":"https://api.github.com/repos/edx/edx-video-pipeline/compare/{base}...{head}","merges_url":"https://api.github.com/repos/edx/edx-video-pipeline/merges","archive_url":"https://api.github.com/repos/edx/edx-video-pipeline/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/edx/edx-video-pipeline/downloads","issues_url":"https://api.github.com/repos/edx/edx-video-pipeline/issues{/number}","pulls_url":"https://api.github.com/repos/edx/edx-video-pipeline/pulls{/number}","milestones_url":"https://api.github.com/repos/edx/edx-video-pipeline/milestones{/number}","notifications_url":"https://api.github.com/repos/edx/edx-video-pipeline/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/edx/edx-video-pipeline/labels{/name}","releases_url":"https://api.github.com/repos/edx/edx-video-pipeline/releases{/id}","deployments_url":"https://api.github.com/repos/edx/edx-video-pipeline/deployments","created_at":"2017-07-03T18:46:34Z","updated_at":"2017-11-02T10:32:00Z","pushed_at":"2017-11-17T19:14:26Z","git_url":"git://github.com/edx/edx-video-pipeline.git","ssh_url":"git@github.com:edx/edx-video-pipeline.git","clone_url":"https://github.com/edx/edx-video-pipeline.git","svn_url":"https://github.com/edx/edx-video-pipeline","homepage":"","size":4591,"stargazers_count":5,"watchers_count":5,"language":"Python","has_issues":false,"has_projects":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":2,"mirror_url":null,"archived":false,"open_issues_count":3,"forks":2,"open_issues":3,"watchers":5,"default_branch":"master"}},"base":{"label":"edx:master","ref":"master","sha":"89d4920e60f1965c3d4d5f1060179369b3b6aba3","user":{"login":"edx","id":3179841,"avatar_url":"https://avatars3.githubusercontent.com/u/3179841?v=4","gravatar_id":"","url":"https://api.github.com/users/edx","html_url":"https://github.com/edx","followers_url":"https://api.github.com/users/edx/followers","following_url":"https://api.github.com/users/edx/following{/other_user}","gists_url":"https://api.github.com/users/edx/gists{/gist_id}","starred_url":"https://api.github.com/users/edx/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/edx/subscriptions","organizations_url":"https://api.github.com/users/edx/orgs","repos_url":"https://api.github.com/users/edx/repos","events_url":"https://api.github.com/users/edx/events{/privacy}","received_events_url":"https://api.github.com/users/edx/received_events","type":"Organization","site_admin":false},"repo":{"id":96140633,"name":"edx-video-pipeline","full_name":"edx/edx-video-pipeline","owner":{"login":"edx","id":3179841,"avatar_url":"https://avatars3.githubusercontent.com/u/3179841?v=4","gravatar_id":"","url":"https://api.github.com/users/edx","html_url":"https://github.com/edx","followers_url":"https://api.github.com/users/edx/followers","following_url":"https://api.github.com/users/edx/following{/other_user}","gists_url":"https://api.github.com/users/edx/gists{/gist_id}","starred_url":"https://api.github.com/users/edx/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/edx/subscriptions","organizations_url":"https://api.github.com/users/edx/orgs","repos_url":"https://api.github.com/users/edx/repos","events_url":"https://api.github.com/users/edx/events{/privacy}","received_events_url":"https://api.github.com/users/edx/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/edx/edx-video-pipeline","description":"Video encode automation for edx-platform","fork":false,"url":"https://api.github.com/repos/edx/edx-video-pipeline","forks_url":"https://api.github.com/repos/edx/edx-video-pipeline/forks","keys_url":"https://api.github.com/repos/edx/edx-video-pipeline/keys{/key_id}","collaborators_url":"https://api.github.com/repos/edx/edx-video-pipeline/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/edx/edx-video-pipeline/teams","hooks_url":"https://api.github.com/repos/edx/edx-video-pipeline/hooks","issue_events_url":"https://api.github.com/repos/edx/edx-video-pipeline/issues/events{/number}","events_url":"https://api.github.com/repos/edx/edx-video-pipeline/events","assignees_url":"https://api.github.com/repos/edx/edx-video-pipeline/assignees{/user}","branches_url":"https://api.github.com/repos/edx/edx-video-pipeline/branches{/branch}","tags_url":"https://api.github.com/repos/edx/edx-video-pipeline/tags","blobs_url":"https://api.github.com/repos/edx/edx-video-pipeline/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/edx/edx-video-pipeline/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/edx/edx-video-pipeline/git/refs{/sha}","trees_url":"https://api.github.com/repos/edx/edx-video-pipeline/git/trees{/sha}","statuses_url":"https://api.github.com/repos/edx/edx-video-pipeline/statuses/{sha}","languages_url":"https://api.github.com/repos/edx/edx-video-pipeline/languages","stargazers_url":"https://api.github.com/repos/edx/edx-video-pipeline/stargazers","contributors_url":"https://api.github.com/repos/edx/edx-video-pipeline/contributors","subscribers_url":"https://api.github.com/repos/edx/edx-video-pipeline/subscribers","subscription_url":"https://api.github.com/repos/edx/edx-video-pipeline/subscription","commits_url":"https://api.github.com/repos/edx/edx-video-pipeline/commits{/sha}","git_commits_url":"https://api.github.com/repos/edx/edx-video-pipeline/git/commits{/sha}","comments_url":"https://api.github.com/repos/edx/edx-video-pipeline/comments{/number}","issue_comment_url":"https://api.github.com/repos/edx/edx-video-pipeline/issues/comments{/number}","contents_url":"https://api.github.com/repos/edx/edx-video-pipeline/contents/{+path}","compare_url":"https://api.github.com/repos/edx/edx-video-pipeline/compare/{base}...{head}","merges_url":"https://api.github.com/repos/edx/edx-video-pipeline/merges","archive_url":"https://api.github.com/repos/edx/edx-video-pipeline/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/edx/edx-video-pipeline/downloads","issues_url":"https://api.github.com/repos/edx/edx-video-pipeline/issues{/number}","pulls_url":"https://api.github.com/repos/edx/edx-video-pipeline/pulls{/number}","milestones_url":"https://api.github.com/repos/edx/edx-video-pipeline/milestones{/number}","notifications_url":"https://api.github.com/repos/edx/edx-video-pipeline/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/edx/edx-video-pipeline/labels{/name}","releases_url":"https://api.github.com/repos/edx/edx-video-pipeline/releases{/id}","deployments_url":"https://api.github.com/repos/edx/edx-video-pipeline/deployments","created_at":"2017-07-03T18:46:34Z","updated_at":"2017-11-02T10:32:00Z","pushed_at":"2017-11-17T19:14:26Z","git_url":"git://github.com/edx/edx-video-pipeline.git","ssh_url":"git@github.com:edx/edx-video-pipeline.git","clone_url":"https://github.com/edx/edx-video-pipeline.git","svn_url":"https://github.com/edx/edx-video-pipeline","homepage":"","size":4591,"stargazers_count":5,"watchers_count":5,"language":"Python","has_issues":false,"has_projects":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":2,"mirror_url":null,"archived":false,"open_issues_count":3,"forks":2,"open_issues":3,"watchers":5,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/edx/edx-video-pipeline/pulls/69"},"html":{"href":"https://github.com/edx/edx-video-pipeline/pull/69"},"issue":{"href":"https://api.github.com/repos/edx/edx-video-pipeline/issues/69"},"comments":{"href":"https://api.github.com/repos/edx/edx-video-pipeline/issues/69/comments"},"review_comments":{"href":"https://api.github.com/repos/edx/edx-video-pipeline/pulls/69/comments"},"review_comment":{"href":"https://api.github.com/repos/edx/edx-video-pipeline/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/edx/edx-video-pipeline/pulls/69/commits"},"statuses":{"href":"https://api.github.com/repos/edx/edx-video-pipeline/statuses/3883ab11ef466ff6ebc9e68ea610dd02827d0a18"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"yro"}}