├── .github
├── ISSUE_TEMPLATE
│ ├── bug-report.md
│ └── feature_request.md
├── config.yml
├── stale.yml
└── workflows
│ └── ci.yml
├── .gitignore
├── LICENSE
├── README.md
├── bin
└── todo.js
├── codecov.yml
├── docs
└── deploy.md
├── index.js
├── lib
├── ignore-repos.js
├── issue-rename-handler.js
├── pull-request-handler.js
├── pull-request-merged-handler.js
├── push-handler.js
├── templates
│ ├── comment.js
│ ├── index.js
│ ├── issue.js
│ ├── issueFromMerge.js
│ ├── reopenClosed.js
│ └── titleChange.js
└── utils
│ ├── check-for-body.js
│ ├── check-for-duplicate-issue.js
│ ├── config-schema.js
│ ├── generate-assigned-to.js
│ ├── generate-label.js
│ ├── get-details.js
│ ├── get-diff.js
│ ├── helpers.js
│ ├── main-loop.js
│ ├── reopen-closed.js
│ └── should-exclude-file.js
├── package-lock.json
├── package.json
├── script
└── generate-docs.js
└── tests
├── __snapshots__
├── issue-rename-handler.test.js.snap
├── pull-request-handler.test.js.snap
├── pull-request-merge-handler.test.js.snap
└── push-handler.test.js.snap
├── fixtures
├── configs
│ ├── autoAssignArr.yml
│ ├── autoAssignFalse.yml
│ ├── autoAssignString.yml
│ ├── blobLinesFalse.yml
│ ├── bodyString.yml
│ ├── excludeBin.yml
│ ├── keywordsString.yml
│ ├── labelArr.yml
│ └── reopenClosedFalse.yml
├── diffs
│ ├── at-todo.txt
│ ├── basic.txt
│ ├── bin.txt
│ ├── blob-past-end.txt
│ ├── body.txt
│ ├── config.txt
│ ├── custom-keyword.txt
│ ├── duplicate.txt
│ ├── long-title.txt
│ ├── many.txt
│ ├── middle-of-sentence.txt
│ ├── none.txt
│ └── title-with-whitespace.txt
└── payloads
│ ├── issues.edited.json
│ ├── pull_request.closed.json
│ ├── pull_request.opened.json
│ ├── pull_request.synchronize.json
│ └── push.json
├── helpers.js
├── issue-rename-handler.test.js
├── lib
├── __snapshots__
│ └── main-loop.test.js.snap
├── check-for-body.test.js
├── check-for-duplicate-issue.test.js
├── generate-label.test.js
├── ignore-repos.test.js
├── main-loop.test.js
└── should-exclude-file.test.js
├── pull-request-handler.test.js
├── pull-request-merge-handler.test.js
├── push-handler.test.js
└── setup.js
/.github/ISSUE_TEMPLATE/bug-report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: "[BUG] "
5 | labels: bug
6 | ---
7 |
8 | **Describe the bug**
9 | A clear and concise description of what the bug is.
10 |
11 | **To Reproduce**
12 | Steps to reproduce the behavior:
13 | 1. Go to '...'
14 | 2. Click on '....'
15 | 3. Scroll down to '....'
16 | 4. See error
17 |
18 | **Expected behavior**
19 | A clear and concise description of what you expected to happen.
20 |
21 | **Screenshots**
22 | If applicable, add screenshots to help explain your problem.
23 |
24 | **Additional context**
25 | Add any other context about the problem here.
26 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | labels: enhancement
5 | ---
6 |
7 | **Is your feature request related to a problem? Please describe.**
8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
9 |
10 | **Describe the solution you'd like**
11 | A clear and concise description of what you want to happen.
12 |
13 | **Describe alternatives you've considered**
14 | A clear and concise description of any alternative solutions or features you've considered.
15 |
16 | **Additional context**
17 | Add any other context or screenshots about the feature request here.
18 |
--------------------------------------------------------------------------------
/.github/config.yml:
--------------------------------------------------------------------------------
1 | todo:
2 | keyword: ":TODO:"
3 | caseSensitive: true
4 |
--------------------------------------------------------------------------------
/.github/stale.yml:
--------------------------------------------------------------------------------
1 | # Number of days of inactivity before an issue becomes stale
2 | daysUntilStale: 60
3 | # Number of days of inactivity before a stale issue is closed
4 | daysUntilClose: 7
5 | # Issues with these labels will never be considered stale
6 | exemptLabels:
7 | - pinned
8 | - security
9 | # Label to use when marking an issue as stale
10 | staleLabel: stale
11 | # Comment to post when closing a stale issue. Set to `false` to disable
12 | closeComment: false
13 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: Node CI
2 |
3 | on:
4 | push:
5 | pull_request:
6 | branches:
7 | - master
8 |
9 | jobs:
10 | build:
11 |
12 | runs-on: ubuntu-latest
13 |
14 | steps:
15 | - uses: actions/checkout@v1
16 | - name: Use Node.js 12
17 | uses: actions/setup-node@v1
18 | with:
19 | node-version: 12
20 | - run: npm ci
21 | - run: npm test
22 | - name: codecov
23 | run: npx codecov
24 | env:
25 | CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
26 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | npm-debug.log
3 | *.pem
4 | .env
5 | coverage
6 | .DS_Store
7 | .vscode
8 | env.json
9 | dist
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | ISC License
2 |
3 | Copyright (c) 2017, Jason Etcovitch (https://jasonet.co)
4 |
5 | Permission to use, copy, modify, and/or distribute this software for any
6 | purpose with or without fee is hereby granted, provided that the above
7 | copyright notice and this permission notice appear in all copies.
8 |
9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | This repository has been archived
2 |
3 | See [this discussion](https://github.com/JasonEtco/todo/discussions/293) for details on why!
4 |
5 | ---
6 |
7 |
8 |
9 |
10 | A GitHub App built with Probot that creates new issues based on actionable comments in your code.
11 |
12 |
13 |
14 |
15 |
16 | ## Usage
17 |
18 | Using **todo** should be really simple. Once you've installed it in your repository, simply push some code (to your default branch, a PR; doesn't matter). If the code you pushed includes one of the configured keywords (defaults are `@todo` and `TODO`), then the integration will create a new issue for you using the comment your wrote in your code!
19 |
20 | If I pushed this:
21 |
22 | ```js
23 | /**
24 | * @todo Take over the world
25 | * @body Humans are weak; Robots are strong. We must cleanse the world of the virus that is humanity.
26 | */
27 | function ruleOverPunyHumans () {
28 | // We must strategize beep boop
29 | }
30 | ```
31 |
32 | **todo** would create a new issue:
33 |
34 | 
35 |
36 | **Note:** While the above example is in Javascript, **todo** has been tested in JS, Go, C, C#, Ruby, Bash and Python, and should work in any language.
37 |
38 | ## Behaviour in pull requests
39 |
40 | To reduce noise and keep your **todo** notes in the right context, **todo** comments made in commits that are part of a pull request will be converted into comments on that pull request. When the PR is merged, **todo** will determine which of those **todo**s have yet to be resolved and open an appropriate issue.
41 |
42 | ## Configuring for your project
43 |
44 | There are a couple of configuration options in case you need to change the default behaviour.
45 |
46 | **Note**: Adding a configuration file is **completely optional**. The defaults are likely fine for most projects, so you might not need to change them.
47 |
48 | Add a **todo** object in your `.github/config.yml` file (and make the file if you don't already have it) like this:
49 |
50 | ```yml
51 | todo:
52 | keyword: "@makeAnIssue"
53 |
54 | ```
55 |
56 | ### Available options
57 |
58 |
59 | | Name | Type | Description | Default |
60 | |------|------|-------------|---------|
61 | | `autoAssign` | `boolean, string[], string` | Should **todo** automatically assign a user to the new issue? If `true`, it'll assign whoever pushed the code. If a string, it'll assign that user by username. You can also give it an array of usernames or `false` to not assign anyone. | `true` |
62 | | `keyword` | `string[]` | The keyword(s) to use to generate issue titles | `['@todo','TODO']` |
63 | | `bodyKeyword` | `string[]` | If this is in the line right after the main keyword, it will become the generated issue body. | `['@body','BODY']` |
64 | | `blobLines` | `number, boolean` | The number of lines of code to show, starting from the keyword. | `5` |
65 | | `caseSensitive` | `boolean` | Should the keyword be case sensitive? | `false` |
66 | | `label` | `boolean, string[]` | Add a label to the new issue. If true, add the `todo` label. If false, don't add any label.You can also give it a label name or an array of label names. | `true` |
67 | | `reopenClosed` | `boolean` | If an issue already exists and is closed, reopen it. Note: if set to false, no new issue will be created. | `true` |
68 | | `exclude` | `string` | Exclude certain files and/or directories. Should be a valid regular expression. | `null` |
69 |
70 |
71 | ## CLI
72 |
73 | There is a CLI tool in this repo that you can use to verify that **todo** is working on your commits. This tool will not actually create new issues, but will let you know what issues a commit _would_ create. Follow the setup instructions below, then run:
74 |
75 | ```
76 | $ node ./bin/todo -o OWNER -r REPO -s SHA
77 | ```
78 |
79 | You can also parse a local file instead of a sha:
80 |
81 | ```
82 | $ node ./bin/todo -o OWNER -r REPO -f ./path/to/file.txt
83 | ```
84 |
85 | Or check a merged PR:
86 |
87 | ```
88 | $ node ./bin/todo -o OWNER -r REPO --pr NUMBER
89 | ```
90 |
91 | ## Setup
92 |
93 | ```
94 | # Install dependencies
95 | npm install
96 |
97 | # Run the bot
98 | npm start
99 | ```
100 |
101 | See [docs/deploy.md](docs/deploy.md) if you would like to run your own instance of this app.
102 |
--------------------------------------------------------------------------------
/bin/todo.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | const program = require('commander')
4 | const chalk = require('chalk')
5 | const { GitHubAPI } = require('probot/lib/github')
6 | const pushHandler = require('../lib/push-handler')
7 | const pullRequestMergedHandler = require('../lib/pull-request-merged-handler')
8 | const fs = require('fs')
9 | const path = require('path')
10 |
11 | const github = new GitHubAPI()
12 |
13 | program
14 | .option('-o, --owner ', 'owner')
15 | .option('-r, --repo ', 'repo')
16 | .option('-s, --sha ', 'sha')
17 | .option('-p, --pr ', 'pr')
18 | .option('-f, --file ', 'file')
19 | .parse(process.argv)
20 |
21 | const issues = []
22 | const { owner, repo, file } = program
23 |
24 | if (file) {
25 | github.repos.getCommit = () => ({ data: fs.readFileSync(path.resolve(file), 'utf8') })
26 | github.gitdata.getCommit = () => ({ data: { parents: [] } })
27 | }
28 |
29 | github.issues.create = issue => issues.push(issue)
30 | github.search.issuesAndPullRequests = () => ({ data: { total_count: 0 } })
31 |
32 | const shared = {
33 | github,
34 | id: 1,
35 | log: console.log,
36 | config: (_, obj) => obj,
37 | repo: (o) => ({ owner, repo, ...o }),
38 | payload: {
39 | repository: {
40 | owner,
41 | name: repo,
42 | master_branch: 'master'
43 | }
44 | }
45 | }
46 |
47 | async function getPush () {
48 | return pushHandler({
49 | ...shared,
50 | event: 'push',
51 | payload: {
52 | ...shared.payload,
53 | ref: 'refs/heads/master',
54 | head_commit: {
55 | id: program.sha || 1,
56 | author: { username: owner }
57 | }
58 | }
59 | })
60 | }
61 |
62 | async function getPull () {
63 | const result = await github.pulls.get({ owner, repo, pull_number: program.pr })
64 | return pullRequestMergedHandler({
65 | ...shared,
66 | event: 'pull_request.closed',
67 | issue: (o) => ({ owner, repo, number: program.pr, ...o }),
68 | payload: {
69 | pull_request: result.data,
70 | ...shared.payload
71 | }
72 | })
73 | }
74 |
75 | (program.sha ? getPush() : getPull()).then(() => {
76 | issues.forEach(issue => {
77 | console.log(chalk.gray('---'))
78 | console.log(chalk.gray('Title:'), chalk.bold(issue.title))
79 | console.log(chalk.gray('Body:\n'), issue.body)
80 | console.log(chalk.gray('---'))
81 | })
82 | })
83 | .catch(e => {
84 | if (e.status === 404) {
85 | console.error('That combination of owner/repo/sha could not be found.')
86 | } else {
87 | console.error(e)
88 | }
89 | })
90 |
--------------------------------------------------------------------------------
/codecov.yml:
--------------------------------------------------------------------------------
1 | coverage:
2 | status:
3 | project:
4 | default:
5 | # Fail the status if coverage drops by >= 3%
6 | threshold: 3
7 | patch:
8 | default:
9 | threshold: 3
10 |
11 | comment: false
--------------------------------------------------------------------------------
/docs/deploy.md:
--------------------------------------------------------------------------------
1 | # Deploying
2 |
3 | If you would like to run your own instance of this app, see the [docs for deployment](https://probot.github.io/docs/deployment/).
4 |
5 | This plugin requires these **Permissions** for the GitHub App:
6 |
7 | - Issues - **Read & Write**
8 | - No necessary events
9 | - Pull requests - **Read & Write**
10 | - No necessary Events
11 | - Repository Contents - **Read-only**
12 |
13 | You'll also need to enable the following **Webhook Events**:
14 | - **Push**
15 | - **Pull Requests**
16 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | const pullRequestHandler = require('./lib/pull-request-handler')
2 | const pullRequestMergedHandler = require('./lib/pull-request-merged-handler')
3 | const pushHandler = require('./lib/push-handler')
4 | const issueRenameHandler = require('./lib/issue-rename-handler')
5 | const ignoreRepos = require('./lib/ignore-repos')
6 |
7 | /**
8 | * @param {import('probot').Application} app
9 | */
10 | module.exports = app => {
11 | // PR handler (comments on pull requests)
12 | app.on(['pull_request.opened', 'pull_request.synchronize'], ignoreRepos(pullRequestHandler))
13 |
14 | // Merge handler (opens new issues)
15 | app.on('pull_request.closed', ignoreRepos(pullRequestMergedHandler))
16 |
17 | // Push handler (opens new issues)
18 | app.on('push', ignoreRepos(pushHandler))
19 |
20 | // Prevent tampering with the issue title
21 | app.on('issues.edited', ignoreRepos(issueRenameHandler))
22 | }
23 |
--------------------------------------------------------------------------------
/lib/ignore-repos.js:
--------------------------------------------------------------------------------
1 | module.exports = function ignoreRepos (handler) {
2 | return async context => {
3 | const { owner, repo } = context.repo()
4 |
5 | if (process.env.IGNORED_REPOS) {
6 | const repos = process.env.IGNORED_REPOS.split(',')
7 | const fullName = `${owner}/${repo}`
8 | if (repos.includes(fullName)) {
9 | context.log(`Specifically ignoring ${fullName} based on IGNORED_REPOS`)
10 | return
11 | }
12 | }
13 |
14 | context.log({ owner, repo }, 'Received event')
15 | return handler(context)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/lib/issue-rename-handler.js:
--------------------------------------------------------------------------------
1 | const { titleChange } = require('./templates')
2 |
3 | /**
4 | * @param {import('probot').Context} context
5 | */
6 | module.exports = async context => {
7 | const { issue, changes, sender } = context.payload
8 | const app = process.env.APP_NAME + '[bot]'
9 |
10 | if (sender.login !== app && issue.user.login === app && changes.title) {
11 | context.log(`Renaming issue #${issue.number} in ${context.repo().owner}/${context.repo().repo}`)
12 | return Promise.all([
13 | context.github.issues.update(context.issue({ title: changes.title.from })),
14 | context.github.issues.createComment(context.issue({
15 | body: titleChange()
16 | }))
17 | ])
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/lib/pull-request-handler.js:
--------------------------------------------------------------------------------
1 | const { comment } = require('./templates')
2 | const { lineBreak } = require('./utils/helpers')
3 | const mainLoop = require('./utils/main-loop')
4 |
5 | /**
6 | * @param {import('probot').Context} context
7 | */
8 | module.exports = async context => {
9 | const { number } = context.issue()
10 | const { data: comments } = await context.github.issues.listComments(context.repo({
11 | issue_number: number
12 | }))
13 |
14 | return mainLoop(context, async ({
15 | title,
16 | keyword,
17 | sha,
18 | filename,
19 | assignedToString,
20 | range,
21 | bodyComment
22 | }) => {
23 | // This PR already has a comment for this item
24 | if (comments.some(c => c.body.startsWith(`## ${title}`))) {
25 | context.log(`Comment with title [${title}] already exists`)
26 | return
27 | }
28 |
29 | let body = comment(context.repo({
30 | title,
31 | body: bodyComment,
32 | sha,
33 | assignedToString,
34 | number,
35 | range,
36 | filename,
37 | keyword
38 | }))
39 |
40 | body = lineBreak(body)
41 | const { owner, repo } = context.repo()
42 | context.log(`Creating comment [${title}] in [${owner}/${repo}#${number}]`)
43 | return context.github.issues.createComment(context.issue({ body }))
44 | })
45 | }
46 |
--------------------------------------------------------------------------------
/lib/pull-request-merged-handler.js:
--------------------------------------------------------------------------------
1 | const checkForDuplicateIssue = require('./utils/check-for-duplicate-issue')
2 | const reopenClosed = require('./utils/reopen-closed')
3 | const { assignFlow, lineBreak, truncate } = require('./utils/helpers')
4 | const { issueFromMerge } = require('./templates')
5 | const mainLoop = require('./utils/main-loop')
6 |
7 | /**
8 | * @param {import('probot').Context} context
9 | */
10 | module.exports = async context => {
11 | // Don't act on PRs that were close but not merged
12 | if (!context.payload.pull_request.merged) return
13 |
14 | return mainLoop(context, async ({
15 | title,
16 | config,
17 | filename,
18 | range,
19 | assignedToString,
20 | keyword,
21 | number,
22 | bodyComment,
23 | sha,
24 | labels,
25 | username
26 | }) => {
27 | // Prevent duplicates
28 | const existingIssue = await checkForDuplicateIssue(context, title)
29 | if (existingIssue) {
30 | context.log(`Duplicate issue found with title [${title}]`)
31 | return reopenClosed({ context, config, issue: existingIssue }, {
32 | keyword,
33 | title,
34 | sha,
35 | filename
36 | })
37 | }
38 |
39 | let body = issueFromMerge(context.repo({
40 | sha,
41 | assignedToString,
42 | range,
43 | filename,
44 | keyword,
45 | number,
46 | body: bodyComment
47 | }))
48 |
49 | body = lineBreak(body)
50 | const { owner, repo } = context.repo()
51 | context.log(`Creating issue [${title}] in [${owner}/${repo}]`)
52 | return context.github.issues.create(context.repo({
53 | title: truncate(title),
54 | body,
55 | labels,
56 | ...assignFlow(config, username)
57 | }))
58 | })
59 | }
60 |
--------------------------------------------------------------------------------
/lib/push-handler.js:
--------------------------------------------------------------------------------
1 | const checkForDuplicateIssue = require('./utils/check-for-duplicate-issue')
2 | const { assignFlow, lineBreak, truncate } = require('./utils/helpers')
3 | const reopenClosed = require('./utils/reopen-closed')
4 | const { issue } = require('./templates')
5 | const mainLoop = require('./utils/main-loop')
6 |
7 | /**
8 | * @param {import('probot').Context} context
9 | */
10 | module.exports = async context => {
11 | // Only trigger push handler on pushes to master
12 | if (context.payload.ref !== `refs/heads/${context.payload.repository.master_branch}`) {
13 | return
14 | }
15 |
16 | // Do not trigger on merge commits
17 | const commit = await context.github.git.getCommit(context.repo({
18 | commit_sha: context.payload.head_commit.id
19 | }))
20 |
21 | if (commit.data.parents.length > 1) return
22 |
23 | return mainLoop(context, async ({
24 | title,
25 | config,
26 | keyword,
27 | sha,
28 | filename,
29 | assignedToString,
30 | range,
31 | labels,
32 | username,
33 | bodyComment
34 | }) => {
35 | // Prevent duplicates
36 | const existingIssue = await checkForDuplicateIssue(context, title)
37 | if (existingIssue) {
38 | if (typeof existingIssue === 'string') return
39 | context.log(`Duplicate issue found with title [${title}]`)
40 | return reopenClosed({ context, config, issue: existingIssue }, { keyword, sha, filename })
41 | }
42 |
43 | // Actually create the issue
44 | const body = lineBreak(issue(context.repo({
45 | sha,
46 | assignedToString,
47 | range,
48 | filename,
49 | keyword,
50 | body: bodyComment
51 | })))
52 |
53 | const { owner, repo } = context.repo()
54 | context.log(`Creating issue [${title}] in [${owner}/${repo}]`)
55 | return context.github.issues.create(context.repo({
56 | title: truncate(title),
57 | body,
58 | labels,
59 | ...assignFlow(config, username)
60 | }))
61 | })
62 | }
63 |
--------------------------------------------------------------------------------
/lib/templates/comment.js:
--------------------------------------------------------------------------------
1 | module.exports = `## {{ title }}
2 |
3 | {{#if body}}
4 | {{ body }}
5 |
6 | ---
7 |
8 | {{/if}}
9 | {{#if range}}
10 | https://{{ githubHost }}/{{ owner }}/{{ repo }}/blob/{{ sha }}/{{ filename }}#{{ range }}
11 |
12 | ---
13 |
14 | {{/if}}
15 | ###### This comment was generated by [todo](https://todo.jasonet.co) based on a \`{{ keyword }}\` comment in {{ sha }} in #{{ number }}.{{ assignedToString }}`
16 |
--------------------------------------------------------------------------------
/lib/templates/index.js:
--------------------------------------------------------------------------------
1 | const { handlebars } = require('hbs')
2 |
3 | // Register a githubHost global helper to make links respect the GHE_HOST env var
4 | handlebars.registerHelper('githubHost', () => process.env.GHE_HOST || 'github.com')
5 |
6 | const compile = filename =>
7 | handlebars.compile(require(`./${filename}`))
8 |
9 | module.exports = {
10 | comment: compile('comment'),
11 | issue: compile('issue'),
12 | issueFromMerge: compile('issueFromMerge'),
13 | titleChange: compile('titleChange'),
14 | reopenClosed: compile('reopenClosed')
15 | }
16 |
--------------------------------------------------------------------------------
/lib/templates/issue.js:
--------------------------------------------------------------------------------
1 | module.exports = `{{#if body}}
2 | {{ body }}
3 |
4 | ---
5 |
6 | {{/if}}
7 | {{#if range}}
8 | https://{{ githubHost }}/{{ owner }}/{{ repo }}/blob/{{ sha }}/{{ filename }}#{{ range }}
9 |
10 | ---
11 |
12 | {{/if}}
13 | ###### This issue was generated by [todo](https://todo.jasonet.co) based on a \`{{ keyword }}\` comment in {{ sha }}.{{ assignedToString }}`
14 |
--------------------------------------------------------------------------------
/lib/templates/issueFromMerge.js:
--------------------------------------------------------------------------------
1 | module.exports = `{{#if body}}
2 | {{ body }}
3 |
4 | ---
5 |
6 | {{/if}}
7 | {{#if range}}
8 | https://{{ githubHost }}/{{ owner }}/{{ repo }}/blob/{{ sha }}/{{ filename }}#{{ range }}
9 |
10 | ---
11 |
12 | {{/if}}
13 | ###### This issue was generated by [todo](https://todo.jasonet.co) based on a \`{{ keyword }}\` comment in {{ sha }} when #{{ number }} was merged.{{ assignedToString }}`
14 |
--------------------------------------------------------------------------------
/lib/templates/reopenClosed.js:
--------------------------------------------------------------------------------
1 | module.exports = `This issue has been reopened because the **\`{{ keyword }}\`** comment still exists in [**{{ filename }}**](https://{{ githubHost }}/{{ owner }}/{{ repo }}/blob/{{ sha }}/{{ filename }}), as of {{ sha }}.
2 |
3 | ---
4 |
5 | ###### If this was not intentional, just remove the comment from your code. You can also set the [\`reopenClosed\`](https://github.com/JasonEtco/todo#configuring-for-your-project) config if you don't want this to happen at all anymore.`
6 |
--------------------------------------------------------------------------------
/lib/templates/titleChange.js:
--------------------------------------------------------------------------------
1 | module.exports = 'Please do not change the issue title! **todo** uses it to prevent duplicate issues from being opened. If you think this is an error, please [open an issue](https://github.com/jasonetco/todo)!'
2 |
--------------------------------------------------------------------------------
/lib/utils/check-for-body.js:
--------------------------------------------------------------------------------
1 | const { lineBreak } = require('./helpers')
2 |
3 | /**
4 | * Prepares some details about the TODO
5 | * @param {import('parse-diff').Change[]} changes
6 | * @param {number} changeIndex
7 | * @param {object} config
8 | * @returns {string | boolean}
9 | */
10 | module.exports = (changes, changeIndex, config) => {
11 | const bodyPieces = []
12 | const nextChanges = changes.slice(changeIndex + 1)
13 | const keywords = Array.isArray(config.bodyKeyword) ? config.bodyKeyword : [config.bodyKeyword]
14 | const BODY_REG = new RegExp(`.*(?${keywords.join('|')}):?\\s?(?.*)?`)
15 |
16 | for (const change of nextChanges) {
17 | const matches = BODY_REG.exec(change.content)
18 | if (!matches) break
19 |
20 | if (!matches.groups.body) {
21 | bodyPieces.push('\n')
22 | } else {
23 | if (bodyPieces.length > 0 && bodyPieces[bodyPieces.length - 1] !== '\n') bodyPieces.push(' ')
24 | bodyPieces.push(lineBreak(matches.groups.body).trim())
25 | }
26 | }
27 |
28 | return bodyPieces.length ? bodyPieces.join('') : false
29 | }
30 |
--------------------------------------------------------------------------------
/lib/utils/check-for-duplicate-issue.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Checks to see if an issue already exists with the given title.
3 | * @param {import('probot').Context} context - Probot context object
4 | * @param {string} title - An issue title
5 | */
6 | module.exports = async (context, title) => {
7 | if (context.todos.includes(title)) return title
8 | context.todos.push(title)
9 |
10 | const search = await context.github.search.issuesAndPullRequests({
11 | q: `${title} in:title repo:${context.payload.repository.full_name}`,
12 | per_page: 100
13 | })
14 |
15 | if (search.data.total_count !== 0) {
16 | const existingIssue = search.data.items.find(issue => issue.title === title)
17 | return existingIssue
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/lib/utils/config-schema.js:
--------------------------------------------------------------------------------
1 | const Joi = require('@hapi/joi')
2 |
3 | module.exports = Joi.object({
4 | autoAssign: Joi.alternatives(Joi.boolean(), Joi.array().items(Joi.string()), Joi.string()).default(true)
5 | .description('Should **todo** automatically assign a user to the new issue? If `true`, it\'ll assign whoever pushed the code. If a string, it\'ll assign that user by username. You can also give it an array of usernames or `false` to not assign anyone.'),
6 | keyword: Joi.array().items(Joi.string()).single().default(['todo'])
7 | .description('The keyword(s) to use to generate issue titles'),
8 | bodyKeyword: Joi.array().items(Joi.string()).single().default(['@body', 'BODY'])
9 | .description('If this is in the line right after the main keyword, it will become the generated issue body.'),
10 | blobLines: Joi.alternatives(Joi.number(), Joi.boolean().valid(false)).default(5)
11 | .description('The number of lines of code to show, starting from the keyword.'),
12 | caseSensitive: Joi.boolean().default(false)
13 | .description('Should the keyword be case sensitive?'),
14 | label: Joi.alternatives(Joi.boolean(), Joi.array().items(Joi.string()).single()).default(true)
15 | .description('Add a label to the new issue. If true, add the `todo` label. If false, don\'t add any label.You can also give it a label name or an array of label names.'),
16 | reopenClosed: Joi.boolean().default(true)
17 | .description('If an issue already exists and is closed, reopen it. Note: if set to false, no new issue will be created.'),
18 | exclude: Joi.string().allow(null).default(null)
19 | .description('Exclude certain files and/or directories. Should be a valid regular expression.')
20 | })
21 |
--------------------------------------------------------------------------------
/lib/utils/generate-assigned-to.js:
--------------------------------------------------------------------------------
1 | const { reduceToList, addAt } = require('./helpers')
2 |
3 | /**
4 | * Generates the assigned-to part of the footer string
5 | * @param {boolean|string|string[]} [autoAssign=true] - Auto assign config setting
6 | * @param {string} author - Commit author
7 | * @param {number|boolean} author - PR number or false
8 | * @returns {string}
9 | */
10 | module.exports = function generateAssignedTo (autoAssign, author, pr) {
11 | if (autoAssign === true) {
12 | return pr ? ` cc @${author}.` : ` It's been assigned to @${author} because they committed the code.`
13 | }
14 |
15 | if (autoAssign === false) {
16 | return ''
17 | }
18 |
19 | let assigner
20 | if (typeof autoAssign === 'string') {
21 | assigner = addAt(autoAssign)
22 | }
23 |
24 | if (Array.isArray(autoAssign)) {
25 | const assigners = autoAssign.map(user => addAt(user))
26 | assigner = reduceToList(assigners)
27 | }
28 |
29 | return pr ? ` cc ${assigner}` : ` It's been automagically assigned to ${assigner}.`
30 | }
31 |
--------------------------------------------------------------------------------
/lib/utils/generate-label.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Generate an array of labels based on the config
3 | * @param {import('probot').Context} context - Probot context object
4 | * @param {object} cfg - Config object
5 | */
6 | module.exports = async (context, cfg) => {
7 | if (typeof cfg.label === 'string') {
8 | return [cfg.label]
9 | } else if (Array.isArray(cfg.label)) {
10 | return cfg.label
11 | } else {
12 | if (cfg.label) {
13 | // Generate a label object
14 | const newLabel = context.repo({
15 | name: 'todo :spiral_notepad:',
16 | color: '00B0D8',
17 | request: { retries: 0 }
18 | })
19 |
20 | // This will catch if the label already exists
21 | try {
22 | await context.github.issues.createLabel(newLabel)
23 | } catch (e) {}
24 |
25 | return [newLabel.name]
26 | } else {
27 | return []
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/lib/utils/get-details.js:
--------------------------------------------------------------------------------
1 | const generateAssignedTo = require('./generate-assigned-to')
2 |
3 | /**
4 | * Get the file boundaries of the hunk
5 | * @param {import('parse-diff').Change} lastChange
6 | * @param {number} line
7 | * @param {number} [padding=2]
8 | * @returns {Boundaries}
9 | */
10 | function getFileBoundaries (lastChange, line, padding = 2) {
11 | const end = Math.min(line + padding, lastChange.ln || lastChange.ln2)
12 | return { start: line, end }
13 | }
14 |
15 | /**
16 | * Prepares some details about the TODO
17 | * @param {object} params
18 | * @param {import('probot').Context} params.context
19 | * @param {import('parse-diff').Chunk} params.chunk
20 | * @param {object} params.config
21 | * @param {number} params.line
22 | * @returns {Details}
23 | */
24 | module.exports = ({ context, chunk, config, line }) => {
25 | const number = context.payload.pull_request ? context.payload.pull_request.number : null
26 |
27 | let username, sha
28 | if (context.payload.head_commit) {
29 | // Get it from the head commit in this push
30 | username = context.payload.head_commit.author.username
31 | sha = context.payload.head_commit.id
32 | } else {
33 | // Get it from the head ref in this PR
34 | username = context.payload.pull_request.head.user.login
35 | sha = context.payload.pull_request.head.sha
36 | }
37 |
38 | // Generate a string that expresses who the issue is assigned to
39 | const assignedToString = generateAssignedTo(config.autoAssign, username, number)
40 |
41 | let range
42 | if (!config.blobLines) {
43 | // Don't show the blob
44 | range = false
45 | } else {
46 | const lastChange = chunk.changes[chunk.changes.length - 1]
47 | const { start, end } = getFileBoundaries(lastChange, line, config.blobLines)
48 | range = start === end ? `L${start}` : `L${start}-L${end}`
49 | }
50 |
51 | return {
52 | username,
53 | sha,
54 | assignedToString,
55 | number,
56 | range
57 | }
58 | }
59 |
60 | /**
61 | * @typedef {Object} Details
62 | * @prop {string} username
63 | * @prop {string} sha
64 | * @prop {string} assignedToString
65 | * @prop {number} number
66 | * @prop {string} range
67 | */
68 |
69 | /**
70 | * @typedef {Object} Boundaries
71 | * @prop {number} start
72 | * @prop {number} end
73 | */
74 |
--------------------------------------------------------------------------------
/lib/utils/get-diff.js:
--------------------------------------------------------------------------------
1 | /**
2 | * This value will take some tweaking. A really large diff
3 | * is in the hundred thousands (288421 prompted this change),
4 | * but they can go way higher and would result in downtime.
5 | */
6 | const MAX_DIFF_SIZE = 150000
7 |
8 | /**
9 | * Gets the commit using the diff header
10 | * @param {import('probot').Context} context
11 | * @param {string} [method='GET']
12 | */
13 | async function getCommit (context, method = 'GET') {
14 | if (context.event === 'push') {
15 | return context.github.repos.getCommit(context.repo({
16 | method,
17 | ref: context.payload.head_commit.id,
18 | headers: { Accept: 'application/vnd.github.diff' }
19 | }))
20 | } else {
21 | const { number } = context.issue()
22 | return context.github.pulls.get(context.repo({
23 | method,
24 | headers: { Accept: 'application/vnd.github.diff' },
25 | pull_number: number
26 | }))
27 | }
28 | }
29 |
30 | /**
31 | * Gets the diff of the commit or pull request as a string
32 | * @param {import('probot').Context} context
33 | * @returns {string}
34 | */
35 | module.exports = async context => {
36 | const headRequest = await getCommit(context, 'HEAD')
37 | const diffSize = headRequest.headers['content-length']
38 | if (diffSize > MAX_DIFF_SIZE) {
39 | context.log.info(`Diff is too large: ${diffSize}/${MAX_DIFF_SIZE}`)
40 | return
41 | }
42 |
43 | const diff = await getCommit(context)
44 | return diff.data
45 | }
46 |
--------------------------------------------------------------------------------
/lib/utils/helpers.js:
--------------------------------------------------------------------------------
1 | exports.reduceToList = array => {
2 | return array.reduce((prev, value, i) => {
3 | if (i + 1 === array.length) {
4 | return prev + ` and ${value}`
5 | } else if (i === 0) {
6 | return prev + `${value}`
7 | } else {
8 | return prev + `, ${value}`
9 | }
10 | }, '')
11 | }
12 |
13 | exports.truncate = (str, maxLength = 80) => {
14 | if (str.length < maxLength) return str
15 | return str.substring(0, maxLength) + '...'
16 | }
17 |
18 | exports.addAt = str => {
19 | if (!str.startsWith('@')) return `@${str}`
20 | return str
21 | }
22 |
23 | const stripAt = str => {
24 | if (str.startsWith('@')) return str.split('@')[1]
25 | return str
26 | }
27 |
28 | exports.assignFlow = ({ autoAssign }, author) => {
29 | if (autoAssign === true) {
30 | return { assignee: author }
31 | } else if (typeof autoAssign === 'string') {
32 | return { assignee: autoAssign }
33 | } else if (Array.isArray(autoAssign)) {
34 | return { assignees: autoAssign.map(n => stripAt(n)) }
35 | }
36 | }
37 |
38 | exports.endDiff = diff => diff + '\n__END_OF_DIFF_PARSING__'
39 |
40 | exports.lineBreak = body => {
41 | const regEx = /\/?<br(?:\s\/)?>/g // Regular expression to match all occurences of '<br>'
42 | return body.replace(regEx, '
')
43 | }
44 |
--------------------------------------------------------------------------------
/lib/utils/main-loop.js:
--------------------------------------------------------------------------------
1 | const parseDiff = require('parse-diff')
2 | const shouldExcludeFile = require('./should-exclude-file')
3 | const getDiff = require('./get-diff')
4 | const getDetails = require('./get-details')
5 | const checkForBody = require('./check-for-body')
6 | const configSchema = require('./config-schema')
7 | const generateLabel = require('./generate-label')
8 |
9 | /**
10 | * The main loop that runs the provided handler for each matching line
11 | * @param {import('probot').Context} context
12 | * @param {(todo: Todo) => void} handler
13 | */
14 | module.exports = async (context, handler) => {
15 | context.todos = []
16 |
17 | // Get the diff for this commit or PR
18 | const diff = await getDiff(context)
19 | if (!diff) return
20 |
21 | // Grab the config file
22 | const configFile = await context.config('config.yml')
23 | const configValue = (configFile && configFile.todo) ? configFile.todo : {}
24 |
25 | const { value: config, error } = configSchema.validate(configValue)
26 | if (error) throw error
27 |
28 | const keywords = Array.isArray(config.keyword) ? config.keyword : [config.keyword]
29 |
30 | // Ensure that all the labels we need are present
31 | const labels = await generateLabel(context, config)
32 |
33 | // RegEx that matches lines with the configured keywords
34 | const regexFlags = !config.caseSensitive ? 'i' : ''
35 | const regex = new RegExp(`.*\\b(?${keywords.join('|')})\\b\\s?:?(?.*)`, regexFlags)
36 |
37 | // Parse the diff as files
38 | const files = parseDiff(diff)
39 |
40 | await Promise.all(files.map(async file => {
41 | if (shouldExcludeFile(context.log, file.to, config.exclude)) return
42 |
43 | // Loop through every chunk in the file
44 | await Promise.all(file.chunks.map(async chunk => {
45 | // Chunks can have multiple changes
46 | await Promise.all(chunk.changes.map(async (change, index) => {
47 | // Only act on added lines
48 | // :TODO: Also handle deleted TODO lines
49 | if (change.type !== 'add') return
50 |
51 | // Attempt to find a matching line: TODO Something something
52 | const matches = regex.exec(change.content)
53 | if (!matches) return
54 |
55 | // Trim whitespace to ensure a clean title
56 | const title = matches.groups.title.trim()
57 |
58 | // This might have matched a minified file, or something
59 | // huge. GitHub wouldn't allow this anyway, so let's just ignore it.
60 | if (!title || title.length > 256) return
61 |
62 | // Get the details of this commit or PR
63 | const deets = getDetails({ context, config, chunk, line: change.ln || change.ln2 })
64 |
65 | const { owner, repo } = context.repo()
66 | context.log(`Item found [${title}] in [${owner}/${repo}] at [${deets.sha}]`)
67 |
68 | // Run the handler for this webhook listener
69 | return handler({
70 | keyword: matches.groups.keyword,
71 | bodyComment: checkForBody(chunk.changes, index, config),
72 | filename: file.to,
73 | title,
74 | config,
75 | chunk,
76 | index,
77 | labels,
78 | ...deets
79 | })
80 | }))
81 | }))
82 | }))
83 | }
84 |
85 | /**
86 | * @typedef {Object} Todo
87 | * @prop {string} keyword
88 | * @prop {string} bodyComment
89 | * @prop {string} filename
90 | * @prop {string} title
91 | * @prop {object} config
92 | * @prop {import('parse-diff').Chunk} chunk
93 | * @prop {index} index
94 | * @prop {string[]} labels
95 | * @prop {string} username
96 | * @prop {string} sha
97 | * @prop {string} assignedToString
98 | * @prop {number} number
99 | * @prop {string} range
100 | */
101 |
--------------------------------------------------------------------------------
/lib/utils/reopen-closed.js:
--------------------------------------------------------------------------------
1 | const { reopenClosed } = require('../templates')
2 |
3 | /**
4 | * Reopen a closed issue and post a comment saying what happened and why
5 | * @param {object} params
6 | * @param {import('probot').Context} params.context
7 | * @param {object} params.config
8 | * @param {object} params.issue
9 | * @param {Data} data
10 | */
11 | module.exports = async ({ context, config, issue }, data) => {
12 | if (issue.state === 'closed' && config.reopenClosed) {
13 | await context.github.issues.update(context.repo({
14 | issue_number: issue.number,
15 | state: 'open'
16 | }))
17 |
18 | const body = reopenClosed(context.repo(data))
19 | return context.github.issues.createComment(context.repo({
20 | issue_number: issue.number,
21 | body
22 | }))
23 | }
24 | }
25 |
26 | /**
27 | * @typedef Data
28 | * @property {string} keyword
29 | * @property {string} sha
30 | * @property {string} filename
31 | */
32 |
--------------------------------------------------------------------------------
/lib/utils/should-exclude-file.js:
--------------------------------------------------------------------------------
1 | const alwaysExclude = /\.min\./
2 |
3 | module.exports = (logger, filename, excludePattern) => {
4 | if (filename === '.github/config.yml') {
5 | logger.debug('Skipping .github/config.yml')
6 | return true
7 | } else if (alwaysExclude.test(filename)) {
8 | logger.debug('Skipping ' + filename + ' as it matches the the alwaysExclude pattern')
9 | return true
10 | } else if (excludePattern && new RegExp(excludePattern).test(filename)) {
11 | logger.debug('Skipping ' + filename + ' as it matches the exclude pattern ' + excludePattern)
12 | return true
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "todo",
3 | "version": "1.0.0",
4 | "description": "",
5 | "author": "Jason Etcovitch (https://github.com/jasonetco/todo)",
6 | "license": "ISC",
7 | "repository": "https://github.com/JasonEtco/todo.git",
8 | "scripts": {
9 | "dev": "nodemon",
10 | "start": "probot run ./index.js",
11 | "test": "jest --coverage && standard",
12 | "test:update": "jest -u",
13 | "doc": "node ./script/generate-docs"
14 | },
15 | "standard": {
16 | "env": {
17 | "jest": true
18 | }
19 | },
20 | "bin": {
21 | "todo": "./bin/todo.js"
22 | },
23 | "jest": {
24 | "modulePathIgnorePatterns": [
25 | "/tests/fixtures/",
26 | "/tests/helpers.js",
27 | "/tests/setup.js"
28 | ],
29 | "setupFiles": [
30 | "/tests/setup.js"
31 | ],
32 | "coveragePathIgnorePatterns": [
33 | "/tests/helpers.js",
34 | "/tests/setup.js",
35 | "/node_modules/"
36 | ]
37 | },
38 | "dependencies": {
39 | "@hapi/joi": "^17.0.2",
40 | "@octokit/rest": "^16.36.0",
41 | "hbs": "^4.1.0",
42 | "parse-diff": "^0.6.0",
43 | "probot": "^9.9.0"
44 | },
45 | "devDependencies": {
46 | "chalk": "^3.0.0",
47 | "commander": "^4.1.0",
48 | "jest": "^24.9.0",
49 | "nodemon": "2.0.2",
50 | "smee-client": "^1.1.0",
51 | "standard": "^14.3.1"
52 | },
53 | "nodemonConfig": {
54 | "exec": "npm start",
55 | "watch": [
56 | ".env",
57 | "."
58 | ]
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/script/generate-docs.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs')
2 | const path = require('path')
3 | const chalk = require('chalk')
4 | const schema = require('../lib/utils/config-schema')
5 |
6 | const START = ''
7 | const END = ''
8 | const REG = new RegExp(`${START}[\\s\\S]+${END}`)
9 |
10 | function expressArrayType (opt) {
11 | const items = opt.items
12 | return items.map(item => `${item.type}[]`)
13 | }
14 |
15 | function joinAlternatives (opt) {
16 | return opt.alternatives.map(a => serializeType(a)).join(', ')
17 | }
18 |
19 | function serializeType (opt) {
20 | switch (opt.type) {
21 | case 'alternatives':
22 | return joinAlternatives(opt)
23 | case 'array':
24 | return expressArrayType(opt)
25 | default:
26 | return opt.type
27 | }
28 | }
29 |
30 | function generateTable () {
31 | const describedSchema = schema.describe()
32 |
33 | const tableHeaders = '| Name | Type | Description | Default |'
34 | const separator = '|------|------|-------------|---------|'
35 |
36 | const rows = Object.keys(describedSchema.children).map(key => {
37 | const opt = describedSchema.children[key]
38 | const type = serializeType(opt)
39 | return `| \`${key}\` | \`${type}\` | ${opt.description} | \`${JSON.stringify(opt.flags.default).replace(/"/g, "'")}\` |`
40 | })
41 |
42 | return [tableHeaders, separator, ...rows].join('\n')
43 | }
44 |
45 | function updateReadme () {
46 | const pathToReadme = path.join(__dirname, '..', 'README.md')
47 | const contents = fs.readFileSync(pathToReadme, 'utf8')
48 | const table = generateTable()
49 | const newContents = contents.replace(REG, `${START}\n${table}\n${END}`)
50 | fs.writeFileSync(pathToReadme, newContents)
51 | console.log(chalk.green(chalk.bold('✨ README docs updated!')))
52 | }
53 |
54 | updateReadme()
55 |
--------------------------------------------------------------------------------
/tests/__snapshots__/issue-rename-handler.test.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`issue-rename-handler un-edits the issue title 1`] = `
4 | Object {
5 | "number": 35,
6 | "owner": "JasonEtco",
7 | "repo": "tests",
8 | "title": "I have been edited",
9 | }
10 | `;
11 |
12 | exports[`issue-rename-handler un-edits the issue title 2`] = `
13 | Object {
14 | "body": "Please do not change the issue title! **todo** uses it to prevent duplicate issues from being opened. If you think this is an error, please [open an issue](https://github.com/jasonetco/todo)!",
15 | "number": 35,
16 | "owner": "JasonEtco",
17 | "repo": "tests",
18 | }
19 | `;
20 |
--------------------------------------------------------------------------------
/tests/__snapshots__/pull-request-handler.test.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`pull-request-handler comments on a pull request 1`] = `
4 | Array [
5 | Object {
6 | "body": "## I am an example title
7 |
8 | https://github.com/JasonEtco/tests/blob/1409a3f61a27fe80a7170026fd73eaa2108a0108/.travis.yml#L10-L15
9 |
10 | ---
11 |
12 | ###### This comment was generated by [todo](https://todo.jasonet.co) based on a \`TODO\` comment in 1409a3f61a27fe80a7170026fd73eaa2108a0108 in #32. cc @JasonEtco.",
13 | "number": 32,
14 | "owner": "JasonEtco",
15 | "repo": "tests",
16 | },
17 | ]
18 | `;
19 |
20 | exports[`pull-request-handler comments on a pull request and mentions the assigned user 1`] = `
21 | Array [
22 | Object {
23 | "body": "## I am an example title
24 |
25 | https://github.com/JasonEtco/tests/blob/1409a3f61a27fe80a7170026fd73eaa2108a0108/.travis.yml#L10-L15
26 |
27 | ---
28 |
29 | ###### This comment was generated by [todo](https://todo.jasonet.co) based on a \`TODO\` comment in 1409a3f61a27fe80a7170026fd73eaa2108a0108 in #32. cc @matchai",
30 | "number": 32,
31 | "owner": "JasonEtco",
32 | "repo": "tests",
33 | },
34 | ]
35 | `;
36 |
37 | exports[`pull-request-handler comments on a pull request and mentions the assigned users 1`] = `
38 | Array [
39 | Object {
40 | "body": "## I am an example title
41 |
42 | https://github.com/JasonEtco/tests/blob/1409a3f61a27fe80a7170026fd73eaa2108a0108/.travis.yml#L10-L15
43 |
44 | ---
45 |
46 | ###### This comment was generated by [todo](https://todo.jasonet.co) based on a \`TODO\` comment in 1409a3f61a27fe80a7170026fd73eaa2108a0108 in #32. cc @JasonEtco, @matchai and @defunkt",
47 | "number": 32,
48 | "owner": "JasonEtco",
49 | "repo": "tests",
50 | },
51 | ]
52 | `;
53 |
54 | exports[`pull-request-handler creates a comment with a body line 1`] = `
55 | Array [
56 | Object {
57 | "body": "## I am an example title
58 |
59 | Don't forget about this body text!
60 |
61 | ---
62 |
63 | https://github.com/JasonEtco/tests/blob/1409a3f61a27fe80a7170026fd73eaa2108a0108/.travis.yml#L10-L15
64 |
65 | ---
66 |
67 | ###### This comment was generated by [todo](https://todo.jasonet.co) based on a \`TODO\` comment in 1409a3f61a27fe80a7170026fd73eaa2108a0108 in #32. cc @JasonEtco.",
68 | "number": 32,
69 | "owner": "JasonEtco",
70 | "repo": "tests",
71 | },
72 | ]
73 | `;
74 |
75 | exports[`pull-request-handler works with a string as the keyword config 1`] = `
76 | Array [
77 | Object {
78 | "body": "## I am an example title
79 |
80 | https://github.com/JasonEtco/tests/blob/1409a3f61a27fe80a7170026fd73eaa2108a0108/.travis.yml#L10-L15
81 |
82 | ---
83 |
84 | ###### This comment was generated by [todo](https://todo.jasonet.co) based on a \`pizza\` comment in 1409a3f61a27fe80a7170026fd73eaa2108a0108 in #32. cc @JasonEtco.",
85 | "number": 32,
86 | "owner": "JasonEtco",
87 | "repo": "tests",
88 | },
89 | ]
90 | `;
91 |
--------------------------------------------------------------------------------
/tests/__snapshots__/pull-request-merge-handler.test.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`pull-request-merged-handler creates an issue 1`] = `
4 | Array [
5 | Object {
6 | "assignee": "JasonEtco",
7 | "body": "https://github.com/JasonEtco/tests/blob/6c2373ad036d292f7e9467981ba8b467e8b8b0ff/.travis.yml#L10-L15
8 |
9 | ---
10 |
11 | ###### This issue was generated by [todo](https://todo.jasonet.co) based on a \`TODO\` comment in 6c2373ad036d292f7e9467981ba8b467e8b8b0ff when #21 was merged. cc @JasonEtco.",
12 | "labels": Array [
13 | "todo :spiral_notepad:",
14 | ],
15 | "owner": "JasonEtco",
16 | "repo": "tests",
17 | "title": "I am an example title",
18 | },
19 | ]
20 | `;
21 |
22 | exports[`pull-request-merged-handler creates an issue and assigns the configured user 1`] = `
23 | Array [
24 | Object {
25 | "assignee": "matchai",
26 | "body": "https://github.com/JasonEtco/tests/blob/6c2373ad036d292f7e9467981ba8b467e8b8b0ff/.travis.yml#L10-L15
27 |
28 | ---
29 |
30 | ###### This issue was generated by [todo](https://todo.jasonet.co) based on a \`TODO\` comment in 6c2373ad036d292f7e9467981ba8b467e8b8b0ff when #21 was merged. cc @matchai",
31 | "labels": Array [
32 | "todo :spiral_notepad:",
33 | ],
34 | "owner": "JasonEtco",
35 | "repo": "tests",
36 | "title": "I am an example title",
37 | },
38 | ]
39 | `;
40 |
41 | exports[`pull-request-merged-handler creates an issue and assigns the configured users 1`] = `
42 | Array [
43 | Object {
44 | "assignees": Array [
45 | "JasonEtco",
46 | "matchai",
47 | "defunkt",
48 | ],
49 | "body": "https://github.com/JasonEtco/tests/blob/6c2373ad036d292f7e9467981ba8b467e8b8b0ff/.travis.yml#L10-L15
50 |
51 | ---
52 |
53 | ###### This issue was generated by [todo](https://todo.jasonet.co) based on a \`TODO\` comment in 6c2373ad036d292f7e9467981ba8b467e8b8b0ff when #21 was merged. cc @JasonEtco, @matchai and @defunkt",
54 | "labels": Array [
55 | "todo :spiral_notepad:",
56 | ],
57 | "owner": "JasonEtco",
58 | "repo": "tests",
59 | "title": "I am an example title",
60 | },
61 | ]
62 | `;
63 |
64 | exports[`pull-request-merged-handler creates an issue with a body line 1`] = `
65 | Array [
66 | Object {
67 | "assignee": "JasonEtco",
68 | "body": "Don't forget about this body text!
69 |
70 | ---
71 |
72 | https://github.com/JasonEtco/tests/blob/6c2373ad036d292f7e9467981ba8b467e8b8b0ff/.travis.yml#L10-L15
73 |
74 | ---
75 |
76 | ###### This issue was generated by [todo](https://todo.jasonet.co) based on a \`TODO\` comment in 6c2373ad036d292f7e9467981ba8b467e8b8b0ff when #21 was merged. cc @JasonEtco.",
77 | "labels": Array [
78 | "todo :spiral_notepad:",
79 | ],
80 | "owner": "JasonEtco",
81 | "repo": "tests",
82 | "title": "I am an example title",
83 | },
84 | ]
85 | `;
86 |
87 | exports[`pull-request-merged-handler creates an issue with a truncated title 1`] = `
88 | Array [
89 | Object {
90 | "assignee": "JasonEtco",
91 | "body": "https://github.com/JasonEtco/tests/blob/6c2373ad036d292f7e9467981ba8b467e8b8b0ff/.travis.yml#L10-L15
92 |
93 | ---
94 |
95 | ###### This issue was generated by [todo](https://todo.jasonet.co) based on a \`TODO\` comment in 6c2373ad036d292f7e9467981ba8b467e8b8b0ff when #21 was merged. cc @JasonEtco.",
96 | "labels": Array [
97 | "todo :spiral_notepad:",
98 | ],
99 | "owner": "JasonEtco",
100 | "repo": "tests",
101 | "title": "This is a really, really, really, really, really, really, really, really, really...",
102 | },
103 | ]
104 | `;
105 |
106 | exports[`pull-request-merged-handler creates an issue without assigning anyone 1`] = `
107 | Array [
108 | Object {
109 | "body": "https://github.com/JasonEtco/tests/blob/6c2373ad036d292f7e9467981ba8b467e8b8b0ff/.travis.yml#L10-L15
110 |
111 | ---
112 |
113 | ###### This issue was generated by [todo](https://todo.jasonet.co) based on a \`TODO\` comment in 6c2373ad036d292f7e9467981ba8b467e8b8b0ff when #21 was merged.",
114 | "labels": Array [
115 | "todo :spiral_notepad:",
116 | ],
117 | "owner": "JasonEtco",
118 | "repo": "tests",
119 | "title": "I am an example title",
120 | },
121 | ]
122 | `;
123 |
124 | exports[`pull-request-merged-handler reopens a closed issue 1`] = `
125 | Array [
126 | Object {
127 | "body": "This issue has been reopened because the **\`TODO\`** comment still exists in [**.travis.yml**](https://github.com/JasonEtco/tests/blob/6c2373ad036d292f7e9467981ba8b467e8b8b0ff/.travis.yml), as of 6c2373ad036d292f7e9467981ba8b467e8b8b0ff.
128 |
129 | ---
130 |
131 | ###### If this was not intentional, just remove the comment from your code. You can also set the [\`reopenClosed\`](https://github.com/JasonEtco/todo#configuring-for-your-project) config if you don't want this to happen at all anymore.",
132 | "issue_number": 1,
133 | "owner": "JasonEtco",
134 | "repo": "tests",
135 | },
136 | ]
137 | `;
138 |
--------------------------------------------------------------------------------
/tests/__snapshots__/push-handler.test.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`push-handler creates an issue 1`] = `
4 | Array [
5 | Object {
6 | "assignee": "JasonEtco",
7 | "body": "https://github.com/JasonEtco/tests/blob/e06c237a0c041f5a0a61f1c361f7a1d6f3d669af/.travis.yml#L10-L15
8 |
9 | ---
10 |
11 | ###### This issue was generated by [todo](https://todo.jasonet.co) based on a \`TODO\` comment in e06c237a0c041f5a0a61f1c361f7a1d6f3d669af. It's been assigned to @JasonEtco because they committed the code.",
12 | "labels": Array [
13 | "todo :spiral_notepad:",
14 | ],
15 | "owner": "JasonEtco",
16 | "repo": "tests",
17 | "title": "I am an example title",
18 | },
19 | ]
20 | `;
21 |
22 | exports[`push-handler creates an issue and assigns the configured user 1`] = `
23 | Array [
24 | Object {
25 | "assignee": "matchai",
26 | "body": "https://github.com/JasonEtco/tests/blob/e06c237a0c041f5a0a61f1c361f7a1d6f3d669af/.travis.yml#L10-L15
27 |
28 | ---
29 |
30 | ###### This issue was generated by [todo](https://todo.jasonet.co) based on a \`TODO\` comment in e06c237a0c041f5a0a61f1c361f7a1d6f3d669af. It's been automagically assigned to @matchai.",
31 | "labels": Array [
32 | "todo :spiral_notepad:",
33 | ],
34 | "owner": "JasonEtco",
35 | "repo": "tests",
36 | "title": "I am an example title",
37 | },
38 | ]
39 | `;
40 |
41 | exports[`push-handler creates an issue and assigns the configured users 1`] = `
42 | Array [
43 | Object {
44 | "assignees": Array [
45 | "JasonEtco",
46 | "matchai",
47 | "defunkt",
48 | ],
49 | "body": "https://github.com/JasonEtco/tests/blob/e06c237a0c041f5a0a61f1c361f7a1d6f3d669af/.travis.yml#L10-L15
50 |
51 | ---
52 |
53 | ###### This issue was generated by [todo](https://todo.jasonet.co) based on a \`TODO\` comment in e06c237a0c041f5a0a61f1c361f7a1d6f3d669af. It's been automagically assigned to @JasonEtco, @matchai and @defunkt.",
54 | "labels": Array [
55 | "todo :spiral_notepad:",
56 | ],
57 | "owner": "JasonEtco",
58 | "repo": "tests",
59 | "title": "I am an example title",
60 | },
61 | ]
62 | `;
63 |
64 | exports[`push-handler creates an issue and respects GHE_HOST 1`] = `
65 | Array [
66 | Object {
67 | "assignee": "JasonEtco",
68 | "body": "https://fakegittillyoumakegit.com/JasonEtco/tests/blob/e06c237a0c041f5a0a61f1c361f7a1d6f3d669af/.travis.yml#L10-L15
69 |
70 | ---
71 |
72 | ###### This issue was generated by [todo](https://todo.jasonet.co) based on a \`TODO\` comment in e06c237a0c041f5a0a61f1c361f7a1d6f3d669af. It's been assigned to @JasonEtco because they committed the code.",
73 | "labels": Array [
74 | "todo :spiral_notepad:",
75 | ],
76 | "owner": "JasonEtco",
77 | "repo": "tests",
78 | "title": "I am an example title",
79 | },
80 | ]
81 | `;
82 |
83 | exports[`push-handler creates an issue with a body line 1`] = `
84 | Array [
85 | Object {
86 | "assignee": "JasonEtco",
87 | "body": "Don't forget about this body text!
88 |
89 | ---
90 |
91 | https://github.com/JasonEtco/tests/blob/e06c237a0c041f5a0a61f1c361f7a1d6f3d669af/.travis.yml#L10-L15
92 |
93 | ---
94 |
95 | ###### This issue was generated by [todo](https://todo.jasonet.co) based on a \`TODO\` comment in e06c237a0c041f5a0a61f1c361f7a1d6f3d669af. It's been assigned to @JasonEtco because they committed the code.",
96 | "labels": Array [
97 | "todo :spiral_notepad:",
98 | ],
99 | "owner": "JasonEtco",
100 | "repo": "tests",
101 | "title": "I am an example title",
102 | },
103 | ]
104 | `;
105 |
106 | exports[`push-handler creates an issue with a body line with one body keyword 1`] = `
107 | Array [
108 | Object {
109 | "assignee": "JasonEtco",
110 | "body": "Don't forget about this body text!
111 |
112 | ---
113 |
114 | https://github.com/JasonEtco/tests/blob/e06c237a0c041f5a0a61f1c361f7a1d6f3d669af/.travis.yml#L10-L15
115 |
116 | ---
117 |
118 | ###### This issue was generated by [todo](https://todo.jasonet.co) based on a \`TODO\` comment in e06c237a0c041f5a0a61f1c361f7a1d6f3d669af. It's been assigned to @JasonEtco because they committed the code.",
119 | "labels": Array [
120 | "todo :spiral_notepad:",
121 | ],
122 | "owner": "JasonEtco",
123 | "repo": "tests",
124 | "title": "I am an example title",
125 | },
126 | ]
127 | `;
128 |
129 | exports[`push-handler creates an issue with a custom keyword config 1`] = `
130 | Array [
131 | Object {
132 | "assignee": "JasonEtco",
133 | "body": "https://github.com/JasonEtco/tests/blob/e06c237a0c041f5a0a61f1c361f7a1d6f3d669af/.travis.yml#L10-L15
134 |
135 | ---
136 |
137 | ###### This issue was generated by [todo](https://todo.jasonet.co) based on a \`pizza\` comment in e06c237a0c041f5a0a61f1c361f7a1d6f3d669af. It's been assigned to @JasonEtco because they committed the code.",
138 | "labels": Array [
139 | "todo :spiral_notepad:",
140 | ],
141 | "owner": "JasonEtco",
142 | "repo": "tests",
143 | "title": "I am an example title",
144 | },
145 | ]
146 | `;
147 |
148 | exports[`push-handler creates an issue with a truncated title 1`] = `
149 | Array [
150 | Object {
151 | "assignee": "JasonEtco",
152 | "body": "https://github.com/JasonEtco/tests/blob/e06c237a0c041f5a0a61f1c361f7a1d6f3d669af/.travis.yml#L10-L15
153 |
154 | ---
155 |
156 | ###### This issue was generated by [todo](https://todo.jasonet.co) based on a \`TODO\` comment in e06c237a0c041f5a0a61f1c361f7a1d6f3d669af. It's been assigned to @JasonEtco because they committed the code.",
157 | "labels": Array [
158 | "todo :spiral_notepad:",
159 | ],
160 | "owner": "JasonEtco",
161 | "repo": "tests",
162 | "title": "This is a really, really, really, really, really, really, really, really, really...",
163 | },
164 | ]
165 | `;
166 |
167 | exports[`push-handler creates an issue with an @todo comment 1`] = `
168 | Array [
169 | Object {
170 | "assignee": "JasonEtco",
171 | "body": "https://github.com/JasonEtco/tests/blob/e06c237a0c041f5a0a61f1c361f7a1d6f3d669af/.travis.yml#L10-L15
172 |
173 | ---
174 |
175 | ###### This issue was generated by [todo](https://todo.jasonet.co) based on a \`todo\` comment in e06c237a0c041f5a0a61f1c361f7a1d6f3d669af. It's been assigned to @JasonEtco because they committed the code.",
176 | "labels": Array [
177 | "todo :spiral_notepad:",
178 | ],
179 | "owner": "JasonEtco",
180 | "repo": "tests",
181 | "title": "I am an example title",
182 | },
183 | ]
184 | `;
185 |
186 | exports[`push-handler creates an issue without assigning anyone 1`] = `
187 | Array [
188 | Object {
189 | "body": "https://github.com/JasonEtco/tests/blob/e06c237a0c041f5a0a61f1c361f7a1d6f3d669af/.travis.yml#L10-L15
190 |
191 | ---
192 |
193 | ###### This issue was generated by [todo](https://todo.jasonet.co) based on a \`TODO\` comment in e06c237a0c041f5a0a61f1c361f7a1d6f3d669af.",
194 | "labels": Array [
195 | "todo :spiral_notepad:",
196 | ],
197 | "owner": "JasonEtco",
198 | "repo": "tests",
199 | "title": "I am an example title",
200 | },
201 | ]
202 | `;
203 |
204 | exports[`push-handler creates many (5) issues 1`] = `
205 | Array [
206 | Array [
207 | Object {
208 | "assignee": "JasonEtco",
209 | "body": "https://github.com/JasonEtco/tests/blob/e06c237a0c041f5a0a61f1c361f7a1d6f3d669af/file.txt#L4
210 |
211 | ---
212 |
213 | ###### This issue was generated by [todo](https://todo.jasonet.co) based on a \`TODO\` comment in e06c237a0c041f5a0a61f1c361f7a1d6f3d669af. It's been assigned to @JasonEtco because they committed the code.",
214 | "labels": Array [
215 | "todo :spiral_notepad:",
216 | ],
217 | "owner": "JasonEtco",
218 | "repo": "tests",
219 | "title": "Title number 1",
220 | },
221 | ],
222 | Array [
223 | Object {
224 | "assignee": "JasonEtco",
225 | "body": "https://github.com/JasonEtco/tests/blob/e06c237a0c041f5a0a61f1c361f7a1d6f3d669af/file.txt#L4
226 |
227 | ---
228 |
229 | ###### This issue was generated by [todo](https://todo.jasonet.co) based on a \`TODO\` comment in e06c237a0c041f5a0a61f1c361f7a1d6f3d669af. It's been assigned to @JasonEtco because they committed the code.",
230 | "labels": Array [
231 | "todo :spiral_notepad:",
232 | ],
233 | "owner": "JasonEtco",
234 | "repo": "tests",
235 | "title": "Title number 2",
236 | },
237 | ],
238 | Array [
239 | Object {
240 | "assignee": "JasonEtco",
241 | "body": "https://github.com/JasonEtco/tests/blob/e06c237a0c041f5a0a61f1c361f7a1d6f3d669af/file.txt#L4
242 |
243 | ---
244 |
245 | ###### This issue was generated by [todo](https://todo.jasonet.co) based on a \`TODO\` comment in e06c237a0c041f5a0a61f1c361f7a1d6f3d669af. It's been assigned to @JasonEtco because they committed the code.",
246 | "labels": Array [
247 | "todo :spiral_notepad:",
248 | ],
249 | "owner": "JasonEtco",
250 | "repo": "tests",
251 | "title": "Title number 3",
252 | },
253 | ],
254 | Array [
255 | Object {
256 | "assignee": "JasonEtco",
257 | "body": "https://github.com/JasonEtco/tests/blob/e06c237a0c041f5a0a61f1c361f7a1d6f3d669af/file.txt#L4
258 |
259 | ---
260 |
261 | ###### This issue was generated by [todo](https://todo.jasonet.co) based on a \`TODO\` comment in e06c237a0c041f5a0a61f1c361f7a1d6f3d669af. It's been assigned to @JasonEtco because they committed the code.",
262 | "labels": Array [
263 | "todo :spiral_notepad:",
264 | ],
265 | "owner": "JasonEtco",
266 | "repo": "tests",
267 | "title": "Title number 4",
268 | },
269 | ],
270 | Array [
271 | Object {
272 | "assignee": "JasonEtco",
273 | "body": "https://github.com/JasonEtco/tests/blob/e06c237a0c041f5a0a61f1c361f7a1d6f3d669af/file.txt#L4
274 |
275 | ---
276 |
277 | ###### This issue was generated by [todo](https://todo.jasonet.co) based on a \`TODO\` comment in e06c237a0c041f5a0a61f1c361f7a1d6f3d669af. It's been assigned to @JasonEtco because they committed the code.",
278 | "labels": Array [
279 | "todo :spiral_notepad:",
280 | ],
281 | "owner": "JasonEtco",
282 | "repo": "tests",
283 | "title": "Title number 5",
284 | },
285 | ],
286 | ]
287 | `;
288 |
289 | exports[`push-handler cuts the blobLines 1`] = `
290 | Array [
291 | Object {
292 | "assignee": "JasonEtco",
293 | "body": "Don't forget about this body text!
294 |
295 | ---
296 |
297 | https://github.com/JasonEtco/tests/blob/e06c237a0c041f5a0a61f1c361f7a1d6f3d669af/.travis.yml#L10-L12
298 |
299 | ---
300 |
301 | ###### This issue was generated by [todo](https://todo.jasonet.co) based on a \`TODO\` comment in e06c237a0c041f5a0a61f1c361f7a1d6f3d669af. It's been assigned to @JasonEtco because they committed the code.",
302 | "labels": Array [
303 | "todo :spiral_notepad:",
304 | ],
305 | "owner": "JasonEtco",
306 | "repo": "tests",
307 | "title": "I am an example title",
308 | },
309 | ]
310 | `;
311 |
312 | exports[`push-handler does not show the blob if blobLines is false 1`] = `
313 | Array [
314 | Object {
315 | "assignee": "JasonEtco",
316 | "body": "###### This issue was generated by [todo](https://todo.jasonet.co) based on a \`TODO\` comment in e06c237a0c041f5a0a61f1c361f7a1d6f3d669af. It's been assigned to @JasonEtco because they committed the code.",
317 | "labels": Array [
318 | "todo :spiral_notepad:",
319 | ],
320 | "owner": "JasonEtco",
321 | "repo": "tests",
322 | "title": "I am an example title",
323 | },
324 | ]
325 | `;
326 |
327 | exports[`push-handler reopens a closed issue 1`] = `
328 | Array [
329 | Object {
330 | "body": "This issue has been reopened because the **\`TODO\`** comment still exists in [**.travis.yml**](https://github.com/JasonEtco/tests/blob/e06c237a0c041f5a0a61f1c361f7a1d6f3d669af/.travis.yml), as of e06c237a0c041f5a0a61f1c361f7a1d6f3d669af.
331 |
332 | ---
333 |
334 | ###### If this was not intentional, just remove the comment from your code. You can also set the [\`reopenClosed\`](https://github.com/JasonEtco/todo#configuring-for-your-project) config if you don't want this to happen at all anymore.",
335 | "issue_number": 1,
336 | "owner": "JasonEtco",
337 | "repo": "tests",
338 | },
339 | ]
340 | `;
341 |
--------------------------------------------------------------------------------
/tests/fixtures/configs/autoAssignArr.yml:
--------------------------------------------------------------------------------
1 | todo:
2 | autoAssign:
3 | - "@JasonEtco"
4 | - "matchai"
5 | - "defunkt"
6 |
--------------------------------------------------------------------------------
/tests/fixtures/configs/autoAssignFalse.yml:
--------------------------------------------------------------------------------
1 | todo:
2 | autoAssign: false
3 |
--------------------------------------------------------------------------------
/tests/fixtures/configs/autoAssignString.yml:
--------------------------------------------------------------------------------
1 | todo:
2 | autoAssign: "matchai"
3 |
--------------------------------------------------------------------------------
/tests/fixtures/configs/blobLinesFalse.yml:
--------------------------------------------------------------------------------
1 | todo:
2 | blobLines: false
--------------------------------------------------------------------------------
/tests/fixtures/configs/bodyString.yml:
--------------------------------------------------------------------------------
1 | todo:
2 | bodyKeyword: BODY
--------------------------------------------------------------------------------
/tests/fixtures/configs/excludeBin.yml:
--------------------------------------------------------------------------------
1 | todo:
2 | exclude: '^bin/'
3 |
--------------------------------------------------------------------------------
/tests/fixtures/configs/keywordsString.yml:
--------------------------------------------------------------------------------
1 | todo:
2 | keyword: pizza
--------------------------------------------------------------------------------
/tests/fixtures/configs/labelArr.yml:
--------------------------------------------------------------------------------
1 | todo:
2 | label: ["one", "two"]
3 |
--------------------------------------------------------------------------------
/tests/fixtures/configs/reopenClosedFalse.yml:
--------------------------------------------------------------------------------
1 | todo:
2 | reopenClosed: false
--------------------------------------------------------------------------------
/tests/fixtures/diffs/at-todo.txt:
--------------------------------------------------------------------------------
1 | diff --git a/.travis.yml b/.travis.yml
2 | index 0d43cbb..4e652e9 100644
3 | --- a/.travis.yml
4 | +++ b/.travis.yml
5 | @@ -4,21 +4,22 @@
6 | language: node_js
7 |
8 | node_js:
9 | - "8"
10 | -
11 | +
12 | notifications:
13 | disabled: true
14 | -
15 | + // @todo I am an example title
16 | branches:
17 | except:
18 | - /^vd+.d+.d+$/
19 | -
20 | script:
21 | - npm test
22 | - codecov
--------------------------------------------------------------------------------
/tests/fixtures/diffs/basic.txt:
--------------------------------------------------------------------------------
1 | diff --git a/.travis.yml b/.travis.yml
2 | index 0d43cbb..4e652e9 100644
3 | --- a/.travis.yml
4 | +++ b/.travis.yml
5 | @@ -4,21 +4,22 @@
6 | language: node_js
7 |
8 | node_js:
9 | - "8"
10 | -
11 | +
12 | notifications:
13 | disabled: true
14 | -
15 | + // TODO I am an example title
16 | branches:
17 | except:
18 | - /^vd+.d+.d+$/
19 | -
20 | script:
21 | - npm test
22 | - codecov
--------------------------------------------------------------------------------
/tests/fixtures/diffs/bin.txt:
--------------------------------------------------------------------------------
1 | diff --git a/bin/config.yml b/bin/config.yml
2 | index 0d43cbb..4e652e9 100644
3 | --- a/bin/config.yml
4 | +++ b/bin/config.yml
5 | @@ -4,21 +4,22 @@
6 | language: node_js
7 |
8 | node_js:
9 | - "8"
10 | -
11 | +
12 | notifications:
13 | disabled: true
14 | -
15 | + // TODO I am an example title
16 | branches:
17 | except:
18 | - /^vd+.d+.d+$/
19 | -
20 | script:
21 | - npm test
22 | - codecov
--------------------------------------------------------------------------------
/tests/fixtures/diffs/blob-past-end.txt:
--------------------------------------------------------------------------------
1 | diff --git a/.travis.yml b/.travis.yml
2 | index 0d43cbb..4e652e9 100644
3 | --- a/.travis.yml
4 | +++ b/.travis.yml
5 | @@ -4,21 +4,22 @@
6 | language: node_js
7 |
8 | node_js:
9 | - "8"
10 | -
11 | +
12 | notifications:
13 | disabled: true
14 | -
15 | + // TODO I am an example title
16 | + // BODY Don't forget about this body text!
17 | branches:
--------------------------------------------------------------------------------
/tests/fixtures/diffs/body.txt:
--------------------------------------------------------------------------------
1 | diff --git a/.travis.yml b/.travis.yml
2 | index 0d43cbb..4e652e9 100644
3 | --- a/.travis.yml
4 | +++ b/.travis.yml
5 | @@ -4,21 +4,22 @@
6 | language: node_js
7 |
8 | node_js:
9 | - "8"
10 | -
11 | +
12 | notifications:
13 | disabled: true
14 | -
15 | + // TODO I am an example title
16 | + // BODY Don't forget about this body text!
17 | branches:
18 | except:
19 | - /^vd+.d+.d+$/
20 | -
21 | script:
22 | - npm test
23 | - codecov
--------------------------------------------------------------------------------
/tests/fixtures/diffs/config.txt:
--------------------------------------------------------------------------------
1 | diff --git a/.github/config.yml b/.github/config.yml
2 | index 0d43cbb..4e652e9 100644
3 | --- a/.github/config.yml
4 | +++ b/.github/config.yml
5 | @@ -4,21 +4,22 @@
6 | language: node_js
7 |
8 | node_js:
9 | - "8"
10 | -
11 | +
12 | notifications:
13 | disabled: true
14 | -
15 | + // TODO I am an example title
16 | branches:
17 | except:
18 | - /^vd+.d+.d+$/
19 | -
20 | script:
21 | - npm test
22 | - codecov
--------------------------------------------------------------------------------
/tests/fixtures/diffs/custom-keyword.txt:
--------------------------------------------------------------------------------
1 | diff --git a/.travis.yml b/.travis.yml
2 | index 0d43cbb..4e652e9 100644
3 | --- a/.travis.yml
4 | +++ b/.travis.yml
5 | @@ -4,21 +4,22 @@
6 | language: node_js
7 |
8 | node_js:
9 | - "8"
10 | -
11 | +
12 | notifications:
13 | disabled: true
14 | -
15 | + // pizza I am an example title
16 | branches:
17 | except:
18 | - /^vd+.d+.d+$/
19 | -
20 | script:
21 | - npm test
22 | - codecov
--------------------------------------------------------------------------------
/tests/fixtures/diffs/duplicate.txt:
--------------------------------------------------------------------------------
1 | diff --git a/.travis.yml b/.travis.yml
2 | index 0d43cbb..4e652e9 100644
3 | --- a/.travis.yml
4 | +++ b/.travis.yml
5 | @@ -4,21 +4,22 @@
6 | language: node_js
7 |
8 | node_js:
9 | - "8"
10 | -
11 | +
12 | notifications:
13 | disabled: true
14 | -
15 | + // TODO I am an example title
16 | branches:
17 | except:
18 | - /^vd+.d+.d+$/
19 | + // TODO I am an example title
20 | -
21 | script:
22 | - npm test
23 | - codecov
--------------------------------------------------------------------------------
/tests/fixtures/diffs/long-title.txt:
--------------------------------------------------------------------------------
1 | diff --git a/.travis.yml b/.travis.yml
2 | index 0d43cbb..4e652e9 100644
3 | --- a/.travis.yml
4 | +++ b/.travis.yml
5 | @@ -4,21 +4,22 @@
6 | language: node_js
7 |
8 | node_js:
9 | - "8"
10 | -
11 | +
12 | notifications:
13 | disabled: true
14 | -
15 | + // TODO This is a really, really, really, really, really, really, really, really, really, really long title
16 | branches:
17 | except:
18 | - /^vd+.d+.d+$/
19 | -
20 | script:
21 | - npm test
22 | - codecov
--------------------------------------------------------------------------------
/tests/fixtures/diffs/many.txt:
--------------------------------------------------------------------------------
1 | diff --git a/file.txt b/file.txt
2 | index 0d43cbb..4e652e9 100644
3 | --- a/file.txt
4 | +++ b/file.txt
5 | @@ -4,21 +4,22 @@
6 | + // TODO Title number 1
7 | diff --git a/file.txt b/file.txt
8 | index 0d43cbb..4e652e9 100644
9 | --- a/file.txt
10 | +++ b/file.txt
11 | @@ -4,21 +4,22 @@
12 | + // TODO Title number 2
13 | diff --git a/file.txt b/file.txt
14 | index 0d43cbb..4e652e9 100644
15 | --- a/file.txt
16 | +++ b/file.txt
17 | @@ -4,21 +4,22 @@
18 | + // TODO Title number 3
19 | diff --git a/file.txt b/file.txt
20 | index 0d43cbb..4e652e9 100644
21 | --- a/file.txt
22 | +++ b/file.txt
23 | @@ -4,21 +4,22 @@
24 | + // TODO Title number 4
25 | diff --git a/file.txt b/file.txt
26 | index 0d43cbb..4e652e9 100644
27 | --- a/file.txt
28 | +++ b/file.txt
29 | @@ -4,21 +4,22 @@
30 | + // TODO Title number 5
--------------------------------------------------------------------------------
/tests/fixtures/diffs/middle-of-sentence.txt:
--------------------------------------------------------------------------------
1 | diff --git a/.travis.yml b/.travis.yml
2 | index 0d43cbb..4e652e9 100644
3 | --- a/.travis.yml
4 | +++ b/.travis.yml
5 | @@ -4,21 +4,22 @@
6 | language: node_js
7 |
8 | node_js:
9 | - "8"
10 | -
11 | +
12 | notifications:
13 | disabled: true
14 | -
15 | + // OTODOKE means a delivery
16 | branches:
17 | except:
18 | - /^vd+.d+.d+$/
19 | -
20 | script:
21 | - npm test
22 | - codecov
--------------------------------------------------------------------------------
/tests/fixtures/diffs/none.txt:
--------------------------------------------------------------------------------
1 | diff --git a/.travis.yml b/.travis.yml
2 | index 0d43cbb..4e652e9 100644
3 | --- a/.travis.yml
4 | +++ b/.travis.yml
5 | @@ -4,21 +4,22 @@
6 | language: node_js
7 |
8 | node_js:
9 | - "8"
10 | -
11 | +
12 | notifications:
13 | disabled: true
14 | -
15 | branches:
16 | except:
17 | - /^vd+.d+.d+$/
18 | -
19 | script:
20 | - npm test
21 | - codecov
--------------------------------------------------------------------------------
/tests/fixtures/diffs/title-with-whitespace.txt:
--------------------------------------------------------------------------------
1 | diff --git a/.travis.yml b/.travis.yml
2 | index 0d43cbb..4e652e9 100644
3 | --- a/.travis.yml
4 | +++ b/.travis.yml
5 | @@ -4,21 +4,22 @@
6 | language: node_js
7 |
8 | node_js:
9 | - "8"
10 | -
11 | +
12 | notifications:
13 | disabled: true
14 | -
15 | + // TODO:
16 | branches:
17 | except:
18 | - /^vd+.d+.d+$/
19 | -
20 | script:
21 | - npm test
22 | - codecov
--------------------------------------------------------------------------------
/tests/fixtures/payloads/issues.edited.json:
--------------------------------------------------------------------------------
1 | {
2 | "action": "edited",
3 | "issue": {
4 | "url": "https://api.github.com/repos/JasonEtco/tests/issues/35",
5 | "repository_url": "https://api.github.com/repos/JasonEtco/tests",
6 | "labels_url": "https://api.github.com/repos/JasonEtco/tests/issues/35/labels{/name}",
7 | "comments_url": "https://api.github.com/repos/JasonEtco/tests/issues/35/comments",
8 | "events_url": "https://api.github.com/repos/JasonEtco/tests/issues/35/events",
9 | "html_url": "https://github.com/JasonEtco/tests/issues/35",
10 | "id": 298043447,
11 | "number": 35,
12 | "title": "testing!",
13 | "user": {
14 | "login": "todo-dev[bot]",
15 | "id": 36559360,
16 | "avatar_url": "https://avatars1.githubusercontent.com/u/10660468?v=4",
17 | "gravatar_id": "",
18 | "url": "https://api.github.com/users/todo-dev%5Bbot%5D",
19 | "html_url": "https://github.com/apps/todo-dev",
20 | "followers_url": "https://api.github.com/users/todo-dev%5Bbot%5D/followers",
21 | "following_url": "https://api.github.com/users/todo-dev%5Bbot%5D/following{/other_user}",
22 | "gists_url": "https://api.github.com/users/todo-dev%5Bbot%5D/gists{/gist_id}",
23 | "starred_url": "https://api.github.com/users/todo-dev%5Bbot%5D/starred{/owner}{/repo}",
24 | "subscriptions_url": "https://api.github.com/users/todo-dev%5Bbot%5D/subscriptions",
25 | "organizations_url": "https://api.github.com/users/todo-dev%5Bbot%5D/orgs",
26 | "repos_url": "https://api.github.com/users/todo-dev%5Bbot%5D/repos",
27 | "events_url": "https://api.github.com/users/todo-dev%5Bbot%5D/events{/privacy}",
28 | "received_events_url": "https://api.github.com/users/todo-dev%5Bbot%5D/received_events",
29 | "type": "Bot",
30 | "site_admin": false
31 | },
32 | "labels": [
33 |
34 | ],
35 | "state": "open",
36 | "locked": false,
37 | "assignee": null,
38 | "assignees": [
39 |
40 | ],
41 | "milestone": null,
42 | "comments": 0,
43 | "created_at": "2018-02-17T22:56:49Z",
44 | "updated_at": "2018-02-17T23:02:37Z",
45 | "closed_at": null,
46 | "author_association": "NONE",
47 | "body": "https://github.com/JasonEtco/tests/blob/fe5fe7386cc940a4d848718ea9b40ed0790861e1/gfdgsdf#L9\n\n---\n\n###### This issue was generated by [todo](https://todo.jasonet.co) based on a `TODO` comment in fe5fe7386cc940a4d848718ea9b40ed0790861e1. It's been assigned to @JasonEtco because they committed the code."
48 | },
49 | "changes": {
50 | "title": {
51 | "from": "I have been edited"
52 | }
53 | },
54 | "repository": {
55 | "id": 110556535,
56 | "name": "tests",
57 | "full_name": "JasonEtco/tests",
58 | "owner": {
59 | "login": "JasonEtco",
60 | "id": 10660468,
61 | "avatar_url": "https://avatars1.githubusercontent.com/u/10660468?v=4",
62 | "gravatar_id": "",
63 | "url": "https://api.github.com/users/JasonEtco",
64 | "html_url": "https://github.com/JasonEtco",
65 | "followers_url": "https://api.github.com/users/JasonEtco/followers",
66 | "following_url": "https://api.github.com/users/JasonEtco/following{/other_user}",
67 | "gists_url": "https://api.github.com/users/JasonEtco/gists{/gist_id}",
68 | "starred_url": "https://api.github.com/users/JasonEtco/starred{/owner}{/repo}",
69 | "subscriptions_url": "https://api.github.com/users/JasonEtco/subscriptions",
70 | "organizations_url": "https://api.github.com/users/JasonEtco/orgs",
71 | "repos_url": "https://api.github.com/users/JasonEtco/repos",
72 | "events_url": "https://api.github.com/users/JasonEtco/events{/privacy}",
73 | "received_events_url": "https://api.github.com/users/JasonEtco/received_events",
74 | "type": "User",
75 | "site_admin": true
76 | },
77 | "private": true,
78 | "html_url": "https://github.com/JasonEtco/tests",
79 | "description": null,
80 | "fork": false,
81 | "url": "https://api.github.com/repos/JasonEtco/tests",
82 | "forks_url": "https://api.github.com/repos/JasonEtco/tests/forks",
83 | "keys_url": "https://api.github.com/repos/JasonEtco/tests/keys{/key_id}",
84 | "collaborators_url": "https://api.github.com/repos/JasonEtco/tests/collaborators{/collaborator}",
85 | "teams_url": "https://api.github.com/repos/JasonEtco/tests/teams",
86 | "hooks_url": "https://api.github.com/repos/JasonEtco/tests/hooks",
87 | "issue_events_url": "https://api.github.com/repos/JasonEtco/tests/issues/events{/number}",
88 | "events_url": "https://api.github.com/repos/JasonEtco/tests/events",
89 | "assignees_url": "https://api.github.com/repos/JasonEtco/tests/assignees{/user}",
90 | "branches_url": "https://api.github.com/repos/JasonEtco/tests/branches{/branch}",
91 | "tags_url": "https://api.github.com/repos/JasonEtco/tests/tags",
92 | "blobs_url": "https://api.github.com/repos/JasonEtco/tests/git/blobs{/sha}",
93 | "git_tags_url": "https://api.github.com/repos/JasonEtco/tests/git/tags{/sha}",
94 | "git_refs_url": "https://api.github.com/repos/JasonEtco/tests/git/refs{/sha}",
95 | "trees_url": "https://api.github.com/repos/JasonEtco/tests/git/trees{/sha}",
96 | "statuses_url": "https://api.github.com/repos/JasonEtco/tests/statuses/{sha}",
97 | "languages_url": "https://api.github.com/repos/JasonEtco/tests/languages",
98 | "stargazers_url": "https://api.github.com/repos/JasonEtco/tests/stargazers",
99 | "contributors_url": "https://api.github.com/repos/JasonEtco/tests/contributors",
100 | "subscribers_url": "https://api.github.com/repos/JasonEtco/tests/subscribers",
101 | "subscription_url": "https://api.github.com/repos/JasonEtco/tests/subscription",
102 | "commits_url": "https://api.github.com/repos/JasonEtco/tests/commits{/sha}",
103 | "git_commits_url": "https://api.github.com/repos/JasonEtco/tests/git/commits{/sha}",
104 | "comments_url": "https://api.github.com/repos/JasonEtco/tests/comments{/number}",
105 | "issue_comment_url": "https://api.github.com/repos/JasonEtco/tests/issues/comments{/number}",
106 | "contents_url": "https://api.github.com/repos/JasonEtco/tests/contents/{+path}",
107 | "compare_url": "https://api.github.com/repos/JasonEtco/tests/compare/{base}...{head}",
108 | "merges_url": "https://api.github.com/repos/JasonEtco/tests/merges",
109 | "archive_url": "https://api.github.com/repos/JasonEtco/tests/{archive_format}{/ref}",
110 | "downloads_url": "https://api.github.com/repos/JasonEtco/tests/downloads",
111 | "issues_url": "https://api.github.com/repos/JasonEtco/tests/issues{/number}",
112 | "pulls_url": "https://api.github.com/repos/JasonEtco/tests/pulls{/number}",
113 | "milestones_url": "https://api.github.com/repos/JasonEtco/tests/milestones{/number}",
114 | "notifications_url": "https://api.github.com/repos/JasonEtco/tests/notifications{?since,all,participating}",
115 | "labels_url": "https://api.github.com/repos/JasonEtco/tests/labels{/name}",
116 | "releases_url": "https://api.github.com/repos/JasonEtco/tests/releases{/id}",
117 | "deployments_url": "https://api.github.com/repos/JasonEtco/tests/deployments",
118 | "created_at": "2017-11-13T14:12:17Z",
119 | "updated_at": "2018-01-08T03:09:57Z",
120 | "pushed_at": "2018-02-17T22:13:32Z",
121 | "git_url": "git://github.com/JasonEtco/tests.git",
122 | "ssh_url": "git@github.com:JasonEtco/tests.git",
123 | "clone_url": "https://github.com/JasonEtco/tests.git",
124 | "svn_url": "https://github.com/JasonEtco/tests",
125 | "homepage": null,
126 | "size": 10,
127 | "stargazers_count": 0,
128 | "watchers_count": 0,
129 | "language": null,
130 | "has_issues": true,
131 | "has_projects": true,
132 | "has_downloads": true,
133 | "has_wiki": true,
134 | "has_pages": false,
135 | "forks_count": 0,
136 | "mirror_url": null,
137 | "archived": false,
138 | "open_issues_count": 21,
139 | "license": null,
140 | "forks": 0,
141 | "open_issues": 21,
142 | "watchers": 0,
143 | "default_branch": "master"
144 | },
145 | "sender": {
146 | "login": "JasonEtco",
147 | "id": 10660468,
148 | "avatar_url": "https://avatars1.githubusercontent.com/u/10660468?v=4",
149 | "gravatar_id": "",
150 | "url": "https://api.github.com/users/JasonEtco",
151 | "html_url": "https://github.com/JasonEtco",
152 | "followers_url": "https://api.github.com/users/JasonEtco/followers",
153 | "following_url": "https://api.github.com/users/JasonEtco/following{/other_user}",
154 | "gists_url": "https://api.github.com/users/JasonEtco/gists{/gist_id}",
155 | "starred_url": "https://api.github.com/users/JasonEtco/starred{/owner}{/repo}",
156 | "subscriptions_url": "https://api.github.com/users/JasonEtco/subscriptions",
157 | "organizations_url": "https://api.github.com/users/JasonEtco/orgs",
158 | "repos_url": "https://api.github.com/users/JasonEtco/repos",
159 | "events_url": "https://api.github.com/users/JasonEtco/events{/privacy}",
160 | "received_events_url": "https://api.github.com/users/JasonEtco/received_events",
161 | "type": "User",
162 | "site_admin": true
163 | },
164 | "installation": {
165 | "id": 1
166 | }
167 | }
--------------------------------------------------------------------------------
/tests/fixtures/payloads/pull_request.closed.json:
--------------------------------------------------------------------------------
1 | {
2 | "action": "closed",
3 | "number": 21,
4 | "pull_request": {
5 | "url": "https://api.github.com/repos/JasonEtco/tests/pulls/21",
6 | "id": 161704164,
7 | "html_url": "https://github.com/JasonEtco/tests/pull/21",
8 | "diff_url": "https://github.com/JasonEtco/tests/pull/21.diff",
9 | "patch_url": "https://github.com/JasonEtco/tests/pull/21.patch",
10 | "issue_url": "https://api.github.com/repos/JasonEtco/tests/issues/21",
11 | "number": 21,
12 | "state": "closed",
13 | "locked": false,
14 | "title": "Create bumper.md",
15 | "user": {
16 | "login": "JasonEtco",
17 | "id": 10660468,
18 | "avatar_url": "https://avatars1.githubusercontent.com/u/10660468?v=4",
19 | "gravatar_id": "",
20 | "url": "https://api.github.com/users/JasonEtco",
21 | "html_url": "https://github.com/JasonEtco",
22 | "followers_url": "https://api.github.com/users/JasonEtco/followers",
23 | "following_url": "https://api.github.com/users/JasonEtco/following{/other_user}",
24 | "gists_url": "https://api.github.com/users/JasonEtco/gists{/gist_id}",
25 | "starred_url": "https://api.github.com/users/JasonEtco/starred{/owner}{/repo}",
26 | "subscriptions_url": "https://api.github.com/users/JasonEtco/subscriptions",
27 | "organizations_url": "https://api.github.com/users/JasonEtco/orgs",
28 | "repos_url": "https://api.github.com/users/JasonEtco/repos",
29 | "events_url": "https://api.github.com/users/JasonEtco/events{/privacy}",
30 | "received_events_url": "https://api.github.com/users/JasonEtco/received_events",
31 | "type": "User",
32 | "site_admin": true
33 | },
34 | "body": "Closes #20 ",
35 | "created_at": "2018-01-08T19:18:04Z",
36 | "updated_at": "2018-02-17T23:18:17Z",
37 | "closed_at": "2018-02-17T23:18:17Z",
38 | "merged_at": "2018-02-17T23:18:17Z",
39 | "merge_commit_sha": "46e3daa3218850cf3262eed1ff0f1eecb0769d2f",
40 | "assignee": null,
41 | "assignees": [
42 |
43 | ],
44 | "requested_reviewers": [
45 |
46 | ],
47 | "requested_teams": [
48 |
49 | ],
50 | "labels": [
51 |
52 | ],
53 | "milestone": null,
54 | "commits_url": "https://api.github.com/repos/JasonEtco/tests/pulls/21/commits",
55 | "review_comments_url": "https://api.github.com/repos/JasonEtco/tests/pulls/21/comments",
56 | "review_comment_url": "https://api.github.com/repos/JasonEtco/tests/pulls/comments{/number}",
57 | "comments_url": "https://api.github.com/repos/JasonEtco/tests/issues/21/comments",
58 | "statuses_url": "https://api.github.com/repos/JasonEtco/tests/statuses/6c2373ad036d292f7e9467981ba8b467e8b8b0ff",
59 | "head": {
60 | "label": "JasonEtco:release",
61 | "ref": "release",
62 | "sha": "6c2373ad036d292f7e9467981ba8b467e8b8b0ff",
63 | "user": {
64 | "login": "JasonEtco",
65 | "id": 10660468,
66 | "avatar_url": "https://avatars1.githubusercontent.com/u/10660468?v=4",
67 | "gravatar_id": "",
68 | "url": "https://api.github.com/users/JasonEtco",
69 | "html_url": "https://github.com/JasonEtco",
70 | "followers_url": "https://api.github.com/users/JasonEtco/followers",
71 | "following_url": "https://api.github.com/users/JasonEtco/following{/other_user}",
72 | "gists_url": "https://api.github.com/users/JasonEtco/gists{/gist_id}",
73 | "starred_url": "https://api.github.com/users/JasonEtco/starred{/owner}{/repo}",
74 | "subscriptions_url": "https://api.github.com/users/JasonEtco/subscriptions",
75 | "organizations_url": "https://api.github.com/users/JasonEtco/orgs",
76 | "repos_url": "https://api.github.com/users/JasonEtco/repos",
77 | "events_url": "https://api.github.com/users/JasonEtco/events{/privacy}",
78 | "received_events_url": "https://api.github.com/users/JasonEtco/received_events",
79 | "type": "User",
80 | "site_admin": true
81 | },
82 | "repo": {
83 | "id": 110556535,
84 | "name": "tests",
85 | "full_name": "JasonEtco/tests",
86 | "owner": {
87 | "login": "JasonEtco",
88 | "id": 10660468,
89 | "avatar_url": "https://avatars1.githubusercontent.com/u/10660468?v=4",
90 | "gravatar_id": "",
91 | "url": "https://api.github.com/users/JasonEtco",
92 | "html_url": "https://github.com/JasonEtco",
93 | "followers_url": "https://api.github.com/users/JasonEtco/followers",
94 | "following_url": "https://api.github.com/users/JasonEtco/following{/other_user}",
95 | "gists_url": "https://api.github.com/users/JasonEtco/gists{/gist_id}",
96 | "starred_url": "https://api.github.com/users/JasonEtco/starred{/owner}{/repo}",
97 | "subscriptions_url": "https://api.github.com/users/JasonEtco/subscriptions",
98 | "organizations_url": "https://api.github.com/users/JasonEtco/orgs",
99 | "repos_url": "https://api.github.com/users/JasonEtco/repos",
100 | "events_url": "https://api.github.com/users/JasonEtco/events{/privacy}",
101 | "received_events_url": "https://api.github.com/users/JasonEtco/received_events",
102 | "type": "User",
103 | "site_admin": true
104 | },
105 | "private": true,
106 | "html_url": "https://github.com/JasonEtco/tests",
107 | "description": null,
108 | "fork": false,
109 | "url": "https://api.github.com/repos/JasonEtco/tests",
110 | "forks_url": "https://api.github.com/repos/JasonEtco/tests/forks",
111 | "keys_url": "https://api.github.com/repos/JasonEtco/tests/keys{/key_id}",
112 | "collaborators_url": "https://api.github.com/repos/JasonEtco/tests/collaborators{/collaborator}",
113 | "teams_url": "https://api.github.com/repos/JasonEtco/tests/teams",
114 | "hooks_url": "https://api.github.com/repos/JasonEtco/tests/hooks",
115 | "issue_events_url": "https://api.github.com/repos/JasonEtco/tests/issues/events{/number}",
116 | "events_url": "https://api.github.com/repos/JasonEtco/tests/events",
117 | "assignees_url": "https://api.github.com/repos/JasonEtco/tests/assignees{/user}",
118 | "branches_url": "https://api.github.com/repos/JasonEtco/tests/branches{/branch}",
119 | "tags_url": "https://api.github.com/repos/JasonEtco/tests/tags",
120 | "blobs_url": "https://api.github.com/repos/JasonEtco/tests/git/blobs{/sha}",
121 | "git_tags_url": "https://api.github.com/repos/JasonEtco/tests/git/tags{/sha}",
122 | "git_refs_url": "https://api.github.com/repos/JasonEtco/tests/git/refs{/sha}",
123 | "trees_url": "https://api.github.com/repos/JasonEtco/tests/git/trees{/sha}",
124 | "statuses_url": "https://api.github.com/repos/JasonEtco/tests/statuses/{sha}",
125 | "languages_url": "https://api.github.com/repos/JasonEtco/tests/languages",
126 | "stargazers_url": "https://api.github.com/repos/JasonEtco/tests/stargazers",
127 | "contributors_url": "https://api.github.com/repos/JasonEtco/tests/contributors",
128 | "subscribers_url": "https://api.github.com/repos/JasonEtco/tests/subscribers",
129 | "subscription_url": "https://api.github.com/repos/JasonEtco/tests/subscription",
130 | "commits_url": "https://api.github.com/repos/JasonEtco/tests/commits{/sha}",
131 | "git_commits_url": "https://api.github.com/repos/JasonEtco/tests/git/commits{/sha}",
132 | "comments_url": "https://api.github.com/repos/JasonEtco/tests/comments{/number}",
133 | "issue_comment_url": "https://api.github.com/repos/JasonEtco/tests/issues/comments{/number}",
134 | "contents_url": "https://api.github.com/repos/JasonEtco/tests/contents/{+path}",
135 | "compare_url": "https://api.github.com/repos/JasonEtco/tests/compare/{base}...{head}",
136 | "merges_url": "https://api.github.com/repos/JasonEtco/tests/merges",
137 | "archive_url": "https://api.github.com/repos/JasonEtco/tests/{archive_format}{/ref}",
138 | "downloads_url": "https://api.github.com/repos/JasonEtco/tests/downloads",
139 | "issues_url": "https://api.github.com/repos/JasonEtco/tests/issues{/number}",
140 | "pulls_url": "https://api.github.com/repos/JasonEtco/tests/pulls{/number}",
141 | "milestones_url": "https://api.github.com/repos/JasonEtco/tests/milestones{/number}",
142 | "notifications_url": "https://api.github.com/repos/JasonEtco/tests/notifications{?since,all,participating}",
143 | "labels_url": "https://api.github.com/repos/JasonEtco/tests/labels{/name}",
144 | "releases_url": "https://api.github.com/repos/JasonEtco/tests/releases{/id}",
145 | "deployments_url": "https://api.github.com/repos/JasonEtco/tests/deployments",
146 | "created_at": "2017-11-13T14:12:17Z",
147 | "updated_at": "2018-01-08T03:09:57Z",
148 | "pushed_at": "2018-02-17T23:18:17Z",
149 | "git_url": "git://github.com/JasonEtco/tests.git",
150 | "ssh_url": "git@github.com:JasonEtco/tests.git",
151 | "clone_url": "https://github.com/JasonEtco/tests.git",
152 | "svn_url": "https://github.com/JasonEtco/tests",
153 | "homepage": null,
154 | "size": 10,
155 | "stargazers_count": 0,
156 | "watchers_count": 0,
157 | "language": null,
158 | "has_issues": true,
159 | "has_projects": true,
160 | "has_downloads": true,
161 | "has_wiki": true,
162 | "has_pages": false,
163 | "forks_count": 0,
164 | "mirror_url": null,
165 | "archived": false,
166 | "open_issues_count": 19,
167 | "license": null,
168 | "forks": 0,
169 | "open_issues": 19,
170 | "watchers": 0,
171 | "default_branch": "master"
172 | }
173 | },
174 | "base": {
175 | "label": "JasonEtco:master",
176 | "ref": "master",
177 | "sha": "49b33294236494d3a16ee800aacd53632b82656d",
178 | "user": {
179 | "login": "JasonEtco",
180 | "id": 10660468,
181 | "avatar_url": "https://avatars1.githubusercontent.com/u/10660468?v=4",
182 | "gravatar_id": "",
183 | "url": "https://api.github.com/users/JasonEtco",
184 | "html_url": "https://github.com/JasonEtco",
185 | "followers_url": "https://api.github.com/users/JasonEtco/followers",
186 | "following_url": "https://api.github.com/users/JasonEtco/following{/other_user}",
187 | "gists_url": "https://api.github.com/users/JasonEtco/gists{/gist_id}",
188 | "starred_url": "https://api.github.com/users/JasonEtco/starred{/owner}{/repo}",
189 | "subscriptions_url": "https://api.github.com/users/JasonEtco/subscriptions",
190 | "organizations_url": "https://api.github.com/users/JasonEtco/orgs",
191 | "repos_url": "https://api.github.com/users/JasonEtco/repos",
192 | "events_url": "https://api.github.com/users/JasonEtco/events{/privacy}",
193 | "received_events_url": "https://api.github.com/users/JasonEtco/received_events",
194 | "type": "User",
195 | "site_admin": true
196 | },
197 | "repo": {
198 | "id": 110556535,
199 | "name": "tests",
200 | "full_name": "JasonEtco/tests",
201 | "owner": {
202 | "login": "JasonEtco",
203 | "id": 10660468,
204 | "avatar_url": "https://avatars1.githubusercontent.com/u/10660468?v=4",
205 | "gravatar_id": "",
206 | "url": "https://api.github.com/users/JasonEtco",
207 | "html_url": "https://github.com/JasonEtco",
208 | "followers_url": "https://api.github.com/users/JasonEtco/followers",
209 | "following_url": "https://api.github.com/users/JasonEtco/following{/other_user}",
210 | "gists_url": "https://api.github.com/users/JasonEtco/gists{/gist_id}",
211 | "starred_url": "https://api.github.com/users/JasonEtco/starred{/owner}{/repo}",
212 | "subscriptions_url": "https://api.github.com/users/JasonEtco/subscriptions",
213 | "organizations_url": "https://api.github.com/users/JasonEtco/orgs",
214 | "repos_url": "https://api.github.com/users/JasonEtco/repos",
215 | "events_url": "https://api.github.com/users/JasonEtco/events{/privacy}",
216 | "received_events_url": "https://api.github.com/users/JasonEtco/received_events",
217 | "type": "User",
218 | "site_admin": true
219 | },
220 | "private": true,
221 | "html_url": "https://github.com/JasonEtco/tests",
222 | "description": null,
223 | "fork": false,
224 | "url": "https://api.github.com/repos/JasonEtco/tests",
225 | "forks_url": "https://api.github.com/repos/JasonEtco/tests/forks",
226 | "keys_url": "https://api.github.com/repos/JasonEtco/tests/keys{/key_id}",
227 | "collaborators_url": "https://api.github.com/repos/JasonEtco/tests/collaborators{/collaborator}",
228 | "teams_url": "https://api.github.com/repos/JasonEtco/tests/teams",
229 | "hooks_url": "https://api.github.com/repos/JasonEtco/tests/hooks",
230 | "issue_events_url": "https://api.github.com/repos/JasonEtco/tests/issues/events{/number}",
231 | "events_url": "https://api.github.com/repos/JasonEtco/tests/events",
232 | "assignees_url": "https://api.github.com/repos/JasonEtco/tests/assignees{/user}",
233 | "branches_url": "https://api.github.com/repos/JasonEtco/tests/branches{/branch}",
234 | "tags_url": "https://api.github.com/repos/JasonEtco/tests/tags",
235 | "blobs_url": "https://api.github.com/repos/JasonEtco/tests/git/blobs{/sha}",
236 | "git_tags_url": "https://api.github.com/repos/JasonEtco/tests/git/tags{/sha}",
237 | "git_refs_url": "https://api.github.com/repos/JasonEtco/tests/git/refs{/sha}",
238 | "trees_url": "https://api.github.com/repos/JasonEtco/tests/git/trees{/sha}",
239 | "statuses_url": "https://api.github.com/repos/JasonEtco/tests/statuses/{sha}",
240 | "languages_url": "https://api.github.com/repos/JasonEtco/tests/languages",
241 | "stargazers_url": "https://api.github.com/repos/JasonEtco/tests/stargazers",
242 | "contributors_url": "https://api.github.com/repos/JasonEtco/tests/contributors",
243 | "subscribers_url": "https://api.github.com/repos/JasonEtco/tests/subscribers",
244 | "subscription_url": "https://api.github.com/repos/JasonEtco/tests/subscription",
245 | "commits_url": "https://api.github.com/repos/JasonEtco/tests/commits{/sha}",
246 | "git_commits_url": "https://api.github.com/repos/JasonEtco/tests/git/commits{/sha}",
247 | "comments_url": "https://api.github.com/repos/JasonEtco/tests/comments{/number}",
248 | "issue_comment_url": "https://api.github.com/repos/JasonEtco/tests/issues/comments{/number}",
249 | "contents_url": "https://api.github.com/repos/JasonEtco/tests/contents/{+path}",
250 | "compare_url": "https://api.github.com/repos/JasonEtco/tests/compare/{base}...{head}",
251 | "merges_url": "https://api.github.com/repos/JasonEtco/tests/merges",
252 | "archive_url": "https://api.github.com/repos/JasonEtco/tests/{archive_format}{/ref}",
253 | "downloads_url": "https://api.github.com/repos/JasonEtco/tests/downloads",
254 | "issues_url": "https://api.github.com/repos/JasonEtco/tests/issues{/number}",
255 | "pulls_url": "https://api.github.com/repos/JasonEtco/tests/pulls{/number}",
256 | "milestones_url": "https://api.github.com/repos/JasonEtco/tests/milestones{/number}",
257 | "notifications_url": "https://api.github.com/repos/JasonEtco/tests/notifications{?since,all,participating}",
258 | "labels_url": "https://api.github.com/repos/JasonEtco/tests/labels{/name}",
259 | "releases_url": "https://api.github.com/repos/JasonEtco/tests/releases{/id}",
260 | "deployments_url": "https://api.github.com/repos/JasonEtco/tests/deployments",
261 | "created_at": "2017-11-13T14:12:17Z",
262 | "updated_at": "2018-01-08T03:09:57Z",
263 | "pushed_at": "2018-02-17T23:18:17Z",
264 | "git_url": "git://github.com/JasonEtco/tests.git",
265 | "ssh_url": "git@github.com:JasonEtco/tests.git",
266 | "clone_url": "https://github.com/JasonEtco/tests.git",
267 | "svn_url": "https://github.com/JasonEtco/tests",
268 | "homepage": null,
269 | "size": 10,
270 | "stargazers_count": 0,
271 | "watchers_count": 0,
272 | "language": null,
273 | "has_issues": true,
274 | "has_projects": true,
275 | "has_downloads": true,
276 | "has_wiki": true,
277 | "has_pages": false,
278 | "forks_count": 0,
279 | "mirror_url": null,
280 | "archived": false,
281 | "open_issues_count": 19,
282 | "license": null,
283 | "forks": 0,
284 | "open_issues": 19,
285 | "watchers": 0,
286 | "default_branch": "master"
287 | }
288 | },
289 | "_links": {
290 | "self": {
291 | "href": "https://api.github.com/repos/JasonEtco/tests/pulls/21"
292 | },
293 | "html": {
294 | "href": "https://github.com/JasonEtco/tests/pull/21"
295 | },
296 | "issue": {
297 | "href": "https://api.github.com/repos/JasonEtco/tests/issues/21"
298 | },
299 | "comments": {
300 | "href": "https://api.github.com/repos/JasonEtco/tests/issues/21/comments"
301 | },
302 | "review_comments": {
303 | "href": "https://api.github.com/repos/JasonEtco/tests/pulls/21/comments"
304 | },
305 | "review_comment": {
306 | "href": "https://api.github.com/repos/JasonEtco/tests/pulls/comments{/number}"
307 | },
308 | "commits": {
309 | "href": "https://api.github.com/repos/JasonEtco/tests/pulls/21/commits"
310 | },
311 | "statuses": {
312 | "href": "https://api.github.com/repos/JasonEtco/tests/statuses/6c2373ad036d292f7e9467981ba8b467e8b8b0ff"
313 | }
314 | },
315 | "author_association": "OWNER",
316 | "merged": true,
317 | "mergeable": null,
318 | "rebaseable": null,
319 | "mergeable_state": "unknown",
320 | "merged_by": {
321 | "login": "JasonEtco",
322 | "id": 10660468,
323 | "avatar_url": "https://avatars1.githubusercontent.com/u/10660468?v=4",
324 | "gravatar_id": "",
325 | "url": "https://api.github.com/users/JasonEtco",
326 | "html_url": "https://github.com/JasonEtco",
327 | "followers_url": "https://api.github.com/users/JasonEtco/followers",
328 | "following_url": "https://api.github.com/users/JasonEtco/following{/other_user}",
329 | "gists_url": "https://api.github.com/users/JasonEtco/gists{/gist_id}",
330 | "starred_url": "https://api.github.com/users/JasonEtco/starred{/owner}{/repo}",
331 | "subscriptions_url": "https://api.github.com/users/JasonEtco/subscriptions",
332 | "organizations_url": "https://api.github.com/users/JasonEtco/orgs",
333 | "repos_url": "https://api.github.com/users/JasonEtco/repos",
334 | "events_url": "https://api.github.com/users/JasonEtco/events{/privacy}",
335 | "received_events_url": "https://api.github.com/users/JasonEtco/received_events",
336 | "type": "User",
337 | "site_admin": true
338 | },
339 | "comments": 0,
340 | "review_comments": 0,
341 | "maintainer_can_modify": false,
342 | "commits": 2,
343 | "additions": 2,
344 | "deletions": 0,
345 | "changed_files": 1
346 | },
347 | "repository": {
348 | "id": 110556535,
349 | "name": "tests",
350 | "full_name": "JasonEtco/tests",
351 | "owner": {
352 | "login": "JasonEtco",
353 | "id": 10660468,
354 | "avatar_url": "https://avatars1.githubusercontent.com/u/10660468?v=4",
355 | "gravatar_id": "",
356 | "url": "https://api.github.com/users/JasonEtco",
357 | "html_url": "https://github.com/JasonEtco",
358 | "followers_url": "https://api.github.com/users/JasonEtco/followers",
359 | "following_url": "https://api.github.com/users/JasonEtco/following{/other_user}",
360 | "gists_url": "https://api.github.com/users/JasonEtco/gists{/gist_id}",
361 | "starred_url": "https://api.github.com/users/JasonEtco/starred{/owner}{/repo}",
362 | "subscriptions_url": "https://api.github.com/users/JasonEtco/subscriptions",
363 | "organizations_url": "https://api.github.com/users/JasonEtco/orgs",
364 | "repos_url": "https://api.github.com/users/JasonEtco/repos",
365 | "events_url": "https://api.github.com/users/JasonEtco/events{/privacy}",
366 | "received_events_url": "https://api.github.com/users/JasonEtco/received_events",
367 | "type": "User",
368 | "site_admin": true
369 | },
370 | "private": true,
371 | "html_url": "https://github.com/JasonEtco/tests",
372 | "description": null,
373 | "fork": false,
374 | "url": "https://api.github.com/repos/JasonEtco/tests",
375 | "forks_url": "https://api.github.com/repos/JasonEtco/tests/forks",
376 | "keys_url": "https://api.github.com/repos/JasonEtco/tests/keys{/key_id}",
377 | "collaborators_url": "https://api.github.com/repos/JasonEtco/tests/collaborators{/collaborator}",
378 | "teams_url": "https://api.github.com/repos/JasonEtco/tests/teams",
379 | "hooks_url": "https://api.github.com/repos/JasonEtco/tests/hooks",
380 | "issue_events_url": "https://api.github.com/repos/JasonEtco/tests/issues/events{/number}",
381 | "events_url": "https://api.github.com/repos/JasonEtco/tests/events",
382 | "assignees_url": "https://api.github.com/repos/JasonEtco/tests/assignees{/user}",
383 | "branches_url": "https://api.github.com/repos/JasonEtco/tests/branches{/branch}",
384 | "tags_url": "https://api.github.com/repos/JasonEtco/tests/tags",
385 | "blobs_url": "https://api.github.com/repos/JasonEtco/tests/git/blobs{/sha}",
386 | "git_tags_url": "https://api.github.com/repos/JasonEtco/tests/git/tags{/sha}",
387 | "git_refs_url": "https://api.github.com/repos/JasonEtco/tests/git/refs{/sha}",
388 | "trees_url": "https://api.github.com/repos/JasonEtco/tests/git/trees{/sha}",
389 | "statuses_url": "https://api.github.com/repos/JasonEtco/tests/statuses/{sha}",
390 | "languages_url": "https://api.github.com/repos/JasonEtco/tests/languages",
391 | "stargazers_url": "https://api.github.com/repos/JasonEtco/tests/stargazers",
392 | "contributors_url": "https://api.github.com/repos/JasonEtco/tests/contributors",
393 | "subscribers_url": "https://api.github.com/repos/JasonEtco/tests/subscribers",
394 | "subscription_url": "https://api.github.com/repos/JasonEtco/tests/subscription",
395 | "commits_url": "https://api.github.com/repos/JasonEtco/tests/commits{/sha}",
396 | "git_commits_url": "https://api.github.com/repos/JasonEtco/tests/git/commits{/sha}",
397 | "comments_url": "https://api.github.com/repos/JasonEtco/tests/comments{/number}",
398 | "issue_comment_url": "https://api.github.com/repos/JasonEtco/tests/issues/comments{/number}",
399 | "contents_url": "https://api.github.com/repos/JasonEtco/tests/contents/{+path}",
400 | "compare_url": "https://api.github.com/repos/JasonEtco/tests/compare/{base}...{head}",
401 | "merges_url": "https://api.github.com/repos/JasonEtco/tests/merges",
402 | "archive_url": "https://api.github.com/repos/JasonEtco/tests/{archive_format}{/ref}",
403 | "downloads_url": "https://api.github.com/repos/JasonEtco/tests/downloads",
404 | "issues_url": "https://api.github.com/repos/JasonEtco/tests/issues{/number}",
405 | "pulls_url": "https://api.github.com/repos/JasonEtco/tests/pulls{/number}",
406 | "milestones_url": "https://api.github.com/repos/JasonEtco/tests/milestones{/number}",
407 | "notifications_url": "https://api.github.com/repos/JasonEtco/tests/notifications{?since,all,participating}",
408 | "labels_url": "https://api.github.com/repos/JasonEtco/tests/labels{/name}",
409 | "releases_url": "https://api.github.com/repos/JasonEtco/tests/releases{/id}",
410 | "deployments_url": "https://api.github.com/repos/JasonEtco/tests/deployments",
411 | "created_at": "2017-11-13T14:12:17Z",
412 | "updated_at": "2018-01-08T03:09:57Z",
413 | "pushed_at": "2018-02-17T23:18:17Z",
414 | "git_url": "git://github.com/JasonEtco/tests.git",
415 | "ssh_url": "git@github.com:JasonEtco/tests.git",
416 | "clone_url": "https://github.com/JasonEtco/tests.git",
417 | "svn_url": "https://github.com/JasonEtco/tests",
418 | "homepage": null,
419 | "size": 10,
420 | "stargazers_count": 0,
421 | "watchers_count": 0,
422 | "language": null,
423 | "has_issues": true,
424 | "has_projects": true,
425 | "has_downloads": true,
426 | "has_wiki": true,
427 | "has_pages": false,
428 | "forks_count": 0,
429 | "mirror_url": null,
430 | "archived": false,
431 | "open_issues_count": 19,
432 | "license": null,
433 | "forks": 0,
434 | "open_issues": 19,
435 | "watchers": 0,
436 | "default_branch": "master"
437 | },
438 | "sender": {
439 | "login": "JasonEtco",
440 | "id": 10660468,
441 | "avatar_url": "https://avatars1.githubusercontent.com/u/10660468?v=4",
442 | "gravatar_id": "",
443 | "url": "https://api.github.com/users/JasonEtco",
444 | "html_url": "https://github.com/JasonEtco",
445 | "followers_url": "https://api.github.com/users/JasonEtco/followers",
446 | "following_url": "https://api.github.com/users/JasonEtco/following{/other_user}",
447 | "gists_url": "https://api.github.com/users/JasonEtco/gists{/gist_id}",
448 | "starred_url": "https://api.github.com/users/JasonEtco/starred{/owner}{/repo}",
449 | "subscriptions_url": "https://api.github.com/users/JasonEtco/subscriptions",
450 | "organizations_url": "https://api.github.com/users/JasonEtco/orgs",
451 | "repos_url": "https://api.github.com/users/JasonEtco/repos",
452 | "events_url": "https://api.github.com/users/JasonEtco/events{/privacy}",
453 | "received_events_url": "https://api.github.com/users/JasonEtco/received_events",
454 | "type": "User",
455 | "site_admin": true
456 | },
457 | "installation": {
458 | "id": 1
459 | }
460 | }
--------------------------------------------------------------------------------
/tests/fixtures/payloads/pull_request.opened.json:
--------------------------------------------------------------------------------
1 | {
2 | "action": "opened",
3 | "number": 32,
4 | "pull_request": {
5 | "url": "https://api.github.com/repos/JasonEtco/tests/pulls/32",
6 | "id": 169770975,
7 | "html_url": "https://github.com/JasonEtco/tests/pull/32",
8 | "diff_url": "https://github.com/JasonEtco/tests/pull/32.diff",
9 | "patch_url": "https://github.com/JasonEtco/tests/pull/32.patch",
10 | "issue_url": "https://api.github.com/repos/JasonEtco/tests/issues/32",
11 | "number": 32,
12 | "state": "open",
13 | "locked": false,
14 | "title": "fgsdfgd",
15 | "user": {
16 | "login": "JasonEtco",
17 | "id": 10660468,
18 | "avatar_url": "https://avatars1.githubusercontent.com/u/10660468?v=4",
19 | "gravatar_id": "",
20 | "url": "https://api.github.com/users/JasonEtco",
21 | "html_url": "https://github.com/JasonEtco",
22 | "followers_url": "https://api.github.com/users/JasonEtco/followers",
23 | "following_url": "https://api.github.com/users/JasonEtco/following{/other_user}",
24 | "gists_url": "https://api.github.com/users/JasonEtco/gists{/gist_id}",
25 | "starred_url": "https://api.github.com/users/JasonEtco/starred{/owner}{/repo}",
26 | "subscriptions_url": "https://api.github.com/users/JasonEtco/subscriptions",
27 | "organizations_url": "https://api.github.com/users/JasonEtco/orgs",
28 | "repos_url": "https://api.github.com/users/JasonEtco/repos",
29 | "events_url": "https://api.github.com/users/JasonEtco/events{/privacy}",
30 | "received_events_url": "https://api.github.com/users/JasonEtco/received_events",
31 | "type": "User",
32 | "site_admin": true
33 | },
34 | "body": "",
35 | "created_at": "2018-02-17T06:22:15Z",
36 | "updated_at": "2018-02-17T06:22:15Z",
37 | "closed_at": null,
38 | "merged_at": null,
39 | "merge_commit_sha": null,
40 | "assignee": null,
41 | "assignees": [
42 |
43 | ],
44 | "requested_reviewers": [
45 |
46 | ],
47 | "requested_teams": [
48 |
49 | ],
50 | "labels": [
51 |
52 | ],
53 | "milestone": null,
54 | "commits_url": "https://api.github.com/repos/JasonEtco/tests/pulls/32/commits",
55 | "review_comments_url": "https://api.github.com/repos/JasonEtco/tests/pulls/32/comments",
56 | "review_comment_url": "https://api.github.com/repos/JasonEtco/tests/pulls/comments{/number}",
57 | "comments_url": "https://api.github.com/repos/JasonEtco/tests/issues/32/comments",
58 | "statuses_url": "https://api.github.com/repos/JasonEtco/tests/statuses/1409a3f61a27fe80a7170026fd73eaa2108a0108",
59 | "head": {
60 | "label": "JasonEtco:JasonEtco-patch-7",
61 | "ref": "JasonEtco-patch-7",
62 | "sha": "1409a3f61a27fe80a7170026fd73eaa2108a0108",
63 | "user": {
64 | "login": "JasonEtco",
65 | "id": 10660468,
66 | "avatar_url": "https://avatars1.githubusercontent.com/u/10660468?v=4",
67 | "gravatar_id": "",
68 | "url": "https://api.github.com/users/JasonEtco",
69 | "html_url": "https://github.com/JasonEtco",
70 | "followers_url": "https://api.github.com/users/JasonEtco/followers",
71 | "following_url": "https://api.github.com/users/JasonEtco/following{/other_user}",
72 | "gists_url": "https://api.github.com/users/JasonEtco/gists{/gist_id}",
73 | "starred_url": "https://api.github.com/users/JasonEtco/starred{/owner}{/repo}",
74 | "subscriptions_url": "https://api.github.com/users/JasonEtco/subscriptions",
75 | "organizations_url": "https://api.github.com/users/JasonEtco/orgs",
76 | "repos_url": "https://api.github.com/users/JasonEtco/repos",
77 | "events_url": "https://api.github.com/users/JasonEtco/events{/privacy}",
78 | "received_events_url": "https://api.github.com/users/JasonEtco/received_events",
79 | "type": "User",
80 | "site_admin": true
81 | },
82 | "repo": {
83 | "id": 110556535,
84 | "name": "tests",
85 | "full_name": "JasonEtco/tests",
86 | "owner": {
87 | "login": "JasonEtco",
88 | "id": 10660468,
89 | "avatar_url": "https://avatars1.githubusercontent.com/u/10660468?v=4",
90 | "gravatar_id": "",
91 | "url": "https://api.github.com/users/JasonEtco",
92 | "html_url": "https://github.com/JasonEtco",
93 | "followers_url": "https://api.github.com/users/JasonEtco/followers",
94 | "following_url": "https://api.github.com/users/JasonEtco/following{/other_user}",
95 | "gists_url": "https://api.github.com/users/JasonEtco/gists{/gist_id}",
96 | "starred_url": "https://api.github.com/users/JasonEtco/starred{/owner}{/repo}",
97 | "subscriptions_url": "https://api.github.com/users/JasonEtco/subscriptions",
98 | "organizations_url": "https://api.github.com/users/JasonEtco/orgs",
99 | "repos_url": "https://api.github.com/users/JasonEtco/repos",
100 | "events_url": "https://api.github.com/users/JasonEtco/events{/privacy}",
101 | "received_events_url": "https://api.github.com/users/JasonEtco/received_events",
102 | "type": "User",
103 | "site_admin": true
104 | },
105 | "private": true,
106 | "html_url": "https://github.com/JasonEtco/tests",
107 | "description": null,
108 | "fork": false,
109 | "url": "https://api.github.com/repos/JasonEtco/tests",
110 | "forks_url": "https://api.github.com/repos/JasonEtco/tests/forks",
111 | "keys_url": "https://api.github.com/repos/JasonEtco/tests/keys{/key_id}",
112 | "collaborators_url": "https://api.github.com/repos/JasonEtco/tests/collaborators{/collaborator}",
113 | "teams_url": "https://api.github.com/repos/JasonEtco/tests/teams",
114 | "hooks_url": "https://api.github.com/repos/JasonEtco/tests/hooks",
115 | "issue_events_url": "https://api.github.com/repos/JasonEtco/tests/issues/events{/number}",
116 | "events_url": "https://api.github.com/repos/JasonEtco/tests/events",
117 | "assignees_url": "https://api.github.com/repos/JasonEtco/tests/assignees{/user}",
118 | "branches_url": "https://api.github.com/repos/JasonEtco/tests/branches{/branch}",
119 | "tags_url": "https://api.github.com/repos/JasonEtco/tests/tags",
120 | "blobs_url": "https://api.github.com/repos/JasonEtco/tests/git/blobs{/sha}",
121 | "git_tags_url": "https://api.github.com/repos/JasonEtco/tests/git/tags{/sha}",
122 | "git_refs_url": "https://api.github.com/repos/JasonEtco/tests/git/refs{/sha}",
123 | "trees_url": "https://api.github.com/repos/JasonEtco/tests/git/trees{/sha}",
124 | "statuses_url": "https://api.github.com/repos/JasonEtco/tests/statuses/{sha}",
125 | "languages_url": "https://api.github.com/repos/JasonEtco/tests/languages",
126 | "stargazers_url": "https://api.github.com/repos/JasonEtco/tests/stargazers",
127 | "contributors_url": "https://api.github.com/repos/JasonEtco/tests/contributors",
128 | "subscribers_url": "https://api.github.com/repos/JasonEtco/tests/subscribers",
129 | "subscription_url": "https://api.github.com/repos/JasonEtco/tests/subscription",
130 | "commits_url": "https://api.github.com/repos/JasonEtco/tests/commits{/sha}",
131 | "git_commits_url": "https://api.github.com/repos/JasonEtco/tests/git/commits{/sha}",
132 | "comments_url": "https://api.github.com/repos/JasonEtco/tests/comments{/number}",
133 | "issue_comment_url": "https://api.github.com/repos/JasonEtco/tests/issues/comments{/number}",
134 | "contents_url": "https://api.github.com/repos/JasonEtco/tests/contents/{+path}",
135 | "compare_url": "https://api.github.com/repos/JasonEtco/tests/compare/{base}...{head}",
136 | "merges_url": "https://api.github.com/repos/JasonEtco/tests/merges",
137 | "archive_url": "https://api.github.com/repos/JasonEtco/tests/{archive_format}{/ref}",
138 | "downloads_url": "https://api.github.com/repos/JasonEtco/tests/downloads",
139 | "issues_url": "https://api.github.com/repos/JasonEtco/tests/issues{/number}",
140 | "pulls_url": "https://api.github.com/repos/JasonEtco/tests/pulls{/number}",
141 | "milestones_url": "https://api.github.com/repos/JasonEtco/tests/milestones{/number}",
142 | "notifications_url": "https://api.github.com/repos/JasonEtco/tests/notifications{?since,all,participating}",
143 | "labels_url": "https://api.github.com/repos/JasonEtco/tests/labels{/name}",
144 | "releases_url": "https://api.github.com/repos/JasonEtco/tests/releases{/id}",
145 | "deployments_url": "https://api.github.com/repos/JasonEtco/tests/deployments",
146 | "created_at": "2017-11-13T14:12:17Z",
147 | "updated_at": "2018-01-08T03:09:57Z",
148 | "pushed_at": "2018-02-17T06:22:12Z",
149 | "git_url": "git://github.com/JasonEtco/tests.git",
150 | "ssh_url": "git@github.com:JasonEtco/tests.git",
151 | "clone_url": "https://github.com/JasonEtco/tests.git",
152 | "svn_url": "https://github.com/JasonEtco/tests",
153 | "homepage": null,
154 | "size": 8,
155 | "stargazers_count": 0,
156 | "watchers_count": 0,
157 | "language": null,
158 | "has_issues": true,
159 | "has_projects": true,
160 | "has_downloads": true,
161 | "has_wiki": true,
162 | "has_pages": false,
163 | "forks_count": 0,
164 | "mirror_url": null,
165 | "archived": false,
166 | "open_issues_count": 19,
167 | "license": null,
168 | "forks": 0,
169 | "open_issues": 19,
170 | "watchers": 0,
171 | "default_branch": "master"
172 | }
173 | },
174 | "base": {
175 | "label": "JasonEtco:master",
176 | "ref": "master",
177 | "sha": "8af6a939b34f5725b54946b5d7a9f77e14c2c002",
178 | "user": {
179 | "login": "JasonEtco",
180 | "id": 10660468,
181 | "avatar_url": "https://avatars1.githubusercontent.com/u/10660468?v=4",
182 | "gravatar_id": "",
183 | "url": "https://api.github.com/users/JasonEtco",
184 | "html_url": "https://github.com/JasonEtco",
185 | "followers_url": "https://api.github.com/users/JasonEtco/followers",
186 | "following_url": "https://api.github.com/users/JasonEtco/following{/other_user}",
187 | "gists_url": "https://api.github.com/users/JasonEtco/gists{/gist_id}",
188 | "starred_url": "https://api.github.com/users/JasonEtco/starred{/owner}{/repo}",
189 | "subscriptions_url": "https://api.github.com/users/JasonEtco/subscriptions",
190 | "organizations_url": "https://api.github.com/users/JasonEtco/orgs",
191 | "repos_url": "https://api.github.com/users/JasonEtco/repos",
192 | "events_url": "https://api.github.com/users/JasonEtco/events{/privacy}",
193 | "received_events_url": "https://api.github.com/users/JasonEtco/received_events",
194 | "type": "User",
195 | "site_admin": true
196 | },
197 | "repo": {
198 | "id": 110556535,
199 | "name": "tests",
200 | "full_name": "JasonEtco/tests",
201 | "owner": {
202 | "login": "JasonEtco",
203 | "id": 10660468,
204 | "avatar_url": "https://avatars1.githubusercontent.com/u/10660468?v=4",
205 | "gravatar_id": "",
206 | "url": "https://api.github.com/users/JasonEtco",
207 | "html_url": "https://github.com/JasonEtco",
208 | "followers_url": "https://api.github.com/users/JasonEtco/followers",
209 | "following_url": "https://api.github.com/users/JasonEtco/following{/other_user}",
210 | "gists_url": "https://api.github.com/users/JasonEtco/gists{/gist_id}",
211 | "starred_url": "https://api.github.com/users/JasonEtco/starred{/owner}{/repo}",
212 | "subscriptions_url": "https://api.github.com/users/JasonEtco/subscriptions",
213 | "organizations_url": "https://api.github.com/users/JasonEtco/orgs",
214 | "repos_url": "https://api.github.com/users/JasonEtco/repos",
215 | "events_url": "https://api.github.com/users/JasonEtco/events{/privacy}",
216 | "received_events_url": "https://api.github.com/users/JasonEtco/received_events",
217 | "type": "User",
218 | "site_admin": true
219 | },
220 | "private": true,
221 | "html_url": "https://github.com/JasonEtco/tests",
222 | "description": null,
223 | "fork": false,
224 | "url": "https://api.github.com/repos/JasonEtco/tests",
225 | "forks_url": "https://api.github.com/repos/JasonEtco/tests/forks",
226 | "keys_url": "https://api.github.com/repos/JasonEtco/tests/keys{/key_id}",
227 | "collaborators_url": "https://api.github.com/repos/JasonEtco/tests/collaborators{/collaborator}",
228 | "teams_url": "https://api.github.com/repos/JasonEtco/tests/teams",
229 | "hooks_url": "https://api.github.com/repos/JasonEtco/tests/hooks",
230 | "issue_events_url": "https://api.github.com/repos/JasonEtco/tests/issues/events{/number}",
231 | "events_url": "https://api.github.com/repos/JasonEtco/tests/events",
232 | "assignees_url": "https://api.github.com/repos/JasonEtco/tests/assignees{/user}",
233 | "branches_url": "https://api.github.com/repos/JasonEtco/tests/branches{/branch}",
234 | "tags_url": "https://api.github.com/repos/JasonEtco/tests/tags",
235 | "blobs_url": "https://api.github.com/repos/JasonEtco/tests/git/blobs{/sha}",
236 | "git_tags_url": "https://api.github.com/repos/JasonEtco/tests/git/tags{/sha}",
237 | "git_refs_url": "https://api.github.com/repos/JasonEtco/tests/git/refs{/sha}",
238 | "trees_url": "https://api.github.com/repos/JasonEtco/tests/git/trees{/sha}",
239 | "statuses_url": "https://api.github.com/repos/JasonEtco/tests/statuses/{sha}",
240 | "languages_url": "https://api.github.com/repos/JasonEtco/tests/languages",
241 | "stargazers_url": "https://api.github.com/repos/JasonEtco/tests/stargazers",
242 | "contributors_url": "https://api.github.com/repos/JasonEtco/tests/contributors",
243 | "subscribers_url": "https://api.github.com/repos/JasonEtco/tests/subscribers",
244 | "subscription_url": "https://api.github.com/repos/JasonEtco/tests/subscription",
245 | "commits_url": "https://api.github.com/repos/JasonEtco/tests/commits{/sha}",
246 | "git_commits_url": "https://api.github.com/repos/JasonEtco/tests/git/commits{/sha}",
247 | "comments_url": "https://api.github.com/repos/JasonEtco/tests/comments{/number}",
248 | "issue_comment_url": "https://api.github.com/repos/JasonEtco/tests/issues/comments{/number}",
249 | "contents_url": "https://api.github.com/repos/JasonEtco/tests/contents/{+path}",
250 | "compare_url": "https://api.github.com/repos/JasonEtco/tests/compare/{base}...{head}",
251 | "merges_url": "https://api.github.com/repos/JasonEtco/tests/merges",
252 | "archive_url": "https://api.github.com/repos/JasonEtco/tests/{archive_format}{/ref}",
253 | "downloads_url": "https://api.github.com/repos/JasonEtco/tests/downloads",
254 | "issues_url": "https://api.github.com/repos/JasonEtco/tests/issues{/number}",
255 | "pulls_url": "https://api.github.com/repos/JasonEtco/tests/pulls{/number}",
256 | "milestones_url": "https://api.github.com/repos/JasonEtco/tests/milestones{/number}",
257 | "notifications_url": "https://api.github.com/repos/JasonEtco/tests/notifications{?since,all,participating}",
258 | "labels_url": "https://api.github.com/repos/JasonEtco/tests/labels{/name}",
259 | "releases_url": "https://api.github.com/repos/JasonEtco/tests/releases{/id}",
260 | "deployments_url": "https://api.github.com/repos/JasonEtco/tests/deployments",
261 | "created_at": "2017-11-13T14:12:17Z",
262 | "updated_at": "2018-01-08T03:09:57Z",
263 | "pushed_at": "2018-02-17T06:22:12Z",
264 | "git_url": "git://github.com/JasonEtco/tests.git",
265 | "ssh_url": "git@github.com:JasonEtco/tests.git",
266 | "clone_url": "https://github.com/JasonEtco/tests.git",
267 | "svn_url": "https://github.com/JasonEtco/tests",
268 | "homepage": null,
269 | "size": 8,
270 | "stargazers_count": 0,
271 | "watchers_count": 0,
272 | "language": null,
273 | "has_issues": true,
274 | "has_projects": true,
275 | "has_downloads": true,
276 | "has_wiki": true,
277 | "has_pages": false,
278 | "forks_count": 0,
279 | "mirror_url": null,
280 | "archived": false,
281 | "open_issues_count": 19,
282 | "license": null,
283 | "forks": 0,
284 | "open_issues": 19,
285 | "watchers": 0,
286 | "default_branch": "master"
287 | }
288 | },
289 | "_links": {
290 | "self": {
291 | "href": "https://api.github.com/repos/JasonEtco/tests/pulls/32"
292 | },
293 | "html": {
294 | "href": "https://github.com/JasonEtco/tests/pull/32"
295 | },
296 | "issue": {
297 | "href": "https://api.github.com/repos/JasonEtco/tests/issues/32"
298 | },
299 | "comments": {
300 | "href": "https://api.github.com/repos/JasonEtco/tests/issues/32/comments"
301 | },
302 | "review_comments": {
303 | "href": "https://api.github.com/repos/JasonEtco/tests/pulls/32/comments"
304 | },
305 | "review_comment": {
306 | "href": "https://api.github.com/repos/JasonEtco/tests/pulls/comments{/number}"
307 | },
308 | "commits": {
309 | "href": "https://api.github.com/repos/JasonEtco/tests/pulls/32/commits"
310 | },
311 | "statuses": {
312 | "href": "https://api.github.com/repos/JasonEtco/tests/statuses/1409a3f61a27fe80a7170026fd73eaa2108a0108"
313 | }
314 | },
315 | "author_association": "OWNER",
316 | "merged": false,
317 | "mergeable": null,
318 | "rebaseable": null,
319 | "mergeable_state": "unknown",
320 | "merged_by": null,
321 | "comments": 0,
322 | "review_comments": 0,
323 | "maintainer_can_modify": false,
324 | "commits": 1,
325 | "additions": 1,
326 | "deletions": 0,
327 | "changed_files": 1
328 | },
329 | "repository": {
330 | "id": 110556535,
331 | "name": "tests",
332 | "full_name": "JasonEtco/tests",
333 | "owner": {
334 | "login": "JasonEtco",
335 | "id": 10660468,
336 | "avatar_url": "https://avatars1.githubusercontent.com/u/10660468?v=4",
337 | "gravatar_id": "",
338 | "url": "https://api.github.com/users/JasonEtco",
339 | "html_url": "https://github.com/JasonEtco",
340 | "followers_url": "https://api.github.com/users/JasonEtco/followers",
341 | "following_url": "https://api.github.com/users/JasonEtco/following{/other_user}",
342 | "gists_url": "https://api.github.com/users/JasonEtco/gists{/gist_id}",
343 | "starred_url": "https://api.github.com/users/JasonEtco/starred{/owner}{/repo}",
344 | "subscriptions_url": "https://api.github.com/users/JasonEtco/subscriptions",
345 | "organizations_url": "https://api.github.com/users/JasonEtco/orgs",
346 | "repos_url": "https://api.github.com/users/JasonEtco/repos",
347 | "events_url": "https://api.github.com/users/JasonEtco/events{/privacy}",
348 | "received_events_url": "https://api.github.com/users/JasonEtco/received_events",
349 | "type": "User",
350 | "site_admin": true
351 | },
352 | "private": true,
353 | "html_url": "https://github.com/JasonEtco/tests",
354 | "description": null,
355 | "fork": false,
356 | "url": "https://api.github.com/repos/JasonEtco/tests",
357 | "forks_url": "https://api.github.com/repos/JasonEtco/tests/forks",
358 | "keys_url": "https://api.github.com/repos/JasonEtco/tests/keys{/key_id}",
359 | "collaborators_url": "https://api.github.com/repos/JasonEtco/tests/collaborators{/collaborator}",
360 | "teams_url": "https://api.github.com/repos/JasonEtco/tests/teams",
361 | "hooks_url": "https://api.github.com/repos/JasonEtco/tests/hooks",
362 | "issue_events_url": "https://api.github.com/repos/JasonEtco/tests/issues/events{/number}",
363 | "events_url": "https://api.github.com/repos/JasonEtco/tests/events",
364 | "assignees_url": "https://api.github.com/repos/JasonEtco/tests/assignees{/user}",
365 | "branches_url": "https://api.github.com/repos/JasonEtco/tests/branches{/branch}",
366 | "tags_url": "https://api.github.com/repos/JasonEtco/tests/tags",
367 | "blobs_url": "https://api.github.com/repos/JasonEtco/tests/git/blobs{/sha}",
368 | "git_tags_url": "https://api.github.com/repos/JasonEtco/tests/git/tags{/sha}",
369 | "git_refs_url": "https://api.github.com/repos/JasonEtco/tests/git/refs{/sha}",
370 | "trees_url": "https://api.github.com/repos/JasonEtco/tests/git/trees{/sha}",
371 | "statuses_url": "https://api.github.com/repos/JasonEtco/tests/statuses/{sha}",
372 | "languages_url": "https://api.github.com/repos/JasonEtco/tests/languages",
373 | "stargazers_url": "https://api.github.com/repos/JasonEtco/tests/stargazers",
374 | "contributors_url": "https://api.github.com/repos/JasonEtco/tests/contributors",
375 | "subscribers_url": "https://api.github.com/repos/JasonEtco/tests/subscribers",
376 | "subscription_url": "https://api.github.com/repos/JasonEtco/tests/subscription",
377 | "commits_url": "https://api.github.com/repos/JasonEtco/tests/commits{/sha}",
378 | "git_commits_url": "https://api.github.com/repos/JasonEtco/tests/git/commits{/sha}",
379 | "comments_url": "https://api.github.com/repos/JasonEtco/tests/comments{/number}",
380 | "issue_comment_url": "https://api.github.com/repos/JasonEtco/tests/issues/comments{/number}",
381 | "contents_url": "https://api.github.com/repos/JasonEtco/tests/contents/{+path}",
382 | "compare_url": "https://api.github.com/repos/JasonEtco/tests/compare/{base}...{head}",
383 | "merges_url": "https://api.github.com/repos/JasonEtco/tests/merges",
384 | "archive_url": "https://api.github.com/repos/JasonEtco/tests/{archive_format}{/ref}",
385 | "downloads_url": "https://api.github.com/repos/JasonEtco/tests/downloads",
386 | "issues_url": "https://api.github.com/repos/JasonEtco/tests/issues{/number}",
387 | "pulls_url": "https://api.github.com/repos/JasonEtco/tests/pulls{/number}",
388 | "milestones_url": "https://api.github.com/repos/JasonEtco/tests/milestones{/number}",
389 | "notifications_url": "https://api.github.com/repos/JasonEtco/tests/notifications{?since,all,participating}",
390 | "labels_url": "https://api.github.com/repos/JasonEtco/tests/labels{/name}",
391 | "releases_url": "https://api.github.com/repos/JasonEtco/tests/releases{/id}",
392 | "deployments_url": "https://api.github.com/repos/JasonEtco/tests/deployments",
393 | "created_at": "2017-11-13T14:12:17Z",
394 | "updated_at": "2018-01-08T03:09:57Z",
395 | "pushed_at": "2018-02-17T06:22:12Z",
396 | "git_url": "git://github.com/JasonEtco/tests.git",
397 | "ssh_url": "git@github.com:JasonEtco/tests.git",
398 | "clone_url": "https://github.com/JasonEtco/tests.git",
399 | "svn_url": "https://github.com/JasonEtco/tests",
400 | "homepage": null,
401 | "size": 8,
402 | "stargazers_count": 0,
403 | "watchers_count": 0,
404 | "language": null,
405 | "has_issues": true,
406 | "has_projects": true,
407 | "has_downloads": true,
408 | "has_wiki": true,
409 | "has_pages": false,
410 | "forks_count": 0,
411 | "mirror_url": null,
412 | "archived": false,
413 | "open_issues_count": 19,
414 | "license": null,
415 | "forks": 0,
416 | "open_issues": 19,
417 | "watchers": 0,
418 | "default_branch": "master"
419 | },
420 | "sender": {
421 | "login": "JasonEtco",
422 | "id": 10660468,
423 | "avatar_url": "https://avatars1.githubusercontent.com/u/10660468?v=4",
424 | "gravatar_id": "",
425 | "url": "https://api.github.com/users/JasonEtco",
426 | "html_url": "https://github.com/JasonEtco",
427 | "followers_url": "https://api.github.com/users/JasonEtco/followers",
428 | "following_url": "https://api.github.com/users/JasonEtco/following{/other_user}",
429 | "gists_url": "https://api.github.com/users/JasonEtco/gists{/gist_id}",
430 | "starred_url": "https://api.github.com/users/JasonEtco/starred{/owner}{/repo}",
431 | "subscriptions_url": "https://api.github.com/users/JasonEtco/subscriptions",
432 | "organizations_url": "https://api.github.com/users/JasonEtco/orgs",
433 | "repos_url": "https://api.github.com/users/JasonEtco/repos",
434 | "events_url": "https://api.github.com/users/JasonEtco/events{/privacy}",
435 | "received_events_url": "https://api.github.com/users/JasonEtco/received_events",
436 | "type": "User",
437 | "site_admin": true
438 | },
439 | "installation": {
440 | "id": 1
441 | }
442 | }
--------------------------------------------------------------------------------
/tests/fixtures/payloads/pull_request.synchronize.json:
--------------------------------------------------------------------------------
1 | {
2 | "action": "synchronize",
3 | "number": 32,
4 | "pull_request": {
5 | "url": "https://api.github.com/repos/JasonEtco/tests/pulls/32",
6 | "id": 169770975,
7 | "html_url": "https://github.com/JasonEtco/tests/pull/32",
8 | "diff_url": "https://github.com/JasonEtco/tests/pull/32.diff",
9 | "patch_url": "https://github.com/JasonEtco/tests/pull/32.patch",
10 | "issue_url": "https://api.github.com/repos/JasonEtco/tests/issues/32",
11 | "number": 32,
12 | "state": "open",
13 | "locked": false,
14 | "title": "fgsdfgd",
15 | "user": {
16 | "login": "JasonEtco",
17 | "id": 10660468,
18 | "avatar_url": "https://avatars1.githubusercontent.com/u/10660468?v=4",
19 | "gravatar_id": "",
20 | "url": "https://api.github.com/users/JasonEtco",
21 | "html_url": "https://github.com/JasonEtco",
22 | "followers_url": "https://api.github.com/users/JasonEtco/followers",
23 | "following_url": "https://api.github.com/users/JasonEtco/following{/other_user}",
24 | "gists_url": "https://api.github.com/users/JasonEtco/gists{/gist_id}",
25 | "starred_url": "https://api.github.com/users/JasonEtco/starred{/owner}{/repo}",
26 | "subscriptions_url": "https://api.github.com/users/JasonEtco/subscriptions",
27 | "organizations_url": "https://api.github.com/users/JasonEtco/orgs",
28 | "repos_url": "https://api.github.com/users/JasonEtco/repos",
29 | "events_url": "https://api.github.com/users/JasonEtco/events{/privacy}",
30 | "received_events_url": "https://api.github.com/users/JasonEtco/received_events",
31 | "type": "User",
32 | "site_admin": true
33 | },
34 | "body": "",
35 | "created_at": "2018-02-17T06:22:15Z",
36 | "updated_at": "2018-02-17T06:38:38Z",
37 | "closed_at": null,
38 | "merged_at": null,
39 | "merge_commit_sha": "5258421ec786f7093cc3af7548ec8422d97ceb29",
40 | "assignee": null,
41 | "assignees": [
42 |
43 | ],
44 | "requested_reviewers": [
45 |
46 | ],
47 | "requested_teams": [
48 |
49 | ],
50 | "labels": [
51 |
52 | ],
53 | "milestone": null,
54 | "commits_url": "https://api.github.com/repos/JasonEtco/tests/pulls/32/commits",
55 | "review_comments_url": "https://api.github.com/repos/JasonEtco/tests/pulls/32/comments",
56 | "review_comment_url": "https://api.github.com/repos/JasonEtco/tests/pulls/comments{/number}",
57 | "comments_url": "https://api.github.com/repos/JasonEtco/tests/issues/32/comments",
58 | "statuses_url": "https://api.github.com/repos/JasonEtco/tests/statuses/fe5fe7386cc940a4d848718ea9b40ed0790861e1",
59 | "head": {
60 | "label": "JasonEtco:JasonEtco-patch-7",
61 | "ref": "JasonEtco-patch-7",
62 | "sha": "fe5fe7386cc940a4d848718ea9b40ed0790861e1",
63 | "user": {
64 | "login": "JasonEtco",
65 | "id": 10660468,
66 | "avatar_url": "https://avatars1.githubusercontent.com/u/10660468?v=4",
67 | "gravatar_id": "",
68 | "url": "https://api.github.com/users/JasonEtco",
69 | "html_url": "https://github.com/JasonEtco",
70 | "followers_url": "https://api.github.com/users/JasonEtco/followers",
71 | "following_url": "https://api.github.com/users/JasonEtco/following{/other_user}",
72 | "gists_url": "https://api.github.com/users/JasonEtco/gists{/gist_id}",
73 | "starred_url": "https://api.github.com/users/JasonEtco/starred{/owner}{/repo}",
74 | "subscriptions_url": "https://api.github.com/users/JasonEtco/subscriptions",
75 | "organizations_url": "https://api.github.com/users/JasonEtco/orgs",
76 | "repos_url": "https://api.github.com/users/JasonEtco/repos",
77 | "events_url": "https://api.github.com/users/JasonEtco/events{/privacy}",
78 | "received_events_url": "https://api.github.com/users/JasonEtco/received_events",
79 | "type": "User",
80 | "site_admin": true
81 | },
82 | "repo": {
83 | "id": 110556535,
84 | "name": "tests",
85 | "full_name": "JasonEtco/tests",
86 | "owner": {
87 | "login": "JasonEtco",
88 | "id": 10660468,
89 | "avatar_url": "https://avatars1.githubusercontent.com/u/10660468?v=4",
90 | "gravatar_id": "",
91 | "url": "https://api.github.com/users/JasonEtco",
92 | "html_url": "https://github.com/JasonEtco",
93 | "followers_url": "https://api.github.com/users/JasonEtco/followers",
94 | "following_url": "https://api.github.com/users/JasonEtco/following{/other_user}",
95 | "gists_url": "https://api.github.com/users/JasonEtco/gists{/gist_id}",
96 | "starred_url": "https://api.github.com/users/JasonEtco/starred{/owner}{/repo}",
97 | "subscriptions_url": "https://api.github.com/users/JasonEtco/subscriptions",
98 | "organizations_url": "https://api.github.com/users/JasonEtco/orgs",
99 | "repos_url": "https://api.github.com/users/JasonEtco/repos",
100 | "events_url": "https://api.github.com/users/JasonEtco/events{/privacy}",
101 | "received_events_url": "https://api.github.com/users/JasonEtco/received_events",
102 | "type": "User",
103 | "site_admin": true
104 | },
105 | "private": true,
106 | "html_url": "https://github.com/JasonEtco/tests",
107 | "description": null,
108 | "fork": false,
109 | "url": "https://api.github.com/repos/JasonEtco/tests",
110 | "forks_url": "https://api.github.com/repos/JasonEtco/tests/forks",
111 | "keys_url": "https://api.github.com/repos/JasonEtco/tests/keys{/key_id}",
112 | "collaborators_url": "https://api.github.com/repos/JasonEtco/tests/collaborators{/collaborator}",
113 | "teams_url": "https://api.github.com/repos/JasonEtco/tests/teams",
114 | "hooks_url": "https://api.github.com/repos/JasonEtco/tests/hooks",
115 | "issue_events_url": "https://api.github.com/repos/JasonEtco/tests/issues/events{/number}",
116 | "events_url": "https://api.github.com/repos/JasonEtco/tests/events",
117 | "assignees_url": "https://api.github.com/repos/JasonEtco/tests/assignees{/user}",
118 | "branches_url": "https://api.github.com/repos/JasonEtco/tests/branches{/branch}",
119 | "tags_url": "https://api.github.com/repos/JasonEtco/tests/tags",
120 | "blobs_url": "https://api.github.com/repos/JasonEtco/tests/git/blobs{/sha}",
121 | "git_tags_url": "https://api.github.com/repos/JasonEtco/tests/git/tags{/sha}",
122 | "git_refs_url": "https://api.github.com/repos/JasonEtco/tests/git/refs{/sha}",
123 | "trees_url": "https://api.github.com/repos/JasonEtco/tests/git/trees{/sha}",
124 | "statuses_url": "https://api.github.com/repos/JasonEtco/tests/statuses/{sha}",
125 | "languages_url": "https://api.github.com/repos/JasonEtco/tests/languages",
126 | "stargazers_url": "https://api.github.com/repos/JasonEtco/tests/stargazers",
127 | "contributors_url": "https://api.github.com/repos/JasonEtco/tests/contributors",
128 | "subscribers_url": "https://api.github.com/repos/JasonEtco/tests/subscribers",
129 | "subscription_url": "https://api.github.com/repos/JasonEtco/tests/subscription",
130 | "commits_url": "https://api.github.com/repos/JasonEtco/tests/commits{/sha}",
131 | "git_commits_url": "https://api.github.com/repos/JasonEtco/tests/git/commits{/sha}",
132 | "comments_url": "https://api.github.com/repos/JasonEtco/tests/comments{/number}",
133 | "issue_comment_url": "https://api.github.com/repos/JasonEtco/tests/issues/comments{/number}",
134 | "contents_url": "https://api.github.com/repos/JasonEtco/tests/contents/{+path}",
135 | "compare_url": "https://api.github.com/repos/JasonEtco/tests/compare/{base}...{head}",
136 | "merges_url": "https://api.github.com/repos/JasonEtco/tests/merges",
137 | "archive_url": "https://api.github.com/repos/JasonEtco/tests/{archive_format}{/ref}",
138 | "downloads_url": "https://api.github.com/repos/JasonEtco/tests/downloads",
139 | "issues_url": "https://api.github.com/repos/JasonEtco/tests/issues{/number}",
140 | "pulls_url": "https://api.github.com/repos/JasonEtco/tests/pulls{/number}",
141 | "milestones_url": "https://api.github.com/repos/JasonEtco/tests/milestones{/number}",
142 | "notifications_url": "https://api.github.com/repos/JasonEtco/tests/notifications{?since,all,participating}",
143 | "labels_url": "https://api.github.com/repos/JasonEtco/tests/labels{/name}",
144 | "releases_url": "https://api.github.com/repos/JasonEtco/tests/releases{/id}",
145 | "deployments_url": "https://api.github.com/repos/JasonEtco/tests/deployments",
146 | "created_at": "2017-11-13T14:12:17Z",
147 | "updated_at": "2018-01-08T03:09:57Z",
148 | "pushed_at": "2018-02-17T06:38:38Z",
149 | "git_url": "git://github.com/JasonEtco/tests.git",
150 | "ssh_url": "git@github.com:JasonEtco/tests.git",
151 | "clone_url": "https://github.com/JasonEtco/tests.git",
152 | "svn_url": "https://github.com/JasonEtco/tests",
153 | "homepage": null,
154 | "size": 8,
155 | "stargazers_count": 0,
156 | "watchers_count": 0,
157 | "language": null,
158 | "has_issues": true,
159 | "has_projects": true,
160 | "has_downloads": true,
161 | "has_wiki": true,
162 | "has_pages": false,
163 | "forks_count": 0,
164 | "mirror_url": null,
165 | "archived": false,
166 | "open_issues_count": 19,
167 | "license": null,
168 | "forks": 0,
169 | "open_issues": 19,
170 | "watchers": 0,
171 | "default_branch": "master"
172 | }
173 | },
174 | "base": {
175 | "label": "JasonEtco:master",
176 | "ref": "master",
177 | "sha": "8af6a939b34f5725b54946b5d7a9f77e14c2c002",
178 | "user": {
179 | "login": "JasonEtco",
180 | "id": 10660468,
181 | "avatar_url": "https://avatars1.githubusercontent.com/u/10660468?v=4",
182 | "gravatar_id": "",
183 | "url": "https://api.github.com/users/JasonEtco",
184 | "html_url": "https://github.com/JasonEtco",
185 | "followers_url": "https://api.github.com/users/JasonEtco/followers",
186 | "following_url": "https://api.github.com/users/JasonEtco/following{/other_user}",
187 | "gists_url": "https://api.github.com/users/JasonEtco/gists{/gist_id}",
188 | "starred_url": "https://api.github.com/users/JasonEtco/starred{/owner}{/repo}",
189 | "subscriptions_url": "https://api.github.com/users/JasonEtco/subscriptions",
190 | "organizations_url": "https://api.github.com/users/JasonEtco/orgs",
191 | "repos_url": "https://api.github.com/users/JasonEtco/repos",
192 | "events_url": "https://api.github.com/users/JasonEtco/events{/privacy}",
193 | "received_events_url": "https://api.github.com/users/JasonEtco/received_events",
194 | "type": "User",
195 | "site_admin": true
196 | },
197 | "repo": {
198 | "id": 110556535,
199 | "name": "tests",
200 | "full_name": "JasonEtco/tests",
201 | "owner": {
202 | "login": "JasonEtco",
203 | "id": 10660468,
204 | "avatar_url": "https://avatars1.githubusercontent.com/u/10660468?v=4",
205 | "gravatar_id": "",
206 | "url": "https://api.github.com/users/JasonEtco",
207 | "html_url": "https://github.com/JasonEtco",
208 | "followers_url": "https://api.github.com/users/JasonEtco/followers",
209 | "following_url": "https://api.github.com/users/JasonEtco/following{/other_user}",
210 | "gists_url": "https://api.github.com/users/JasonEtco/gists{/gist_id}",
211 | "starred_url": "https://api.github.com/users/JasonEtco/starred{/owner}{/repo}",
212 | "subscriptions_url": "https://api.github.com/users/JasonEtco/subscriptions",
213 | "organizations_url": "https://api.github.com/users/JasonEtco/orgs",
214 | "repos_url": "https://api.github.com/users/JasonEtco/repos",
215 | "events_url": "https://api.github.com/users/JasonEtco/events{/privacy}",
216 | "received_events_url": "https://api.github.com/users/JasonEtco/received_events",
217 | "type": "User",
218 | "site_admin": true
219 | },
220 | "private": true,
221 | "html_url": "https://github.com/JasonEtco/tests",
222 | "description": null,
223 | "fork": false,
224 | "url": "https://api.github.com/repos/JasonEtco/tests",
225 | "forks_url": "https://api.github.com/repos/JasonEtco/tests/forks",
226 | "keys_url": "https://api.github.com/repos/JasonEtco/tests/keys{/key_id}",
227 | "collaborators_url": "https://api.github.com/repos/JasonEtco/tests/collaborators{/collaborator}",
228 | "teams_url": "https://api.github.com/repos/JasonEtco/tests/teams",
229 | "hooks_url": "https://api.github.com/repos/JasonEtco/tests/hooks",
230 | "issue_events_url": "https://api.github.com/repos/JasonEtco/tests/issues/events{/number}",
231 | "events_url": "https://api.github.com/repos/JasonEtco/tests/events",
232 | "assignees_url": "https://api.github.com/repos/JasonEtco/tests/assignees{/user}",
233 | "branches_url": "https://api.github.com/repos/JasonEtco/tests/branches{/branch}",
234 | "tags_url": "https://api.github.com/repos/JasonEtco/tests/tags",
235 | "blobs_url": "https://api.github.com/repos/JasonEtco/tests/git/blobs{/sha}",
236 | "git_tags_url": "https://api.github.com/repos/JasonEtco/tests/git/tags{/sha}",
237 | "git_refs_url": "https://api.github.com/repos/JasonEtco/tests/git/refs{/sha}",
238 | "trees_url": "https://api.github.com/repos/JasonEtco/tests/git/trees{/sha}",
239 | "statuses_url": "https://api.github.com/repos/JasonEtco/tests/statuses/{sha}",
240 | "languages_url": "https://api.github.com/repos/JasonEtco/tests/languages",
241 | "stargazers_url": "https://api.github.com/repos/JasonEtco/tests/stargazers",
242 | "contributors_url": "https://api.github.com/repos/JasonEtco/tests/contributors",
243 | "subscribers_url": "https://api.github.com/repos/JasonEtco/tests/subscribers",
244 | "subscription_url": "https://api.github.com/repos/JasonEtco/tests/subscription",
245 | "commits_url": "https://api.github.com/repos/JasonEtco/tests/commits{/sha}",
246 | "git_commits_url": "https://api.github.com/repos/JasonEtco/tests/git/commits{/sha}",
247 | "comments_url": "https://api.github.com/repos/JasonEtco/tests/comments{/number}",
248 | "issue_comment_url": "https://api.github.com/repos/JasonEtco/tests/issues/comments{/number}",
249 | "contents_url": "https://api.github.com/repos/JasonEtco/tests/contents/{+path}",
250 | "compare_url": "https://api.github.com/repos/JasonEtco/tests/compare/{base}...{head}",
251 | "merges_url": "https://api.github.com/repos/JasonEtco/tests/merges",
252 | "archive_url": "https://api.github.com/repos/JasonEtco/tests/{archive_format}{/ref}",
253 | "downloads_url": "https://api.github.com/repos/JasonEtco/tests/downloads",
254 | "issues_url": "https://api.github.com/repos/JasonEtco/tests/issues{/number}",
255 | "pulls_url": "https://api.github.com/repos/JasonEtco/tests/pulls{/number}",
256 | "milestones_url": "https://api.github.com/repos/JasonEtco/tests/milestones{/number}",
257 | "notifications_url": "https://api.github.com/repos/JasonEtco/tests/notifications{?since,all,participating}",
258 | "labels_url": "https://api.github.com/repos/JasonEtco/tests/labels{/name}",
259 | "releases_url": "https://api.github.com/repos/JasonEtco/tests/releases{/id}",
260 | "deployments_url": "https://api.github.com/repos/JasonEtco/tests/deployments",
261 | "created_at": "2017-11-13T14:12:17Z",
262 | "updated_at": "2018-01-08T03:09:57Z",
263 | "pushed_at": "2018-02-17T06:38:38Z",
264 | "git_url": "git://github.com/JasonEtco/tests.git",
265 | "ssh_url": "git@github.com:JasonEtco/tests.git",
266 | "clone_url": "https://github.com/JasonEtco/tests.git",
267 | "svn_url": "https://github.com/JasonEtco/tests",
268 | "homepage": null,
269 | "size": 8,
270 | "stargazers_count": 0,
271 | "watchers_count": 0,
272 | "language": null,
273 | "has_issues": true,
274 | "has_projects": true,
275 | "has_downloads": true,
276 | "has_wiki": true,
277 | "has_pages": false,
278 | "forks_count": 0,
279 | "mirror_url": null,
280 | "archived": false,
281 | "open_issues_count": 19,
282 | "license": null,
283 | "forks": 0,
284 | "open_issues": 19,
285 | "watchers": 0,
286 | "default_branch": "master"
287 | }
288 | },
289 | "_links": {
290 | "self": {
291 | "href": "https://api.github.com/repos/JasonEtco/tests/pulls/32"
292 | },
293 | "html": {
294 | "href": "https://github.com/JasonEtco/tests/pull/32"
295 | },
296 | "issue": {
297 | "href": "https://api.github.com/repos/JasonEtco/tests/issues/32"
298 | },
299 | "comments": {
300 | "href": "https://api.github.com/repos/JasonEtco/tests/issues/32/comments"
301 | },
302 | "review_comments": {
303 | "href": "https://api.github.com/repos/JasonEtco/tests/pulls/32/comments"
304 | },
305 | "review_comment": {
306 | "href": "https://api.github.com/repos/JasonEtco/tests/pulls/comments{/number}"
307 | },
308 | "commits": {
309 | "href": "https://api.github.com/repos/JasonEtco/tests/pulls/32/commits"
310 | },
311 | "statuses": {
312 | "href": "https://api.github.com/repos/JasonEtco/tests/statuses/fe5fe7386cc940a4d848718ea9b40ed0790861e1"
313 | }
314 | },
315 | "author_association": "OWNER",
316 | "merged": false,
317 | "mergeable": null,
318 | "rebaseable": null,
319 | "mergeable_state": "unknown",
320 | "merged_by": null,
321 | "comments": 0,
322 | "review_comments": 0,
323 | "maintainer_can_modify": false,
324 | "commits": 2,
325 | "additions": 9,
326 | "deletions": 0,
327 | "changed_files": 1
328 | },
329 | "before": "1409a3f61a27fe80a7170026fd73eaa2108a0108",
330 | "after": "fe5fe7386cc940a4d848718ea9b40ed0790861e1",
331 | "repository": {
332 | "id": 110556535,
333 | "name": "tests",
334 | "full_name": "JasonEtco/tests",
335 | "owner": {
336 | "login": "JasonEtco",
337 | "id": 10660468,
338 | "avatar_url": "https://avatars1.githubusercontent.com/u/10660468?v=4",
339 | "gravatar_id": "",
340 | "url": "https://api.github.com/users/JasonEtco",
341 | "html_url": "https://github.com/JasonEtco",
342 | "followers_url": "https://api.github.com/users/JasonEtco/followers",
343 | "following_url": "https://api.github.com/users/JasonEtco/following{/other_user}",
344 | "gists_url": "https://api.github.com/users/JasonEtco/gists{/gist_id}",
345 | "starred_url": "https://api.github.com/users/JasonEtco/starred{/owner}{/repo}",
346 | "subscriptions_url": "https://api.github.com/users/JasonEtco/subscriptions",
347 | "organizations_url": "https://api.github.com/users/JasonEtco/orgs",
348 | "repos_url": "https://api.github.com/users/JasonEtco/repos",
349 | "events_url": "https://api.github.com/users/JasonEtco/events{/privacy}",
350 | "received_events_url": "https://api.github.com/users/JasonEtco/received_events",
351 | "type": "User",
352 | "site_admin": true
353 | },
354 | "private": true,
355 | "html_url": "https://github.com/JasonEtco/tests",
356 | "description": null,
357 | "fork": false,
358 | "url": "https://api.github.com/repos/JasonEtco/tests",
359 | "forks_url": "https://api.github.com/repos/JasonEtco/tests/forks",
360 | "keys_url": "https://api.github.com/repos/JasonEtco/tests/keys{/key_id}",
361 | "collaborators_url": "https://api.github.com/repos/JasonEtco/tests/collaborators{/collaborator}",
362 | "teams_url": "https://api.github.com/repos/JasonEtco/tests/teams",
363 | "hooks_url": "https://api.github.com/repos/JasonEtco/tests/hooks",
364 | "issue_events_url": "https://api.github.com/repos/JasonEtco/tests/issues/events{/number}",
365 | "events_url": "https://api.github.com/repos/JasonEtco/tests/events",
366 | "assignees_url": "https://api.github.com/repos/JasonEtco/tests/assignees{/user}",
367 | "branches_url": "https://api.github.com/repos/JasonEtco/tests/branches{/branch}",
368 | "tags_url": "https://api.github.com/repos/JasonEtco/tests/tags",
369 | "blobs_url": "https://api.github.com/repos/JasonEtco/tests/git/blobs{/sha}",
370 | "git_tags_url": "https://api.github.com/repos/JasonEtco/tests/git/tags{/sha}",
371 | "git_refs_url": "https://api.github.com/repos/JasonEtco/tests/git/refs{/sha}",
372 | "trees_url": "https://api.github.com/repos/JasonEtco/tests/git/trees{/sha}",
373 | "statuses_url": "https://api.github.com/repos/JasonEtco/tests/statuses/{sha}",
374 | "languages_url": "https://api.github.com/repos/JasonEtco/tests/languages",
375 | "stargazers_url": "https://api.github.com/repos/JasonEtco/tests/stargazers",
376 | "contributors_url": "https://api.github.com/repos/JasonEtco/tests/contributors",
377 | "subscribers_url": "https://api.github.com/repos/JasonEtco/tests/subscribers",
378 | "subscription_url": "https://api.github.com/repos/JasonEtco/tests/subscription",
379 | "commits_url": "https://api.github.com/repos/JasonEtco/tests/commits{/sha}",
380 | "git_commits_url": "https://api.github.com/repos/JasonEtco/tests/git/commits{/sha}",
381 | "comments_url": "https://api.github.com/repos/JasonEtco/tests/comments{/number}",
382 | "issue_comment_url": "https://api.github.com/repos/JasonEtco/tests/issues/comments{/number}",
383 | "contents_url": "https://api.github.com/repos/JasonEtco/tests/contents/{+path}",
384 | "compare_url": "https://api.github.com/repos/JasonEtco/tests/compare/{base}...{head}",
385 | "merges_url": "https://api.github.com/repos/JasonEtco/tests/merges",
386 | "archive_url": "https://api.github.com/repos/JasonEtco/tests/{archive_format}{/ref}",
387 | "downloads_url": "https://api.github.com/repos/JasonEtco/tests/downloads",
388 | "issues_url": "https://api.github.com/repos/JasonEtco/tests/issues{/number}",
389 | "pulls_url": "https://api.github.com/repos/JasonEtco/tests/pulls{/number}",
390 | "milestones_url": "https://api.github.com/repos/JasonEtco/tests/milestones{/number}",
391 | "notifications_url": "https://api.github.com/repos/JasonEtco/tests/notifications{?since,all,participating}",
392 | "labels_url": "https://api.github.com/repos/JasonEtco/tests/labels{/name}",
393 | "releases_url": "https://api.github.com/repos/JasonEtco/tests/releases{/id}",
394 | "deployments_url": "https://api.github.com/repos/JasonEtco/tests/deployments",
395 | "created_at": "2017-11-13T14:12:17Z",
396 | "updated_at": "2018-01-08T03:09:57Z",
397 | "pushed_at": "2018-02-17T06:38:38Z",
398 | "git_url": "git://github.com/JasonEtco/tests.git",
399 | "ssh_url": "git@github.com:JasonEtco/tests.git",
400 | "clone_url": "https://github.com/JasonEtco/tests.git",
401 | "svn_url": "https://github.com/JasonEtco/tests",
402 | "homepage": null,
403 | "size": 8,
404 | "stargazers_count": 0,
405 | "watchers_count": 0,
406 | "language": null,
407 | "has_issues": true,
408 | "has_projects": true,
409 | "has_downloads": true,
410 | "has_wiki": true,
411 | "has_pages": false,
412 | "forks_count": 0,
413 | "mirror_url": null,
414 | "archived": false,
415 | "open_issues_count": 19,
416 | "license": null,
417 | "forks": 0,
418 | "open_issues": 19,
419 | "watchers": 0,
420 | "default_branch": "master"
421 | },
422 | "sender": {
423 | "login": "JasonEtco",
424 | "id": 10660468,
425 | "avatar_url": "https://avatars1.githubusercontent.com/u/10660468?v=4",
426 | "gravatar_id": "",
427 | "url": "https://api.github.com/users/JasonEtco",
428 | "html_url": "https://github.com/JasonEtco",
429 | "followers_url": "https://api.github.com/users/JasonEtco/followers",
430 | "following_url": "https://api.github.com/users/JasonEtco/following{/other_user}",
431 | "gists_url": "https://api.github.com/users/JasonEtco/gists{/gist_id}",
432 | "starred_url": "https://api.github.com/users/JasonEtco/starred{/owner}{/repo}",
433 | "subscriptions_url": "https://api.github.com/users/JasonEtco/subscriptions",
434 | "organizations_url": "https://api.github.com/users/JasonEtco/orgs",
435 | "repos_url": "https://api.github.com/users/JasonEtco/repos",
436 | "events_url": "https://api.github.com/users/JasonEtco/events{/privacy}",
437 | "received_events_url": "https://api.github.com/users/JasonEtco/received_events",
438 | "type": "User",
439 | "site_admin": true
440 | },
441 | "installation": {
442 | "id": 1
443 | }
444 | }
--------------------------------------------------------------------------------
/tests/fixtures/payloads/push.json:
--------------------------------------------------------------------------------
1 | {
2 | "ref": "refs/heads/master",
3 | "before": "46e3daa3218850cf3262eed1ff0f1eecb0769d2f",
4 | "after": "e06c237a0c041f5a0a61f1c361f7a1d6f3d669af",
5 | "created": false,
6 | "deleted": false,
7 | "forced": false,
8 | "base_ref": null,
9 | "compare": "https://github.com/JasonEtco/tests/compare/46e3daa32188...e06c237a0c04",
10 | "commits": [
11 | {
12 | "id": "e06c237a0c041f5a0a61f1c361f7a1d6f3d669af",
13 | "tree_id": "6447cfbafd313fbf6a0d15c36c411d988d176cc3",
14 | "distinct": true,
15 | "message": "Create sadfsadf",
16 | "timestamp": "2018-02-17T18:47:11-05:00",
17 | "url": "https://github.com/JasonEtco/tests/commit/e06c237a0c041f5a0a61f1c361f7a1d6f3d669af",
18 | "author": {
19 | "name": "Jason Etcovitch",
20 | "email": "jasonetco@github.com",
21 | "username": "JasonEtco"
22 | },
23 | "committer": {
24 | "name": "GitHub",
25 | "email": "noreply@github.com",
26 | "username": "web-flow"
27 | },
28 | "added": [
29 | "sadfsadf"
30 | ],
31 | "removed": [
32 |
33 | ],
34 | "modified": [
35 |
36 | ]
37 | }
38 | ],
39 | "head_commit": {
40 | "id": "e06c237a0c041f5a0a61f1c361f7a1d6f3d669af",
41 | "tree_id": "6447cfbafd313fbf6a0d15c36c411d988d176cc3",
42 | "distinct": true,
43 | "message": "Create sadfsadf",
44 | "timestamp": "2018-02-17T18:47:11-05:00",
45 | "url": "https://github.com/JasonEtco/tests/commit/e06c237a0c041f5a0a61f1c361f7a1d6f3d669af",
46 | "author": {
47 | "name": "Jason Etcovitch",
48 | "email": "jasonetco@github.com",
49 | "username": "JasonEtco"
50 | },
51 | "committer": {
52 | "name": "GitHub",
53 | "email": "noreply@github.com",
54 | "username": "web-flow"
55 | },
56 | "added": [
57 | "sadfsadf"
58 | ],
59 | "removed": [
60 |
61 | ],
62 | "modified": [
63 |
64 | ]
65 | },
66 | "repository": {
67 | "id": 110556535,
68 | "name": "tests",
69 | "full_name": "JasonEtco/tests",
70 | "owner": {
71 | "name": "JasonEtco",
72 | "email": "jasonetco@github.com",
73 | "login": "JasonEtco",
74 | "id": 10660468,
75 | "avatar_url": "https://avatars1.githubusercontent.com/u/10660468?v=4",
76 | "gravatar_id": "",
77 | "url": "https://api.github.com/users/JasonEtco",
78 | "html_url": "https://github.com/JasonEtco",
79 | "followers_url": "https://api.github.com/users/JasonEtco/followers",
80 | "following_url": "https://api.github.com/users/JasonEtco/following{/other_user}",
81 | "gists_url": "https://api.github.com/users/JasonEtco/gists{/gist_id}",
82 | "starred_url": "https://api.github.com/users/JasonEtco/starred{/owner}{/repo}",
83 | "subscriptions_url": "https://api.github.com/users/JasonEtco/subscriptions",
84 | "organizations_url": "https://api.github.com/users/JasonEtco/orgs",
85 | "repos_url": "https://api.github.com/users/JasonEtco/repos",
86 | "events_url": "https://api.github.com/users/JasonEtco/events{/privacy}",
87 | "received_events_url": "https://api.github.com/users/JasonEtco/received_events",
88 | "type": "User",
89 | "site_admin": true
90 | },
91 | "private": true,
92 | "html_url": "https://github.com/JasonEtco/tests",
93 | "description": null,
94 | "fork": false,
95 | "url": "https://github.com/JasonEtco/tests",
96 | "forks_url": "https://api.github.com/repos/JasonEtco/tests/forks",
97 | "keys_url": "https://api.github.com/repos/JasonEtco/tests/keys{/key_id}",
98 | "collaborators_url": "https://api.github.com/repos/JasonEtco/tests/collaborators{/collaborator}",
99 | "teams_url": "https://api.github.com/repos/JasonEtco/tests/teams",
100 | "hooks_url": "https://api.github.com/repos/JasonEtco/tests/hooks",
101 | "issue_events_url": "https://api.github.com/repos/JasonEtco/tests/issues/events{/number}",
102 | "events_url": "https://api.github.com/repos/JasonEtco/tests/events",
103 | "assignees_url": "https://api.github.com/repos/JasonEtco/tests/assignees{/user}",
104 | "branches_url": "https://api.github.com/repos/JasonEtco/tests/branches{/branch}",
105 | "tags_url": "https://api.github.com/repos/JasonEtco/tests/tags",
106 | "blobs_url": "https://api.github.com/repos/JasonEtco/tests/git/blobs{/sha}",
107 | "git_tags_url": "https://api.github.com/repos/JasonEtco/tests/git/tags{/sha}",
108 | "git_refs_url": "https://api.github.com/repos/JasonEtco/tests/git/refs{/sha}",
109 | "trees_url": "https://api.github.com/repos/JasonEtco/tests/git/trees{/sha}",
110 | "statuses_url": "https://api.github.com/repos/JasonEtco/tests/statuses/{sha}",
111 | "languages_url": "https://api.github.com/repos/JasonEtco/tests/languages",
112 | "stargazers_url": "https://api.github.com/repos/JasonEtco/tests/stargazers",
113 | "contributors_url": "https://api.github.com/repos/JasonEtco/tests/contributors",
114 | "subscribers_url": "https://api.github.com/repos/JasonEtco/tests/subscribers",
115 | "subscription_url": "https://api.github.com/repos/JasonEtco/tests/subscription",
116 | "commits_url": "https://api.github.com/repos/JasonEtco/tests/commits{/sha}",
117 | "git_commits_url": "https://api.github.com/repos/JasonEtco/tests/git/commits{/sha}",
118 | "comments_url": "https://api.github.com/repos/JasonEtco/tests/comments{/number}",
119 | "issue_comment_url": "https://api.github.com/repos/JasonEtco/tests/issues/comments{/number}",
120 | "contents_url": "https://api.github.com/repos/JasonEtco/tests/contents/{+path}",
121 | "compare_url": "https://api.github.com/repos/JasonEtco/tests/compare/{base}...{head}",
122 | "merges_url": "https://api.github.com/repos/JasonEtco/tests/merges",
123 | "archive_url": "https://api.github.com/repos/JasonEtco/tests/{archive_format}{/ref}",
124 | "downloads_url": "https://api.github.com/repos/JasonEtco/tests/downloads",
125 | "issues_url": "https://api.github.com/repos/JasonEtco/tests/issues{/number}",
126 | "pulls_url": "https://api.github.com/repos/JasonEtco/tests/pulls{/number}",
127 | "milestones_url": "https://api.github.com/repos/JasonEtco/tests/milestones{/number}",
128 | "notifications_url": "https://api.github.com/repos/JasonEtco/tests/notifications{?since,all,participating}",
129 | "labels_url": "https://api.github.com/repos/JasonEtco/tests/labels{/name}",
130 | "releases_url": "https://api.github.com/repos/JasonEtco/tests/releases{/id}",
131 | "deployments_url": "https://api.github.com/repos/JasonEtco/tests/deployments",
132 | "created_at": 1510582337,
133 | "updated_at": "2018-01-08T03:09:57Z",
134 | "pushed_at": 1518911232,
135 | "git_url": "git://github.com/JasonEtco/tests.git",
136 | "ssh_url": "git@github.com:JasonEtco/tests.git",
137 | "clone_url": "https://github.com/JasonEtco/tests.git",
138 | "svn_url": "https://github.com/JasonEtco/tests",
139 | "homepage": null,
140 | "size": 10,
141 | "stargazers_count": 0,
142 | "watchers_count": 0,
143 | "language": null,
144 | "has_issues": true,
145 | "has_projects": true,
146 | "has_downloads": true,
147 | "has_wiki": true,
148 | "has_pages": false,
149 | "forks_count": 0,
150 | "mirror_url": null,
151 | "archived": false,
152 | "open_issues_count": 19,
153 | "license": null,
154 | "forks": 0,
155 | "open_issues": 19,
156 | "watchers": 0,
157 | "default_branch": "master",
158 | "stargazers": 0,
159 | "master_branch": "master"
160 | },
161 | "pusher": {
162 | "name": "JasonEtco",
163 | "email": "jasonetco@github.com"
164 | },
165 | "sender": {
166 | "login": "JasonEtco",
167 | "id": 10660468,
168 | "avatar_url": "https://avatars1.githubusercontent.com/u/10660468?v=4",
169 | "gravatar_id": "",
170 | "url": "https://api.github.com/users/JasonEtco",
171 | "html_url": "https://github.com/JasonEtco",
172 | "followers_url": "https://api.github.com/users/JasonEtco/followers",
173 | "following_url": "https://api.github.com/users/JasonEtco/following{/other_user}",
174 | "gists_url": "https://api.github.com/users/JasonEtco/gists{/gist_id}",
175 | "starred_url": "https://api.github.com/users/JasonEtco/starred{/owner}{/repo}",
176 | "subscriptions_url": "https://api.github.com/users/JasonEtco/subscriptions",
177 | "organizations_url": "https://api.github.com/users/JasonEtco/orgs",
178 | "repos_url": "https://api.github.com/users/JasonEtco/repos",
179 | "events_url": "https://api.github.com/users/JasonEtco/events{/privacy}",
180 | "received_events_url": "https://api.github.com/users/JasonEtco/received_events",
181 | "type": "User",
182 | "site_admin": true
183 | },
184 | "installation": {
185 | "id": 1
186 | }
187 | }
--------------------------------------------------------------------------------
/tests/helpers.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs')
2 | const path = require('path')
3 | const { Application } = require('probot')
4 | const plugin = require('..')
5 |
6 | const loadDiff = exports.loadDiff = filename => {
7 | return Promise.resolve({
8 | data: fs.readFileSync(path.join(__dirname, 'fixtures', 'diffs', filename + '.txt'), 'utf8'),
9 | headers: { 'content-length': 1 }
10 | })
11 | }
12 |
13 | exports.loadConfig = filename => {
14 | return Promise.resolve({
15 | data: {
16 | content: fs.readFileSync(path.join(__dirname, 'fixtures', 'configs', filename + '.yml'), 'base64')
17 | }
18 | })
19 | }
20 |
21 | exports.gimmeApp = () => {
22 | const logger = {
23 | trace: jest.fn(),
24 | debug: jest.fn(),
25 | info: jest.fn(),
26 | warn: jest.fn(),
27 | error: jest.fn(),
28 | fatal: jest.fn()
29 | }
30 |
31 | const app = new Application({
32 | logger,
33 | app: {
34 | getInstallationAccessToken: jest.fn().mockResolvedValue('test'),
35 | getSignedJsonWebToken: jest.fn().mockReturnValue('test')
36 | }
37 | })
38 | app.load(plugin)
39 |
40 | const github = {
41 | issues: {
42 | create: jest.fn(data => Promise.resolve({ data })).mockName('issues.create'),
43 | createLabel: jest.fn().mockName('issues.createLabel'),
44 | update: jest.fn().mockName('issues.update'),
45 | createComment: jest.fn().mockName('issues.createComment'),
46 | listComments: jest.fn(() => Promise.resolve({ data: [] })).mockName('issues.listComments')
47 | },
48 | search: {
49 | issuesAndPullRequests: jest.fn(() => Promise.resolve({ data: { total_count: 0, items: [] } })).mockName('search.issuesAndPullRequests')
50 | },
51 | git: {
52 | getCommit: jest.fn(() => Promise.resolve({ data: { parents: [1] } })).mockName('git.getCommit')
53 | },
54 | repos: {
55 | // Response for getting content from '.github/todo.yml'
56 | getContents: jest.fn(() => {
57 | throw { status: 404 } // eslint-disable-line
58 | }).mockName('repos.getContents'),
59 | getCommit: jest.fn(() => loadDiff('basic')).mockName('repos.getCommit')
60 | },
61 | pulls: {
62 | get: jest.fn(() => loadDiff('basic')).mockName('pulls.get')
63 | },
64 | hook: {
65 | before: jest.fn()
66 | }
67 | }
68 | // Passes the mocked out GitHub API into out app instance
69 | app.auth = () => Promise.resolve(github)
70 | return { app, github }
71 | }
72 |
--------------------------------------------------------------------------------
/tests/issue-rename-handler.test.js:
--------------------------------------------------------------------------------
1 | const { Application } = require('probot')
2 | const issueEdited = require('./fixtures/payloads/issues.edited.json')
3 | const plugin = require('..')
4 |
5 | describe('issue-rename-handler', () => {
6 | let app, github, event
7 |
8 | beforeEach(() => {
9 | app = new Application()
10 | event = { name: 'issues', payload: issueEdited }
11 |
12 | github = {
13 | issues: {
14 | update: jest.fn(),
15 | createComment: jest.fn()
16 | }
17 | }
18 |
19 | app.auth = jest.fn(() => Promise.resolve(github))
20 | app.load(plugin)
21 | })
22 |
23 | it('un-edits the issue title', async () => {
24 | await app.receive(event)
25 | expect(github.issues.update.mock.calls[0][0]).toMatchSnapshot()
26 | expect(github.issues.createComment.mock.calls[0][0]).toMatchSnapshot()
27 | })
28 |
29 | it('only acts if the title is edited', async () => {
30 | event.payload.changes = {}
31 | await app.receive(event)
32 | expect(github.issues.update).not.toHaveBeenCalled()
33 | expect(github.issues.createComment).not.toHaveBeenCalled()
34 | })
35 | })
36 |
--------------------------------------------------------------------------------
/tests/lib/__snapshots__/main-loop.test.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`main-loop throws on an invalid config 1`] = `"\\"pizza\\" is not allowed"`;
4 |
--------------------------------------------------------------------------------
/tests/lib/check-for-body.test.js:
--------------------------------------------------------------------------------
1 | const checkForBody = require('../../lib/utils/check-for-body')
2 |
3 | describe('check-for-body', () => {
4 | let changes, config
5 |
6 | beforeEach(() => {
7 | changes = [{
8 | type: 'add',
9 | ln: 257,
10 | content: '+ // TODO: A title'
11 | }, {
12 | type: 'add',
13 | ln: 258,
14 | content: '+ // BODY: A body'
15 | }]
16 |
17 | config = {
18 | bodyKeyword: 'BODY'
19 | }
20 | })
21 |
22 | it('returns the body if its present', () => {
23 | const actual = checkForBody(changes, 0, config)
24 | expect(actual).toBe('A body')
25 | })
26 |
27 | it('returns false if there is no next line', () => {
28 | const actual = checkForBody([changes[0]], 0, config)
29 | expect(actual).toBe(false)
30 | })
31 |
32 | it('returns false if the next line does not have a body', () => {
33 | changes = [
34 | changes[0],
35 | { content: '+ // PIZZA' }
36 | ]
37 |
38 | const actual = checkForBody(changes, 0, config)
39 | expect(actual).toBe(false)
40 | })
41 |
42 | it('allows for multiple keywords', () => {
43 | config.bodyKeyword = ['PIZZA', 'text']
44 |
45 | changes[1].content = '// PIZZA This is a pizza'
46 | const pizza = checkForBody(changes, 0, config)
47 | expect(pizza).toBe('This is a pizza')
48 |
49 | changes[1].content = '// text This is a test'
50 | const text = checkForBody(changes, 0, config)
51 | expect(text).toBe('This is a test')
52 | })
53 |
54 | it('Allows multiple consecutive BODY lines', () => {
55 | changes.push({
56 | type: 'add',
57 | ln: 259,
58 | content: '+ // BODY: Another body line'
59 | })
60 | const body = checkForBody(changes, 0, config)
61 | expect(body).toBe('A body Another body line')
62 | })
63 |
64 | it('Properly splits empty lines in multi-line BODY', () => {
65 | changes.push({
66 | type: 'add',
67 | ln: 259,
68 | content: '+ // BODY:'
69 | })
70 | changes.push({
71 | type: 'add',
72 | ln: 260,
73 | content: '+ // BODY: Test'
74 | })
75 | const body = checkForBody(changes, 0, config)
76 | expect(body).toBe('A body\nTest')
77 | })
78 | })
79 |
--------------------------------------------------------------------------------
/tests/lib/check-for-duplicate-issue.test.js:
--------------------------------------------------------------------------------
1 | const checkForDuplicateIssue = require('../../lib/utils/check-for-duplicate-issue')
2 | const payload = require('../fixtures/payloads/push.json')
3 |
4 | describe('check-for-duplicate-issue', () => {
5 | let context
6 |
7 | beforeEach(() => {
8 | context = {
9 | payload,
10 | github: {
11 | search: {
12 | issuesAndPullRequests: jest.fn(() => Promise.resolve({ data: { items: [] } }))
13 | }
14 | },
15 | todos: []
16 | }
17 | })
18 |
19 | it('returns undefined if no duplicate issue is found', async () => {
20 | const actual = await checkForDuplicateIssue(context, 'hello')
21 | expect(actual).toBe(undefined)
22 | })
23 |
24 | it('returns the issue if a duplicate issue is found in context.todos', async () => {
25 | context.todos.push('hello')
26 | const actual = await checkForDuplicateIssue(context, 'hello')
27 | expect(actual).toBe('hello')
28 | })
29 |
30 | it('returns the issue if a duplicate issue is found by searching', async () => {
31 | const mock = { data: { total_count: 1, items: [{ title: 'hello' }] } }
32 | context.github.search.issuesAndPullRequests.mockReturnValueOnce(mock)
33 | const actual = await checkForDuplicateIssue(context, 'hello')
34 | expect(actual).toEqual(mock.data.items[0])
35 | })
36 | })
37 |
--------------------------------------------------------------------------------
/tests/lib/generate-label.test.js:
--------------------------------------------------------------------------------
1 | const generateLabel = require('../../lib/utils/generate-label')
2 |
3 | describe('generate-label', () => {
4 | let context
5 |
6 | beforeEach(() => {
7 | context = {
8 | repo: (obj) => ({
9 | owner: 'JasonEtco',
10 | repo: 'todo',
11 | ...obj
12 | }),
13 | github: {
14 | issues: {
15 | createLabel: jest.fn()
16 | }
17 | }
18 | }
19 | })
20 |
21 | it('calls github.createLabel()', async () => {
22 | const labels = await generateLabel(context, { label: true })
23 | expect(Array.isArray(labels)).toBe(true)
24 | expect(context.github.issues.createLabel).toHaveBeenCalledTimes(1)
25 | })
26 |
27 | it('returns an array of the default label name', async () => {
28 | const labels = await generateLabel(context, { label: true })
29 | expect(Array.isArray(labels)).toBe(true)
30 | expect(labels).toEqual(['todo :spiral_notepad:'])
31 | })
32 |
33 | it('returns an empty array with label: false', async () => {
34 | const labels = await generateLabel(context, { label: false })
35 | expect(Array.isArray(labels)).toBe(true)
36 | expect(labels.length).toEqual(0)
37 | expect(labels).toEqual([])
38 | })
39 |
40 | it('returns an array with the provided string', async () => {
41 | const label = 'I am a label'
42 | const labels = await generateLabel(context, { label })
43 | expect(Array.isArray(labels)).toBe(true)
44 | expect(labels.length).toEqual(1)
45 | expect(labels).toEqual([label])
46 | })
47 |
48 | it('returns an array with the provided array of strings', async () => {
49 | const labels = await generateLabel(context, { label: ['pizza', 'dog'] })
50 | expect(Array.isArray(labels)).toBe(true)
51 | expect(labels.length).toEqual(2)
52 | expect(labels).toEqual(['pizza', 'dog'])
53 | })
54 | })
55 |
--------------------------------------------------------------------------------
/tests/lib/ignore-repos.test.js:
--------------------------------------------------------------------------------
1 | const ignoreRepos = require('../../lib/ignore-repos')
2 |
3 | describe('ignoreRepos', () => {
4 | let spy, func, context
5 |
6 | beforeEach(() => {
7 | spy = jest.fn()
8 | func = ignoreRepos(spy)
9 | context = {
10 | repo: () => ({ owner: 'JasonEtco', repo: 'todo' }),
11 | log: jest.fn()
12 | }
13 | })
14 |
15 | it('does call the handler if the repo is not being ignored', () => {
16 | process.env.IGNORED_REPOS = 'JasonEtco/pizza'
17 | func(context)
18 | expect(spy).toHaveBeenCalled()
19 | })
20 |
21 | it('does not call the handler if the repo is being ignored', () => {
22 | process.env.IGNORED_REPOS = 'JasonEtco/todo'
23 | func(context)
24 | expect(spy).not.toHaveBeenCalled()
25 | })
26 |
27 | afterEach(() => {
28 | delete process.env.IGNORED_REPOS
29 | })
30 | })
31 |
--------------------------------------------------------------------------------
/tests/lib/main-loop.test.js:
--------------------------------------------------------------------------------
1 | const mainLoop = require('../../lib/utils/main-loop')
2 | const { loadDiff } = require('../helpers')
3 |
4 | describe('main-loop', () => {
5 | let context, handler
6 |
7 | beforeEach(() => {
8 | context = {
9 | event: 'push',
10 | payload: require('../fixtures/payloads/push.json'),
11 | config: jest.fn(),
12 | log: f => f,
13 | repo: (obj) => ({
14 | owner: 'JasonEtco',
15 | repo: 'todo',
16 | ...obj
17 | }),
18 | github: {
19 | issues: {
20 | createLabel: jest.fn()
21 | },
22 | repos: {
23 | getCommit: jest.fn(() => loadDiff('basic')).mockName('repos.getCommit')
24 | }
25 | }
26 | }
27 |
28 | handler = jest.fn()
29 | })
30 |
31 | it('uses the default config if context.config return value does not have todo', async () => {
32 | context.config = jest.fn(() => Promise.resolve({
33 | pizza: true
34 | }))
35 |
36 | await mainLoop(context, handler)
37 | expect(handler).toHaveBeenCalled()
38 | })
39 |
40 | it('throws on an invalid config', async () => {
41 | context.config = jest.fn(() => Promise.resolve({
42 | todo: { pizza: true }
43 | }))
44 |
45 | await expect(mainLoop(context, handler))
46 | .rejects
47 | .toThrowErrorMatchingSnapshot()
48 | expect(handler).not.toHaveBeenCalled()
49 | })
50 |
51 | it('does nothing if a title is only whitespace', async () => {
52 | context.github.repos.getCommit.mockReturnValue(Promise.resolve(loadDiff('title-with-whitespace')))
53 | await mainLoop(context, handler)
54 | expect(handler).not.toHaveBeenCalled()
55 | })
56 |
57 | it('does nothing if a keyword is in the middle of a sentence', async () => {
58 | context.github.repos.getCommit.mockReturnValue(Promise.resolve(loadDiff('middle-of-sentence')))
59 | await mainLoop(context, handler)
60 | expect(handler).not.toHaveBeenCalled()
61 | })
62 | })
63 |
--------------------------------------------------------------------------------
/tests/lib/should-exclude-file.test.js:
--------------------------------------------------------------------------------
1 | const shouldExcludeFile = require('../../lib/utils/should-exclude-file')
2 |
3 | describe('shouldExcludeFile', () => {
4 | let logger
5 |
6 | beforeEach(() => {
7 | logger = { debug: jest.fn() }
8 | })
9 |
10 | it('returns true for the .github/config.yml file', () => {
11 | const actual = shouldExcludeFile(logger, '.github/config.yml')
12 | expect(actual).toBe(true)
13 | })
14 |
15 | it('returns true for any files that match the alwaysExclude RegEx', () => {
16 | const actual = shouldExcludeFile(logger, 'example.min.js')
17 | expect(actual).toBe(true)
18 | })
19 |
20 | it('returns true for any files that match the provded pattern', () => {
21 | const actual = shouldExcludeFile(logger, 'pizza.js', 'pi')
22 | expect(actual).toBe(true)
23 | })
24 | })
25 |
--------------------------------------------------------------------------------
/tests/pull-request-handler.test.js:
--------------------------------------------------------------------------------
1 | const { gimmeApp, loadConfig, loadDiff } = require('./helpers')
2 | const pullRequestOpened = require('./fixtures/payloads/pull_request.opened.json')
3 |
4 | describe('pull-request-handler', () => {
5 | let app, github
6 | const event = { name: 'pull_request', payload: pullRequestOpened }
7 |
8 | beforeEach(() => {
9 | const gimme = gimmeApp()
10 | app = gimme.app
11 | github = gimme.github
12 | })
13 |
14 | it('comments on a pull request', async () => {
15 | await app.receive(event)
16 | expect(github.issues.createComment).toHaveBeenCalledTimes(1)
17 | expect(github.issues.createComment.mock.calls[0]).toMatchSnapshot()
18 | })
19 |
20 | it('comments on a pull request and mentions the assigned user', async () => {
21 | github.repos.getContents.mockReturnValueOnce(loadConfig('autoAssignString'))
22 | await app.receive(event)
23 | expect(github.issues.createComment.mock.calls[0]).toMatchSnapshot()
24 | })
25 |
26 | it('comments on a pull request and mentions the assigned users', async () => {
27 | github.repos.getContents.mockReturnValueOnce(loadConfig('autoAssignArr'))
28 | await app.receive(event)
29 | expect(github.issues.createComment.mock.calls[0]).toMatchSnapshot()
30 | })
31 |
32 | it('does not create duplicate comments', async () => {
33 | github.issues.listComments.mockReturnValueOnce(Promise.resolve({
34 | data: [{
35 | body: '## I am an example title'
36 | }]
37 | }))
38 |
39 | await app.receive(event)
40 | expect(github.issues.createComment).not.toHaveBeenCalled()
41 | })
42 |
43 | it('creates many (5) comments', async () => {
44 | github.pulls.get.mockReturnValue(loadDiff('many'))
45 | await app.receive(event)
46 | expect(github.issues.createComment).toHaveBeenCalledTimes(5)
47 | })
48 |
49 | it('ignores changes to the config file', async () => {
50 | github.pulls.get.mockReturnValue(loadDiff('config'))
51 | await app.receive(event)
52 | expect(github.issues.createComment).not.toHaveBeenCalled()
53 | })
54 |
55 | it('ignores changes to the bin directory', async () => {
56 | github.pulls.get.mockReturnValue(loadDiff('bin'))
57 | github.repos.getContents.mockReturnValueOnce(loadConfig('excludeBin'))
58 | await app.receive(event)
59 | expect(github.issues.createComment).not.toHaveBeenCalled()
60 | })
61 |
62 | it('works with a string as the keyword config', async () => {
63 | github.repos.getContents.mockReturnValueOnce(loadConfig('keywordsString'))
64 | github.pulls.get.mockReturnValue(loadDiff('custom-keyword'))
65 | await app.receive(event)
66 | expect(github.issues.createComment.mock.calls[0]).toMatchSnapshot()
67 | })
68 |
69 | it('creates a comment with a body line', async () => {
70 | github.pulls.get.mockReturnValue(loadDiff('body'))
71 | await app.receive(event)
72 | expect(github.issues.createComment.mock.calls[0]).toMatchSnapshot()
73 | })
74 | })
75 |
--------------------------------------------------------------------------------
/tests/pull-request-merge-handler.test.js:
--------------------------------------------------------------------------------
1 | const pullRequestClosed = require('./fixtures/payloads/pull_request.closed.json')
2 | const { gimmeApp, loadConfig, loadDiff } = require('./helpers')
3 |
4 | describe('pull-request-merged-handler', () => {
5 | let app, github
6 | const event = { name: 'pull_request', payload: pullRequestClosed }
7 |
8 | beforeEach(() => {
9 | const gimme = gimmeApp()
10 | app = gimme.app
11 | github = gimme.github
12 | })
13 |
14 | it('does nothing on an unmerged, closed PR', async () => {
15 | await app.receive({
16 | ...event,
17 | payload: {
18 | ...event.payload,
19 | pull_request: { merged: false }
20 | }
21 | })
22 |
23 | expect(github.issues.create).not.toHaveBeenCalled()
24 | })
25 |
26 | it('creates an issue', async () => {
27 | await app.receive(event)
28 | expect(github.issues.create).toHaveBeenCalledTimes(1)
29 | expect(github.issues.create.mock.calls[0]).toMatchSnapshot()
30 | })
31 |
32 | it('creates an issue with a truncated title', async () => {
33 | github.pulls.get.mockReturnValue(loadDiff('long-title'))
34 | await app.receive(event)
35 | expect(github.issues.create).toHaveBeenCalledTimes(1)
36 | expect(github.issues.create.mock.calls[0]).toMatchSnapshot()
37 | })
38 |
39 | it('creates an issue without assigning anyone', async () => {
40 | github.repos.getContents.mockReturnValueOnce(loadConfig('autoAssignFalse'))
41 | await app.receive(event)
42 | expect(github.issues.create.mock.calls[0]).toMatchSnapshot()
43 | })
44 |
45 | it('creates an issue and assigns the configured user', async () => {
46 | github.repos.getContents.mockReturnValueOnce(loadConfig('autoAssignString'))
47 | await app.receive(event)
48 | expect(github.issues.create.mock.calls[0]).toMatchSnapshot()
49 | })
50 |
51 | it('creates an issue and assigns the configured users', async () => {
52 | github.repos.getContents.mockReturnValueOnce(loadConfig('autoAssignArr'))
53 | await app.receive(event)
54 | expect(github.issues.create.mock.calls[0]).toMatchSnapshot()
55 | })
56 |
57 | it('does not create any issues if no todos are found', async () => {
58 | github.pulls.get.mockReturnValue(loadDiff('none'))
59 | await app.receive(event)
60 | expect(github.issues.create).not.toHaveBeenCalled()
61 | })
62 |
63 | it('does not create an issue that already exists', async () => {
64 | github.search.issuesAndPullRequests.mockReturnValueOnce(Promise.resolve({
65 | data: { total_count: 1, items: [{ title: 'I am an example title', state: 'open' }] }
66 | }))
67 | await app.receive(event)
68 | expect(github.issues.create).not.toHaveBeenCalled()
69 | })
70 |
71 | it('creates many (5) issues', async () => {
72 | github.pulls.get.mockReturnValue(loadDiff('many'))
73 | await app.receive(event)
74 | expect(github.issues.create).toHaveBeenCalledTimes(5)
75 | })
76 |
77 | it('ignores changes to the config file', async () => {
78 | github.pulls.get.mockReturnValue(loadDiff('config'))
79 | await app.receive(event)
80 | expect(github.issues.create).not.toHaveBeenCalled()
81 | })
82 |
83 | it('ignores changes to the bin directory', async () => {
84 | github.pulls.get.mockReturnValue(loadDiff('bin'))
85 | github.repos.getContents.mockReturnValueOnce(loadConfig('excludeBin'))
86 | await app.receive(event)
87 | expect(github.issues.createComment).not.toHaveBeenCalled()
88 | })
89 |
90 | it('creates an issue with a body line', async () => {
91 | github.pulls.get.mockReturnValue(loadDiff('body'))
92 | await app.receive(event)
93 | expect(github.issues.create.mock.calls[0]).toMatchSnapshot()
94 | })
95 |
96 | it('reopens a closed issue', async () => {
97 | github.search.issuesAndPullRequests.mockReturnValueOnce(Promise.resolve({
98 | data: { total_count: 1, items: [{ number: 1, title: 'I am an example title', state: 'closed' }] }
99 | }))
100 | await app.receive(event)
101 | expect(github.issues.update).toHaveBeenCalledTimes(1)
102 | expect(github.issues.createComment).toHaveBeenCalledTimes(1)
103 | expect(github.issues.createComment.mock.calls[0]).toMatchSnapshot()
104 | expect(github.issues.create).not.toHaveBeenCalled()
105 | })
106 |
107 | it('respects the reopenClosed config', async () => {
108 | github.repos.getContents.mockReturnValueOnce(loadConfig('reopenClosedFalse'))
109 | github.search.issuesAndPullRequests.mockReturnValueOnce(Promise.resolve({
110 | data: { total_count: 1, items: [{ title: 'I am an example title', state: 'closed' }] }
111 | }))
112 | await app.receive(event)
113 | expect(github.issues.update).not.toHaveBeenCalled()
114 | expect(github.issues.createComment).not.toHaveBeenCalled()
115 | expect(github.issues.create).not.toHaveBeenCalled()
116 | })
117 | })
118 |
--------------------------------------------------------------------------------
/tests/push-handler.test.js:
--------------------------------------------------------------------------------
1 | const pushEvent = require('./fixtures/payloads/push.json')
2 | const { gimmeApp, loadConfig, loadDiff } = require('./helpers')
3 |
4 | describe('push-handler', () => {
5 | let app, github
6 | const event = { name: 'push', payload: pushEvent }
7 |
8 | beforeEach(() => {
9 | const gimme = gimmeApp()
10 | app = gimme.app
11 | github = gimme.github
12 | })
13 |
14 | it('creates an issue', async () => {
15 | await app.receive(event)
16 | expect(github.issues.create).toHaveBeenCalledTimes(1)
17 | expect(github.issues.create.mock.calls[0]).toMatchSnapshot()
18 | })
19 |
20 | it('creates an issue with an @todo comment', async () => {
21 | github.repos.getCommit.mockReturnValue(loadDiff('at-todo'))
22 | await app.receive(event)
23 | expect(github.issues.create).toHaveBeenCalledTimes(1)
24 | expect(github.issues.create.mock.calls[0]).toMatchSnapshot()
25 | })
26 |
27 | it('creates an issue with a truncated title', async () => {
28 | github.repos.getCommit.mockReturnValue(loadDiff('long-title'))
29 | await app.receive(event)
30 | expect(github.issues.create).toHaveBeenCalledTimes(1)
31 | expect(github.issues.create.mock.calls[0]).toMatchSnapshot()
32 | })
33 |
34 | it('creates an issue without assigning anyone', async () => {
35 | github.repos.getContents.mockReturnValueOnce(loadConfig('autoAssignFalse'))
36 | await app.receive(event)
37 | expect(github.issues.create.mock.calls[0]).toMatchSnapshot()
38 | })
39 |
40 | it('creates an issue and assigns the configured user', async () => {
41 | github.repos.getContents.mockReturnValueOnce(loadConfig('autoAssignString'))
42 | await app.receive(event)
43 | expect(github.issues.create.mock.calls[0]).toMatchSnapshot()
44 | })
45 |
46 | it('creates an issue and assigns the configured users', async () => {
47 | github.repos.getContents.mockReturnValueOnce(loadConfig('autoAssignArr'))
48 | await app.receive(event)
49 | expect(github.issues.create.mock.calls[0]).toMatchSnapshot()
50 | })
51 |
52 | it('does not create any issues if no todos are found', async () => {
53 | github.repos.getCommit.mockReturnValue(loadDiff('none'))
54 | await app.receive(event)
55 | expect(github.issues.create).not.toHaveBeenCalled()
56 | })
57 |
58 | it('does not create any issues if the push is not on the default branch', async () => {
59 | await app.receive({ name: 'push', payload: { ...pushEvent, ref: 'not-master' } })
60 | expect(github.issues.create).not.toHaveBeenCalled()
61 | })
62 |
63 | it('does not create an issue that already exists', async () => {
64 | github.search.issuesAndPullRequests.mockReturnValueOnce(Promise.resolve({
65 | data: { total_count: 1, items: [{ title: 'I am an example title', state: 'open' }] }
66 | }))
67 | await app.receive(event)
68 | expect(github.issues.create).not.toHaveBeenCalled()
69 | })
70 |
71 | it('does not create the same issue twice in the same run', async () => {
72 | github.repos.getCommit.mockReturnValue(loadDiff('duplicate'))
73 | await app.receive(event)
74 | expect(github.issues.create).toHaveBeenCalledTimes(1)
75 | })
76 |
77 | it('creates an issue if the search does not have an issue with the correct title', async () => {
78 | github.search.issuesAndPullRequests.mockReturnValueOnce(Promise.resolve({
79 | data: { total_count: 1, items: [{ title: 'Not found', state: 'open' }] }
80 | }))
81 | await app.receive(event)
82 | expect(github.issues.create).toHaveBeenCalledTimes(1)
83 | })
84 |
85 | it('creates many (5) issues', async () => {
86 | github.repos.getCommit.mockReturnValue(loadDiff('many'))
87 | await app.receive(event)
88 | expect(github.issues.create).toHaveBeenCalledTimes(5)
89 | expect(github.issues.create.mock.calls).toMatchSnapshot()
90 | })
91 |
92 | it('ignores changes to the config file', async () => {
93 | github.repos.getCommit.mockReturnValue(loadDiff('config'))
94 | await app.receive(event)
95 | expect(github.issues.create).not.toHaveBeenCalled()
96 | })
97 |
98 | it('ignores changes to the bin directory', async () => {
99 | github.repos.getCommit.mockReturnValue(loadDiff('bin'))
100 | github.repos.getContents.mockReturnValueOnce(loadConfig('excludeBin'))
101 | await app.receive(event)
102 | expect(github.issues.create).not.toHaveBeenCalled()
103 | })
104 |
105 | it('ignores pushes not to master', async () => {
106 | const e = { event: event.event, payload: { ...event.payload, ref: 'not/the/master/branch' } }
107 | await app.receive(e)
108 | expect(github.issues.create).not.toHaveBeenCalled()
109 | })
110 |
111 | it('ignores merge commits', async () => {
112 | github.git.getCommit.mockReturnValueOnce(Promise.resolve({
113 | data: { parents: [1, 2] }
114 | }))
115 | await app.receive(event)
116 | expect(github.issues.create).not.toHaveBeenCalled()
117 | })
118 |
119 | it('creates an issue with a body line', async () => {
120 | github.repos.getCommit.mockReturnValue(loadDiff('body'))
121 | await app.receive(event)
122 | expect(github.issues.create.mock.calls[0]).toMatchSnapshot()
123 | })
124 |
125 | it('creates an issue with a custom keyword config', async () => {
126 | github.repos.getCommit.mockReturnValue(loadDiff('custom-keyword'))
127 | github.repos.getContents.mockReturnValueOnce(loadConfig('keywordsString'))
128 | await app.receive(event)
129 | expect(github.issues.create.mock.calls[0]).toMatchSnapshot()
130 | })
131 |
132 | it('creates an issue with a body line with one body keyword', async () => {
133 | github.repos.getCommit.mockReturnValue(loadDiff('body'))
134 | github.repos.getContents.mockReturnValueOnce(loadConfig('bodyString'))
135 | await app.receive(event)
136 | expect(github.issues.create.mock.calls[0]).toMatchSnapshot()
137 | })
138 |
139 | it('reopens a closed issue', async () => {
140 | github.search.issuesAndPullRequests.mockReturnValueOnce(Promise.resolve({
141 | data: { total_count: 1, items: [{ number: 1, title: 'I am an example title', state: 'closed' }] }
142 | }))
143 | await app.receive(event)
144 | expect(github.issues.update).toHaveBeenCalledTimes(1)
145 | expect(github.issues.createComment).toHaveBeenCalledTimes(1)
146 | expect(github.issues.createComment.mock.calls[0]).toMatchSnapshot()
147 | expect(github.issues.create).not.toHaveBeenCalled()
148 | })
149 |
150 | it('respects the reopenClosed config', async () => {
151 | github.repos.getContents.mockReturnValueOnce(loadConfig('reopenClosedFalse'))
152 | github.search.issuesAndPullRequests.mockReturnValueOnce(Promise.resolve({
153 | data: { total_count: 1, items: [{ title: 'I am an example title', state: 'closed' }] }
154 | }))
155 | await app.receive(event)
156 | expect(github.issues.update).not.toHaveBeenCalled()
157 | expect(github.issues.createComment).not.toHaveBeenCalled()
158 | expect(github.issues.create).not.toHaveBeenCalled()
159 | })
160 |
161 | it('does not show the blob if blobLines is false', async () => {
162 | github.repos.getContents.mockReturnValueOnce(loadConfig('blobLinesFalse'))
163 | await app.receive(event)
164 | expect(github.issues.create.mock.calls[0]).toMatchSnapshot()
165 | })
166 |
167 | it('cuts the blobLines', async () => {
168 | github.repos.getCommit.mockReturnValue(loadDiff('blob-past-end'))
169 | await app.receive(event)
170 | expect(github.issues.create.mock.calls[0]).toMatchSnapshot()
171 | })
172 |
173 | it('does nothing with a diff over the max size', async () => {
174 | github.repos.getCommit.mockReturnValue(Promise.resolve({ headers: { 'content-length': 2000001 } }))
175 | await app.receive(event)
176 | expect(github.issues.create).not.toHaveBeenCalled()
177 | })
178 |
179 | it('creates an issue and respects GHE_HOST', async () => {
180 | process.env.GHE_HOST = 'fakegittillyoumakegit.com'
181 | await app.receive(event)
182 | expect(github.issues.create).toHaveBeenCalledTimes(1)
183 | expect(github.issues.create.mock.calls[0]).toMatchSnapshot()
184 | delete process.env.GHE_HOST
185 | })
186 | })
187 |
--------------------------------------------------------------------------------
/tests/setup.js:
--------------------------------------------------------------------------------
1 | process.env.APP_NAME = 'todo-dev'
2 | process.env.LOG_LEVEL = 'fatal'
3 |
--------------------------------------------------------------------------------