') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); Only request infos for issue and/or pull request by nMustaki · Pull Request #13 · behaviorbot/request-info · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -28,8 +28,15 @@ requestInfoDefaultTitles:

# *OPTIONAL* Label to be added to Issues and Pull Requests with insufficient information given
requestInfoLabelToAdd: needs-more-info

# *OPTIONAL* Only warn about insufficient information on these events type
# Keys must be lowercase. Valid values are 'issue' and 'pullRequest'
requestInfoLabelToAdd:
pullRequest: true
issue: true

```
3. If you' prefer not to add a `.github/config.yml`, you can simply install the bot and it was comment on issues and pull reuqests with empty bodies with the comment:
3. If you' prefer not to add a `.github/config.yml`, you can simply install the bot and it was comment on issues and pull requests with empty bodies with the comment:
```
The maintainers of this repository would appreciate it if you could provide more information.
```
Expand Down
27 changes: 20 additions & 7 deletions index.js
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,44 @@
const DEFAULT_CONFIG = {
requestInfoReplyComment: 'The maintainers of this repository would appreciate it if you could provide more information.',
requestInfoOn: {
issue: true,
pullRequest: true
}
}

module.exports = robot => {
robot.on('pull_request.opened', receive)
robot.on('issues.opened', receive)
async function receive (context) {
let title
let body
let badTitle

let eventSrc = 'issue'
if (context.payload.pull_request) {
eventSrc = 'pullRequest';
({title, body} = context.payload.pull_request)
} else {
({title, body} = context.payload.issue)
}

try {
const config = await context.config('config.yml', {requestInfoReplyComment: 'The maintainers of this repository would appreciate it if you could provide more information.'})
const config = await context.config('config.yml', DEFAULT_CONFIG)

if (!config.requestInfoOn[eventSrc]) {
return
}

if (config.requestInfoDefaultTitles) {
if (config.requestInfoDefaultTitles.includes(title.toLowerCase())) {
badTitle = true
}
}
if (!body || badTitle) {
if (config.requestInfoReplyComment) {
context.github.issues.createComment(context.issue({body: config.requestInfoReplyComment}))
} else {
context.github.issues.createComment(context.issue({body: 'The maintainers of this repository would appreciate it if you could provide more information.'}))
}
context.github.issues.createComment(context.issue({body: config.requestInfoReplyComment || DEFAULT_CONFIG.requestInfoReplyComment}))

if (config.requestInfoLabelToAdd) {
// Add label if there is one listed in the yaml file
// Add label if there is one listed in the yaml file
context.github.issues.addLabels(context.issue({labels: [config.requestInfoLabelToAdd]}))
}
}
Expand Down
File renamed without changes.
File renamed without changes.
22 changes: 22 additions & 0 deletions test/events/prFailEvent.json
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
{
"event": "issues",
"payload": {
"action": "opened",
"pull_request": {
"body": "Fix your broken thigns!",
"title": "ur thing is broken fix it!!",
"user": {
"login": "hiimbex"
}
},
"repository": {
"name": "testing-things",
"owner": {
"login": "hiimbex"
}
},
"installation": {
"id": 35471
}
}
}
22 changes: 22 additions & 0 deletions test/events/prSuccessEvent.json
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
{
"event": "issues",
"payload": {
"action": "opened",
"pull_request": {
"body": "",
"title": "ur thing is broken fix it!!",
"user": {
"login": "hiimbex"
}
},
"repository": {
"name": "testing-things",
"owner": {
"login": "hiimbex"
}
},
"installation": {
"id": 35471
}
}
}
175 changes: 166 additions & 9 deletions test/index.js
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
const expect = require('expect')
const {createRobot} = require('probot')
const plugin = require('..')
const successEvent = require('./events/successEvent')
const failEvent = require('./events/failEvent')
const issueSuccessEvent = require('./events/issueSuccessEvent')
const issueFailEvent = require('./events/issueFailEvent')
const prSuccessEvent = require('./events/prSuccessEvent')
const prFailEvent = require('./events/prFailEvent')

describe('new-pr-welcome', () => {
describe('Request info on both issues and pull requests', () => {
let robot
let github

Expand All@@ -28,9 +30,9 @@ describe('new-pr-welcome', () => {
robot.auth = () => Promise.resolve(github)
})

describe('request-info', () => {
it('posts a comment because there wasn\'t enough info provided', async () => {
await robot.receive(successEvent)
describe('Posts a comment because...', () => {
it('there wasn\'t enough info provided in an issue', async () => {
await robot.receive(issueSuccessEvent)

expect(github.repos.getContent).toHaveBeenCalledWith({
owner: 'hiimbex',
Expand All@@ -43,9 +45,149 @@ describe('new-pr-welcome', () => {
})
})

describe('new-pr-welcome fail', () => {
it('does not post a comment because it is not the user\'s first PR', async () => {
await robot.receive(failEvent)
describe('Posts a comment because...', () => {
it('there wasn\'t enough info provided in a pull request', async () => {
await robot.receive(prSuccessEvent)

expect(github.repos.getContent).toHaveBeenCalledWith({
owner: 'hiimbex',
repo: 'testing-things',
path: '.github/config.yml'
})

expect(github.issues.createComment).toHaveBeenCalled()
expect(github.issues.addLabels).toHaveBeenCalled()
})
})

describe('Does not post a comment because...', () => {
it('there was a body in issue', async () => {
await robot.receive(issueFailEvent)

expect(github.repos.getContent).toHaveBeenCalledWith({
owner: 'hiimbex',
repo: 'testing-things',
path: '.github/config.yml'
})

expect(github.issues.createComment).toNotHaveBeenCalled()
expect(github.issues.addLabels).toNotHaveBeenCalled()
})
})
})

describe('Request info disabled for issues', () => {
let robot
let github

beforeEach(() => {
robot = createRobot()
plugin(robot)

github = {
repos: {
getContent: expect.createSpy().andReturn(Promise.resolve({
data: {
content: Buffer.from(`requestInfoLabelToAdd: needs-more-info\nrequestInfoDefaultTitles:\n - readme.md\nrequestInfoReplyComment: >\n Reply comment\nrequestInfoOn:\n issue: false\n pullRequest: true\n`).toString('base64')
}
}))
},
issues: {
createComment: expect.createSpy(),
addLabels: expect.createSpy()
}
}
robot.auth = () => Promise.resolve(github)
})

describe('Does not post a comment because...', () => {
it("'issue' type is disabled even if there wasn't enough info provided", async () => {
await robot.receive(issueSuccessEvent)

expect(github.repos.getContent).toHaveBeenCalledWith({
owner: 'hiimbex',
repo: 'testing-things',
path: '.github/config.yml'
})

expect(github.issues.createComment).toNotHaveBeenCalled()
expect(github.issues.addLabels).toNotHaveBeenCalled()
})
})

describe('Does not post a comment because...', () => {
it('there was a body in issue', async () => {
await robot.receive(issueFailEvent)

expect(github.repos.getContent).toHaveBeenCalledWith({
owner: 'hiimbex',
repo: 'testing-things',
path: '.github/config.yml'
})

expect(github.issues.createComment).toNotHaveBeenCalled()
expect(github.issues.addLabels).toNotHaveBeenCalled()
})
})

describe('Posts a comment because...', () => {
it('there wasn\'t enough info provided in a pull request', async () => {
await robot.receive(prSuccessEvent)

expect(github.repos.getContent).toHaveBeenCalledWith({
owner: 'hiimbex',
repo: 'testing-things',
path: '.github/config.yml'
})

expect(github.issues.createComment).toHaveBeenCalled()
expect(github.issues.addLabels).toHaveBeenCalled()
})
})
})

describe('Request info disabled for pull requests', () => {
let robot
let github

beforeEach(() => {
robot = createRobot()
plugin(robot)

github = {
repos: {
getContent: expect.createSpy().andReturn(Promise.resolve({
data: {
content: Buffer.from(`requestInfoLabelToAdd: needs-more-info\nrequestInfoDefaultTitles:\n - readme.md\nrequestInfoReplyComment: >\n Reply comment\nrequestInfoOn:\n issue: true\n pullRequest: false\n`).toString('base64')
}
}))
},
issues: {
createComment: expect.createSpy(),
addLabels: expect.createSpy()
}
}
robot.auth = () => Promise.resolve(github)
})

describe('Does not post a comment because...', () => {
it("'pullRequest' type is disabled even if there wasn't enough info provided", async () => {
await robot.receive(prSuccessEvent)

expect(github.repos.getContent).toHaveBeenCalledWith({
owner: 'hiimbex',
repo: 'testing-things',
path: '.github/config.yml'
})

expect(github.issues.createComment).toNotHaveBeenCalled()
expect(github.issues.addLabels).toNotHaveBeenCalled()
})
})

describe('Does not post a comment because...', () => {
it('there was a body in pr', async () => {
await robot.receive(prFailEvent)

expect(github.repos.getContent).toHaveBeenCalledWith({
owner: 'hiimbex',
Expand All@@ -57,4 +199,19 @@ describe('new-pr-welcome', () => {
expect(github.issues.addLabels).toNotHaveBeenCalled()
})
})

describe('Posts a comment because...', () => {
it('there wasn\'t enough info provided (issue type still working)', async () => {
await robot.receive(issueSuccessEvent)

expect(github.repos.getContent).toHaveBeenCalledWith({
owner: 'hiimbex',
repo: 'testing-things',
path: '.github/config.yml'
})

expect(github.issues.createComment).toHaveBeenCalled()
expect(github.issues.addLabels).toHaveBeenCalled()
})
})
})