diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..d658236 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,3 @@ +{ + "extends": "standard" +} \ No newline at end of file diff --git a/lib/config.js b/lib/config.js index 69f1f23..7a9eb67 100644 --- a/lib/config.js +++ b/lib/config.js @@ -11,7 +11,7 @@ module.exports = (robot, fileName) => { // Get document, or throw exception on error try { const yaml = require('js-yaml') - const fs = require('fs') + const fs = require('fs') return yaml.safeLoad(fs.readFileSync(fileName, 'utf8')) } catch (e) { diff --git a/lib/slack.js b/lib/slack.js index 5d3ad37..dc8642d 100644 --- a/lib/slack.js +++ b/lib/slack.js @@ -12,13 +12,15 @@ module.exports.sendMessage = async (robot, slackClient, room, message) => { if (slackClient != null) { const channel = slackClient.dataStore.getChannelByName(room) try { - if (!process.env.DRY_RUN) { + if (process.env.DRY_RUN) { + robot.log.debug(`Would have sent '${message}' to '${room}' channel`) + } else { await slackClient.sendMessage(message, channel.id) } - } catch(err) { - robot.log.error(`Failed to send Slack message to ${room} channel`) + } catch (err) { + robot.log.error(`Failed to send Slack message to '${room}' channel`) } } else { - robot.log.debug("Slack client not available") + robot.log.debug('Slack client not available') } } diff --git a/package-lock.json b/package-lock.json index addddfd..61a0078 100644 --- a/package-lock.json +++ b/package-lock.json @@ -235,8 +235,7 @@ "acorn": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.3.0.tgz", - "integrity": "sha512-Yej+zOJ1Dm/IMZzzj78OntP/r3zHEaKcyNoU2lAaxPtrseM6rF0xwqoz5Q5ysAiED9hTjI2hgtvLXitlCN1/Ug==", - "dev": true + "integrity": "sha512-Yej+zOJ1Dm/IMZzzj78OntP/r3zHEaKcyNoU2lAaxPtrseM6rF0xwqoz5Q5ysAiED9hTjI2hgtvLXitlCN1/Ug==" }, "acorn-globals": { "version": "4.1.0", @@ -251,7 +250,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", - "dev": true, "requires": { "acorn": "3.3.0" }, @@ -259,8 +257,7 @@ "acorn": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", - "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", - "dev": true + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=" } } }, @@ -284,10 +281,9 @@ } }, "ajv-keywords": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", - "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=", - "dev": true + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", + "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=" }, "align-text": { "version": "0.1.4", @@ -384,7 +380,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, "requires": { "array-uniq": "1.0.3" } @@ -392,8 +387,7 @@ "array-uniq": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" }, "array-unique": { "version": "0.2.1", @@ -869,7 +863,6 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", - "dev": true, "requires": { "callsites": "0.2.0" }, @@ -877,8 +870,7 @@ "callsites": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", - "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", - "dev": true + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=" } } }, @@ -918,6 +910,11 @@ "supports-color": "4.5.0" } }, + "chardet": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", + "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=" + }, "ci-info": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.1.2.tgz", @@ -926,23 +923,20 @@ "circular-json": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", - "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", - "dev": true + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==" }, "cli-cursor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", - "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", - "dev": true, + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", "requires": { - "restore-cursor": "1.0.1" + "restore-cursor": "2.0.0" } }, "cli-width": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", - "dev": true + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=" }, "cliui": { "version": "2.1.0", @@ -1019,7 +1013,6 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", - "dev": true, "requires": { "inherits": "2.0.3", "readable-stream": "2.3.3", @@ -1030,7 +1023,6 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", - "dev": true, "requires": { "core-util-is": "1.0.2", "inherits": "2.0.3", @@ -1045,7 +1037,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, "requires": { "safe-buffer": "5.1.1" } @@ -1272,7 +1263,6 @@ "version": "2.2.2", "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", - "dev": true, "requires": { "globby": "5.0.0", "is-path-cwd": "1.0.0", @@ -1286,8 +1276,7 @@ "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" } } }, @@ -1329,7 +1318,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, "requires": { "esutils": "2.0.2" } @@ -1561,72 +1549,61 @@ } }, "eslint": { - "version": "3.19.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-3.19.0.tgz", - "integrity": "sha1-yPxiAcf0DdCJQbh8CFdnOGpnmsw=", - "dev": true, + "version": "4.16.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.16.0.tgz", + "integrity": "sha512-YVXV4bDhNoHHcv0qzU4Meof7/P26B4EuaktMi5L1Tnt52Aov85KmYA8c5D+xyZr/BkhvwUqr011jDSD/QTULxg==", "requires": { + "ajv": "5.5.2", "babel-code-frame": "6.26.0", - "chalk": "1.1.3", + "chalk": "2.3.0", "concat-stream": "1.6.0", - "debug": "2.6.9", + "cross-spawn": "5.1.0", + "debug": "3.1.0", "doctrine": "2.1.0", - "escope": "3.6.0", + "eslint-scope": "3.7.1", + "eslint-visitor-keys": "1.0.0", "espree": "3.5.2", "esquery": "1.0.0", - "estraverse": "4.2.0", "esutils": "2.0.2", "file-entry-cache": "2.0.0", + "functional-red-black-tree": "1.0.1", "glob": "7.1.2", - "globals": "9.18.0", + "globals": "11.2.0", "ignore": "3.3.7", "imurmurhash": "0.1.4", - "inquirer": "0.12.0", - "is-my-json-valid": "2.17.1", - "is-resolvable": "1.0.1", + "inquirer": "3.3.0", + "is-resolvable": "1.1.0", "js-yaml": "3.10.0", - "json-stable-stringify": "1.0.1", + "json-stable-stringify-without-jsonify": "1.0.1", "levn": "0.3.0", "lodash": "4.17.4", + "minimatch": "3.0.4", "mkdirp": "0.5.1", "natural-compare": "1.4.0", "optionator": "0.8.2", "path-is-inside": "1.0.2", - "pluralize": "1.2.1", - "progress": "1.1.8", + "pluralize": "7.0.0", + "progress": "2.0.0", "require-uncached": "1.0.3", - "shelljs": "0.7.8", - "strip-bom": "3.0.0", + "semver": "5.5.0", + "strip-ansi": "4.0.0", "strip-json-comments": "2.0.1", - "table": "3.8.3", - "text-table": "0.2.0", - "user-home": "2.0.0" + "table": "4.0.2", + "text-table": "0.2.0" }, "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" + "ms": "2.0.0" } }, "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, "requires": { "fs.realpath": "1.0.0", "inflight": "1.0.6", @@ -1636,27 +1613,17 @@ "path-is-absolute": "1.0.1" } }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "2.1.1" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true + "globals": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.2.0.tgz", + "integrity": "sha512-RDC7Tj17I/56wpVvCVLSXtnn2Fo6CQZ9vaj+ARn+qlzm/ozbKQZe+j9fvHZCbSq+4JSGjTpKEt7p/AA1IKXRFA==" } } }, "eslint-config-standard": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-10.2.1.tgz", - "integrity": "sha1-wGHk0GbzedwXzVYsZOgZtN1FRZE=", + "version": "11.0.0-beta.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-11.0.0-beta.0.tgz", + "integrity": "sha512-f+vs5HAHQo7NRZ3hVe+UVdT5DbebMNaFTWFp95orJ0LUdYPoWdM8xw/bMeO/IZMvHOPmIteGKGc2QOhSXd5nRg==", "dev": true }, "eslint-config-standard-jsx": { @@ -1666,13 +1633,12 @@ "dev": true }, "eslint-import-resolver-node": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.2.3.tgz", - "integrity": "sha1-Wt2BBujJKNssuiMrzZ76hG49oWw=", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", + "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", "dev": true, "requires": { "debug": "2.6.9", - "object-assign": "4.1.1", "resolve": "1.5.0" } }, @@ -1687,21 +1653,21 @@ } }, "eslint-plugin-import": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.2.0.tgz", - "integrity": "sha1-crowb60wXWfEgWNIpGmaQimsi04=", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.8.0.tgz", + "integrity": "sha512-Rf7dfKJxZ16QuTgVv1OYNxkZcsu/hULFnC+e+w0Gzi6jMC3guQoWQgxYxc54IDRinlb6/0v5z/PxxIKmVctN+g==", "dev": true, "requires": { "builtin-modules": "1.1.1", "contains-path": "0.1.0", "debug": "2.6.9", "doctrine": "1.5.0", - "eslint-import-resolver-node": "0.2.3", + "eslint-import-resolver-node": "0.3.2", "eslint-module-utils": "2.1.1", "has": "1.0.1", "lodash.cond": "4.5.2", "minimatch": "3.0.4", - "pkg-up": "1.0.0" + "read-pkg-up": "2.0.0" }, "dependencies": { "doctrine": { @@ -1713,18 +1679,74 @@ "esutils": "2.0.2", "isarray": "1.0.0" } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "strip-bom": "3.0.0" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "1.3.1" + } + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "2.3.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "2.0.0", + "normalize-package-data": "2.4.0", + "path-type": "2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "2.1.0", + "read-pkg": "2.0.0" + } } } }, "eslint-plugin-node": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-4.2.3.tgz", - "integrity": "sha512-vIUQPuwbVYdz/CYnlTLsJrRy7iXHQjdEe5wz0XhhdTym3IInM/zZLlPf9nZ2mThsH0QcsieCOWs2vOeCy/22LQ==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-5.2.1.tgz", + "integrity": "sha512-xhPXrh0Vl/b7870uEbaumb2Q+LxaEcOQ3kS1jtIXanBAwpMre1l5q/l2l/hESYJGEFKuI78bp6Uw50hlpr7B+g==", "dev": true, "requires": { "ignore": "3.3.7", "minimatch": "3.0.4", - "object-assign": "4.1.1", "resolve": "1.5.0", "semver": "5.3.0" }, @@ -1738,9 +1760,9 @@ } }, "eslint-plugin-promise": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.5.0.tgz", - "integrity": "sha1-ePu2/+BHIBYnVp6FpsU3OvKmj8o=", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.6.0.tgz", + "integrity": "sha512-YQzM6TLTlApAr7Li8vWKR+K3WghjwKcYzY0d2roWap4SLK+kzuagJX/leTetIDWsFcTFnKNJXWupDCD6aZkP2Q==", "dev": true }, "eslint-plugin-react": { @@ -1774,22 +1796,27 @@ "integrity": "sha1-NNDJFbRe3G8BA5PH7vOCOwhWXPI=", "dev": true }, + "eslint-scope": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", + "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", + "requires": { + "esrecurse": "4.2.0", + "estraverse": "4.2.0" + } + }, + "eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==" + }, "espree": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.2.tgz", "integrity": "sha512-sadKeYwaR/aJ3stC2CdvgXu1T16TdYN+qwCpcWbMnGJ8s0zNWemzrvb2GbD4OhmJ/fwpJjudThAlLobGbWZbCQ==", - "dev": true, "requires": { "acorn": "5.3.0", "acorn-jsx": "3.0.1" - }, - "dependencies": { - "acorn": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.3.0.tgz", - "integrity": "sha512-Yej+zOJ1Dm/IMZzzj78OntP/r3zHEaKcyNoU2lAaxPtrseM6rF0xwqoz5Q5ysAiED9hTjI2hgtvLXitlCN1/Ug==", - "dev": true - } } }, "esprima": { @@ -1801,7 +1828,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz", "integrity": "sha1-z7qLV9f7qT8XKYqKAGoEzaE9gPo=", - "dev": true, "requires": { "estraverse": "4.2.0" } @@ -1810,7 +1836,6 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", - "dev": true, "requires": { "estraverse": "4.2.0", "object-assign": "4.1.1" @@ -1969,6 +1994,16 @@ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" }, + "external-editor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.1.0.tgz", + "integrity": "sha512-E44iT5QVOUJBKij4IIV3uvxuNlbKS38Tw1HiupxEIHPv9qtC2PrDYohbXV5U+1jnfIXttny8gUhj+oZvflFlzA==", + "requires": { + "chardet": "0.4.2", + "iconv-lite": "0.4.19", + "tmp": "0.0.33" + } + }, "extglob": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", @@ -2011,20 +2046,17 @@ } }, "figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "dev": true, + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", "requires": { - "escape-string-regexp": "1.0.5", - "object-assign": "4.1.1" + "escape-string-regexp": "1.0.5" } }, "file-entry-cache": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", - "dev": true, "requires": { "flat-cache": "1.3.0", "object-assign": "4.1.1" @@ -2103,7 +2135,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", - "dev": true, "requires": { "circular-json": "0.3.3", "del": "2.2.2", @@ -2984,6 +3015,11 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" + }, "generate-function": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", @@ -3088,7 +3124,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", - "dev": true, "requires": { "array-union": "1.0.2", "arrify": "1.0.1", @@ -3102,7 +3137,6 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, "requires": { "fs.realpath": "1.0.0", "inflight": "1.0.6", @@ -3115,8 +3149,7 @@ "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" } } }, @@ -3290,8 +3323,7 @@ "ignore": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz", - "integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA==", - "dev": true + "integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA==" }, "import-local": { "version": "1.0.0", @@ -3334,77 +3366,24 @@ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, "inquirer": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz", - "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", - "dev": true, + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", + "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", "requires": { - "ansi-escapes": "1.4.0", - "ansi-regex": "2.1.1", - "chalk": "1.1.3", - "cli-cursor": "1.0.2", + "ansi-escapes": "3.0.0", + "chalk": "2.3.0", + "cli-cursor": "2.1.0", "cli-width": "2.2.0", - "figures": "1.7.0", + "external-editor": "2.1.0", + "figures": "2.0.0", "lodash": "4.17.4", - "readline2": "1.0.1", - "run-async": "0.1.0", - "rx-lite": "3.1.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", + "mute-stream": "0.0.7", + "run-async": "2.3.0", + "rx-lite": "4.0.8", + "rx-lite-aggregates": "4.0.8", + "string-width": "2.1.1", + "strip-ansi": "4.0.0", "through": "2.3.8" - }, - "dependencies": { - "ansi-escapes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", - "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "2.1.1" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } } }, "interpret": { @@ -3551,14 +3530,12 @@ "is-path-cwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", - "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", - "dev": true + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=" }, "is-path-in-cwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", - "dev": true, "requires": { "is-path-inside": "1.0.1" } @@ -3567,7 +3544,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", - "dev": true, "requires": { "path-is-inside": "1.0.2" } @@ -3582,6 +3558,11 @@ "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=" }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" + }, "is-property": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", @@ -3597,10 +3578,9 @@ } }, "is-resolvable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.1.tgz", - "integrity": "sha512-y5CXYbzvB3jTnWAZH1Nl7ykUWb6T3BcTs56HUruwBf8MhF56n1HWqhDWnVFo8GHrUPDgvUUNVhrc2U8W7iqz5g==", - "dev": true + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==" }, "is-stream": { "version": "1.1.0", @@ -4308,6 +4288,11 @@ "jsonify": "0.0.0" } }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=" + }, "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", @@ -4670,10 +4655,9 @@ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, "mute-stream": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", - "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=", - "dev": true + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" }, "mv": { "version": "2.1.1", @@ -4843,10 +4827,12 @@ } }, "onetime": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", - "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", - "dev": true + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "requires": { + "mimic-fn": "1.1.0" + } }, "optimist": { "version": "0.6.1", @@ -4986,8 +4972,7 @@ "path-is-inside": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=" }, "path-key": { "version": "2.0.1", @@ -5138,10 +5123,9 @@ "integrity": "sha1-tUGO8EOd5UJfxJlQQtztFPsqhP8=" }, "pluralize": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz", - "integrity": "sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU=", - "dev": true + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", + "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==" }, "pn": { "version": "1.1.0", @@ -6466,10 +6450,9 @@ "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" }, "progress": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", - "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", - "dev": true + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", + "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=" }, "promise-events": { "version": "0.1.4", @@ -6671,6 +6654,14 @@ "code-point-at": "1.1.0", "is-fullwidth-code-point": "1.0.0", "mute-stream": "0.0.5" + }, + "dependencies": { + "mute-stream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", + "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=", + "dev": true + } } }, "realpath-native": { @@ -6797,7 +6788,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", - "dev": true, "requires": { "caller-path": "0.1.0", "resolve-from": "1.0.1" @@ -6837,17 +6827,15 @@ "resolve-from": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", - "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", - "dev": true + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=" }, "restore-cursor": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", - "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", - "dev": true, + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", "requires": { - "exit-hook": "1.1.1", - "onetime": "1.1.0" + "onetime": "2.0.1", + "signal-exit": "3.0.2" } }, "retry": { @@ -6873,12 +6861,11 @@ } }, "run-async": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", - "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", - "dev": true, + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", "requires": { - "once": "1.4.0" + "is-promise": "2.1.0" } }, "run-parallel": { @@ -6888,10 +6875,17 @@ "dev": true }, "rx-lite": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", - "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=", - "dev": true + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", + "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=" + }, + "rx-lite-aggregates": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", + "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", + "requires": { + "rx-lite": "4.0.8" + } }, "safe-buffer": { "version": "5.1.1", @@ -7033,10 +7027,19 @@ "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=" }, "slice-ansi": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", - "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", - "dev": true + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", + "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "requires": { + "is-fullwidth-code-point": "2.0.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + } + } }, "smee-client": { "version": "1.0.1", @@ -7147,6 +7150,349 @@ "eslint-plugin-react": "6.10.3", "eslint-plugin-standard": "3.0.1", "standard-engine": "7.0.0" + }, + "dependencies": { + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "dev": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "ajv-keywords": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", + "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=", + "dev": true + }, + "ansi-escapes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", + "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "dev": true, + "requires": { + "restore-cursor": "1.0.1" + } + }, + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, + "requires": { + "esutils": "2.0.2", + "isarray": "1.0.0" + } + }, + "eslint": { + "version": "3.19.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-3.19.0.tgz", + "integrity": "sha1-yPxiAcf0DdCJQbh8CFdnOGpnmsw=", + "dev": true, + "requires": { + "babel-code-frame": "6.26.0", + "chalk": "1.1.3", + "concat-stream": "1.6.0", + "debug": "2.6.9", + "doctrine": "2.1.0", + "escope": "3.6.0", + "espree": "3.5.2", + "esquery": "1.0.0", + "estraverse": "4.2.0", + "esutils": "2.0.2", + "file-entry-cache": "2.0.0", + "glob": "7.1.2", + "globals": "9.18.0", + "ignore": "3.3.7", + "imurmurhash": "0.1.4", + "inquirer": "0.12.0", + "is-my-json-valid": "2.17.1", + "is-resolvable": "1.1.0", + "js-yaml": "3.10.0", + "json-stable-stringify": "1.0.1", + "levn": "0.3.0", + "lodash": "4.17.4", + "mkdirp": "0.5.1", + "natural-compare": "1.4.0", + "optionator": "0.8.2", + "path-is-inside": "1.0.2", + "pluralize": "1.2.1", + "progress": "1.1.8", + "require-uncached": "1.0.3", + "shelljs": "0.7.8", + "strip-bom": "3.0.0", + "strip-json-comments": "2.0.1", + "table": "3.8.3", + "text-table": "0.2.0", + "user-home": "2.0.0" + }, + "dependencies": { + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "2.0.2" + } + } + } + }, + "eslint-config-standard": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-10.2.1.tgz", + "integrity": "sha1-wGHk0GbzedwXzVYsZOgZtN1FRZE=", + "dev": true + }, + "eslint-import-resolver-node": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.2.3.tgz", + "integrity": "sha1-Wt2BBujJKNssuiMrzZ76hG49oWw=", + "dev": true, + "requires": { + "debug": "2.6.9", + "object-assign": "4.1.1", + "resolve": "1.5.0" + } + }, + "eslint-plugin-import": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.2.0.tgz", + "integrity": "sha1-crowb60wXWfEgWNIpGmaQimsi04=", + "dev": true, + "requires": { + "builtin-modules": "1.1.1", + "contains-path": "0.1.0", + "debug": "2.6.9", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "0.2.3", + "eslint-module-utils": "2.1.1", + "has": "1.0.1", + "lodash.cond": "4.5.2", + "minimatch": "3.0.4", + "pkg-up": "1.0.0" + } + }, + "eslint-plugin-node": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-4.2.3.tgz", + "integrity": "sha512-vIUQPuwbVYdz/CYnlTLsJrRy7iXHQjdEe5wz0XhhdTym3IInM/zZLlPf9nZ2mThsH0QcsieCOWs2vOeCy/22LQ==", + "dev": true, + "requires": { + "ignore": "3.3.7", + "minimatch": "3.0.4", + "object-assign": "4.1.1", + "resolve": "1.5.0", + "semver": "5.3.0" + } + }, + "eslint-plugin-promise": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.5.0.tgz", + "integrity": "sha1-ePu2/+BHIBYnVp6FpsU3OvKmj8o=", + "dev": true + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1" + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "inquirer": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz", + "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", + "dev": true, + "requires": { + "ansi-escapes": "1.4.0", + "ansi-regex": "2.1.1", + "chalk": "1.1.3", + "cli-cursor": "1.0.2", + "cli-width": "2.2.0", + "figures": "1.7.0", + "lodash": "4.17.4", + "readline2": "1.0.1", + "run-async": "0.1.0", + "rx-lite": "3.1.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "through": "2.3.8" + } + }, + "onetime": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", + "dev": true + }, + "pluralize": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz", + "integrity": "sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU=", + "dev": true + }, + "progress": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", + "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", + "dev": true + }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "dev": true, + "requires": { + "exit-hook": "1.1.1", + "onetime": "1.1.0" + } + }, + "run-async": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", + "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", + "dev": true, + "requires": { + "once": "1.4.0" + } + }, + "rx-lite": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", + "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=", + "dev": true + }, + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", + "dev": true + }, + "slice-ansi": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", + "dev": true + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "table": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/table/-/table-3.8.3.tgz", + "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", + "dev": true, + "requires": { + "ajv": "4.11.8", + "ajv-keywords": "1.5.1", + "chalk": "1.1.3", + "lodash": "4.17.4", + "slice-ansi": "0.0.4", + "string-width": "2.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + } + } + } } }, "standard-engine": { @@ -7248,8 +7594,7 @@ "strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" }, "superagent": { "version": "3.8.2", @@ -7294,63 +7639,16 @@ "integrity": "sha1-rifbOPZgp64uHDt9G8KQgZuFGeY=" }, "table": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/table/-/table-3.8.3.tgz", - "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", - "dev": true, + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", + "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", "requires": { - "ajv": "4.11.8", - "ajv-keywords": "1.5.1", - "chalk": "1.1.3", + "ajv": "5.5.2", + "ajv-keywords": "2.1.1", + "chalk": "2.3.0", "lodash": "4.17.4", - "slice-ansi": "0.0.4", + "slice-ansi": "1.0.0", "string-width": "2.1.1" - }, - "dependencies": { - "ajv": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", - "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", - "dev": true, - "requires": { - "co": "4.6.0", - "json-stable-stringify": "1.0.1" - } - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "2.1.1" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } } }, "test-exclude": { @@ -7368,8 +7666,7 @@ "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" }, "throat": { "version": "4.1.0", @@ -7379,14 +7676,21 @@ "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" }, "timed-out": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=" }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "requires": { + "os-tmpdir": "1.0.2" + } + }, "tmpl": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", @@ -7461,8 +7765,7 @@ "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" }, "uglify-js": { "version": "2.8.29", @@ -7741,7 +8044,6 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", - "dev": true, "requires": { "mkdirp": "0.5.1" } diff --git a/package.json b/package.json index aa5f328..23fbf0a 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "test": "jest && standard" }, "dependencies": { + "eslint": "^4.16.0", "probot": "^5.0.0", "probot-config": "^0.1.0", "probot-gpg-status": "^0.5.4", @@ -19,6 +20,11 @@ "wip-bot": "github:gr2m/wip-bot" }, "devDependencies": { + "eslint-config-standard": "^11.0.0-beta.0", + "eslint-plugin-import": "^2.8.0", + "eslint-plugin-node": "^5.2.1", + "eslint-plugin-promise": "^3.6.0", + "eslint-plugin-standard": "^3.0.1", "jest": "^22.1.4", "smee-client": "^1.0.1", "standard": "^10.0.3" diff --git a/scripts/assign-approved-pr-to-test.js b/scripts/assign-approved-pr-to-test.js index 700144e..a076db7 100644 --- a/scripts/assign-approved-pr-to-test.js +++ b/scripts/assign-approved-pr-to-test.js @@ -1,6 +1,6 @@ // Description: // Script that listens to GitHub pull reviews -// and assigns the PR to TO TEST column on the "Pipeline for QA" project +// and assigns the PR to TO TEST column on the 'Pipeline for QA' project // // Dependencies: // github: "^13.1.0" @@ -11,41 +11,41 @@ // Author: // PombeirP -const getConfig = require('probot-config') +// const getConfig = require('probot-config') const defaultConfig = require('../lib/config') const createScheduler = require('probot-scheduler') const Slack = require('probot-slack-status') let slackClient = null -module.exports = function(robot) { +module.exports = robot => { // robot.on('slack.connected', ({ slack }) => { Slack(robot, (slack) => { - robot.log.trace("Connected, assigned slackClient") + robot.log.trace('Connected, assigned slackClient') slackClient = slack }) - + createScheduler(robot, { interval: 10 * 60 * 1000 }) robot.on('schedule.repository', context => checkOpenPullRequests(robot, context)) } -async function getReviewApprovalState(github, robot, repo, pullRequest) { +async function getReviewApprovalState (github, robot, repo, pullRequest) { const threshold = 2 // Minimum number of approvers - + var finalReviews = await getPullRequestReviewStates(github, repo, pullRequest) - if (process.env.DRY_RUN_PR_TO_TEST) { + if (process.env.DRY_RUN || process.env.DRY_RUN_PR_TO_TEST) { robot.log.debug(finalReviews) } const approvedReviews = finalReviews.filter(reviewState => reviewState === 'APPROVED') if (approvedReviews.length >= threshold) { const reviewsWithChangesRequested = finalReviews.filter(reviewState => reviewState === 'CHANGES_REQUESTED') - if (reviewsWithChangesRequested.length == 0) { + if (reviewsWithChangesRequested.length === 0) { // Get detailed pull request const fullPullRequest = await github.pullRequests.get({owner: repo.owner.login, repo: repo.name, number: pullRequest.number}) pullRequest = fullPullRequest.data if (pullRequest.mergeable !== null && pullRequest.mergeable !== undefined && !pullRequest.mergeable) { - if (process.env.DRY_RUN_PR_TO_TEST) { + if (process.env.DRY_RUN || process.env.DRY_RUN_PR_TO_TEST) { robot.log.debug(`pullRequest.mergeable is ${pullRequest.mergeable}, considering as failed`) } return 'failed' @@ -60,18 +60,18 @@ async function getReviewApprovalState(github, robot, repo, pullRequest) { state = 'failed' break } - if (process.env.DRY_RUN_PR_TO_TEST) { + if (process.env.DRY_RUN || process.env.DRY_RUN_PR_TO_TEST) { robot.log.debug(`pullRequest.mergeable_state is ${pullRequest.mergeable_state}, considering state as ${state}`) } return state } } - + return 'pending' } - -async function getPullRequestReviewStates(github, repo, pullRequest) { + +async function getPullRequestReviewStates (github, repo, pullRequest) { var finalReviewsMap = new Map() const ghreviews = await github.paginate( github.pullRequests.getReviews({owner: repo.owner.login, repo: repo.name, number: pullRequest.number}), @@ -89,81 +89,82 @@ async function getPullRequestReviewStates(github, repo, pullRequest) { return Array.from(finalReviewsMap.values()) } -async function getProjectFromName(github, ownerName, repoName, projectBoardName) { - ghprojects = await github.projects.getRepoProjects({ +async function getProjectFromName (github, ownerName, repoName, projectBoardName) { + let ghprojects = await github.projects.getRepoProjects({ owner: ownerName, repo: repoName, - state: "open" + state: 'open' }) - + return ghprojects.data.find(p => p.name === projectBoardName) } -async function getProjectCardForPullRequest(github, columnId, pullRequestUrl) { +async function getProjectCardForPullRequest (github, columnId, pullRequestUrl) { const ghcards = await github.projects.getProjectCards({column_id: columnId}) - ghcard = ghcards.data.find(c => c.content_url === pullRequestUrl) - + let ghcard = ghcards.data.find(c => c.content_url === pullRequestUrl) + return ghcard } -async function checkOpenPullRequests(robot, context) { +async function checkOpenPullRequests (robot, context) { const github = context.github const repo = context.payload.repository const ownerName = repo.owner.login const repoName = repo.name - - //const config = await getConfig(context, 'github-bot.yml', defaultConfig(robot, '.github/github-bot.yml')) + + // const config = await getConfig(context, 'github-bot.yml', defaultConfig(robot, '.github/github-bot.yml')) const config = defaultConfig(robot, '.github/github-bot.yml') const projectBoardConfig = config['project-board'] - + if (!projectBoardConfig) { return } - + const reviewColumnName = projectBoardConfig['review-column-name'] const testColumnName = projectBoardConfig['test-column-name'] - + // Fetch repo projects // TODO: The repo project and project column info should be cached // in order to improve performance and reduce roundtrips try { - // Find "Pipeline for QA" project - project = await getProjectFromName(github, ownerName, repoName, projectBoardConfig.name) + // Find 'Pipeline for QA' project + let project = await getProjectFromName(github, ownerName, repoName, projectBoardConfig.name) if (!project) { robot.log.error(`Couldn't find project ${projectBoardConfig.name} in repo ${ownerName}/${repoName}`) return } - + robot.log.debug(`Fetched ${project.name} project (${project.id})`) - + // Fetch column IDs + let ghcolumns = null try { - ghcolumns = await github.projects.getProjectColumns({ project_id: project.id }) + ghcolumns = await github.projects.getProjectColumns({ project_id: project.id }) } catch (err) { robot.log.error(`Couldn't fetch the github columns for project: ${err}`, ownerName, repoName, project.id) return } - + const reviewColumn = ghcolumns.data.find(c => c.name === reviewColumnName) if (!reviewColumn) { robot.log.error(`Couldn't find ${reviewColumnName} column in project ${project.name}`) return } - + const testColumn = ghcolumns.data.find(c => c.name === testColumnName) if (!testColumn) { robot.log.error(`Couldn't find ${testColumnName} column in project ${project.name}`) return } - + robot.log.debug(`Fetched ${reviewColumn.name} (${reviewColumn.id}), ${testColumn.name} (${testColumn.id}) columns`) - + // Gather all open PRs in this repo const allPullRequests = await github.paginate( github.pullRequests.getAll({owner: ownerName, repo: repoName}), res => res.data ) - + // And make sure they are assigned to the correct prject column for (var pullRequest of allPullRequests) { await assignPullRequestToCorrectColumn(github, robot, repo, pullRequest, reviewColumn, testColumn, config.slack.notification.room) @@ -173,32 +174,34 @@ async function checkOpenPullRequests(robot, context) { } } -async function assignPullRequestToCorrectColumn(github, robot, repo, pullRequest, reviewColumn, testColumn, room) { +async function assignPullRequestToCorrectColumn (github, robot, repo, pullRequest, reviewColumn, testColumn, room) { const ownerName = repo.owner.login const repoName = repo.name const prNumber = pullRequest.number - + + let state = null try { state = await getReviewApprovalState(github, robot, repo, pullRequest) } catch (err) { robot.log.error(`Couldn't calculate the PR approval state: ${err}`, ownerName, repoName, prNumber) } - + + let srcColumn, dstColumn switch (state) { case 'approved': srcColumn = reviewColumn dstColumn = testColumn - break; + break case 'failed': srcColumn = testColumn dstColumn = reviewColumn - break; + break default: - return; + return } - + robot.log.debug(`assignPullRequestToTest - Handling Pull Request #${prNumber} on repo ${ownerName}/${repoName}. PR should be in ${dstColumn.name} column`) - + // Look for PR card in source column let ghcard = null try { @@ -207,31 +210,31 @@ async function assignPullRequestToCorrectColumn(github, robot, repo, pullRequest robot.log.error(`Failed to retrieve project card for the PR, aborting: ${err}`, srcColumn.id, pullRequest.issue_url) return } - + if (ghcard) { // Move PR card to the destination column try { robot.log.trace(`Found card in source column`, ghcard.id, srcColumn.id) - - if (!process.env.DRY_RUN && !process.env.DRY_RUN_PR_TO_TEST) { + + if (process.env.DRY_RUN || process.env.DRY_RUN_PR_TO_TEST) { + robot.log.info(`Would have moved card ${ghcard.id} to ${dstColumn.name} for PR #${prNumber}`) + } else { // Found in the source column, let's move it to the destination column await github.projects.moveProjectCard({id: ghcard.id, position: 'bottom', column_id: dstColumn.id}) } - + robot.log.info(`Moved card ${ghcard.id} to ${dstColumn.name} for PR #${prNumber}`) } catch (err) { const slackHelper = require('../lib/slack') - + robot.log.error(`Couldn't move project card for the PR: ${err}`, srcColumn.id, dstColumn.id, pullRequest.id) - if (!process.env.DRY_RUN_PR_TO_TEST) { - slackHelper.sendMessage(robot, slackClient, room, `I couldn't move the PR to ${dstColumnName} column :confused:\n${pullRequest.html_url}`) - } + slackHelper.sendMessage(robot, slackClient, room, `I couldn't move the PR to ${dstColumn.name} column :confused:\n${pullRequest.html_url}`) return } } else { try { robot.log.debug(`Didn't find card in source column`, srcColumn.id) - + // Look for PR card in destination column try { ghcard = await getProjectCardForPullRequest(github, dstColumn.id, pullRequest.issue_url) @@ -243,15 +246,17 @@ async function assignPullRequestToCorrectColumn(github, robot, repo, pullRequest robot.log.error(`Failed to retrieve project card for the PR, aborting: ${err}`, dstColumn.id, pullRequest.issue_url) return } - - if (!process.env.DRY_RUN && !process.env.DRY_RUN_PR_TO_TEST) { + + if (process.env.DRY_RUN || process.env.DRY_RUN_PR_TO_TEST) { + robot.log.info(`Would have created card ${ghcard.data.id} in ${dstColumn.name} for PR #${prNumber}`) + } else { // It wasn't in either the source nor the destination columns, let's create a new card for it in the destination column ghcard = await github.projects.createProjectCard({ column_id: dstColumn.id, content_type: 'PullRequest', content_id: pullRequest.id }) - + robot.log.info(`Created card ${ghcard.data.id} in ${dstColumn.name} for PR #${prNumber}`) } } catch (err) { @@ -260,9 +265,7 @@ async function assignPullRequestToCorrectColumn(github, robot, repo, pullRequest return } } - - if (!process.env.DRY_RUN_PR_TO_TEST) { - const slackHelper = require('../lib/slack') - slackHelper.sendMessage(robot, slackClient, room, `Assigned PR to ${dstColumn.name} column\n${pullRequest.html_url}`) - } + + const slackHelper = require('../lib/slack') + slackHelper.sendMessage(robot, slackClient, room, `Assigned PR to ${dstColumn.name} column\n${pullRequest.html_url}`) } diff --git a/scripts/assign-new-pr-to-review.js b/scripts/assign-new-pr-to-review.js index 01e797b..99c95fd 100644 --- a/scripts/assign-new-pr-to-review.js +++ b/scripts/assign-new-pr-to-review.js @@ -1,6 +1,6 @@ // Description: // Script that listens to new GitHub pull requests -// and assigns them to the REVIEW column on the "Pipeline for QA" project +// and assigns them to the REVIEW column on the 'Pipeline for QA' project // // Dependencies: // github: "^13.1.0" @@ -10,74 +10,76 @@ // Author: // PombeirP -const getConfig = require('probot-config') +// const getConfig = require('probot-config') const defaultConfig = require('../lib/config') const Slack = require('probot-slack-status') let slackClient = null -module.exports = function(robot) { +module.exports = (robot) => { // robot.on('slack.connected', ({ slack }) => { Slack(robot, (slack) => { - robot.log.trace("Connected, assigned slackClient") + robot.log.trace('Connected, assigned slackClient') slackClient = slack }) - + robot.on('pull_request.opened', async context => { // Make sure we don't listen to our own messages if (context.isBot) { return } - + // A new PR was opened await assignPullRequestToReview(context, robot) }) } -async function assignPullRequestToReview(context, robot) { +async function assignPullRequestToReview (context, robot) { const payload = context.payload const github = context.github - //const config = await getConfig(context, 'github-bot.yml', defaultConfig(robot, '.github/github-bot.yml')) + // const config = await getConfig(context, 'github-bot.yml', defaultConfig(robot, '.github/github-bot.yml')) const config = defaultConfig(robot, '.github/github-bot.yml') const ownerName = payload.repository.owner.login const repoName = payload.repository.name const prNumber = payload.pull_request.number - - if (!config['project-board']) { - return; + + const projectBoardConfig = config['project-board'] + if (!projectBoardConfig) { + return } - + robot.log(`assignPullRequestToReview - Handling Pull Request #${prNumber} on repo ${ownerName}/${repoName}`) - + // Fetch repo projects // TODO: The repo project and project column info should be cached // in order to improve performance and reduce roundtrips + let column = null + const projectBoardName = projectBoardConfig.name + const reviewColumnName = projectBoardConfig['review-column-name'] try { - ghprojects = await github.projects.getRepoProjects({ + let ghprojects = await github.projects.getRepoProjects({ owner: ownerName, repo: repoName, - state: "open" + state: 'open' }) - - // Find "Pipeline for QA" project - const projectBoardName = config['project-board'].name + + // Find 'Pipeline for QA' project const project = ghprojects.data.find(p => p.name === projectBoardName) if (!project) { robot.log.error(`Couldn't find project ${projectBoardName} in repo ${ownerName}/${repoName}`) return } - + robot.log.debug(`Fetched ${project.name} project (${project.id})`) - + // Fetch REVIEW column ID try { - ghcolumns = await github.projects.getProjectColumns({ project_id: project.id }) - - const reviewColumnName = config['project-board']['review-column-name'] - const column = ghcolumns.data.find(c => c.name === reviewColumnName) + let ghcolumns = await github.projects.getProjectColumns({ project_id: project.id }) + + column = ghcolumns.data.find(c => c.name === reviewColumnName) if (!column) { robot.log.error(`Couldn't find ${reviewColumnName} column in project ${project.name}`) return } - + robot.log.debug(`Fetched ${column.name} column (${column.id})`) } catch (err) { robot.log.error(`Couldn't fetch the github columns for project: ${err}`, ownerName, repoName, project.id) @@ -87,19 +89,21 @@ async function assignPullRequestToReview(context, robot) { robot.log.error(`Couldn't fetch the github projects for repo: ${err}`, ownerName, repoName) return } - + // Create project card for the PR in the REVIEW column try { - if (!process.env.DRY_RUN) { - ghcard = await github.projects.createProjectCard({ + if (process.env.DRY_RUN) { + robot.log.debug('Would have created card', column.id, payload.pull_request.id) + } else { + let ghcard = await github.projects.createProjectCard({ column_id: column.id, content_type: 'PullRequest', content_id: payload.pull_request.id }) + + robot.log.debug(`Created card: ${ghcard.data.url}`, ghcard.data.id) } - - robot.log.debug(`Created card: ${ghcard.data.url}`, ghcard.data.id) - + // Send message to Slack const slackHelper = require('../lib/slack') slackHelper.sendMessage(robot, slackClient, config.slack.notification.room, `Assigned PR to ${reviewColumnName} in ${projectBoardName} project\n${payload.pull_request.html_url}`) diff --git a/scripts/assign-to-bounty-awaiting-for-approval.js b/scripts/assign-to-bounty-awaiting-for-approval.js index 2e04ff7..240e89d 100644 --- a/scripts/assign-to-bounty-awaiting-for-approval.js +++ b/scripts/assign-to-bounty-awaiting-for-approval.js @@ -1,6 +1,6 @@ // Description: // Script that listens to new labels on GitHub issues -// and assigns the issues to the bounty-awaiting-approval column on the "Status SOB Swarm" project +// and assigns the issues to the bounty-awaiting-approval column on the 'Status SOB Swarm' project // // Dependencies: // github: "^13.1.0" @@ -10,91 +10,92 @@ // Author: // PombeirP -const getConfig = require('probot-config') +// const getConfig = require('probot-config') const defaultConfig = require('../lib/config') const Slack = require('probot-slack-status') let slackClient = null -module.exports = function(robot) { +module.exports = (robot) => { // robot.on('slack.connected', ({ slack }) => { Slack(robot, (slack) => { - robot.log.trace("Connected, assigned slackClient") + robot.log.trace('Connected, assigned slackClient') slackClient = slack }) - + robot.on('issues.labeled', async context => { // Make sure we don't listen to our own messages if (context.isBot) { return } - + // A new issue was labeled await assignIssueToBountyAwaitingForApproval(context, robot, true) }) robot.on('issues.unlabeled', async context => { // Make sure we don't listen to our own messages if (context.isBot) { return } - + // An issue was unlabeled await assignIssueToBountyAwaitingForApproval(context, robot, false) }) } -async function assignIssueToBountyAwaitingForApproval(context, robot, assign) { +async function assignIssueToBountyAwaitingForApproval (context, robot, assign) { const github = context.github const payload = context.payload const ownerName = payload.repository.owner.login const repoName = payload.repository.name - //const config = await getConfig(context, 'github-bot.yml', defaultConfig(robot, '.github/github-bot.yml')) + // const config = await getConfig(context, 'github-bot.yml', defaultConfig(robot, '.github/github-bot.yml')) const config = defaultConfig(robot, '.github/github-bot.yml') - + if (!config['bounty-project-board']) { - return; + return } - + const watchedLabelName = config['bounty-project-board']['label-name'] if (payload.label.name !== watchedLabelName) { robot.log.debug(`assignIssueToBountyAwaitingForApproval - ${payload.label.name} doesn't match watched ${watchedLabelName} label. Ignoring`) return } - + if (assign) { robot.log(`assignIssueToBountyAwaitingForApproval - Handling labeling of #${payload.issue.number} with ${payload.label.name} on repo ${ownerName}/${repoName}`) } else { robot.log(`assignIssueToBountyAwaitingForApproval - Handling unlabeling of #${payload.issue.number} with ${payload.label.name} on repo ${ownerName}/${repoName}`) } - + // Fetch org projects // TODO: The org project and project column info should be cached // in order to improve performance and reduce roundtrips + let column = null + const projectBoardName = config['bounty-project-board'].name + const approvalColumnName = config['bounty-project-board']['awaiting-approval-column-name'] try { const orgName = ownerName - - ghprojects = await github.projects.getOrgProjects({ + + let ghprojects = await github.projects.getOrgProjects({ org: orgName, - state: "open" + state: 'open' }) - - // Find "Status SOB Swarm" project - const projectBoardName = config['bounty-project-board'].name - const project = ghprojects.data.find(function(p) { return p.name === projectBoardName }) + + // Find 'Status SOB Swarm' project + const project = ghprojects.data.find(p => p.name === projectBoardName) if (!project) { robot.log.error(`Couldn't find project ${projectBoardName} in ${orgName} org`) return } - + robot.log.debug(`Fetched ${project.name} project (${project.id})`) - + // Fetch bounty-awaiting-approval column ID try { - ghcolumns = await github.projects.getProjectColumns({ project_id: project.id }) - - const approvalColumnName = config['bounty-project-board']['awaiting-approval-column-name'] - const column = ghcolumns.data.find(c => c.name === approvalColumnName) + let ghcolumns = await github.projects.getProjectColumns({ project_id: project.id }) + + column = ghcolumns.data.find(c => c.name === approvalColumnName) if (!column) { robot.log.error(`Couldn't find ${approvalColumnName} column in project ${project.name}`) return } - + robot.log.debug(`Fetched ${column.name} column (${column.id})`) } catch (err) { robot.log.error(`Couldn't fetch the github columns for project: ${err}`, ownerName, repoName, project.id) @@ -104,8 +105,15 @@ async function assignIssueToBountyAwaitingForApproval(context, robot, assign) { robot.log.error(`Couldn't fetch the github projects for repo: ${err}`, ownerName, repoName) return } - - if (!process.env.DRY_RUN) { + + let ghcard = null + if (process.env.DRY_RUN) { + if (assign) { + robot.log.info(`Would have created card for issue`, column.id, payload.issue.id) + } else { + robot.log.info(`Would have deleted card for issue`, column.id, payload.issue.id) + } + } else { if (assign) { try { // Create project card for the issue in the bounty-awaiting-approval column @@ -115,6 +123,8 @@ async function assignIssueToBountyAwaitingForApproval(context, robot, assign) { content_id: payload.issue.id }) ghcard = ghcard.data + + robot.log(`Created card: ${ghcard.url}`, ghcard.id) } catch (err) { robot.log.error(`Couldn't create project card for the issue: ${err}`, column.id, payload.issue.id) } @@ -122,27 +132,25 @@ async function assignIssueToBountyAwaitingForApproval(context, robot, assign) { try { ghcard = await getProjectCardForIssue(github, column.id, payload.issue.url) await github.projects.deleteProjectCard({id: ghcard.id}) + robot.log(`Deleted card: ${ghcard.url}`, ghcard.id) } catch (err) { robot.log.error(`Couldn't delete project card for the issue: ${err}`, column.id, payload.issue.id) } } } + // Send message to Slack const slackHelper = require('../lib/slack') if (assign) { - robot.log(`Created card: ${ghcard.url}`, ghcard.id) - // Send message to Slack slackHelper.sendMessage(robot, slackClient, config.slack.notification.room, `Assigned issue to ${approvalColumnName} in ${projectBoardName} project\n${payload.issue.html_url}`) } else { - robot.log(`Deleted card: ${ghcard.url}`, ghcard.id) - // Send message to Slack slackHelper.sendMessage(robot, slackClient, config.slack.notification.room, `Unassigned issue from ${approvalColumnName} in ${projectBoardName} project\n${payload.issue.html_url}`) } } -async function getProjectCardForIssue(github, columnId, issueUrl) { +async function getProjectCardForIssue (github, columnId, issueUrl) { const ghcards = await github.projects.getProjectCards({column_id: columnId}) - ghcard = ghcards.data.find(c => c.content_url === issueUrl) - + let ghcard = ghcards.data.find(c => c.content_url === issueUrl) + return ghcard } diff --git a/scripts/greet-new-contributor.js b/scripts/greet-new-contributor.js index d430499..44eb3f3 100644 --- a/scripts/greet-new-contributor.js +++ b/scripts/greet-new-contributor.js @@ -10,56 +10,59 @@ // Author: // PombeirP -const getConfig = require('probot-config') +// const getConfig = require('probot-config') const defaultConfig = require('../lib/config') const Slack = require('probot-slack-status') let slackClient = null -module.exports = function(robot) { +module.exports = (robot) => { // robot.on('slack.connected', ({ slack }) => { Slack(robot, (slack) => { - robot.log.trace("Connected, assigned slackClient") + robot.log.trace('Connected, assigned slackClient') slackClient = slack }) - + robot.on('pull_request.opened', async context => { // Make sure we don't listen to our own messages if (context.isBot) { return } - + // A new PR was opened await greetNewContributor(context, robot) }) } -async function greetNewContributor(context, robot) { +async function greetNewContributor (context, robot) { const payload = context.payload const github = context.github - //const config = await getConfig(context, 'github-bot.yml', defaultConfig(robot, '.github/github-bot.yml')) + // const config = await getConfig(context, 'github-bot.yml', defaultConfig(robot, '.github/github-bot.yml')) const config = defaultConfig(robot, '.github/github-bot.yml') const ownerName = payload.repository.owner.login const repoName = payload.repository.name const prNumber = payload.pull_request.number - - if (!config['welcome-bot']) { - return; + + const welcomeBotConfig = config['welcome-bot'] + if (!welcomeBotConfig) { + return } - + robot.log(`greetNewContributor - Handling Pull Request #${prNumber} on repo ${ownerName}/${repoName}`) - + try { - ghissues = await github.issues.getForRepo({ + let ghissues = await github.issues.getForRepo({ owner: ownerName, repo: repoName, state: 'all', creator: payload.pull_request.user.login }) - + const userPullRequests = ghissues.data.filter(issue => issue.pull_request) if (userPullRequests.length === 1) { try { - const welcomeMessage = config['welcome-bot'].message - if (!process.env.DRY_RUN) { + const welcomeMessage = welcomeBotConfig.message + if (process.env.DRY_RUN) { + robot.log('Would have created comment in GHI', ownerName, repoName, prNumber, welcomeMessage) + } else { await github.issues.createComment({ owner: ownerName, repo: repoName, @@ -67,7 +70,7 @@ async function greetNewContributor(context, robot) { body: welcomeMessage }) } - + // Send message to Slack const slackHelper = require('../lib/slack') slackHelper.sendMessage(robot, slackClient, config.slack.notification.room, `Greeted ${payload.pull_request.user.login} on his first PR in the ${repoName} repo\n${payload.pull_request.html_url}`) @@ -77,9 +80,9 @@ async function greetNewContributor(context, robot) { } } } else { - robot.log.debug("This is not the user's first PR on the repo, ignoring", ownerName, repoName, payload.pull_request.user.login) + robot.log.debug('This is not the user\'s first PR on the repo, ignoring', ownerName, repoName, payload.pull_request.user.login) } } catch (err) { robot.log.error(`Couldn't fetch the user's github issues for repo: ${err}`, ownerName, repoName) } -} \ No newline at end of file +}