https
GET
api.github.com
None
/repos/edx/edx-platform/commits/74e70119a23fa3ffb3db19d4590eccfebd72b659
{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'}
null
200
[('content-length', '18854'), ('vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding'), ('x-served-by', '593010132f82159af0ded24b4932e109'), ('x-oauth-scopes', 'notifications, public_repo, read:org, read:public_key, read:repo_hook, repo:status, repo_deployment'), ('x-xss-protection', '1; mode=block'), ('x-content-type-options', 'nosniff'), ('x-accepted-oauth-scopes', ''), ('etag', '"8e937a4cbcbaef182ddf483ee99a599f"'), ('access-control-allow-credentials', 'true'), ('status', '200 OK'), ('x-ratelimit-remaining', '4993'), ('x-github-media-type', 'github.v3; format=json'), ('access-control-expose-headers', 'ETag, Link, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('x-github-request-id', '12B0076B:2073:5CF629E:56A6A81E'), ('cache-control', 'private, max-age=60, s-maxage=60'), ('last-modified', 'Mon, 14 Dec 2015 12:42:38 GMT'), ('date', 'Mon, 25 Jan 2016 22:56:31 GMT'), ('access-control-allow-origin', '*'), ('content-security-policy', "default-src 'none'"), ('strict-transport-security', 'max-age=31536000; includeSubdomains; preload'), ('server', 'GitHub.com'), ('x-ratelimit-limit', '5000'), ('x-frame-options', 'deny'), ('content-type', 'application/json; charset=utf-8'), ('x-ratelimit-reset', '1453765330')]
{"sha":"74e70119a23fa3ffb3db19d4590eccfebd72b659","commit":{"author":{"name":"John Eskew","email":"jeskew@edx.org","date":"2015-12-04T22:39:27Z"},"committer":{"name":"John Eskew","email":"jeskew@edx.org","date":"2015-12-14T12:42:38Z"},"message":"Use a common MongoDB connection function.\nAdd some missing @autoretry_read() decorators.\nChange to PyMongo 3.x-compatible syntax.","tree":{"sha":"7712c0f7c0c21f706bcbed393f3de71d854d59df","url":"https://api.github.com/repos/edx/edx-platform/git/trees/7712c0f7c0c21f706bcbed393f3de71d854d59df"},"url":"https://api.github.com/repos/edx/edx-platform/git/commits/74e70119a23fa3ffb3db19d4590eccfebd72b659","comment_count":0},"url":"https://api.github.com/repos/edx/edx-platform/commits/74e70119a23fa3ffb3db19d4590eccfebd72b659","html_url":"https://github.com/edx/edx-platform/commit/74e70119a23fa3ffb3db19d4590eccfebd72b659","comments_url":"https://api.github.com/repos/edx/edx-platform/commits/74e70119a23fa3ffb3db19d4590eccfebd72b659/comments","author":{"login":"doctoryes","id":7285237,"avatar_url":"https://avatars.githubusercontent.com/u/7285237?v=3","gravatar_id":"","url":"https://api.github.com/users/doctoryes","html_url":"https://github.com/doctoryes","followers_url":"https://api.github.com/users/doctoryes/followers","following_url":"https://api.github.com/users/doctoryes/following{/other_user}","gists_url":"https://api.github.com/users/doctoryes/gists{/gist_id}","starred_url":"https://api.github.com/users/doctoryes/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/doctoryes/subscriptions","organizations_url":"https://api.github.com/users/doctoryes/orgs","repos_url":"https://api.github.com/users/doctoryes/repos","events_url":"https://api.github.com/users/doctoryes/events{/privacy}","received_events_url":"https://api.github.com/users/doctoryes/received_events","type":"User","site_admin":false},"committer":{"login":"doctoryes","id":7285237,"avatar_url":"https://avatars.githubusercontent.com/u/7285237?v=3","gravatar_id":"","url":"https://api.github.com/users/doctoryes","html_url":"https://github.com/doctoryes","followers_url":"https://api.github.com/users/doctoryes/followers","following_url":"https://api.github.com/users/doctoryes/following{/other_user}","gists_url":"https://api.github.com/users/doctoryes/gists{/gist_id}","starred_url":"https://api.github.com/users/doctoryes/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/doctoryes/subscriptions","organizations_url":"https://api.github.com/users/doctoryes/orgs","repos_url":"https://api.github.com/users/doctoryes/repos","events_url":"https://api.github.com/users/doctoryes/events{/privacy}","received_events_url":"https://api.github.com/users/doctoryes/received_events","type":"User","site_admin":false},"parents":[{"sha":"86227e7711c011490f1db6fdfcc17401511e5ee5","url":"https://api.github.com/repos/edx/edx-platform/commits/86227e7711c011490f1db6fdfcc17401511e5ee5","html_url":"https://github.com/edx/edx-platform/commit/86227e7711c011490f1db6fdfcc17401511e5ee5"}],"stats":{"total":192,"additions":112,"deletions":80},"files":[{"sha":"56ccd039ccff39e297523966c340f1be74876af8","filename":"common/lib/xmodule/xmodule/contentstore/mongo.py","status":"modified","additions":34,"deletions":30,"changes":64,"blob_url":"https://github.com/edx/edx-platform/blob/74e70119a23fa3ffb3db19d4590eccfebd72b659/common/lib/xmodule/xmodule/contentstore/mongo.py","raw_url":"https://github.com/edx/edx-platform/raw/74e70119a23fa3ffb3db19d4590eccfebd72b659/common/lib/xmodule/xmodule/contentstore/mongo.py","contents_url":"https://api.github.com/repos/edx/edx-platform/contents/common/lib/xmodule/xmodule/contentstore/mongo.py?ref=74e70119a23fa3ffb3db19d4590eccfebd72b659","patch":"@@ -1,52 +1,50 @@\n+\"\"\"\n+MongoDB/GridFS-level code for the contentstore.\n+\"\"\"\n+import os\n+import json\n import pymongo\n import gridfs\n from gridfs.errors import NoFile\n-\n-from xmodule.contentstore.content import XASSET_LOCATION_TAG\n-\n-import logging\n-\n-from .content import StaticContent, ContentStore, StaticContentStream\n-from xmodule.exceptions import NotFoundError\n from fs.osfs import OSFS\n-import os\n-import json\n from bson.son import SON\n+\n+from mongodb_proxy import autoretry_read\n from opaque_keys.edx.keys import AssetKey\n+from xmodule.contentstore.content import XASSET_LOCATION_TAG\n+from xmodule.exceptions import NotFoundError\n from xmodule.modulestore.django import ASSET_IGNORE_REGEX\n from xmodule.util.misc import escape_invalid_characters\n+from xmodule.mongo_connection import connect_to_mongodb\n+from .content import StaticContent, ContentStore, StaticContentStream\n \n \n class MongoContentStore(ContentStore):\n-\n-    # pylint: disable=unused-argument\n-    def __init__(self, host, db, port=27017, user=None, password=None, bucket='fs', collection=None, **kwargs):\n+    \"\"\"\n+    MongoDB-backed ContentStore.\n+    \"\"\"\n+    # pylint: disable=unused-argument, bad-continuation\n+    def __init__(\n+        self, host, db,\n+        port=27017, tz_aware=True, user=None, password=None, bucket='fs', collection=None, **kwargs\n+    ):\n         \"\"\"\n         Establish the connection with the mongo backend and connect to the collections\n \n         :param collection: ignores but provided for consistency w/ other doc_store_config patterns\n         \"\"\"\n-        logging.debug('Using MongoDB for static content serving at host={0} port={1} db={2}'.format(host, port, db))\n-\n-        # Remove the replicaSet parameter.\n-        kwargs.pop('replicaSet', None)\n-\n-        _db = pymongo.database.Database(\n-            pymongo.MongoClient(\n-                host=host,\n-                port=port,\n-                document_class=dict,\n-                **kwargs\n-            ),\n-            db\n+        # GridFS will throw an exception if the Database is wrapped in a MongoProxy. So don't wrap it.\n+        # The appropriate methods below are marked as autoretry_read - those methods will handle\n+        # the AutoReconnect errors.\n+        proxy = False\n+        mongo_db = connect_to_mongodb(\n+            db, host,\n+            port=port, tz_aware=tz_aware, user=user, password=password, proxy=proxy, **kwargs\n         )\n \n-        if user is not None and password is not None:\n-            _db.authenticate(user, password)\n-\n-        self.fs = gridfs.GridFS(_db, bucket)\n+        self.fs = gridfs.GridFS(mongo_db, bucket)  # pylint: disable=invalid-name\n \n-        self.fs_files = _db[bucket + \".files\"]  # the underlying collection GridFS uses\n+        self.fs_files = mongo_db[bucket + \".files\"]  # the underlying collection GridFS uses\n \n     def close_connections(self):\n         \"\"\"\n@@ -86,11 +84,15 @@ def save(self, content):\n         return content\n \n     def delete(self, location_or_id):\n+        \"\"\"\n+        Delete an asset.\n+        \"\"\"\n         if isinstance(location_or_id, AssetKey):\n             location_or_id, _ = self.asset_db_key(location_or_id)\n         # Deletes of non-existent files are considered successful\n         self.fs.delete(location_or_id)\n \n+    @autoretry_read()\n     def find(self, location, throw_on_not_found=True, as_stream=False):\n         content_id, __ = self.asset_db_key(location)\n \n@@ -206,6 +208,7 @@ def remove_redundant_content_for_courses(self):\n             self.fs_files.remove(query)\n         return assets_to_delete\n \n+    @autoretry_read()\n     def _get_all_content_for_course(self,\n                                     course_key,\n                                     get_thumbnails=False,\n@@ -288,6 +291,7 @@ def set_attrs(self, location, attr_dict):\n         if not result.get('updatedExisting', True):\n             raise NotFoundError(asset_db_key)\n \n+    @autoretry_read()\n     def get_attrs(self, location):\n         \"\"\"\n         Gets all of the attributes associated with the given asset. Note, returns even built in attrs"},{"sha":"4bcdfa15a878dc6b413ab093f5edc685096c1dfa","filename":"common/lib/xmodule/xmodule/modulestore/mongo/base.py","status":"modified","additions":15,"deletions":24,"changes":39,"blob_url":"https://github.com/edx/edx-platform/blob/74e70119a23fa3ffb3db19d4590eccfebd72b659/common/lib/xmodule/xmodule/modulestore/mongo/base.py","raw_url":"https://github.com/edx/edx-platform/raw/74e70119a23fa3ffb3db19d4590eccfebd72b659/common/lib/xmodule/xmodule/modulestore/mongo/base.py","contents_url":"https://api.github.com/repos/edx/edx-platform/contents/common/lib/xmodule/xmodule/modulestore/mongo/base.py?ref=74e70119a23fa3ffb3db19d4590eccfebd72b659","patch":"@@ -22,7 +22,7 @@\n from bson.son import SON\n from datetime import datetime\n from fs.osfs import OSFS\n-from mongodb_proxy import MongoProxy, autoretry_read\n+from mongodb_proxy import autoretry_read\n from path import Path as path\n from pytz import UTC\n from contracts import contract, new_contract\n@@ -43,6 +43,7 @@\n from xmodule.errortracker import null_error_tracker, exc_info_to_str\n from xmodule.exceptions import HeartbeatFailure\n from xmodule.mako_module import MakoDescriptorSystem\n+from xmodule.mongo_connection import connect_to_mongodb\n from xmodule.modulestore import ModuleStoreWriteBase, ModuleStoreEnum, BulkOperationsMixin, BulkOpsRecord\n from xmodule.modulestore.draft_and_published import ModuleStoreDraftAndPublished, DIRECT_ONLY_CATEGORIES\n from xmodule.modulestore.edit_info import EditInfoRuntimeMixin\n@@ -558,22 +559,16 @@ def do_connection(\n             \"\"\"\n             Create & open the connection, authenticate, and provide pointers to the collection\n             \"\"\"\n-            # Remove the replicaSet parameter.\n-            kwargs.pop('replicaSet', None)\n-\n-            self.database = MongoProxy(\n-                pymongo.database.Database(\n-                    pymongo.MongoClient(\n-                        host=host,\n-                        port=port,\n-                        tz_aware=tz_aware,\n-                        document_class=dict,\n-                        **kwargs\n-                    ),\n-                    db\n-                ),\n-                wait_time=retry_wait_time\n+            # Set a write concern of 1, which makes writes complete successfully to the primary\n+            # only before returning. Also makes pymongo report write errors.\n+            kwargs['w'] = 1\n+\n+            self.database = connect_to_mongodb(\n+                db, host,\n+                port=port, tz_aware=tz_aware, user=user, password=password,\n+                retry_wait_time=retry_wait_time, **kwargs\n             )\n+\n             self.collection = self.database[collection]\n \n             # Collection which stores asset metadata.\n@@ -581,14 +576,8 @@ def do_connection(\n                 asset_collection = self.DEFAULT_ASSET_COLLECTION_NAME\n             self.asset_collection = self.database[asset_collection]\n \n-            if user is not None and password is not None:\n-                self.database.authenticate(user, password)\n-\n         do_connection(**doc_store_config)\n \n-        # Force mongo to report errors, at the expense of performance\n-        self.collection.write_concern = {'w': 1}\n-\n         if default_class is not None:\n             module_path, _, class_name = default_class.rpartition('.')\n             class_ = getattr(import_module(module_path), class_name)\n@@ -1012,6 +1001,7 @@ def get_courses(self, **kwargs):\n         )\n         return [course for course in base_list if not isinstance(course, ErrorDescriptor)]\n \n+    @autoretry_read()\n     def _find_one(self, location):\n         '''Look for a given location in the collection. If the item is not present, raise\n         ItemNotFoundError.\n@@ -1052,6 +1042,7 @@ def get_course(self, course_key, depth=0, **kwargs):\n         except ItemNotFoundError:\n             return None\n \n+    @autoretry_read()\n     def has_course(self, course_key, ignore_case=False, **kwargs):\n         \"\"\"\n         Returns the course_id of the course if it was found, else None\n@@ -1073,7 +1064,7 @@ def has_course(self, course_key, ignore_case=False, **kwargs):\n                     course_query[key] = re.compile(r\"(?i)^{}$\".format(course_query[key]))\n         else:\n             course_query = {'_id': location.to_deprecated_son()}\n-        course = self.collection.find_one(course_query, fields={'_id': True})\n+        course = self.collection.find_one(course_query, projection={'_id': True})\n         if course:\n             return SlashSeparatedCourseKey(course['_id']['org'], course['_id']['course'], course['_id']['name'])\n         else:\n@@ -1234,7 +1225,7 @@ def create_course(self, org, course, run, user_id, fields=None, **kwargs):\n             ('_id.course', re.compile(u'^{}$'.format(course_id.course), re.IGNORECASE)),\n             ('_id.category', 'course'),\n         ])\n-        courses = self.collection.find(course_search_location, fields=('_id'))\n+        courses = self.collection.find(course_search_location, projection={'_id': True})\n         if courses.count() > 0:\n             raise DuplicateCourseError(course_id, courses[0]['_id'])\n "},{"sha":"1352ee95cd39a611a21a2e17dbc70da9b31af433","filename":"common/lib/xmodule/xmodule/modulestore/split_mongo/mongo_connection.py","status":"modified","additions":10,"deletions":26,"changes":36,"blob_url":"https://github.com/edx/edx-platform/blob/74e70119a23fa3ffb3db19d4590eccfebd72b659/common/lib/xmodule/xmodule/modulestore/split_mongo/mongo_connection.py","raw_url":"https://github.com/edx/edx-platform/raw/74e70119a23fa3ffb3db19d4590eccfebd72b659/common/lib/xmodule/xmodule/modulestore/split_mongo/mongo_connection.py","contents_url":"https://api.github.com/repos/edx/edx-platform/contents/common/lib/xmodule/xmodule/modulestore/split_mongo/mongo_connection.py?ref=74e70119a23fa3ffb3db19d4590eccfebd72b659","patch":"@@ -23,10 +23,11 @@\n import dogstats_wrapper as dog_stats_api\n \n from contracts import check, new_contract\n-from mongodb_proxy import autoretry_read, MongoProxy\n+from mongodb_proxy import autoretry_read\n from xmodule.exceptions import HeartbeatFailure\n from xmodule.modulestore import BlockData\n from xmodule.modulestore.split_mongo import BlockKey\n+from xmodule.mongo_connection import connect_to_mongodb\n \n \n new_contract('BlockData', BlockData)\n@@ -287,37 +288,20 @@ def __init__(\n         \"\"\"\n         Create & open the connection, authenticate, and provide pointers to the collections\n         \"\"\"\n-        if kwargs.get('replicaSet') is None:\n-            kwargs.pop('replicaSet', None)\n-            mongo_class = pymongo.MongoClient\n-        else:\n-            mongo_class = pymongo.MongoReplicaSetClient\n-        _client = mongo_class(\n-            host=host,\n-            port=port,\n-            tz_aware=tz_aware,\n-            **kwargs\n-        )\n-        self.database = MongoProxy(\n-            pymongo.database.Database(_client, db),\n-            wait_time=retry_wait_time\n-        )\n+        # Set a write concern of 1, which makes writes complete successfully to the primary\n+        # only before returning. Also makes pymongo report write errors.\n+        kwargs['w'] = 1\n \n-        if user is not None and password is not None:\n-            self.database.authenticate(user, password)\n+        self.database = connect_to_mongodb(\n+            db, host,\n+            port=port, tz_aware=tz_aware, user=user, password=password,\n+            retry_wait_time=retry_wait_time, **kwargs\n+        )\n \n         self.course_index = self.database[collection + '.active_versions']\n         self.structures = self.database[collection + '.structures']\n         self.definitions = self.database[collection + '.definitions']\n \n-        # every app has write access to the db (v having a flag to indicate r/o v write)\n-        # Force mongo to report errors, at the expense of performance\n-        # pymongo docs suck but explanation:\n-        # http://api.mongodb.org/java/2.10.1/com/mongodb/WriteConcern.html\n-        self.course_index.write_concern = {'w': 1}\n-        self.structures.write_concern = {'w': 1}\n-        self.definitions.write_concern = {'w': 1}\n-\n     def heartbeat(self):\n         \"\"\"\n         Check that the db is reachable."},{"sha":"ea353a60b6af9226ce7676495d9572831d99fbd9","filename":"common/lib/xmodule/xmodule/mongo_connection.py","status":"added","additions":53,"deletions":0,"changes":53,"blob_url":"https://github.com/edx/edx-platform/blob/74e70119a23fa3ffb3db19d4590eccfebd72b659/common/lib/xmodule/xmodule/mongo_connection.py","raw_url":"https://github.com/edx/edx-platform/raw/74e70119a23fa3ffb3db19d4590eccfebd72b659/common/lib/xmodule/xmodule/mongo_connection.py","contents_url":"https://api.github.com/repos/edx/edx-platform/contents/common/lib/xmodule/xmodule/mongo_connection.py?ref=74e70119a23fa3ffb3db19d4590eccfebd72b659","patch":"@@ -0,0 +1,53 @@\n+\"\"\"\n+Common MongoDB connection functions.\n+\"\"\"\n+import pymongo\n+from mongodb_proxy import MongoProxy\n+\n+\n+# pylint: disable=bad-continuation\n+def connect_to_mongodb(\n+    db, host,\n+    port=27017, tz_aware=True, user=None, password=None,\n+    retry_wait_time=0.1, proxy=True, **kwargs\n+):\n+    \"\"\"\n+    Returns a MongoDB Database connection, optionally wrapped in a proxy. The proxy\n+    handles AutoReconnect errors by retrying read operations, since these exceptions\n+    typically indicate a temporary step-down condition for MongoDB.\n+    \"\"\"\n+    # The MongoReplicaSetClient class is deprecated in Mongo 3.x, in favor of using\n+    # the MongoClient class for all connections. Update/simplify this code when using\n+    # PyMongo 3.x.\n+    if kwargs.get('replicaSet'):\n+        # Enable reading from secondary nodes in the MongoDB replicaset by using the\n+        # MongoReplicaSetClient class.\n+        # The 'replicaSet' parameter in kwargs is required for secondary reads.\n+        # The read_preference should be set to a proper value, like SECONDARY_PREFERRED.\n+        mongo_client_class = pymongo.MongoReplicaSetClient\n+    else:\n+        # No 'replicaSet' in kwargs - so no secondary reads.\n+        mongo_client_class = pymongo.MongoClient\n+\n+    mongo_conn = pymongo.database.Database(\n+        mongo_client_class(\n+            host=host,\n+            port=port,\n+            tz_aware=tz_aware,\n+            document_class=dict,\n+            **kwargs\n+        ),\n+        db\n+    )\n+\n+    if proxy:\n+        mongo_conn = MongoProxy(\n+            mongo_conn,\n+            wait_time=retry_wait_time\n+        )\n+\n+    # If credentials were provided, authenticate the user.\n+    if user is not None and password is not None:\n+        mongo_conn.authenticate(user, password)\n+\n+    return mongo_conn"}]}

https
GET
api.github.com
None
/repos/edx/edx-platform/commits/74e70119a23fa3ffb3db19d4590eccfebd72b659/status
{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'}
null
200
[('content-length', '6365'), ('vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding'), ('x-served-by', '3e3b9690823fb031da84658eb58aa83b'), ('x-oauth-scopes', 'notifications, public_repo, read:org, read:public_key, read:repo_hook, repo:status, repo_deployment'), ('x-xss-protection', '1; mode=block'), ('x-content-type-options', 'nosniff'), ('x-accepted-oauth-scopes', 'repo, repo:status'), ('etag', '"bfa38f9cceb7ccc231038178037a2013"'), ('access-control-allow-credentials', 'true'), ('status', '200 OK'), ('x-ratelimit-remaining', '4992'), ('x-github-media-type', 'github.v3; format=json'), ('access-control-expose-headers', 'ETag, Link, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('x-github-request-id', '12B0076B:2074:768909A:56A6A81F'), ('cache-control', 'private, max-age=60, s-maxage=60'), ('date', 'Mon, 25 Jan 2016 22:56:31 GMT'), ('access-control-allow-origin', '*'), ('content-security-policy', "default-src 'none'"), ('strict-transport-security', 'max-age=31536000; includeSubdomains; preload'), ('server', 'GitHub.com'), ('x-ratelimit-limit', '5000'), ('x-frame-options', 'deny'), ('content-type', 'application/json; charset=utf-8'), ('x-ratelimit-reset', '1453765330')]
{"state":"success","statuses":[{"url":"https://api.github.com/repos/edx/edx-platform/statuses/74e70119a23fa3ffb3db19d4590eccfebd72b659","id":390601376,"state":"success","description":"Build finished.","target_url":"https://build.testeng.edx.org/job/edx-platform-js-pr/10357/","context":"jenkins/js","created_at":"2015-12-14T12:54:25Z","updated_at":"2015-12-14T12:54:25Z"},{"url":"https://api.github.com/repos/edx/edx-platform/statuses/74e70119a23fa3ffb3db19d4590eccfebd72b659","id":390603044,"state":"success","description":"Build finished.","target_url":"https://build.testeng.edx.org/job/edx-platform-accessibility-pr/10173/","context":"jenkins/a11y","created_at":"2015-12-14T12:56:21Z","updated_at":"2015-12-14T12:56:21Z"},{"url":"https://api.github.com/repos/edx/edx-platform/statuses/74e70119a23fa3ffb3db19d4590eccfebd72b659","id":390615529,"state":"success","description":"Build finished.","target_url":"https://build.testeng.edx.org/job/edx-platform-quality-pr/10214/","context":"jenkins/quality","created_at":"2015-12-14T13:10:22Z","updated_at":"2015-12-14T13:10:22Z"},{"url":"https://api.github.com/repos/edx/edx-platform/statuses/74e70119a23fa3ffb3db19d4590eccfebd72b659","id":390627281,"state":"success","description":"Build finished.","target_url":"https://build.testeng.edx.org/job/edx-platform-bok-choy-pr/10918/","context":"jenkins/bokchoy","created_at":"2015-12-14T13:23:35Z","updated_at":"2015-12-14T13:23:35Z"},{"url":"https://api.github.com/repos/edx/edx-platform/statuses/74e70119a23fa3ffb3db19d4590eccfebd72b659","id":390627989,"state":"success","description":"Build finished.","target_url":"https://build.testeng.edx.org/job/edx-platform-python-unittests-pr/10504/","context":"jenkins/python","created_at":"2015-12-14T13:24:18Z","updated_at":"2015-12-14T13:24:18Z"},{"url":"https://api.github.com/repos/edx/edx-platform/statuses/74e70119a23fa3ffb3db19d4590eccfebd72b659","id":390680150,"state":"success","description":"Build finished.","target_url":"https://build.testeng.edx.org/job/edx-platform-lettuce-pr/10545/","context":"jenkins/lettuce","created_at":"2015-12-14T14:15:40Z","updated_at":"2015-12-14T14:15:40Z"}],"sha":"74e70119a23fa3ffb3db19d4590eccfebd72b659","total_count":6,"repository":{"id":10391073,"name":"edx-platform","full_name":"edx/edx-platform","owner":{"login":"edx","id":3179841,"avatar_url":"https://avatars.githubusercontent.com/u/3179841?v=3","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-platform","description":"The Open edX platform, the software that powers edX!","fork":false,"url":"https://api.github.com/repos/edx/edx-platform","forks_url":"https://api.github.com/repos/edx/edx-platform/forks","keys_url":"https://api.github.com/repos/edx/edx-platform/keys{/key_id}","collaborators_url":"https://api.github.com/repos/edx/edx-platform/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/edx/edx-platform/teams","hooks_url":"https://api.github.com/repos/edx/edx-platform/hooks","issue_events_url":"https://api.github.com/repos/edx/edx-platform/issues/events{/number}","events_url":"https://api.github.com/repos/edx/edx-platform/events","assignees_url":"https://api.github.com/repos/edx/edx-platform/assignees{/user}","branches_url":"https://api.github.com/repos/edx/edx-platform/branches{/branch}","tags_url":"https://api.github.com/repos/edx/edx-platform/tags","blobs_url":"https://api.github.com/repos/edx/edx-platform/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/edx/edx-platform/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/edx/edx-platform/git/refs{/sha}","trees_url":"https://api.github.com/repos/edx/edx-platform/git/trees{/sha}","statuses_url":"https://api.github.com/repos/edx/edx-platform/statuses/{sha}","languages_url":"https://api.github.com/repos/edx/edx-platform/languages","stargazers_url":"https://api.github.com/repos/edx/edx-platform/stargazers","contributors_url":"https://api.github.com/repos/edx/edx-platform/contributors","subscribers_url":"https://api.github.com/repos/edx/edx-platform/subscribers","subscription_url":"https://api.github.com/repos/edx/edx-platform/subscription","commits_url":"https://api.github.com/repos/edx/edx-platform/commits{/sha}","git_commits_url":"https://api.github.com/repos/edx/edx-platform/git/commits{/sha}","comments_url":"https://api.github.com/repos/edx/edx-platform/comments{/number}","issue_comment_url":"https://api.github.com/repos/edx/edx-platform/issues/comments{/number}","contents_url":"https://api.github.com/repos/edx/edx-platform/contents/{+path}","compare_url":"https://api.github.com/repos/edx/edx-platform/compare/{base}...{head}","merges_url":"https://api.github.com/repos/edx/edx-platform/merges","archive_url":"https://api.github.com/repos/edx/edx-platform/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/edx/edx-platform/downloads","issues_url":"https://api.github.com/repos/edx/edx-platform/issues{/number}","pulls_url":"https://api.github.com/repos/edx/edx-platform/pulls{/number}","milestones_url":"https://api.github.com/repos/edx/edx-platform/milestones{/number}","notifications_url":"https://api.github.com/repos/edx/edx-platform/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/edx/edx-platform/labels{/name}","releases_url":"https://api.github.com/repos/edx/edx-platform/releases{/id}","deployments_url":"https://api.github.com/repos/edx/edx-platform/deployments"},"commit_url":"https://api.github.com/repos/edx/edx-platform/commits/74e70119a23fa3ffb3db19d4590eccfebd72b659","url":"https://api.github.com/repos/edx/edx-platform/commits/74e70119a23fa3ffb3db19d4590eccfebd72b659/status"}

