├── .npmignore
├── Procfile
├── index.js
├── .github
└── CODEOWNERS
├── .gitignore
├── .travis.yml
├── images
├── avatar.png
├── badge-blue-large.png
├── badge-blue-small.png
├── logo-blue-large.png
├── logo-blue-medium.png
├── logo-blue-small.png
├── logo-white-large.png
├── logo-white-small.png
├── badge-blue-medium.png
├── badge-white-large.png
├── badge-white-medium.png
├── badge-white-small.png
└── logo-white-medium.png
├── lib
├── commands.js
├── messages.js
├── cli.js
├── helpers.js
└── server.js
├── bin
└── pr-police
├── test
├── messages.js
├── cli.js
└── server.js
├── commitlint.config.js
├── CHANGELOG.md
├── package.json
├── LICENSE
├── app.json
└── README.md
/.npmignore:
--------------------------------------------------------------------------------
1 | images
2 |
--------------------------------------------------------------------------------
/Procfile:
--------------------------------------------------------------------------------
1 | worker: node index.js
2 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | require('./lib/server')()
2 |
--------------------------------------------------------------------------------
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | * @Talkdesk/admin-team
2 |
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .env
3 | node_modules
4 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: false
2 | language: node_js
3 | node_js:
4 | - stable
5 | - 6
6 |
--------------------------------------------------------------------------------
/images/avatar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Talkdesk/pr-police/HEAD/images/avatar.png
--------------------------------------------------------------------------------
/lib/commands.js:
--------------------------------------------------------------------------------
1 | module.exports = [
2 | 'what needs review?',
3 | '!review'
4 | ]
5 |
--------------------------------------------------------------------------------
/images/badge-blue-large.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Talkdesk/pr-police/HEAD/images/badge-blue-large.png
--------------------------------------------------------------------------------
/images/badge-blue-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Talkdesk/pr-police/HEAD/images/badge-blue-small.png
--------------------------------------------------------------------------------
/images/logo-blue-large.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Talkdesk/pr-police/HEAD/images/logo-blue-large.png
--------------------------------------------------------------------------------
/images/logo-blue-medium.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Talkdesk/pr-police/HEAD/images/logo-blue-medium.png
--------------------------------------------------------------------------------
/images/logo-blue-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Talkdesk/pr-police/HEAD/images/logo-blue-small.png
--------------------------------------------------------------------------------
/images/logo-white-large.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Talkdesk/pr-police/HEAD/images/logo-white-large.png
--------------------------------------------------------------------------------
/images/logo-white-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Talkdesk/pr-police/HEAD/images/logo-white-small.png
--------------------------------------------------------------------------------
/images/badge-blue-medium.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Talkdesk/pr-police/HEAD/images/badge-blue-medium.png
--------------------------------------------------------------------------------
/images/badge-white-large.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Talkdesk/pr-police/HEAD/images/badge-white-large.png
--------------------------------------------------------------------------------
/images/badge-white-medium.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Talkdesk/pr-police/HEAD/images/badge-white-medium.png
--------------------------------------------------------------------------------
/images/badge-white-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Talkdesk/pr-police/HEAD/images/badge-white-small.png
--------------------------------------------------------------------------------
/images/logo-white-medium.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Talkdesk/pr-police/HEAD/images/logo-white-medium.png
--------------------------------------------------------------------------------
/bin/pr-police:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | const minimist = require('minimist')
4 |
5 | require('../lib/cli')(minimist(process.argv.slice(2)))
6 |
--------------------------------------------------------------------------------
/test/messages.js:
--------------------------------------------------------------------------------
1 | const test = require('tape')
2 | const messages = require('../lib/messages')
3 |
4 | test('it exports an object', (t) => {
5 | t.plan(1)
6 |
7 | t.equals(typeof messages, 'object')
8 | })
9 |
--------------------------------------------------------------------------------
/lib/messages.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | GITHUB_ERROR: ':rotating_light: Could not fetch pull requests...',
3 | NO_PULL_REQUESTS: ':cop: No pull requests are waiting for review! :tada:',
4 | PR_LIST_HEADER: ':cop: The following pull requests are waiting for a review:'
5 | }
6 |
--------------------------------------------------------------------------------
/test/cli.js:
--------------------------------------------------------------------------------
1 | const test = require('tape')
2 | const proxyquire = require('proxyquire')
3 | const sinon = require('sinon')
4 |
5 | test('when passing no arguments calls server function', (t) => {
6 | t.plan(1)
7 |
8 | const serverStub = sinon.stub().callsFake(() => null)
9 | const cli = proxyquire('../lib/cli', { './server': serverStub })
10 |
11 | cli({ _: [] })
12 |
13 | t.ok(serverStub.called)
14 | })
15 |
--------------------------------------------------------------------------------
/lib/cli.js:
--------------------------------------------------------------------------------
1 | const server = require('./server')
2 | const meta = require('../package.json')
3 |
4 | module.exports = function (args) {
5 | if (args.help) {
6 | showUsage()
7 | process.exit(0)
8 | } else if (args.version) {
9 | showVersion()
10 | process.exit(0)
11 | } else if (args._.length > 0) {
12 | showUsage()
13 | process.exit(-1)
14 | } else {
15 | server()
16 | }
17 | }
18 |
19 | function showUsage () {
20 | console.log(meta.name + ' [--version] [--help]\n')
21 | console.log('\t--version show version info')
22 | console.log('\t--help show this usage info')
23 | }
24 |
25 | function showVersion () {
26 | console.log(meta.name + ' version ' + meta.version)
27 | }
28 |
--------------------------------------------------------------------------------
/lib/helpers.js:
--------------------------------------------------------------------------------
1 | const commands = require('./commands')
2 |
3 | const isDirectMessage = function isDirectMessage (msg) {
4 | // slack direct messages channel id start with D
5 | return msg.type === 'message' && msg.channel.charAt(0) === 'D'
6 | }
7 |
8 | const isBotMessage = function isBotMessage (msg) {
9 | return msg.subtype && msg.subtype === 'bot_message'
10 | }
11 |
12 | const isMessage = function isMessage (msg) {
13 | return msg.type === 'message'
14 | }
15 |
16 | // for now all commands execute the same operation
17 | const isBotCommand = function isBotCommand (msg) {
18 | return commands.some((command) => msg.text === command)
19 | }
20 |
21 | module.exports = { isDirectMessage, isBotMessage, isMessage, isBotCommand }
22 |
--------------------------------------------------------------------------------
/commitlint.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | rules: {
3 | 'body-leading-blank': [1, 'always'],
4 | 'footer-leading-blank': [1, 'always'],
5 | 'header-max-length': [2, 'always', 72],
6 | 'scope-case': [2, 'always', 'lower-case'],
7 | 'subject-case': [
8 | 2,
9 | 'never',
10 | ['sentence-case', 'start-case', 'pascal-case', 'upper-case']
11 | ],
12 | 'subject-empty': [2, 'never'],
13 | 'subject-full-stop': [2, 'never', '.'],
14 | 'type-case': [2, 'always', 'lower-case'],
15 | 'type-empty': [2, 'never'],
16 | 'type-enum': [
17 | 2,
18 | 'always',
19 | [
20 | 'build',
21 | 'chore',
22 | 'ci',
23 | 'docs',
24 | 'feat',
25 | 'fix',
26 | 'perf',
27 | 'refactor',
28 | 'revert',
29 | 'style',
30 | 'test'
31 | ]
32 | ]
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/test/server.js:
--------------------------------------------------------------------------------
1 | const test = require('tape')
2 | const proxyquire = require('proxyquire')
3 | const sinon = require('sinon')
4 |
5 | const SlackbotsMock = function SlackbotsMock () {}
6 | SlackbotsMock.prototype.on = sinon.stub()
7 | SlackbotsMock.prototype.on.withArgs('start').yields(true)
8 |
9 | const envMock = {
10 | SLACK_TOKEN: 'foo',
11 | GH_TOKEN: 'foo',
12 | SLACK_CHANNELS: 'foo',
13 | GH_REPOS: 'foo',
14 | CHECK_INTERVAL: '1'
15 | }
16 |
17 | const pullhubMock = sinon.stub().resolves([])
18 | const clock = sinon.useFakeTimers()
19 |
20 | const server = proxyquire('../lib/server', {
21 | slackbots: SlackbotsMock,
22 | pullhub: pullhubMock
23 | })
24 |
25 | test('it throws error on missing required env var', (t) => {
26 | t.plan(1)
27 |
28 | t.throws(server, Error)
29 | })
30 |
31 | test('it calls slackbots onStart handler', (t) => {
32 | t.plan(1)
33 |
34 | process.env = envMock
35 |
36 | server()
37 | clock.tick(envMock.CHECK_INTERVAL)
38 | t.ok(SlackbotsMock.prototype.on.calledWith('start'))
39 | })
40 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 |
2 | # 1.2.0 (2017-05-11)
3 |
4 |
5 | ### Features
6 |
7 | * add cli to server ([703820b](https://github.com/Talkdesk/pr-police/commit/703820b))
8 |
9 |
10 |
11 |
12 | # 1.1.0 (2017-05-03)
13 |
14 |
15 | ### Bug Fixes
16 |
17 | * remove checkForPRs first call ([d9d5fbb](https://github.com/Talkdesk/pr-police/commit/d9d5fbb))
18 | * remove invalid logo key from apps.json ([94717d9](https://github.com/Talkdesk/pr-police/commit/94717d9))
19 |
20 |
21 | ### Features
22 |
23 | * add different text when no PRs need review ([cd0901c](https://github.com/Talkdesk/pr-police/commit/cd0901c))
24 | * add support for bot commands ([4767f3e](https://github.com/Talkdesk/pr-police/commit/4767f3e))
25 | * add support for slack private groups ([3d55c24](https://github.com/Talkdesk/pr-police/commit/3d55c24))
26 | * first version of the slackbot ([ce7b1a9](https://github.com/Talkdesk/pr-police/commit/ce7b1a9))
27 | * only get pull requests on a fixed hour ([914641d](https://github.com/Talkdesk/pr-police/commit/914641d))
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "pr-police",
3 | "version": "1.2.0",
4 | "description": "Slackbot that warns about open pull requests with given labels",
5 | "main": "index.js",
6 | "scripts": {
7 | "pretest": "standard",
8 | "test": "tape test/*.js | faucet",
9 | "start": "node index.js",
10 | "commitmsg": "commitlint -e",
11 | "version": "standard-changelog"
12 | },
13 | "keywords": [
14 | "slackbot",
15 | "pull",
16 | "request",
17 | "github",
18 | "labels"
19 | ],
20 | "bin": {
21 | "pr-police": "./bin/pr-police"
22 | },
23 | "author": "rogeriopvl",
24 | "license": "MIT",
25 | "dependencies": {
26 | "minimist": "^1.2.0",
27 | "moment": "^2.18.1",
28 | "pullhub": "^1.1.0",
29 | "slackbots": "^1.2.0",
30 | "ws": ">=3.3.1"
31 | },
32 | "devDependencies": {
33 | "commitlint": "^7.6.1",
34 | "faucet": "^0.0.1",
35 | "husky": "^1.3.1",
36 | "proxyquire": "^2.1.0",
37 | "sinon": "^7.3.2",
38 | "standard": "^12.0.1",
39 | "standard-changelog": "^2.0.11",
40 | "tape": "^4.11.0"
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2017 Talkdesk Inc.
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | "Software"), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so, subject to
9 | the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be
12 | included in all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "pr-police",
3 | "description": "A slack bot that reminds you of open PRs for review in your chosen repos",
4 | "repository": "https://github.com/Talkdesk/pr-police",
5 | "keywords": ["pull", "request", "police", "github", "node", "slackbot", "slack"],
6 | "logo": "https://raw.githubusercontent.com/Talkdesk/pr-police/master/images/badge-white-small.png",
7 | "formation": {
8 | "worker": {
9 | "quantity": 1,
10 | "size": "free"
11 | }
12 | },
13 | "env": {
14 | "DAYS_TO_RUN": {
15 | "description": "Which days of the week to run on (locale-specific), comma-separated",
16 | "value": "Monday,Tuesday,Wednesday,Thursday,Friday"
17 | },
18 | "DEBUG": {
19 | "description": "Debug flag to enable more verbose logging",
20 | "value": false
21 | },
22 | "GH_TOKEN": {
23 | "description": "Github account token to access needed repositories",
24 | "value": "secret"
25 | },
26 | "SLACK_TOKEN": {
27 | "description": "Slack token for bot",
28 | "value": "secret"
29 | },
30 | "GH_REPOS": {
31 | "description": "Repositories to watch in user/repo format, comma separated",
32 | "value": "johndoe/somerepo,johndoe/anotherrepo"
33 | },
34 | "GH_EXCLUDE_LABELS": {
35 | "description": "Repository labels that will exclude pull requests, comma-separated. Supercedes GH_LABELS",
36 | "value": "",
37 | "required": false
38 | },
39 | "GH_LABELS": {
40 | "description": "Repository labels to filter pull requests, comma separated",
41 | "value": "",
42 | "required": false
43 | },
44 | "SLACK_CHANNELS": {
45 | "description": "Slack channels to post the announcements, comma separated. Required if SLACK_GROUPS is empty.",
46 | "value": "",
47 | "required": false
48 | },
49 | "SLACK_GROUPS": {
50 | "description": "Slack private groups to post the announcements, comma separated. Required if SLACK_CHANNEL is empty.",
51 | "value": "",
52 | "required": false
53 | },
54 |
55 | "SLACK_BOT_NAME": {
56 | "description": "The name of the bot on your slack organization",
57 | "value": "",
58 | "required": false
59 | },
60 | "SLACK_BOT_ICON": {
61 | "description": "URL of the bot icon to show when posting messages",
62 | "value": "",
63 | "required": false
64 | },
65 | "TIMES_TO_RUN": {
66 | "description": "What times of day to run (24-hour format), comma-separated",
67 | "value": "0900",
68 | "required": false
69 | },
70 | "TZ": {
71 | "description": "The timezone the server should use. Heroku default is UTC. Uses tz database timezone format. Example: 'America/Los_Angeles'",
72 | "value": "",
73 | "required": false
74 | }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/lib/server.js:
--------------------------------------------------------------------------------
1 | const Slackbot = require('slackbots')
2 | const pullhub = require('pullhub')
3 | const moment = require('moment')
4 | const messages = require('./messages')
5 | const {
6 | isDirectMessage,
7 | isBotMessage,
8 | isMessage,
9 | isBotCommand
10 | } = require('./helpers')
11 |
12 | module.exports = function server () {
13 | const env = process.env
14 | const requiredEnvs = ['SLACK_TOKEN', 'GH_TOKEN', 'GH_REPOS']
15 |
16 | if (!requiredEnvs.every((k) => !!env[k])) {
17 | throw (
18 | new Error('Missing one of this required ENV vars: ' + requiredEnvs.join(','))
19 | )
20 | }
21 |
22 | const rawDaysToRun = (env.DAYS_TO_RUN || 'Monday,Tuesday,Wednesday,Thursday,Friday').split(',')
23 | const daysToRun = new Set(rawDaysToRun.map((day) => day.toLowerCase()))
24 |
25 | const channels = env.SLACK_CHANNELS ? env.SLACK_CHANNELS.split(',') : []
26 | const timesToRun = new Set(env.TIMES_TO_RUN ? env.TIMES_TO_RUN.split(',').map((t) => parseInt(t)) : [900])
27 | const groups = env.SLACK_GROUPS ? env.SLACK_GROUPS.split(',') : []
28 | const repos = env.GH_REPOS ? env.GH_REPOS.split(',') : []
29 | const excludeLabels = new Set(env.GH_EXCLUDE_LABELS ? env.GH_EXCLUDE_LABELS.split(',') : [])
30 | const labels = env.GH_LABELS
31 | const checkInterval = 60000 // Run every minute (60000)
32 | const botParams = { icon_url: env.SLACK_BOT_ICON }
33 |
34 | const bot = new Slackbot({
35 | token: env.SLACK_TOKEN,
36 | name: env.SLACK_BOT_NAME || 'Pr. Police'
37 | })
38 |
39 | bot.on('start', () => {
40 | setInterval(() => {
41 | const now = moment()
42 | const runToday = daysToRun.has(now.format('dddd').toLowerCase())
43 | const runThisMinute = timesToRun.has(parseInt(now.format('kmm')))
44 | const readableTimestamp = now.format('dddd YYYY-DD-MM h:mm a')
45 |
46 | if (runToday && runThisMinute) {
47 | console.log(`Running at: ${readableTimestamp}`)
48 |
49 | getPullRequests()
50 | .then(buildMessage)
51 | .then(notifyAllChannels)
52 | } else {
53 | console.log(`Nothing to run at: ${readableTimestamp}`)
54 | }
55 | }, checkInterval)
56 | })
57 |
58 | bot.on('message', (data) => {
59 | if ((isMessage(data) && isBotCommand(data)) ||
60 | (isDirectMessage(data) && !isBotMessage(data))) {
61 | getPullRequests()
62 | .then(buildMessage)
63 | .then((message) => {
64 | bot.postMessage(data.channel, message, botParams)
65 | })
66 | }
67 | })
68 |
69 | bot.on('error', (err) => {
70 | console.error(err)
71 | })
72 |
73 | function getPullRequests () {
74 | console.log('Checking for pull requests...')
75 |
76 | return pullhub(repos, labels).catch((err) => { console.error(err) })
77 | }
78 |
79 | function buildMessage (data) {
80 | if (!data) {
81 | return Promise.resolve(messages.GITHUB_ERROR)
82 | }
83 |
84 | const headers = [ messages.PR_LIST_HEADER, '\n' ]
85 | const excludeLabelsConfigured = !!excludeLabels.length
86 |
87 | let includedPrs = data
88 | if (excludeLabelsConfigured) {
89 | includedPrs = data.filter((pr) => {
90 | const hasExcludedLabel = pr.labels.reduce((acc, label) => acc || excludeLabels.has(label), false)
91 | return !hasExcludedLabel
92 | })
93 | }
94 |
95 | const prMessages = includedPrs.map((pr) => `:star: ${pr.title} | ${pr.html_url}`)
96 |
97 | if (prMessages.length < 1) {
98 | return Promise.resolve(messages.NO_PULL_REQUESTS)
99 | } else {
100 | return Promise.resolve(headers.concat(prMessages).join('\n'))
101 | }
102 | }
103 |
104 | function notifyAllChannels (message) {
105 | channels.map((channel) => {
106 | bot.postMessageToChannel(channel, message, botParams)
107 | })
108 |
109 | groups.map((group) => {
110 | bot.postMessageToGroup(group, message, botParams)
111 | })
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # :warning: Pr. Police is deprecated and no longer supported :warning:
2 |
3 | GitHub has incorporated a similar feature and now enables [you](https://docs.github.com/en/github/setting-up-and-managing-your-github-user-account/managing-your-scheduled-reminders), your [team](https://docs.github.com/en/github/setting-up-and-managing-organizations-and-teams/managing-scheduled-reminders-for-your-team) or [organization](https://docs.github.com/en/github/setting-up-and-managing-your-github-user-account/managing-your-scheduled-reminders) to be reminded when pull requests are waiting for review.
4 |
5 | --------------------
6 |
7 | # Pr. Police
8 |
9 | 
10 |
11 | ## About
12 |
13 | Pr. Police is a slackbot that sends to configured slack channels a listing of open pull requests that are waiting for a review. It supports watching multiple repositories, and filtering the pull requests by label.
14 |
15 | This project is part of the Talkdesk Hackathon April 2017.
16 |
17 | ## Running the bot
18 |
19 | ### The quick and easy way
20 |
21 | The easiest way to get an instance of Pr. Police up and running is to deploy it to Heroku by clicking on the button below.
22 |
23 | [](https://heroku.com/deploy)
24 |
25 | You'll still need to fill in all the environment variables. For more info on this, head down to the Configuration section.
26 |
27 |
28 | ### Via NPM
29 |
30 | npm install pr-police
31 |
32 | ### Manually
33 |
34 | Git clone this repository then:
35 |
36 | npm install
37 |
38 | #### Run
39 |
40 | npm start
41 |
42 | This will start the server locally until `Ctrl-C` is pressed.
43 |
44 | **Note:** You will need to pass all the required env vars.
45 |
46 | ## Configuration
47 |
48 | Pr. Police has the following environment variables available:
49 |
50 | ##### `DEBUG`
51 | Debug flag used to enable more verbose logging. Default: `false`
52 |
53 | ##### `DAYS_TO_RUN`
54 | Which days of the week to run on. Default: `Monday,Tuesday,Wednesday,Thursday,Friday`
55 |
56 | ##### `GH_TOKEN`
57 | The github account token to access the repos. Required.
58 |
59 | ##### `SLACK_TOKEN`
60 | The slack token for the bot to access your slack team. Required.
61 |
62 | ##### `GH_REPOS`
63 | The list of repositories to watch. The format is `user/repo` and comma separated. Required.
64 |
65 | Example: `rogeriopvl/gulp-ejs,rogeriopvl/pullhub,talkdesk/pr-police`
66 |
67 | ##### `GH_EXCLUDE_LABELS`
68 | The list of labels that will cause a pull-request to be excluded. So imagine, your team uses the label `in-progress` for pull-requests not yet requiring review, you'll have to fill in: `in-progress`. Supercedes `GH_LABELS`. Multiple labels are comma separated.
69 |
70 | Example: `do-not-merge,in-progress,needs-work`
71 |
72 | ##### `GH_LABELS`
73 | The list of labels to filter pull-requests. So imagine, your team uses the label `needs review` for pull-requests waiting for review, you'll have to fill in: `needs review`. Multiple labels are comma separated. Optional.
74 |
75 | NOTE: Omitting both `GH_EXCLUDE_LABELS` and `GH_LABELS` will result in _all_ open pull-requests being reported for the specified `GH_REPOS`.
76 |
77 | ##### `SLACK_CHANNELS`
78 | The list of channel names on your team where Pr. Police will post the announcements. Multiple channels are comma separated. Either `SLACK_CHANNELS` or `SLACK_GROUPS` is required.
79 |
80 | Example: `notifications`
81 |
82 | ##### `SLACK_GROUPS`
83 | The list of private group names on your team where Pr. Police will post the announcements. Multiple channels are comma separated. Either `SLACK_CHANNELS` or `SLACK_GROUPS` is required.
84 |
85 | ##### `SLACK_BOT_NAME`
86 | The name of your Pr. Police bot on slack. Optional.
87 |
88 | ##### `SLACK_BOT_ICON`
89 | URL of the icon for the slack bot when sending messages.
90 |
91 | ##### `TIMES_TO_RUN`
92 | What times of day to run (24-hour format, leading zeroes are not necessary). Multiple times are comma-separated. Default: `0900`.
93 |
94 | ##### `TZ`
95 | The timezone the server should use. Heroku default is UTC. Uses tz database timezone format. Example: `America/Los_Angeles`.
96 |
97 | ## Heroku configuration
98 |
99 | If heroku attempts to start a web process instead of a worker, you may need to run: `heroku ps:scale web=0 worker=1 -a {HEROKU_APP_NAME}`
100 |
101 | ## Credits
102 |
103 | Pr. Police was developed by [Rogério Vicente](https://github.com/rogeriopvl) during one of Talkdesk's internal hackathons.
104 |
105 | Artwork created by [Micaela Neto](https://cargocollective.com/micaelaneto)
106 |
--------------------------------------------------------------------------------