diff --git a/.eslintrc.js b/.eslintrc.js index 6b1e6689..f68650cc 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,3 +1,6 @@ module.exports = { - extends: ['@tophat', '@tophat/eslint-config/jest'] + extends: ['@tophat', '@tophat/eslint-config/jest'], + rules: { + camelcase: 0 + } } diff --git a/src/CommentReply/index.js b/src/CommentReply/index.js new file mode 100644 index 00000000..4aa48c64 --- /dev/null +++ b/src/CommentReply/index.js @@ -0,0 +1,30 @@ +/* + * Queues all replies, and sends in one message + */ +class CommentReply { + constructor({ context }) { + this.context = context + this.message = '' + } + + replyingToWho() { + return this.context.payload.comment.user.login + } + + replyingToWhere() { + return this.context.payload.comment.html_url + } + + reply(message) { + this.message = `\n\n${message}` + } + + async send() { + const fromUser = this.replyingToWho() + const body = `@${fromUser} ${this.message}` + const issueComment = this.context.issue({ body }) + return this.context.github.issues.createComment(issueComment) + } +} + +module.exports = CommentReply diff --git a/src/ContentFiles/index.js b/src/ContentFiles/index.js new file mode 100644 index 00000000..e03ef7f9 --- /dev/null +++ b/src/ContentFiles/index.js @@ -0,0 +1,43 @@ +const { generate: generateContentFile } = require('all-contributors-cli') + +/* + * Fetches, stores, generates, and updates the readme content files for the contributors list + */ +class ContentFiles { + constructor({ context, repository }) { + this.context = context + this.repository = repository + this.contentFilesByPath = null + } + + async fetch(optionsConfig) { + const options = optionsConfig.get() + if (Array.isArray(options.files)) { + this.contentFilesByPath = this.repository.getMultipleFileContents( + options.files, + ) + } else { + this.contentFilesByPath = this.repository.getMultipleFileContents([ + 'README.md', + ]) + } + } + + async generate(optionsConfig) { + const options = optionsConfig.get() + const newReadmeFileContentsByPath = {} + Object.entires(this.contentFilesByPath).forEach( + ([filePath, fileContents]) => { + const newFileContents = generateContentFile( + options, + options.contributors, + fileContents, + ) + newReadmeFileContentsByPath[filePath] = newFileContents + }, + ) + this.contentFilesByPath = newReadmeFileContentsByPath + } +} + +module.exports = ContentFiles diff --git a/src/OptionsConfig/index.js b/src/OptionsConfig/index.js new file mode 100644 index 00000000..59129317 --- /dev/null +++ b/src/OptionsConfig/index.js @@ -0,0 +1,79 @@ +const ALL_CONTRIBUTORS_RC = '.all-contributorsrc' + +const { addContributorWithDetails } = require('all-contributors-cli') + +const { ResourceNotFoundError } = require('../utils/errors') + +class OptionsConfig { + constructor({ context, repository, commentReply }) { + this.context = context + this.repository = repository + this.commentReply = commentReply + this.options = null + } + + async fetch() { + try { + const rawOptionsFileContent = await this.repository.getFileContents( + ALL_CONTRIBUTORS_RC, + ) + try { + const optionsConfig = JSON.parse(rawOptionsFileContent) + this.options = optionsConfig + return optionsConfig + } catch (error) { + if (error instanceof SyntaxError) { + this.commentReply.reply( + `This project's configuration file has malformed JSON: ${ALL_CONTRIBUTORS_RC}. Error:: ${ + error.message + }`, + ) + this.context.log(error) + error.handled = true + throw error + } + } + } catch (error) { + if (error instanceof ResourceNotFoundError) { + this.commentReply + .reply(`This project is not yet setup for [all-contributors](https://github.com/all-contributors/all-contributors).\n + You will need to first setup [${ + this.repository.repo + }](https://github.com/${this.repository.getFullname()}) using the [all-contributors-cli](https://github.com/all-contributors/all-contributors-cli) tool.`) + error.handled = true + throw error + } + } + } + + get() { + return this.options + } + + getRaw() { + return JSON.stringify(this.options) + } + + getPath() { + return ALL_CONTRIBUTORS_RC + } + + async addContributor({ login, contributions, name, avatar_url, profile }) { + const newContributorsList = await addContributorWithDetails({ + options: this.options, + login, + contributions, + name, + avatar_url, + profile, + }) + const newOptions = { + ...this.options, + contributors: newContributorsList, + } + this.options = newOptions + return newOptions + } +} + +module.exports = OptionsConfig diff --git a/src/repository/index.js b/src/Repository/index.js similarity index 73% rename from src/repository/index.js rename to src/Repository/index.js index d2750e07..02335b3f 100644 --- a/src/repository/index.js +++ b/src/Repository/index.js @@ -1,9 +1,4 @@ -class ResourceNotFoundError extends Error { - constructor(filepath, fullRepoName) { - super(`File ${filepath} was not found in repository (${fullRepoName}).`) - this.name = this.constructor.name - } -} +const { ResourceNotFoundError } = require('../utils/errors') class Repository { constructor(context) { @@ -38,6 +33,7 @@ class Repository { } async getMultipleFileContents(filePathsArray) { + // TODO: can probably optimise this instead of sending a request per file const repository = this if (filePathsArray.length > 5) { throw new Error(`Cannot fetch more than 5 files.`) @@ -58,9 +54,17 @@ class Repository { return } -} -module.exports = { - Repository, - ResourceNotFoundError, + async createPullRequest({title, body, fileContentsByPath}) { + // TODO: Create branch, update files + // GET master state when we read files + // https://octokit.github.io/rest.js/#api-Git-createRef + // https://octokit.github.io/rest.js/#api-Repos-updateFile + + // TODO: post pull request + // https://octokit.github.io/rest.js/#api-Pulls-createFromIssue + return pullRequestNumber + } } + +module.exports = Repository diff --git a/src/index.js b/src/index.js index 178bbc97..05c402d9 100644 --- a/src/index.js +++ b/src/index.js @@ -1,189 +1,10 @@ -/* eslint-disable camelcase */ - -const { - addContributorWithDetails, - generate: generateContentFile, -} = require('all-contributors-cli') - -const { Repository, ResourceNotFoundError } = require('./repository') -// const parseComment = require('./parse-comment') - -const GIHUB_BOT_NAME = '@AllContributorsBot' -const ALL_CONTRIBUTORS_RC = '.all-contributorsrc' - -async function createComment({ context, body }) { - const issueComment = context.issue({ body }) - return context.github.issues.createComment(issueComment) -} - -async function getReadmeFileContentsByPath({ repository, files }) { - if (Array.isArray(files)) { - return repository.getMultipleFileContents(files) - } else { - // default 'files' is ['README.md'] - return repository.getMultipleFileContents(['README.md']) - } -} - -async function getUserDetials({ context, username }) { - // TODO: optimzation, if commenting user is the user we're adding we can avoid an api call - // const commentUser = context.payload.comment.user.login - // if (user === commentUser) { - // return { - // name: context.payload.comment.user.name - // avatarUrl: context.payload.comment.avatar_url - // profile: - // } - // } - - const result = await context.github.users.getByUsername({ username }) - const { avatar_url, blog, html_url, name } = result.data - - return { - name: name || username, - avatar_url, - profile: blog || html_url, - } -} - -async function addContributor({ - options, - login, - contributions, - name, - avatar_url, - profile, -}) { - const newContributorsList = await addContributorWithDetails({ - options, - login, - contributions, - name, - avatar_url, - profile, - }) - return { ...options, contributors: newContributorsList } -} - -async function generateContentFiles({ options, readmeFileContentsByPath }) { - const newReadmeFileContentsByPath = {} - Object.entires(readmeFileContentsByPath).forEach( - ([filePath, fileContents]) => { - const newFileContents = generateContentFile( - options, - options.contributors, - fileContents, - ) - newReadmeFileContentsByPath[filePath] = newFileContents - }, - ) - return newReadmeFileContentsByPath -} - -async function processNewIssueComment(context) { - if (context.isBot) { - context.log('From a bot, exiting') - return - } - - const fromUser = context.payload.comment.user.login - const commentBody = context.payload.comment.body - const hasMentionedBotName = commentBody.includes(GIHUB_BOT_NAME) - - if (!hasMentionedBotName) { - context.log('Message not for us, exiting') - return - } - - const repository = new Repository(context) - - let optionsFileContent - try { - const rawOptionsFileContent = await repository.getFileContents( - ALL_CONTRIBUTORS_RC, - ) - optionsFileContent = JSON.parse(rawOptionsFileContent) - // TODO: if JSON has error report that - } catch (error) { - if (error instanceof ResourceNotFoundError) { - await createComment({ - context, - body: `@${fromUser} This project is not yet setup for [all-contributors](https://github.com/all-contributors/all-contributors).\n -You will need to first setup [${ - repository.repo - }](https://github.com/${repository.getFullname()}) using the [all-contributors-cli](https://github.com/all-contributors/all-contributors-cli) tool.`, - }) - context.log(error) - return - } - } - context.log('Options Content') - context.log(optionsFileContent) - - // TODO parse comment and gain intentions - // const { who, contributions } = parseComment(commentBody) - // We had trouble reading your comment. Basic usage:\n\n\`@${GIHUB_BOT_NAME} please add jakebolam for code\` - const who = 'jakebolam' - const contributions = ['code'] - - const { name, avatar_url, profile } = await getUserDetials({ - context, - username: who, - }) - - const newOptionsContent = await addContributor({ - options: optionsFileContent, - login: who, - contributions, - name, - avatar_url, - profile, - }) - context.log('New Options Content') - context.log(newOptionsContent) - - const readmeFileContentsByPath = await getReadmeFileContentsByPath({ - repository, - files: optionsFileContent.files, - }) - - context.log('Readme file contents by path') - context.log(readmeFileContentsByPath) - - const newReadmeFileContentsByPath = await generateContentFiles({ - options: newOptionsContent, - readmeFileContentsByPath, - }) - context.log('New readme file contents by path') - context.log(newReadmeFileContentsByPath) - - // TODO: Create branch, update files - // GET master state when we read files - // https://octokit.github.io/rest.js/#api-Git-createRef - // https://octokit.github.io/rest.js/#api-Repos-updateFile - - // TODO: post pull request - // https://octokit.github.io/rest.js/#api-Pulls-createFromIssue - - // TODO: Comment back with link to pull request -} +const processIssueComment = require('./processIssueComment') module.exports = app => { // issueComment.edited // Issue comments and PR comments both create issue_comment events app.on('issue_comment.created', async context => { - try { - await processNewIssueComment(context) - } catch (error) { - await createComment({ - context, - body: `@${ - context.payload.comment.user.login - } we had trouble processing your request. \n\nError: ${ - error.message - }`, - }) - throw error - } + app.log(context) + await processIssueComment(context) }) } diff --git a/src/processIssueComment.js b/src/processIssueComment.js new file mode 100644 index 00000000..23296f20 --- /dev/null +++ b/src/processIssueComment.js @@ -0,0 +1,95 @@ +const CommentReply = require('./CommentReply') +const Repository = require('./Repository') +const OptionsConfig = require('./OptionsConfig') +const ContentFiles = require('./ContentFiles') + +const getUserDetails = require('./utils/getUserDetails') +// const parseComment = require('./parse-comment') + +const { GIHUB_BOT_NAME } = require('./utils/settings') + +function hasMentionedBotName(context) { + const commentBody = context.payload.comment.body + const hasMentionedBotName = commentBody.includes(GIHUB_BOT_NAME) + return hasMentionedBotName +} + +async function processIssueComment({ context, commentReply }) { + if (context.isBot) { + context.log('From a bot, exiting') + return + } + + if (!hasMentionedBotName(context)) { + context.log('Message not for us, exiting') + return + } + + const repository = new Repository(context) + const optionsConfig = new OptionsConfig({ + context, + repository, + commentReply, + }) + await optionsConfig.fetch() + + // TODO parse comment and gain intentions + // const { who, contributions } = parseComment(commentBody) + // We had trouble reading your comment. Basic usage:\n\n\`@${GIHUB_BOT_NAME} please add jakebolam for code\` + const who = 'jakebolam' + const contributions = ['code'] + + const { name, avatar_url, profile } = await getUserDetails({ + context, + username: who, + }) + + await optionsConfig.addContributor({ + login: who, + contributions, + name, + avatar_url, + profile, + }) + + const contentFiles = new ContentFiles({ + context, + repository, + }) + await contentFiles.fetch(optionsConfig) + await contentFiles.generate(optionsConfig) + const fileContentsByPathToUpdate = contentFiles.get() + fileContentsByPathToUpdate[optionsConfig.getPath()] = optionsConfig.getRaw() + + const pullRequestNumber = await repository.createPullRequest({ + title: `docs: add ${who} as contributor`, + body: `Adds ${who} as a contributor for ${contributions.join( + ',', + )}.\n\n This was requested by ${commentReply.replyingToWho()} on ${ + commentReply.replyingToWhere + }`, + fileContentsByPath: fileContentsByPathToUpdate, + }) + + commentReply.reply( + `I've put up [a pull request](#${pullRequestNumber}) to add ${who}! :tada:`, + ) +} + +async function processIssueCommentSafe(context) { + const commentReply = new CommentReply(context) + try { + await processIssueComment({ context, commentReply }) + } catch (error) { + if (!error.handled) { + commentReply.reply(`We had trouble processing your request`) + commentReply.reply(`Error: ${error.message}`) + } + context.log(error) // TODO: if handled context.log as debug? + throw error + } finally { + await commentReply.send() + } +} + +module.exports = processIssueCommentSafe diff --git a/src/utils/errors.js b/src/utils/errors.js new file mode 100644 index 00000000..2c44a05e --- /dev/null +++ b/src/utils/errors.js @@ -0,0 +1,10 @@ +class ResourceNotFoundError extends Error { + constructor(filepath, fullRepoName) { + super(`File ${filepath} was not found in repository (${fullRepoName}).`) + this.name = this.constructor.name + } +} + +module.exports = { + ResourceNotFoundError, +} diff --git a/src/utils/getUserDetails.js b/src/utils/getUserDetails.js new file mode 100644 index 00000000..2dcd57ea --- /dev/null +++ b/src/utils/getUserDetails.js @@ -0,0 +1,22 @@ +async function getUserDetials({ context, username }) { + // TODO: optimzation, if commenting user is the user we're adding we can avoid an api call + // const commentUser = context.payload.comment.user.login + // if (user === commentUser) { + // return { + // name: context.payload.comment.user.name + // avatarUrl: context.payload.comment.avatar_url + // profile: + // } + // } + + const result = await context.github.users.getByUsername({ username }) + const { avatar_url, blog, html_url, name } = result.data + + return { + name: name || username, + avatar_url, + profile: blog || html_url, + } +} + +module.exports = getUserDetials diff --git a/src/parse-comment/index.js b/src/utils/parse-comment/index.js similarity index 100% rename from src/parse-comment/index.js rename to src/utils/parse-comment/index.js diff --git a/src/parse-comment/refiners/start-of-day.js b/src/utils/parse-comment/refiners/start-of-day.js similarity index 100% rename from src/parse-comment/refiners/start-of-day.js rename to src/utils/parse-comment/refiners/start-of-day.js diff --git a/src/utils/settings.js b/src/utils/settings.js new file mode 100644 index 00000000..28a5baf8 --- /dev/null +++ b/src/utils/settings.js @@ -0,0 +1,5 @@ +const GIHUB_BOT_NAME = '@AllContributorsBot' + +module.exports = { + GIHUB_BOT_NAME, +} diff --git a/test/fixtures/issue_comment.created.json b/test/fixtures/issue_comment.created.json new file mode 100644 index 00000000..6191df09 --- /dev/null +++ b/test/fixtures/issue_comment.created.json @@ -0,0 +1,223 @@ +{ + "payload": { + "action": "created", + "issue": { + "url": "https://api.github.com/repos/all-contributors/all-contributors-bot/issues/1", + "repository_url": "https://api.github.com/repos/all-contributors/all-contributors-bot", + "labels_url": "https://api.github.com/repos/all-contributors/all-contributors-bot/issues/1/labels{/name}", + "comments_url": "https://api.github.com/repos/all-contributors/all-contributors-bot/issues/1/comments", + "events_url": "https://api.github.com/repos/all-contributors/all-contributors-bot/issues/1/events", + "html_url": "https://github.com/all-contributors/all-contributors-bot/pull/1", + "id": 396481824, + "node_id": "MDExOlB1bGxSZXF1ZXN0MjQyNjU0MDM0", + "number": 1, + "title": "(wip) test: test pr for the bot", + "user": { + "login": "jakebolam", + "id": 3534236, + "node_id": "MDQ6VXNlcjM1MzQyMzY=", + "avatar_url": "https://avatars2.githubusercontent.com/u/3534236?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/jakebolam", + "html_url": "https://github.com/jakebolam", + "followers_url": "https://api.github.com/users/jakebolam/followers", + "following_url": "https://api.github.com/users/jakebolam/following{/other_user}", + "gists_url": "https://api.github.com/users/jakebolam/gists{/gist_id}", + "starred_url": "https://api.github.com/users/jakebolam/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/jakebolam/subscriptions", + "organizations_url": "https://api.github.com/users/jakebolam/orgs", + "repos_url": "https://api.github.com/users/jakebolam/repos", + "events_url": "https://api.github.com/users/jakebolam/events{/privacy}", + "received_events_url": "https://api.github.com/users/jakebolam/received_events", + "type": "User", + "site_admin": false + }, + "labels": [], + "state": "open", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 60, + "created_at": "2019-01-07T13:12:39Z", + "updated_at": "2019-01-10T08:36:52Z", + "closed_at": null, + "author_association": "MEMBER", + "pull_request": { + "url": "https://api.github.com/repos/all-contributors/all-contributors-bot/pulls/1", + "html_url": "https://github.com/all-contributors/all-contributors-bot/pull/1", + "diff_url": "https://github.com/all-contributors/all-contributors-bot/pull/1.diff", + "patch_url": "https://github.com/all-contributors/all-contributors-bot/pull/1.patch" + }, + "body": "" + }, + "comment": { + "url": "https://api.github.com/repos/all-contributors/all-contributors-bot/issues/comments/453012966", + "html_url": "https://github.com/all-contributors/all-contributors-bot/pull/1#issuecomment-453012966", + "issue_url": "https://api.github.com/repos/all-contributors/all-contributors-bot/issues/1", + "id": 453012966, + "node_id": "MDEyOklzc3VlQ29tbWVudDQ1MzAxMjk2Ng==", + "user": { + "login": "jakebolam", + "id": 3534236, + "node_id": "MDQ6VXNlcjM1MzQyMzY=", + "avatar_url": "https://avatars2.githubusercontent.com/u/3534236?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/jakebolam", + "html_url": "https://github.com/jakebolam", + "followers_url": "https://api.github.com/users/jakebolam/followers", + "following_url": "https://api.github.com/users/jakebolam/following{/other_user}", + "gists_url": "https://api.github.com/users/jakebolam/gists{/gist_id}", + "starred_url": "https://api.github.com/users/jakebolam/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/jakebolam/subscriptions", + "organizations_url": "https://api.github.com/users/jakebolam/orgs", + "repos_url": "https://api.github.com/users/jakebolam/repos", + "events_url": "https://api.github.com/users/jakebolam/events{/privacy}", + "received_events_url": "https://api.github.com/users/jakebolam/received_events", + "type": "User", + "site_admin": false + }, + "created_at": "2019-01-10T08:36:52Z", + "updated_at": "2019-01-10T08:36:52Z", + "author_association": "MEMBER", + "body": "@AllContributorsBot please add jakebolam for code" + }, + "repository": { + "id": 164268911, + "node_id": "MDEwOlJlcG9zaXRvcnkxNjQyNjg5MTE=", + "name": "all-contributors-bot", + "full_name": "all-contributors/all-contributors-bot", + "private": false, + "owner": { + "login": "all-contributors", + "id": 46410174, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjQ2NDEwMTc0", + "avatar_url": "https://avatars1.githubusercontent.com/u/46410174?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/all-contributors", + "html_url": "https://github.com/all-contributors", + "followers_url": "https://api.github.com/users/all-contributors/followers", + "following_url": "https://api.github.com/users/all-contributors/following{/other_user}", + "gists_url": "https://api.github.com/users/all-contributors/gists{/gist_id}", + "starred_url": "https://api.github.com/users/all-contributors/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/all-contributors/subscriptions", + "organizations_url": "https://api.github.com/users/all-contributors/orgs", + "repos_url": "https://api.github.com/users/all-contributors/repos", + "events_url": "https://api.github.com/users/all-contributors/events{/privacy}", + "received_events_url": "https://api.github.com/users/all-contributors/received_events", + "type": "Organization", + "site_admin": false + }, + "html_url": "https://github.com/all-contributors/all-contributors-bot", + "description": "A GitHub bot for automatically adding all-contributors", + "fork": false, + "url": "https://api.github.com/repos/all-contributors/all-contributors-bot", + "forks_url": "https://api.github.com/repos/all-contributors/all-contributors-bot/forks", + "keys_url": "https://api.github.com/repos/all-contributors/all-contributors-bot/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/all-contributors/all-contributors-bot/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/all-contributors/all-contributors-bot/teams", + "hooks_url": "https://api.github.com/repos/all-contributors/all-contributors-bot/hooks", + "issue_events_url": "https://api.github.com/repos/all-contributors/all-contributors-bot/issues/events{/number}", + "events_url": "https://api.github.com/repos/all-contributors/all-contributors-bot/events", + "assignees_url": "https://api.github.com/repos/all-contributors/all-contributors-bot/assignees{/user}", + "branches_url": "https://api.github.com/repos/all-contributors/all-contributors-bot/branches{/branch}", + "tags_url": "https://api.github.com/repos/all-contributors/all-contributors-bot/tags", + "blobs_url": "https://api.github.com/repos/all-contributors/all-contributors-bot/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/all-contributors/all-contributors-bot/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/all-contributors/all-contributors-bot/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/all-contributors/all-contributors-bot/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/all-contributors/all-contributors-bot/statuses/{sha}", + "languages_url": "https://api.github.com/repos/all-contributors/all-contributors-bot/languages", + "stargazers_url": "https://api.github.com/repos/all-contributors/all-contributors-bot/stargazers", + "contributors_url": "https://api.github.com/repos/all-contributors/all-contributors-bot/contributors", + "subscribers_url": "https://api.github.com/repos/all-contributors/all-contributors-bot/subscribers", + "subscription_url": "https://api.github.com/repos/all-contributors/all-contributors-bot/subscription", + "commits_url": "https://api.github.com/repos/all-contributors/all-contributors-bot/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/all-contributors/all-contributors-bot/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/all-contributors/all-contributors-bot/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/all-contributors/all-contributors-bot/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/all-contributors/all-contributors-bot/contents/{+path}", + "compare_url": "https://api.github.com/repos/all-contributors/all-contributors-bot/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/all-contributors/all-contributors-bot/merges", + "archive_url": "https://api.github.com/repos/all-contributors/all-contributors-bot/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/all-contributors/all-contributors-bot/downloads", + "issues_url": "https://api.github.com/repos/all-contributors/all-contributors-bot/issues{/number}", + "pulls_url": "https://api.github.com/repos/all-contributors/all-contributors-bot/pulls{/number}", + "milestones_url": "https://api.github.com/repos/all-contributors/all-contributors-bot/milestones{/number}", + "notifications_url": "https://api.github.com/repos/all-contributors/all-contributors-bot/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/all-contributors/all-contributors-bot/labels{/name}", + "releases_url": "https://api.github.com/repos/all-contributors/all-contributors-bot/releases{/id}", + "deployments_url": "https://api.github.com/repos/all-contributors/all-contributors-bot/deployments", + "created_at": "2019-01-06T02:33:42Z", + "updated_at": "2019-01-10T07:07:49Z", + "pushed_at": "2019-01-10T07:07:47Z", + "git_url": "git://github.com/all-contributors/all-contributors-bot.git", + "ssh_url": "git@github.com:all-contributors/all-contributors-bot.git", + "clone_url": "https://github.com/all-contributors/all-contributors-bot.git", + "svn_url": "https://github.com/all-contributors/all-contributors-bot", + "homepage": "", + "size": 292, + "stargazers_count": 1, + "watchers_count": 1, + "language": "JavaScript", + "has_issues": true, + "has_projects": true, + "has_downloads": true, + "has_wiki": false, + "has_pages": false, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "open_issues_count": 4, + "license": { + "key": "mit", + "name": "MIT License", + "spdx_id": "MIT", + "url": "https://api.github.com/licenses/mit", + "node_id": "MDc6TGljZW5zZTEz" + }, + "forks": 0, + "open_issues": 4, + "watchers": 1, + "default_branch": "master" + }, + "organization": { + "login": "all-contributors", + "id": 46410174, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjQ2NDEwMTc0", + "url": "https://api.github.com/orgs/all-contributors", + "repos_url": "https://api.github.com/orgs/all-contributors/repos", + "events_url": "https://api.github.com/orgs/all-contributors/events", + "hooks_url": "https://api.github.com/orgs/all-contributors/hooks", + "issues_url": "https://api.github.com/orgs/all-contributors/issues", + "members_url": "https://api.github.com/orgs/all-contributors/members{/member}", + "public_members_url": "https://api.github.com/orgs/all-contributors/public_members{/member}", + "avatar_url": "https://avatars1.githubusercontent.com/u/46410174?v=4", + "description": "✨ Recognize all contributors, not just the ones who push code ✨" + }, + "sender": { + "login": "jakebolam", + "id": 3534236, + "node_id": "MDQ6VXNlcjM1MzQyMzY=", + "avatar_url": "https://avatars2.githubusercontent.com/u/3534236?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/jakebolam", + "html_url": "https://github.com/jakebolam", + "followers_url": "https://api.github.com/users/jakebolam/followers", + "following_url": "https://api.github.com/users/jakebolam/following{/other_user}", + "gists_url": "https://api.github.com/users/jakebolam/gists{/gist_id}", + "starred_url": "https://api.github.com/users/jakebolam/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/jakebolam/subscriptions", + "organizations_url": "https://api.github.com/users/jakebolam/orgs", + "repos_url": "https://api.github.com/users/jakebolam/repos", + "events_url": "https://api.github.com/users/jakebolam/events{/privacy}", + "received_events_url": "https://api.github.com/users/jakebolam/received_events", + "type": "User", + "site_admin": false + }, + "installation": { + "id": 562975, + "node_id": "MDIzOkludGVncmF0aW9uSW5zdGFsbGF0aW9uNTYyOTc1" + } + } +} diff --git a/test/fixtures/issues.opened.json b/test/fixtures/issues.opened.json deleted file mode 100644 index dfd976c6..00000000 --- a/test/fixtures/issues.opened.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "action": "opened", - "issue": { - "number": 1, - "user": { - "login": "hiimbex" - } - }, - "repository": { - "name": "testing-things", - "owner": { - "login": "hiimbex" - } - } -} diff --git a/test/parse-comment/index.js b/test/utils/parse-comment/index.test.js similarity index 100% rename from test/parse-comment/index.js rename to test/utils/parse-comment/index.test.js