{"action":"created","comment":{"url":"https://api.github.com/repos/girder/girder/pulls/comments/77757259","id":77757259,"diff_hunk":"@@ -0,0 +1,33 @@\n+/**\n+ * Define tasks that download and copy fontello font files.\n+ */\n+module.exports = function (grunt) {\n+    var path = require('path');\n+\n+    grunt.config.merge({\n+        curl: {\n+            fontello: {\n+                src: 'https://data.kitware.com/api/v1/file/57c5d1fc8d777f10f269dece/download',","path":"grunt_tasks/fontello.js","position":10,"original_position":10,"commit_id":"ff5564f9aedaba896540d9283f8f9e12cc220b51","original_commit_id":"5d7a5e12c7d593d94148467f4b4b795740b42042","user":{"login":"sebastienbarre","id":329967,"avatar_url":"https://avatars.githubusercontent.com/u/329967?v=3","gravatar_id":"","url":"https://api.github.com/users/sebastienbarre","html_url":"https://github.com/sebastienbarre","followers_url":"https://api.github.com/users/sebastienbarre/followers","following_url":"https://api.github.com/users/sebastienbarre/following{/other_user}","gists_url":"https://api.github.com/users/sebastienbarre/gists{/gist_id}","starred_url":"https://api.github.com/users/sebastienbarre/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sebastienbarre/subscriptions","organizations_url":"https://api.github.com/users/sebastienbarre/orgs","repos_url":"https://api.github.com/users/sebastienbarre/repos","events_url":"https://api.github.com/users/sebastienbarre/events{/privacy}","received_events_url":"https://api.github.com/users/sebastienbarre/received_events","type":"User","site_admin":false},"body":"So I'm curious. Why are we not sticking the Fontello files directly in the repo?","created_at":"2016-09-07T04:01:36Z","updated_at":"2016-09-07T04:01:36Z","html_url":"https://github.com/girder/girder/pull/1476#discussion_r77757259","pull_request_url":"https://api.github.com/repos/girder/girder/pulls/1476","_links":{"self":{"href":"https://api.github.com/repos/girder/girder/pulls/comments/77757259"},"html":{"href":"https://github.com/girder/girder/pull/1476#discussion_r77757259"},"pull_request":{"href":"https://api.github.com/repos/girder/girder/pulls/1476"}}},"pull_request":{"url":"https://api.github.com/repos/girder/girder/pulls/1476","id":78332938,"html_url":"https://github.com/girder/girder/pull/1476","diff_url":"https://github.com/girder/girder/pull/1476.diff","patch_url":"https://github.com/girder/girder/pull/1476.patch","issue_url":"https://api.github.com/repos/girder/girder/issues/1476","number":1476,"state":"closed","locked":false,"title":"Webpack","user":{"login":"sebastienbarre","id":329967,"avatar_url":"https://avatars.githubusercontent.com/u/329967?v=3","gravatar_id":"","url":"https://api.github.com/users/sebastienbarre","html_url":"https://github.com/sebastienbarre","followers_url":"https://api.github.com/users/sebastienbarre/followers","following_url":"https://api.github.com/users/sebastienbarre/following{/other_user}","gists_url":"https://api.github.com/users/sebastienbarre/gists{/gist_id}","starred_url":"https://api.github.com/users/sebastienbarre/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sebastienbarre/subscriptions","organizations_url":"https://api.github.com/users/sebastienbarre/orgs","repos_url":"https://api.github.com/users/sebastienbarre/repos","events_url":"https://api.github.com/users/sebastienbarre/events{/privacy}","received_events_url":"https://api.github.com/users/sebastienbarre/received_events","type":"User","site_admin":false},"body":"Here we go.\r\n\r\n## Scope\r\n\r\nThis PR holds all changes related to the [ES6/ES2015 modularization](http://www.2ality.com/2014/09/es6-modules-final.html) of the Girder web client and 20+ of its plugins, as well as the subsequent bundling using [Webpack](https://webpack.github.io/).\r\n\r\nAlmost all source files have been updated to no longer rely on the global `girder` object/singleton. Specific functionalities, Jade templates, as well as Stylus/CSS styles must now be imported *explicitly*. For example:\r\n\r\n```javascript\r\nimport _ from 'underscore';\r\n\r\nimport FileModel from 'girder/models/FileModel';\r\nimport View from 'girder/views/View';\r\nimport events from 'girder/events';\r\nimport { renderMarkdown, formatSize } from 'girder/misc';\r\n\r\nimport MarkdownWidgetTemplate from 'girder/templates/widgets/markdownWidget.jade';\r\nimport 'girder/stylesheets/widgets/markdownWidget.styl';\r\n\r\nvar MarkdownWidget = View.extend({\r\n    events: {\r\n        'show.bs.tab .g-preview-link': function () {\r\n            renderMarkdown(this.val().trim() || 'Nothing to show', this.$('.g-markdown-preview'));\r\n        },\r\n...\r\n});\r\n\r\nexport default MarkdownWidget;\r\n```\r\n\r\nImporting on a \"per-needed\" basis will provide the added benefit of facilitating [tree shaking](http://www.2ality.com/2015/12/webpack-tree-shaking.html) and build-time checks.\r\n\r\n## Directory Structure\r\n\r\nThe directory structure in `clients\\web\\src` was not altered, but some functions/classes were moved to their own files. For example:\r\n\r\n- authentication-related code is now in `auth.js`,\r\n- constants are now in `constants.js`,\r\n- dialog (UI) related code is in `dialog.js`,\r\n- the event emitter is now in `events.js`,\r\n- miscellaneous functions are now in `misc.js`,\r\n- REST-related code is now in `rest.js`,\r\n- the router is now in `router.js`,\r\n- routes definitions are *all* in `routes.js`,\r\n- server related code is in `server.js`,\r\n- `collection.js` was moved to `collections\\Collection.js`,\r\n- `model.js` was split into `Model.js`, `AccessControlledModel.js` and `MetadataMixin.js` inside the `models` subdir,\r\n- `plugin_utils.js` is now in `utilities\\PluginUtils.js`,\r\n- jQuery plugins are now in the `utilities\\jquery` subdir,\r\n\r\n## Plugins\r\n\r\nAll plugins were cleaned-up to adopt the same directory structure and naming conventions as the core files, and to better convey which core files are being extended or wrapped. Specifically:\r\n\r\n- all plugins feature a `main.js` entry point,\r\n- routes, if any, are defined in `routes.js`,\r\n- views are to be found in a `views` subdir,\r\n- all templates, stylesheets, and views were renamed, when needed, to be consistent with each-others (e.g. `views/ItemPreviewWidget.js`, `templates/itemPreviewWidget.jade`, `stylesheets/itemPreviewWidget.styl`),\r\n- any core model/collection/view being extended prototypically or `wrap()`'ed is now to be found in a single file matching the same model/collection/view name and location (say, `plugins/curation/web_client/views/HierarchyWidget.js`).\r\n\r\n## Migration\r\n\r\nI would recommend checking any collection, model, view, or plugin to help transitioning your own code. Search for instances of the `girder.` string to find the functions previously attached to the `girder` global namespace, and bring them into your code using `import... from...`. Export your own code using `export default ...` to make it available to the outside world as a module. Start a new plugin by copy/pasting an existing one.\r\n   \r\nNote that it is still possible, although not recommended, to use a higher-level namespace. \r\nFor example, the old:\r\n```javascript\r\ngirder.fetchCurrentUser(blah blah);\r\n```\r\nis now coded this way:\r\n```javascript\r\nimport { fetchCurrentUser } from 'girder/auth';\r\n[...]\r\nfetchCurrentUser(blah blah);\r\n```\r\nyet, it could also be written this way:\r\n```javascript\r\nimport * as auth from 'girder/auth';\r\n[...]\r\nauth.fetchCurrentUser(blah blah);\r\n```\r\n...but your bundler of choice (say, Webpack) would no longer be able to check at build-time if `fetchCurrentUser` is to be found in `girder/auth`. It could also be rewritten as:\r\n```javascript\r\nimport * as girder from 'girder';\r\n[...]\r\ngirder.auth.fetchCurrentUser(blah blah);\r\n```\r\n... but the risk here would be even higher, should the `auth` namespace or its contents be moved or renamed.\r\n\r\nBe aware that if you passed the `girder` global to a Jade template, you will now need to pass individual functions separately, and update the Jade template accordingly. For example:\r\n\r\nin `clients/web/src/views/body/CollectionsView.js`:\r\n```javascript\r\n       this.$el.html(girder.templates.collectionList({\r\n             collections: this.collection.toArray(),             \r\n             girder: girder\r\n         }));\r\n```\r\nbecomes:\r\n```javascript\r\nimport { formatSize } from 'girder/misc';\r\nimport { getCurrentUser } from 'girder/auth';\r\nimport CollectionListTemplate from 'girder/templates/body/collectionList.jade'; \r\n[...]\r\n       this.$el.html(CollectionListTemplate({\r\n             collections: this.collection.toArray(),\r\n             getCurrentUser: getCurrentUser,\r\n             formatSize: formatSize\r\n         }));\r\n``` \r\nand in the corresponding `clients/web/src/templates/body/collectionList.jade`\r\n```jade\r\nif girder.currentUser\r\n[...]\r\n        span.g-user-space-used  #{girder.formatSize(collection.get('size'))}\r\n```\r\nbecomes:\r\n```\r\nif getCurrentUser()\r\n[...]\r\n        span.g-user-space-used  #{formatSize(collection.get('size'))}\r\n```\r\n\r\nAlso note that a `girder` global is still available to facilitate testing, but only *after* the core Javascript bundles and all plugins have been loaded. It is nearly identical to the previously available global, but some functions were shuffled around, as described in the \"Directory Structure\" section.\r\n\r\nTip: use `console.dir(girder)` to browse the new tree.\r\n```\r\n$ console.dir(girder)\r\n> views\r\n> auth\r\n> collections\r\n> utilities\r\n> server\r\n> dialog\r\n  > confirm\r\n     [...]\r\n[...]\r\n```\r\nthen follow the same \"path\" to migrate to the new `import...from` statement:\r\n```javascript\r\nimport { confirm } from 'girder/dialog';\r\n```\r\nImporting from one plugin to another can be done using the `plugins/` prefix. For example,\r\nconsider `JobStatus` being exported by the `jobs` plugin in `/plugins/jobs/web_client/JobStatus.js`:\r\n```javascript\r\nvar JobStatus = {\r\n    registerStatus: function (status) {\r\n        [...]\r\n    }\r\n}\r\nexport default JobStatus;\r\n```\r\nthen later on used by the `worker` plugin in `/plugins/worker/web_client/JobStatus.js`, like this (note that there is no `web_client` subdir here):\r\n```javascript\r\nimport JobStatus from 'plugins/jobs/JobStatus';\r\nJobStatus.registerStatus({\r\n    WORKER_FETCHING_INPUT: {\r\n        [...]\r\n    }\r\n});\r\n```\r\n\r\n## TODO\r\n\r\n- [x] This work was done on Mac OSX, which is case-insensitive -- there may be some lingering, trivial file naming issues that Unix users will notice right away.\r\n\r\n### Grunt Build-process\r\n\r\nThe old, Grunt build process is still in place. I do not advocate removing it actually, as Webpack is a bundler, not a task runner. It was nonetheless slimmed down, as `grunt_tasks/build.js` is almost 100% Webpack code at this point. A few Grunt plugins remain, and could potentially be removed in favor of Webpack (see such plugins as [kevlened/copy-webpack-plugin](https://github.com/kevlened/copy-webpack-plugin) as a replacement to `grunt-contrib-copy`). \r\n\r\n- [ ] **Testing**: `grunt_tasks/dev.js`still uses `grunt-contrib-uglify`; it needs to be exercised, converted to the new modules, and likely fixed before it is Webpack'ed; UPDATE: soon to be webpack'ed,\r\n- [ ] **Packaging**: `grunt_tasks/package.js` uses `grunt-shell`; **it needs to be exercised and likely fixed**,\r\n- [x] **Fontello**: `grunt_tasks/fontello.js` uses `grunt-contrib-copy` and `grunt-fontello`; it is functional and would likely be fine as is,\r\n- [x] **Plugins**: `grunt_tasks/plugin.js` still uses `grunt-contrib-copy` and `grunt-npm-install`; the code that handles Javascript, Jade, and Stylus for each plugin was moved and integrated into the single Webpack target in `grunt_tasks/build.js`; while plugins appear to be generated correctly, ***a large section (starting at `grunt.file.expand()`) needs to be exercised and likely be fixed or removed**,\r\n- [x] **Sphinx**: `grunt_tasks/sphinx.js` uses `grunt-shell`; it appears functional and would likely be fine left as is,\r\n- [x] **Swagger**: `grunt_tasks/swagger.js` uses `grunt-contrib-copy` and `grunt-contrib-stylus`; it is functional but could be Webpack'ed, or left as is,\r\n- [x] **Versioning**: `grunt_tasks/version.js` uses `grunt-file-creator` and `grunt-gitinfo`; it is functional and would likely be fine as is,\r\n\r\n### Webpack\r\n\r\nThe Webpack target generates, in `clients\\web\\static\\built`:\r\n- `girder.ext.min.js` and `girder.ext.min.css` (and corresponding source maps): all third-party/vendor Javascript and CSS (e.g. imported from `node_modules`), \r\n- `girder.app.min.js` and `girder.app.min.css` (and corresponding source maps): all Girder core Javascript/Jade/CSS (e.g. found in `clients\\web\\src`) used by the client *and* the plugins,\r\n- `plugin.min.js` and `plugin.min.css` (and corresponding source maps) for each plugin, in `plugins\\name_of_plugin`: plugin code only, typically small, making calls into `girder.app`  (and `girder.ext`),\r\n- glyphicons in the `assets` subdir\r\n\r\nHowever:\r\n- [ ] There still appears to be too much duplicated code going in `girder.main.min.js` and each `plugin.min.js`; this needs to be investigated and fixed by myself (Seb; consider [robertknight/webpack-bundle-size-analyzer](https://github.com/robertknight/webpack-bundle-size-analyzer)), also consider the `DllPlugin`, which would increase performance as well ([Webpack Plugins we been keepin on the DLL](https://medium.com/@soederpop/webpack-plugins-been-we-been-keepin-on-the-dll-cdfdd6cb8cd7), [Optimizing Webpack for Faster React Builds](http://engineering.invisionapp.com/post/optimizing-webpack/), [Optimizing Webpack build times and improving caching with DLL bundles](https://robertknight.github.io/posts/webpack-dll-plugins/), [webpack/examples/dll](https://github.com/webpack/webpack/tree/master/examples/dll)). Also check [trivago/parallel-webpack: Builds multi-config webpack projects in parallel](https://github.com/trivago/parallel-webpack)\r\n- [x] The Grunt `watch` target in `build.js` needs to be converted to a similar capability compatible with Webpack; (use `grunt --watch` or `grunt webpack:watch`, for `grunt-contrib-watch` is too slow),\r\n- [x] Support for ES2015 code through Babel should be enabled (by myself, Seb),\r\n- [x] Importing `$.girderModal()` looks too much like a side effect: `import 'girder/utilities/jQuery';`; let's find a way to make it more explicit (check how jQuery does it nowadays), or restructure the files so that we have one prototype method per file, so that it would be more obvious why it's getting imported, e.g. `import 'girder/utilities/jQuery/girderModal';`\r\n- [x] It is still unclear at this point how minimization and debugging will ultimately be enabled in Webpack 2.0 (see [What's new in webpack 2](https://gist.github.com/sokra/27b24881210b56bbaff7#loader-options--minimize), [Why does the UglifyJsPlugin affect other loaders?](https://github.com/webpack/webpack/issues/283), [this comment](https://github.com/webpack/webpack/issues/2061#issuecomment-228932941)), so the 2 (or 3) different ways to do so are used at the same time (see how `environment` and `debugJs` are used in `grunt_tasks/build.js`), but this will need some clean up later on,\r\n\r\n### Testing\r\n\r\n- [x] Programmatic testing of the web client was disabled, and **needs to be converted and re-enabled ASAP**, or Continuous Integration will fail (see `grunt_tasks/dev.js`, remove early `return` in (`grunt.registerTask`); I (Seb) could use some help for this one, from the original testing author **Update: most tests are passing, but the way the test driver exists make it look like they are failing on some laptops**,\r\n\r\n### Plugins\r\n\r\nAll plugins were converted. Manual testing was performed to check that each plugin's UI is in place, using eye-ball technology.\r\n\r\n- [x] Programmatic testing, if any, **needs to be converted and re-enabled ASAP** (say, `plugins\\autojoin\\plugin_tests\\autoJoin.spec`)\r\n\r\n### Misc, Minor\r\n\r\n- [ ] Consider moving constants from `constants.js` back to more relevant files, closer to the functions that most often use them?\r\n- [x] Consider files like `auth.js`, `events.js`, `rest.js`, `router.js`, which essentially bundle utility functions, vs. the files in `utilities` such as `DialogHelper.js`, `MiscFunctions.js`, or `PluginUtils.js`, which *also* bundle utility functions. Are the former considered more important \"utilities\" then the latter? Or should they all be in the `utilities` dir? Should some be merged somehow in the process? Or named more consistently? \r\n- [x] `girder/router` exports `{ router, splitRoute }`. Therefore, accessing the router from the `girder` singleton will look like `girder.router.router`; not ideal; consider renaming `girder/router` to `girder/routing` to use `girder.routing.router` instead?\r\n- [x] `girder/events` exports `{ events, eventSream }`. Therefore, accessing the events object from the `girder` singleton will look like `girder.events.events`; not ideal; consider renaming `girder/events` to `girder/eventing` to use `girder.eventing.events` instead?\r\n","created_at":"2016-07-21T15:07:52Z","updated_at":"2016-09-07T04:01:36Z","closed_at":"2016-09-06T17:13:08Z","merged_at":"2016-09-06T17:13:08Z","merge_commit_sha":"98b4ec789af2d55d06d8ca52854bf38e36d3b034","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/girder/girder/pulls/1476/commits","review_comments_url":"https://api.github.com/repos/girder/girder/pulls/1476/comments","review_comment_url":"https://api.github.com/repos/girder/girder/pulls/comments{/number}","comments_url":"https://api.github.com/repos/girder/girder/issues/1476/comments","statuses_url":"https://api.github.com/repos/girder/girder/statuses/ff5564f9aedaba896540d9283f8f9e12cc220b51","head":{"label":"girder:webpack","ref":"webpack","sha":"ff5564f9aedaba896540d9283f8f9e12cc220b51","user":{"login":"girder","id":5150517,"avatar_url":"https://avatars.githubusercontent.com/u/5150517?v=3","gravatar_id":"","url":"https://api.github.com/users/girder","html_url":"https://github.com/girder","followers_url":"https://api.github.com/users/girder/followers","following_url":"https://api.github.com/users/girder/following{/other_user}","gists_url":"https://api.github.com/users/girder/gists{/gist_id}","starred_url":"https://api.github.com/users/girder/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/girder/subscriptions","organizations_url":"https://api.github.com/users/girder/orgs","repos_url":"https://api.github.com/users/girder/repos","events_url":"https://api.github.com/users/girder/events{/privacy}","received_events_url":"https://api.github.com/users/girder/received_events","type":"Organization","site_admin":false},"repo":{"id":11854950,"name":"girder","full_name":"girder/girder","owner":{"login":"girder","id":5150517,"avatar_url":"https://avatars.githubusercontent.com/u/5150517?v=3","gravatar_id":"","url":"https://api.github.com/users/girder","html_url":"https://github.com/girder","followers_url":"https://api.github.com/users/girder/followers","following_url":"https://api.github.com/users/girder/following{/other_user}","gists_url":"https://api.github.com/users/girder/gists{/gist_id}","starred_url":"https://api.github.com/users/girder/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/girder/subscriptions","organizations_url":"https://api.github.com/users/girder/orgs","repos_url":"https://api.github.com/users/girder/repos","events_url":"https://api.github.com/users/girder/events{/privacy}","received_events_url":"https://api.github.com/users/girder/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/girder/girder","description":"A data management platform for the web","fork":false,"url":"https://api.github.com/repos/girder/girder","forks_url":"https://api.github.com/repos/girder/girder/forks","keys_url":"https://api.github.com/repos/girder/girder/keys{/key_id}","collaborators_url":"https://api.github.com/repos/girder/girder/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/girder/girder/teams","hooks_url":"https://api.github.com/repos/girder/girder/hooks","issue_events_url":"https://api.github.com/repos/girder/girder/issues/events{/number}","events_url":"https://api.github.com/repos/girder/girder/events","assignees_url":"https://api.github.com/repos/girder/girder/assignees{/user}","branches_url":"https://api.github.com/repos/girder/girder/branches{/branch}","tags_url":"https://api.github.com/repos/girder/girder/tags","blobs_url":"https://api.github.com/repos/girder/girder/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/girder/girder/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/girder/girder/git/refs{/sha}","trees_url":"https://api.github.com/repos/girder/girder/git/trees{/sha}","statuses_url":"https://api.github.com/repos/girder/girder/statuses/{sha}","languages_url":"https://api.github.com/repos/girder/girder/languages","stargazers_url":"https://api.github.com/repos/girder/girder/stargazers","contributors_url":"https://api.github.com/repos/girder/girder/contributors","subscribers_url":"https://api.github.com/repos/girder/girder/subscribers","subscription_url":"https://api.github.com/repos/girder/girder/subscription","commits_url":"https://api.github.com/repos/girder/girder/commits{/sha}","git_commits_url":"https://api.github.com/repos/girder/girder/git/commits{/sha}","comments_url":"https://api.github.com/repos/girder/girder/comments{/number}","issue_comment_url":"https://api.github.com/repos/girder/girder/issues/comments{/number}","contents_url":"https://api.github.com/repos/girder/girder/contents/{+path}","compare_url":"https://api.github.com/repos/girder/girder/compare/{base}...{head}","merges_url":"https://api.github.com/repos/girder/girder/merges","archive_url":"https://api.github.com/repos/girder/girder/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/girder/girder/downloads","issues_url":"https://api.github.com/repos/girder/girder/issues{/number}","pulls_url":"https://api.github.com/repos/girder/girder/pulls{/number}","milestones_url":"https://api.github.com/repos/girder/girder/milestones{/number}","notifications_url":"https://api.github.com/repos/girder/girder/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/girder/girder/labels{/name}","releases_url":"https://api.github.com/repos/girder/girder/releases{/id}","deployments_url":"https://api.github.com/repos/girder/girder/deployments","created_at":"2013-08-02T23:55:54Z","updated_at":"2016-08-27T18:14:06Z","pushed_at":"2016-09-06T20:42:01Z","git_url":"git://github.com/girder/girder.git","ssh_url":"git@github.com:girder/girder.git","clone_url":"https://github.com/girder/girder.git","svn_url":"https://github.com/girder/girder","homepage":"http://girder.readthedocs.io","size":10183,"stargazers_count":60,"watchers_count":60,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":46,"mirror_url":null,"open_issues_count":185,"forks":46,"open_issues":185,"watchers":60,"default_branch":"master"}},"base":{"label":"girder:2.0-integration","ref":"2.0-integration","sha":"970535dd75571f271b6014afd1f93abbc63be89b","user":{"login":"girder","id":5150517,"avatar_url":"https://avatars.githubusercontent.com/u/5150517?v=3","gravatar_id":"","url":"https://api.github.com/users/girder","html_url":"https://github.com/girder","followers_url":"https://api.github.com/users/girder/followers","following_url":"https://api.github.com/users/girder/following{/other_user}","gists_url":"https://api.github.com/users/girder/gists{/gist_id}","starred_url":"https://api.github.com/users/girder/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/girder/subscriptions","organizations_url":"https://api.github.com/users/girder/orgs","repos_url":"https://api.github.com/users/girder/repos","events_url":"https://api.github.com/users/girder/events{/privacy}","received_events_url":"https://api.github.com/users/girder/received_events","type":"Organization","site_admin":false},"repo":{"id":11854950,"name":"girder","full_name":"girder/girder","owner":{"login":"girder","id":5150517,"avatar_url":"https://avatars.githubusercontent.com/u/5150517?v=3","gravatar_id":"","url":"https://api.github.com/users/girder","html_url":"https://github.com/girder","followers_url":"https://api.github.com/users/girder/followers","following_url":"https://api.github.com/users/girder/following{/other_user}","gists_url":"https://api.github.com/users/girder/gists{/gist_id}","starred_url":"https://api.github.com/users/girder/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/girder/subscriptions","organizations_url":"https://api.github.com/users/girder/orgs","repos_url":"https://api.github.com/users/girder/repos","events_url":"https://api.github.com/users/girder/events{/privacy}","received_events_url":"https://api.github.com/users/girder/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/girder/girder","description":"A data management platform for the web","fork":false,"url":"https://api.github.com/repos/girder/girder","forks_url":"https://api.github.com/repos/girder/girder/forks","keys_url":"https://api.github.com/repos/girder/girder/keys{/key_id}","collaborators_url":"https://api.github.com/repos/girder/girder/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/girder/girder/teams","hooks_url":"https://api.github.com/repos/girder/girder/hooks","issue_events_url":"https://api.github.com/repos/girder/girder/issues/events{/number}","events_url":"https://api.github.com/repos/girder/girder/events","assignees_url":"https://api.github.com/repos/girder/girder/assignees{/user}","branches_url":"https://api.github.com/repos/girder/girder/branches{/branch}","tags_url":"https://api.github.com/repos/girder/girder/tags","blobs_url":"https://api.github.com/repos/girder/girder/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/girder/girder/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/girder/girder/git/refs{/sha}","trees_url":"https://api.github.com/repos/girder/girder/git/trees{/sha}","statuses_url":"https://api.github.com/repos/girder/girder/statuses/{sha}","languages_url":"https://api.github.com/repos/girder/girder/languages","stargazers_url":"https://api.github.com/repos/girder/girder/stargazers","contributors_url":"https://api.github.com/repos/girder/girder/contributors","subscribers_url":"https://api.github.com/repos/girder/girder/subscribers","subscription_url":"https://api.github.com/repos/girder/girder/subscription","commits_url":"https://api.github.com/repos/girder/girder/commits{/sha}","git_commits_url":"https://api.github.com/repos/girder/girder/git/commits{/sha}","comments_url":"https://api.github.com/repos/girder/girder/comments{/number}","issue_comment_url":"https://api.github.com/repos/girder/girder/issues/comments{/number}","contents_url":"https://api.github.com/repos/girder/girder/contents/{+path}","compare_url":"https://api.github.com/repos/girder/girder/compare/{base}...{head}","merges_url":"https://api.github.com/repos/girder/girder/merges","archive_url":"https://api.github.com/repos/girder/girder/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/girder/girder/downloads","issues_url":"https://api.github.com/repos/girder/girder/issues{/number}","pulls_url":"https://api.github.com/repos/girder/girder/pulls{/number}","milestones_url":"https://api.github.com/repos/girder/girder/milestones{/number}","notifications_url":"https://api.github.com/repos/girder/girder/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/girder/girder/labels{/name}","releases_url":"https://api.github.com/repos/girder/girder/releases{/id}","deployments_url":"https://api.github.com/repos/girder/girder/deployments","created_at":"2013-08-02T23:55:54Z","updated_at":"2016-08-27T18:14:06Z","pushed_at":"2016-09-06T20:42:01Z","git_url":"git://github.com/girder/girder.git","ssh_url":"git@github.com:girder/girder.git","clone_url":"https://github.com/girder/girder.git","svn_url":"https://github.com/girder/girder","homepage":"http://girder.readthedocs.io","size":10183,"stargazers_count":60,"watchers_count":60,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":46,"mirror_url":null,"open_issues_count":185,"forks":46,"open_issues":185,"watchers":60,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/girder/girder/pulls/1476"},"html":{"href":"https://github.com/girder/girder/pull/1476"},"issue":{"href":"https://api.github.com/repos/girder/girder/issues/1476"},"comments":{"href":"https://api.github.com/repos/girder/girder/issues/1476/comments"},"review_comments":{"href":"https://api.github.com/repos/girder/girder/pulls/1476/comments"},"review_comment":{"href":"https://api.github.com/repos/girder/girder/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/girder/girder/pulls/1476/commits"},"statuses":{"href":"https://api.github.com/repos/girder/girder/statuses/ff5564f9aedaba896540d9283f8f9e12cc220b51"}}}}
{"actor":{"display_login":"sebastienbarre"}}