{"action":"created","comment":{"url":"https://api.github.com/repos/mozilla/publish.webmaker.org/pulls/comments/68992014","id":68992014,"diff_hunk":"@@ -1,411 +1,412 @@\n-var Promise = require('bluebird'); // jshint ignore:line\n-var mime = require('mime');\n-var Path = require('path');\n+\"use strict\";\n \n-var client = require('../../lib/amazon-client').create();\n+const Promise = require(`bluebird`);\n+const mime = require(`mime`);\n+const Path = require(`path`);\n \n-var log = require('../../lib/logger.js');\n-var Remix = require('../../lib/remix');\n+const s3Client = require(`../../lib/s3-client`).connect();\n \n-var Projects = require('../modules/projects/model');\n-var PublishedProjects = require('../modules/publishedProjects/model');\n+const log = require(`../../lib/logger.js`);\n+const Remix = require(`../../lib/remix`);\n \n-// SQL Query Generators\n-var UserQueries = require('../modules/users/model').prototype.queries();\n-var ProjectQueries = Projects.prototype.queries();\n-var PublishedProjectQueries = PublishedProjects.prototype.queries();\n-var PublishedFileQueries = require('../modules/publishedFiles/model').prototype.queries();\n+const Projects = require(`../modules/projects/model`);\n+const PublishedProjects = require(`../modules/publishedProjects/model`);\n \n-var reject  = Promise.reject;\n+// SQL Query Generators\n+const usersQueryBuilder = require(`../modules/users/model`).prototype.queryBuilder();\n+const projectsQueryBuilder = Projects.prototype.queryBuilder();\n+const publishedProjectsQueryBuilder = PublishedProjects.prototype.queryBuilder();\n+const publishedFilesQueryBuilder = require(`../modules/publishedFiles/model`).prototype.queryBuilder();\n \n-/**\n+/*\n  * Utility functions\n  */\n function success(type, username) {\n   return function(message) {\n-    log.info('Publish for ' + username + ' - [' + type + '] ' + message);\n+    log.info(`Publish for ${username} - [${type}] ${message}`);\n   };\n }\n \n function failure(type, username) {\n-  return function(err) {\n-    log.error({ error: err }, 'Publish for ' + username + ' - [' + type + ']');\n-    reject(err);\n+  return function(error) {\n+    log.error({ error }, `Publish for ${username} - [${type}]`);\n+    return Promise.reject(error);\n   };\n }\n \n-function getUploadRoot(client, user, project) {\n+function getUploadRoot(publishClient, user, project) {\n   if (!user || !project) {\n     return null;\n   }\n \n-  var httpPrefix = '';\n-  var httpClients = (process.env.HTTP_CLIENTS || '').split(',');\n+  let httpPrefix = ``;\n+  const httpClients = (process.env.HTTP_CLIENTS || ``).split(`,`);\n \n   // If the project's publishing client matches to a list\n   // of \"can publish http://\" clients, prefix the upload root\n   // /with a special \"HTTP\" namespace.\n-  if (client && httpClients.indexOf(client) !== -1) {\n-    httpPrefix = '/HTTP';\n+  if (publishClient && httpClients.indexOf(publishClient) !== -1) {\n+    httpPrefix = `/HTTP`;\n   }\n \n-  return httpPrefix + '/' + user.name + '/' + project.id;\n+  return `${httpPrefix}/${user.name}/${project.id}`;\n }\n \n-function buildUrl(client, user, project) {\n+function buildUrl(publishClient, user, project) {\n   if (!user || !project) {\n     return null;\n   }\n \n-  return process.env.PUBLIC_PROJECT_ENDPOINT + getUploadRoot(client, user, project);\n+  return process.env.PUBLIC_PROJECT_ENDPOINT + getUploadRoot(publishClient, user, project);\n }\n \n // Takes an absolute path and uri-encodes each component\n // of the path to return a fully uri safe path\n function uriSafe(path) {\n-  if (path === '/') {\n-    return '/';\n+  if (path === `/`) {\n+    return `/`;\n   }\n \n-  var uriSafePath = '';\n+  let uriSafePath = ``;\n \n-  while (path !== '/') {\n-    uriSafePath = Path.join('/', encodeURIComponent(Path.basename(path)), uriSafePath);\n+  while(path !== `/`) {\n+    uriSafePath = Path.join(\n+      `/`,\n+      encodeURIComponent(Path.basename(path)),\n+      uriSafePath\n+    );\n     path = Path.dirname(path);\n   }\n \n   return uriSafePath;\n }\n \n \n-/**\n+/*\n  * Remote communication helpers\n  */\n function upload(path, buffer, remixMetadata) {\n-  var mimeType = mime.lookup(path);\n-  if (mimeType === 'text/html' && !remixMetadata.readonly) {\n+  const mimeType = mime.lookup(path);\n+\n+  if (mimeType === `text/html` && !remixMetadata.readonly) {\n     buffer = new Buffer(Remix.inject(buffer.toString(), remixMetadata));\n   }\n-  var headers = {\n-    'Cache-Control': 'max-age=0',\n-    'Content-Type': mimeType + '; charset=utf-8',\n+\n+  const headers = {\n+    'Cache-Control': `max-age=0`,\n+    'Content-Type': `${mimeType}; charset=utf-8`,\n     'Content-Length': buffer.length\n   };\n \n-  var request = client.put(uriSafe(path), headers);\n+  const request = s3Client.put(uriSafe(path), headers);\n \n   return new Promise(function(resolve, reject) {\n-    request.on('error', function(err) {\n-      reject(err);\n-    });\n-    request.on('continue', function() {\n-      request.end(buffer);\n-    });\n-    request.on('response', function(res) {\n-      if (res.statusCode === 200) {\n-        resolve('Uploaded \"' + path + '\"');\n+    request.on(`error`, reject);\n+\n+    request.on(`continue`, function() { request.end(buffer); });\n+\n+    request.on(`response`, function(response) {\n+      if (response.statusCode === 200) {\n+        resolve(`Uploaded \"${path}\"`);\n       } else {\n-        reject('S3 upload returned ' + res.statusCode);\n+        reject(`S3 upload returned ${response.statusCode}`);\n       }\n     });\n   });\n }\n \n function remove(path) {\n   return new Promise(function(resolve, reject) {\n-    var request = client.del(uriSafe(path));\n-    request.on('error', function(err) {\n-      reject(err);\n-    });\n-    request.on('response', function(res) {\n-      if (res.statusCode === 204) {\n-        resolve('Deleted \"' + path + '\"');\n+    const request = s3Client.del(uriSafe(path));\n+\n+    request.on(`error`, reject);\n+\n+    request.on(`response`, function(response) {\n+      if (response.statusCode === 204) {\n+        resolve(`Deleted \"${path}\"`);\n       } else {\n-        reject('S3 delete returned ' + res.statusCode);\n+        reject(`S3 delete returned ${response.statusCode}`);\n       }\n     });\n+\n     request.end();\n   });\n }\n \n \n-/**\n- * Record fetching helpers\n- */\n-function fetchProjectModel(id) {\n-  // We do not use the `ProjectQueries` interface here since we only want\n-  // a Bookshelf model to be returned. The `ProjectQueries` interface returns\n-  // plain javascript objects. This method is primarily used when we want to\n-  // output the same form of data that was sent as an input viz. a Bookshelf\n-  // model.\n-  return Projects.query({\n-    where: {\n-      id: id\n-    }\n-  }).fetch();\n-}\n-\n-function fetchUserForProject() {\n-  var self = this;\n-\n-  return UserQueries.getOne(self.project.user_id)\n-  .then(function(user) {\n-    self.user = user;\n-    return user;\n-  });\n-}\n+class BasePublisher {\n+  /**\n+  * Record fetching helpers\n+  */\n+\n+  fetchProjectModel(id) {\n+    // We do not use the `projectsQueryBuilder` interface here since we only want\n+    // a Bookshelf model to be returned. The `projectsQueryBuilder` interface returns\n+    // plain javascript objects. This method is primarily used when we want to\n+    // output the same form of data that was sent as an input viz. a Bookshelf\n+    // model.\n+    return Projects.query({\n+      where: { id }\n+    })\n+    .fetch();\n+  }\n \n-function fetchPublishedProject() {\n-  var self = this;\n+  fetchUserForProject() {\n+    return usersQueryBuilder\n+    .getOne(this.project.user_id)\n+    .then(user => {\n+      this.user = user;\n \n-  return PublishedProjectQueries.getOne(self.project.published_id)\n-  .then(function(publishedProject) {\n-    self.publishedProject = publishedProject;\n-    self.publishRoot = getUploadRoot(self.project.client, self.user, publishedProject);\n-    return publishedProject;\n-  });\n-}\n+      return user;\n+    });\n+  }\n \n+  fetchPublishedProject() {\n+    return publishedProjectsQueryBuilder\n+    .getOne(this.project.published_id)\n+    .then(publishedProject => {\n+      this.publishedProject = publishedProject;\n+      this.publishRoot = getUploadRoot(\n+        this.project.client,\n+        this.user,\n+        publishedProject\n+      );\n+\n+      return publishedProject;\n+    });\n+  }\n \n-/**\n- * Record update helpers\n- */\n-function updateProjectDetails() {\n-  var self = this;\n-  var publishedProject = self.publishedProject;\n-\n-  return ProjectQueries\n-  .updateOne(self.project.id, {\n-    publish_url: buildUrl(self.project.client, self.user, publishedProject),\n-    published_id: publishedProject && publishedProject.id\n-  })\n-  .then(ProjectQueries.getOne)\n-  .then(function(project) {\n-    self.project = project;\n-  });\n-}\n \n-function setRemixDataForPublishedProject() {\n-  var self = this;\n+  /**\n+  * Record update helpers\n+  */\n+\n+  updateProjectDetails() {\n+    const publishedProject = this.publishedProject;\n+\n+    return projectsQueryBuilder\n+    .updateOne(this.project.id, {\n+      publish_url: buildUrl(\n+        this.project.client,\n+        this.user,\n+        publishedProject\n+      ),\n+      published_id: publishedProject && publishedProject.id\n+    })\n+    .then(id => projectsQueryBuilder.getOne(id))\n+    .then(project => {\n+      this.project = project;\n+    });\n+  }\n \n-  self.remixData = {\n-    projectId: self.publishedProject.id,\n-    projectTitle: self.publishedProject.title,\n-    projectAuthor: self.user.name,\n-    dateUpdated: self.publishedProject.date_updated.toISOString(),\n-    host: Remix.resourceHost,\n-    readonly: self.project.readonly\n-  };\n-}\n+  setRemixDataForPublishedProject() {\n+    this.remixData = {\n+      projectId: this.publishedProject.id,\n+      projectTitle: this.publishedProject.title,\n+      projectAuthor: this.user.name,\n+      dateUpdated: this.publishedProject.date_updated.toISOString(),\n+      host: Remix.resourceHost,\n+      readonly: this.project.readonly\n+    };\n+  }\n \n-function createOrUpdatePublishedProject() {\n-  var self = this;\n-  var project = self.project;\n-  var projectData = {\n-    title: project.title,\n-    tags: project.tags,\n-    description: project.description,\n-    date_updated: (new Date()).toISOString()\n-  };\n+  createOrUpdatePublishedProject() {\n+    const project = this.project;\n+    const projectData = {\n+      title: project.title,\n+      tags: project.tags,\n+      description: project.description,\n+      date_updated: (new Date()).toISOString()\n+    };\n+\n+    return this.fetchPublishedProject()\n+    .then(function(publishedProject) {\n+      if (publishedProject) {\n+        return publishedProjectsQueryBuilder.updateOne(publishedProject.id, projectData);\n+      } else {\n+        projectData.date_created = projectData.date_updated;\n+        return publishedProjectsQueryBuilder.createOne(projectData);\n+      }\n+    })\n+    .then(id => publishedProjectsQueryBuilder.getOne(id))\n+    .then(publishedProject => {\n+      this.publishedProject = publishedProject;\n+      this.publishRoot = getUploadRoot(\n+        this.project.client,\n+        this.user,\n+        publishedProject\n+      );\n+    });\n+  }\n \n-  return fetchPublishedProject.call(self)\n-  .then(function(publishedProject) {\n-    if (publishedProject) {\n-      return PublishedProjectQueries.updateOne(publishedProject.id, projectData);\n-    } else {\n-      projectData.date_created = projectData.date_updated;\n-      return PublishedProjectQueries.createOne(projectData);\n-    }\n-  })\n-  .then(PublishedProjectQueries.getOne)\n-  .then(function(publishedProject) {\n-    self.publishedProject = publishedProject;\n-    self.publishRoot = getUploadRoot(self.project.client, self.user, publishedProject);\n-  });\n-}\n \n+  /**\n+  * Remote record update helpers\n+  */\n \n-/**\n- * Remote record update helpers\n- */\n-function uploadNewFiles() {\n-  var self = this;\n-  var remixData = self.remixData;\n-  var publishedProject = self.publishedProject;\n-  var fileRoot = self.publishRoot;\n-  var username = self.user.name;\n-\n-  return PublishedFileQueries\n-  .getAllNewFiles(self.project.id)\n-  .then(function(files) {\n-    if (!files.length) {\n-      return;\n-    }\n+  uploadNewFiles() {\n+    return publishedFilesQueryBuilder\n+    .getAllNewFiles(this.project.id)\n+    .then(files => {\n+      if (!files.length) {\n+        return;\n+      }\n \n-    return Promise.map(files, function(file) {\n-      return PublishedFileQueries.createOne({\n-        file_id: file.id,\n-        published_id: publishedProject.id,\n-        path: file.path,\n-        buffer: file.buffer\n-      })\n-      .then(function() {\n-        return upload(fileRoot + file.path, file.buffer, remixData);\n-      })\n-      .then(success('CREATE', username))\n-      .catch(failure('CREATE', username));\n+      return Promise.map(files, file => {\n+        return publishedFilesQueryBuilder.createOne({\n+          file_id: file.id,\n+          published_id: this.publishedProject.id,\n+          path: file.path,\n+          buffer: file.buffer\n+        })\n+        .then(() => upload(\n+          `${this.publishRoot}${file.path}`,\n+          file.buffer,\n+          this.remixData\n+        ))\n+        .then(success(`CREATE`, this.user.name))\n+        .catch(failure(`CREATE`, this.user.name));\n+      });\n     });\n-  });\n-}\n+  }\n \n-function uploadModifiedFiles() {\n-  var self = this;\n-  var remixData = self.remixData;\n-  var fileRoot = self.publishRoot;\n-  var username = self.user.name;\n+  uploadModifiedFiles() {\n+    const remixData = this.remixData;\n+    const fileRoot = this.publishRoot;\n+    const username = this.user.name;\n \n-  function updateModelAndUpload(publishedFile) {\n-    var id = publishedFile.id;\n-    delete publishedFile.id;\n+    function updateModelAndUpload(publishedFile) {\n+      const id = publishedFile.id;\n \n-    return PublishedFileQueries\n+      delete publishedFile.id;\n+\n+      return publishedFilesQueryBuilder\n       .updateOne(id, publishedFile)\n       .then(function() {\n-        return upload(fileRoot + publishedFile.path, publishedFile.buffer, remixData);\n+        return upload(\n+          `${fileRoot}${publishedFile.path}`,\n+          publishedFile.buffer,\n+          remixData\n+        );\n       })\n-      .then(success('UPDATE', username))\n-      .catch(failure('UPDATE', username));\n-  }\n-\n-  return PublishedFileQueries\n-  .getAllModifiedFiles(self.publishedProject.id)\n-  .then(function(publishedFiles) {\n-    if (!publishedFiles.length) {\n-      return;\n+      .then(success(`UPDATE`, username))\n+      .catch(failure(`UPDATE`, username));\n     }\n \n-    return Promise.map(publishedFiles, function(publishedFile) {\n-      var oldPath = publishedFile.oldPath;\n-      delete publishedFile.oldPath;\n-\n-      if (oldPath === publishedFile.path) {\n-        return updateModelAndUpload(publishedFile);\n+    return publishedFilesQueryBuilder\n+    .getAllModifiedFiles(this.publishedProject.id)\n+    .then(function(publishedFiles) {\n+      if (!publishedFiles.length) {\n+        return;\n       }\n \n-      return remove(fileRoot + oldPath)\n-      .then(function() {\n-        return updateModelAndUpload(publishedFile);\n+      return Promise.map(publishedFiles, function(publishedFile) {\n+        const oldPath = publishedFile.oldPath;\n+\n+        delete publishedFile.oldPath;","path":"api/classes/publisher.js","position":507,"original_position":507,"commit_id":"bc7c6b95bf2b43b41131eb23b3ccfed8a9dc9922","original_commit_id":"bc7c6b95bf2b43b41131eb23b3ccfed8a9dc9922","user":{"login":"Pomax","id":177243,"avatar_url":"https://avatars.githubusercontent.com/u/177243?v=3","gravatar_id":"","url":"https://api.github.com/users/Pomax","html_url":"https://github.com/Pomax","followers_url":"https://api.github.com/users/Pomax/followers","following_url":"https://api.github.com/users/Pomax/following{/other_user}","gists_url":"https://api.github.com/users/Pomax/gists{/gist_id}","starred_url":"https://api.github.com/users/Pomax/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Pomax/subscriptions","organizations_url":"https://api.github.com/users/Pomax/orgs","repos_url":"https://api.github.com/users/Pomax/repos","events_url":"https://api.github.com/users/Pomax/events{/privacy}","received_events_url":"https://api.github.com/users/Pomax/received_events","type":"User","site_admin":false},"body":"this is a super expensive operation (due to JIT invalidation), do we *need* to delete this, or can we just set it to `undefined`?","created_at":"2016-06-29T17:35:42Z","updated_at":"2016-06-29T17:35:42Z","html_url":"https://github.com/mozilla/publish.webmaker.org/pull/230#discussion_r68992014","pull_request_url":"https://api.github.com/repos/mozilla/publish.webmaker.org/pulls/230","_links":{"self":{"href":"https://api.github.com/repos/mozilla/publish.webmaker.org/pulls/comments/68992014"},"html":{"href":"https://github.com/mozilla/publish.webmaker.org/pull/230#discussion_r68992014"},"pull_request":{"href":"https://api.github.com/repos/mozilla/publish.webmaker.org/pulls/230"}}},"pull_request":{"url":"https://api.github.com/repos/mozilla/publish.webmaker.org/pulls/230","id":75132890,"html_url":"https://github.com/mozilla/publish.webmaker.org/pull/230","diff_url":"https://github.com/mozilla/publish.webmaker.org/pull/230.diff","patch_url":"https://github.com/mozilla/publish.webmaker.org/pull/230.patch","issue_url":"https://api.github.com/repos/mozilla/publish.webmaker.org/issues/230","number":230,"state":"open","locked":false,"title":"ES6 upgrade","user":{"login":"gideonthomas","id":5816130,"avatar_url":"https://avatars.githubusercontent.com/u/5816130?v=3","gravatar_id":"","url":"https://api.github.com/users/gideonthomas","html_url":"https://github.com/gideonthomas","followers_url":"https://api.github.com/users/gideonthomas/followers","following_url":"https://api.github.com/users/gideonthomas/following{/other_user}","gists_url":"https://api.github.com/users/gideonthomas/gists{/gist_id}","starred_url":"https://api.github.com/users/gideonthomas/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gideonthomas/subscriptions","organizations_url":"https://api.github.com/users/gideonthomas/orgs","repos_url":"https://api.github.com/users/gideonthomas/repos","events_url":"https://api.github.com/users/gideonthomas/events{/privacy}","received_events_url":"https://api.github.com/users/gideonthomas/received_events","type":"User","site_admin":false},"body":"**[PLEASE READ]**\r\n\r\nThis patch converts *most* of publish to ES6 syntax to make it easier to keep up with updates to the JS standards as well as make the code cleaner and slightly easier to read.\r\n\r\nWe follow the mofo-style ESLinting rules and conventions with a few overrides as needed for this project (which can be seen in the `.eslintrc.yaml` file).\r\n\r\nFor the sake of sanity, I have tried to keep the commits as distinct as possible with a logical ordering of changes based on MVC. \r\n\r\n*Note to reviewer - it might be easier to review in the order of the commits. For the review, I'm mainly looking for comments on clear logic errors or performance hits that might be a result of this code change, rather than stylistic comments (if you have any, feel free to add \"nits\").*","created_at":"2016-06-24T15:39:39Z","updated_at":"2016-06-29T17:35:42Z","closed_at":null,"merged_at":null,"merge_commit_sha":"cbf271afa120f050359ece2fabd1536b3ef73e00","assignee":{"login":"Pomax","id":177243,"avatar_url":"https://avatars.githubusercontent.com/u/177243?v=3","gravatar_id":"","url":"https://api.github.com/users/Pomax","html_url":"https://github.com/Pomax","followers_url":"https://api.github.com/users/Pomax/followers","following_url":"https://api.github.com/users/Pomax/following{/other_user}","gists_url":"https://api.github.com/users/Pomax/gists{/gist_id}","starred_url":"https://api.github.com/users/Pomax/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Pomax/subscriptions","organizations_url":"https://api.github.com/users/Pomax/orgs","repos_url":"https://api.github.com/users/Pomax/repos","events_url":"https://api.github.com/users/Pomax/events{/privacy}","received_events_url":"https://api.github.com/users/Pomax/received_events","type":"User","site_admin":false},"assignees":[{"login":"Pomax","id":177243,"avatar_url":"https://avatars.githubusercontent.com/u/177243?v=3","gravatar_id":"","url":"https://api.github.com/users/Pomax","html_url":"https://github.com/Pomax","followers_url":"https://api.github.com/users/Pomax/followers","following_url":"https://api.github.com/users/Pomax/following{/other_user}","gists_url":"https://api.github.com/users/Pomax/gists{/gist_id}","starred_url":"https://api.github.com/users/Pomax/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Pomax/subscriptions","organizations_url":"https://api.github.com/users/Pomax/orgs","repos_url":"https://api.github.com/users/Pomax/repos","events_url":"https://api.github.com/users/Pomax/events{/privacy}","received_events_url":"https://api.github.com/users/Pomax/received_events","type":"User","site_admin":false},{"login":"cadecairos","id":438003,"avatar_url":"https://avatars.githubusercontent.com/u/438003?v=3","gravatar_id":"","url":"https://api.github.com/users/cadecairos","html_url":"https://github.com/cadecairos","followers_url":"https://api.github.com/users/cadecairos/followers","following_url":"https://api.github.com/users/cadecairos/following{/other_user}","gists_url":"https://api.github.com/users/cadecairos/gists{/gist_id}","starred_url":"https://api.github.com/users/cadecairos/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cadecairos/subscriptions","organizations_url":"https://api.github.com/users/cadecairos/orgs","repos_url":"https://api.github.com/users/cadecairos/repos","events_url":"https://api.github.com/users/cadecairos/events{/privacy}","received_events_url":"https://api.github.com/users/cadecairos/received_events","type":"User","site_admin":false}],"milestone":null,"commits_url":"https://api.github.com/repos/mozilla/publish.webmaker.org/pulls/230/commits","review_comments_url":"https://api.github.com/repos/mozilla/publish.webmaker.org/pulls/230/comments","review_comment_url":"https://api.github.com/repos/mozilla/publish.webmaker.org/pulls/comments{/number}","comments_url":"https://api.github.com/repos/mozilla/publish.webmaker.org/issues/230/comments","statuses_url":"https://api.github.com/repos/mozilla/publish.webmaker.org/statuses/bc7c6b95bf2b43b41131eb23b3ccfed8a9dc9922","head":{"label":"gideonthomas:eslint","ref":"eslint","sha":"bc7c6b95bf2b43b41131eb23b3ccfed8a9dc9922","user":{"login":"gideonthomas","id":5816130,"avatar_url":"https://avatars.githubusercontent.com/u/5816130?v=3","gravatar_id":"","url":"https://api.github.com/users/gideonthomas","html_url":"https://github.com/gideonthomas","followers_url":"https://api.github.com/users/gideonthomas/followers","following_url":"https://api.github.com/users/gideonthomas/following{/other_user}","gists_url":"https://api.github.com/users/gideonthomas/gists{/gist_id}","starred_url":"https://api.github.com/users/gideonthomas/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gideonthomas/subscriptions","organizations_url":"https://api.github.com/users/gideonthomas/orgs","repos_url":"https://api.github.com/users/gideonthomas/repos","events_url":"https://api.github.com/users/gideonthomas/events{/privacy}","received_events_url":"https://api.github.com/users/gideonthomas/received_events","type":"User","site_admin":false},"repo":{"id":36807804,"name":"publish.webmaker.org","full_name":"gideonthomas/publish.webmaker.org","owner":{"login":"gideonthomas","id":5816130,"avatar_url":"https://avatars.githubusercontent.com/u/5816130?v=3","gravatar_id":"","url":"https://api.github.com/users/gideonthomas","html_url":"https://github.com/gideonthomas","followers_url":"https://api.github.com/users/gideonthomas/followers","following_url":"https://api.github.com/users/gideonthomas/following{/other_user}","gists_url":"https://api.github.com/users/gideonthomas/gists{/gist_id}","starred_url":"https://api.github.com/users/gideonthomas/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gideonthomas/subscriptions","organizations_url":"https://api.github.com/users/gideonthomas/orgs","repos_url":"https://api.github.com/users/gideonthomas/repos","events_url":"https://api.github.com/users/gideonthomas/events{/privacy}","received_events_url":"https://api.github.com/users/gideonthomas/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/gideonthomas/publish.webmaker.org","description":"The teach.org publishing service for goggles and thimble","fork":true,"url":"https://api.github.com/repos/gideonthomas/publish.webmaker.org","forks_url":"https://api.github.com/repos/gideonthomas/publish.webmaker.org/forks","keys_url":"https://api.github.com/repos/gideonthomas/publish.webmaker.org/keys{/key_id}","collaborators_url":"https://api.github.com/repos/gideonthomas/publish.webmaker.org/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/gideonthomas/publish.webmaker.org/teams","hooks_url":"https://api.github.com/repos/gideonthomas/publish.webmaker.org/hooks","issue_events_url":"https://api.github.com/repos/gideonthomas/publish.webmaker.org/issues/events{/number}","events_url":"https://api.github.com/repos/gideonthomas/publish.webmaker.org/events","assignees_url":"https://api.github.com/repos/gideonthomas/publish.webmaker.org/assignees{/user}","branches_url":"https://api.github.com/repos/gideonthomas/publish.webmaker.org/branches{/branch}","tags_url":"https://api.github.com/repos/gideonthomas/publish.webmaker.org/tags","blobs_url":"https://api.github.com/repos/gideonthomas/publish.webmaker.org/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/gideonthomas/publish.webmaker.org/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/gideonthomas/publish.webmaker.org/git/refs{/sha}","trees_url":"https://api.github.com/repos/gideonthomas/publish.webmaker.org/git/trees{/sha}","statuses_url":"https://api.github.com/repos/gideonthomas/publish.webmaker.org/statuses/{sha}","languages_url":"https://api.github.com/repos/gideonthomas/publish.webmaker.org/languages","stargazers_url":"https://api.github.com/repos/gideonthomas/publish.webmaker.org/stargazers","contributors_url":"https://api.github.com/repos/gideonthomas/publish.webmaker.org/contributors","subscribers_url":"https://api.github.com/repos/gideonthomas/publish.webmaker.org/subscribers","subscription_url":"https://api.github.com/repos/gideonthomas/publish.webmaker.org/subscription","commits_url":"https://api.github.com/repos/gideonthomas/publish.webmaker.org/commits{/sha}","git_commits_url":"https://api.github.com/repos/gideonthomas/publish.webmaker.org/git/commits{/sha}","comments_url":"https://api.github.com/repos/gideonthomas/publish.webmaker.org/comments{/number}","issue_comment_url":"https://api.github.com/repos/gideonthomas/publish.webmaker.org/issues/comments{/number}","contents_url":"https://api.github.com/repos/gideonthomas/publish.webmaker.org/contents/{+path}","compare_url":"https://api.github.com/repos/gideonthomas/publish.webmaker.org/compare/{base}...{head}","merges_url":"https://api.github.com/repos/gideonthomas/publish.webmaker.org/merges","archive_url":"https://api.github.com/repos/gideonthomas/publish.webmaker.org/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/gideonthomas/publish.webmaker.org/downloads","issues_url":"https://api.github.com/repos/gideonthomas/publish.webmaker.org/issues{/number}","pulls_url":"https://api.github.com/repos/gideonthomas/publish.webmaker.org/pulls{/number}","milestones_url":"https://api.github.com/repos/gideonthomas/publish.webmaker.org/milestones{/number}","notifications_url":"https://api.github.com/repos/gideonthomas/publish.webmaker.org/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/gideonthomas/publish.webmaker.org/labels{/name}","releases_url":"https://api.github.com/repos/gideonthomas/publish.webmaker.org/releases{/id}","deployments_url":"https://api.github.com/repos/gideonthomas/publish.webmaker.org/deployments","created_at":"2015-06-03T14:08:01Z","updated_at":"2015-06-02T21:02:31Z","pushed_at":"2016-06-24T15:42:55Z","git_url":"git://github.com/gideonthomas/publish.webmaker.org.git","ssh_url":"git@github.com:gideonthomas/publish.webmaker.org.git","clone_url":"https://github.com/gideonthomas/publish.webmaker.org.git","svn_url":"https://github.com/gideonthomas/publish.webmaker.org","homepage":null,"size":890,"stargazers_count":0,"watchers_count":0,"language":null,"has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"mozilla:master","ref":"master","sha":"3a963e29a8d5722f6536362d28857783e0bc4267","user":{"login":"mozilla","id":131524,"avatar_url":"https://avatars.githubusercontent.com/u/131524?v=3","gravatar_id":"","url":"https://api.github.com/users/mozilla","html_url":"https://github.com/mozilla","followers_url":"https://api.github.com/users/mozilla/followers","following_url":"https://api.github.com/users/mozilla/following{/other_user}","gists_url":"https://api.github.com/users/mozilla/gists{/gist_id}","starred_url":"https://api.github.com/users/mozilla/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mozilla/subscriptions","organizations_url":"https://api.github.com/users/mozilla/orgs","repos_url":"https://api.github.com/users/mozilla/repos","events_url":"https://api.github.com/users/mozilla/events{/privacy}","received_events_url":"https://api.github.com/users/mozilla/received_events","type":"Organization","site_admin":false},"repo":{"id":36752205,"name":"publish.webmaker.org","full_name":"mozilla/publish.webmaker.org","owner":{"login":"mozilla","id":131524,"avatar_url":"https://avatars.githubusercontent.com/u/131524?v=3","gravatar_id":"","url":"https://api.github.com/users/mozilla","html_url":"https://github.com/mozilla","followers_url":"https://api.github.com/users/mozilla/followers","following_url":"https://api.github.com/users/mozilla/following{/other_user}","gists_url":"https://api.github.com/users/mozilla/gists{/gist_id}","starred_url":"https://api.github.com/users/mozilla/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mozilla/subscriptions","organizations_url":"https://api.github.com/users/mozilla/orgs","repos_url":"https://api.github.com/users/mozilla/repos","events_url":"https://api.github.com/users/mozilla/events{/privacy}","received_events_url":"https://api.github.com/users/mozilla/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/mozilla/publish.webmaker.org","description":"The teach.org publishing service for goggles and thimble","fork":false,"url":"https://api.github.com/repos/mozilla/publish.webmaker.org","forks_url":"https://api.github.com/repos/mozilla/publish.webmaker.org/forks","keys_url":"https://api.github.com/repos/mozilla/publish.webmaker.org/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mozilla/publish.webmaker.org/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mozilla/publish.webmaker.org/teams","hooks_url":"https://api.github.com/repos/mozilla/publish.webmaker.org/hooks","issue_events_url":"https://api.github.com/repos/mozilla/publish.webmaker.org/issues/events{/number}","events_url":"https://api.github.com/repos/mozilla/publish.webmaker.org/events","assignees_url":"https://api.github.com/repos/mozilla/publish.webmaker.org/assignees{/user}","branches_url":"https://api.github.com/repos/mozilla/publish.webmaker.org/branches{/branch}","tags_url":"https://api.github.com/repos/mozilla/publish.webmaker.org/tags","blobs_url":"https://api.github.com/repos/mozilla/publish.webmaker.org/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mozilla/publish.webmaker.org/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mozilla/publish.webmaker.org/git/refs{/sha}","trees_url":"https://api.github.com/repos/mozilla/publish.webmaker.org/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mozilla/publish.webmaker.org/statuses/{sha}","languages_url":"https://api.github.com/repos/mozilla/publish.webmaker.org/languages","stargazers_url":"https://api.github.com/repos/mozilla/publish.webmaker.org/stargazers","contributors_url":"https://api.github.com/repos/mozilla/publish.webmaker.org/contributors","subscribers_url":"https://api.github.com/repos/mozilla/publish.webmaker.org/subscribers","subscription_url":"https://api.github.com/repos/mozilla/publish.webmaker.org/subscription","commits_url":"https://api.github.com/repos/mozilla/publish.webmaker.org/commits{/sha}","git_commits_url":"https://api.github.com/repos/mozilla/publish.webmaker.org/git/commits{/sha}","comments_url":"https://api.github.com/repos/mozilla/publish.webmaker.org/comments{/number}","issue_comment_url":"https://api.github.com/repos/mozilla/publish.webmaker.org/issues/comments{/number}","contents_url":"https://api.github.com/repos/mozilla/publish.webmaker.org/contents/{+path}","compare_url":"https://api.github.com/repos/mozilla/publish.webmaker.org/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mozilla/publish.webmaker.org/merges","archive_url":"https://api.github.com/repos/mozilla/publish.webmaker.org/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mozilla/publish.webmaker.org/downloads","issues_url":"https://api.github.com/repos/mozilla/publish.webmaker.org/issues{/number}","pulls_url":"https://api.github.com/repos/mozilla/publish.webmaker.org/pulls{/number}","milestones_url":"https://api.github.com/repos/mozilla/publish.webmaker.org/milestones{/number}","notifications_url":"https://api.github.com/repos/mozilla/publish.webmaker.org/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mozilla/publish.webmaker.org/labels{/name}","releases_url":"https://api.github.com/repos/mozilla/publish.webmaker.org/releases{/id}","deployments_url":"https://api.github.com/repos/mozilla/publish.webmaker.org/deployments","created_at":"2015-06-02T18:10:38Z","updated_at":"2016-02-23T16:52:27Z","pushed_at":"2016-06-27T17:11:28Z","git_url":"git://github.com/mozilla/publish.webmaker.org.git","ssh_url":"git@github.com:mozilla/publish.webmaker.org.git","clone_url":"https://github.com/mozilla/publish.webmaker.org.git","svn_url":"https://github.com/mozilla/publish.webmaker.org","homepage":"https://publish-webmaker-org-prod.herokuapp.com/","size":935,"stargazers_count":4,"watchers_count":4,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":11,"mirror_url":null,"open_issues_count":26,"forks":11,"open_issues":26,"watchers":4,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/mozilla/publish.webmaker.org/pulls/230"},"html":{"href":"https://github.com/mozilla/publish.webmaker.org/pull/230"},"issue":{"href":"https://api.github.com/repos/mozilla/publish.webmaker.org/issues/230"},"comments":{"href":"https://api.github.com/repos/mozilla/publish.webmaker.org/issues/230/comments"},"review_comments":{"href":"https://api.github.com/repos/mozilla/publish.webmaker.org/pulls/230/comments"},"review_comment":{"href":"https://api.github.com/repos/mozilla/publish.webmaker.org/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/mozilla/publish.webmaker.org/pulls/230/commits"},"statuses":{"href":"https://api.github.com/repos/mozilla/publish.webmaker.org/statuses/bc7c6b95bf2b43b41131eb23b3ccfed8a9dc9922"}}}}
{"actor":{"display_login":"Pomax"}}