From 038944f361bbe17b69e7a756db67a101bba9fb31 Mon Sep 17 00:00:00 2001 From: Pedro Pombeiro Date: Tue, 23 Jan 2018 19:38:25 +0100 Subject: [PATCH] Make the functionality to move a PR to test a scheduled task, instead of an event handler Sidesteps the problem that a build will still be running when we get the event, and therefore we'll never be in a position where all checks have passed --- lib/slack.js | 4 +- package-lock.json | 1126 ++++++++++++----- package.json | 1 + scripts/assign-approved-pr-to-test.js | 302 +++-- scripts/assign-new-pr-to-review.js | 40 +- .../assign-to-bounty-awaiting-for-approval.js | 40 +- scripts/greet-new-contributor.js | 16 +- 7 files changed, 1087 insertions(+), 442 deletions(-) diff --git a/lib/slack.js b/lib/slack.js index b0f8884..5d3ad37 100644 --- a/lib/slack.js +++ b/lib/slack.js @@ -12,7 +12,9 @@ module.exports.sendMessage = async (robot, slackClient, room, message) => { if (slackClient != null) { const channel = slackClient.dataStore.getChannelByName(room) try { - await slackClient.sendMessage(message, channel.id) + if (!process.env.DRY_RUN) { + await slackClient.sendMessage(message, channel.id) + } } catch(err) { robot.log.error(`Failed to send Slack message to ${room} channel`) } diff --git a/package-lock.json b/package-lock.json index 52f2d2d..addddfd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -235,12 +235,14 @@ "acorn": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.3.0.tgz", - "integrity": "sha512-Yej+zOJ1Dm/IMZzzj78OntP/r3zHEaKcyNoU2lAaxPtrseM6rF0xwqoz5Q5ysAiED9hTjI2hgtvLXitlCN1/Ug==" + "integrity": "sha512-Yej+zOJ1Dm/IMZzzj78OntP/r3zHEaKcyNoU2lAaxPtrseM6rF0xwqoz5Q5ysAiED9hTjI2hgtvLXitlCN1/Ug==", + "dev": true }, "acorn-globals": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.1.0.tgz", "integrity": "sha512-KjZwU26uG3u6eZcfGbTULzFcsoz6pegNKtHPksZPOUsiKo5bUmiBPa38FuHZ/Eun+XYh/JCCkS9AS3Lu4McQOQ==", + "dev": true, "requires": { "acorn": "5.3.0" } @@ -436,7 +438,8 @@ "async-limiter": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", - "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", + "dev": true }, "asynckit": { "version": "0.4.0", @@ -783,7 +786,8 @@ "browser-process-hrtime": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.2.tgz", - "integrity": "sha1-Ql1opY00R/AqBKqJQYf86K+Le44=" + "integrity": "sha1-Ql1opY00R/AqBKqJQYf86K+Le44=", + "dev": true }, "browser-resolve": { "version": "1.11.2", @@ -1330,52 +1334,15 @@ "esutils": "2.0.2" } }, - "dom-serializer": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", - "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", - "requires": { - "domelementtype": "1.1.3", - "entities": "1.1.1" - }, - "dependencies": { - "domelementtype": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", - "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=" - } - } - }, - "domelementtype": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", - "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=" - }, "domexception": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", + "dev": true, "requires": { "webidl-conversions": "4.0.2" } }, - "domhandler": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.1.tgz", - "integrity": "sha1-iS5HAAqZvlW783dP/qBWHYh5wlk=", - "requires": { - "domelementtype": "1.3.0" - } - }, - "domutils": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.6.2.tgz", - "integrity": "sha1-GVjMC0yUJuntNn+xyOhUiRsPo/8=", - "requires": { - "dom-serializer": "0.1.0", - "domelementtype": "1.3.0" - } - }, "dotenv": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-4.0.0.tgz", @@ -1423,11 +1390,6 @@ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz", "integrity": "sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA=" }, - "entities": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", - "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=" - }, "errno": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.6.tgz", @@ -2227,6 +2189,795 @@ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, + "fsevents": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz", + "integrity": "sha512-WIr7iDkdmdbxu/Gh6eKEZJL6KPE74/5MEsf2whTOFNxbIoIixogroLdKYqB6FDav4Wavh/lZdzzd3b2KxIXC5Q==", + "optional": true, + "requires": { + "nan": "2.8.0", + "node-pre-gyp": "0.6.39" + }, + "dependencies": { + "abbrev": { + "version": "1.1.0", + "bundled": true, + "optional": true + }, + "ajv": { + "version": "4.11.8", + "bundled": true, + "optional": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "aproba": { + "version": "1.1.1", + "bundled": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "optional": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.2.9" + } + }, + "asn1": { + "version": "0.2.3", + "bundled": true, + "optional": true + }, + "assert-plus": { + "version": "0.2.0", + "bundled": true, + "optional": true + }, + "asynckit": { + "version": "0.4.0", + "bundled": true, + "optional": true + }, + "aws-sign2": { + "version": "0.6.0", + "bundled": true, + "optional": true + }, + "aws4": { + "version": "1.6.0", + "bundled": true, + "optional": true + }, + "balanced-match": { + "version": "0.4.2", + "bundled": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "bundled": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "block-stream": { + "version": "0.0.9", + "bundled": true, + "requires": { + "inherits": "2.0.3" + } + }, + "boom": { + "version": "2.10.1", + "bundled": true, + "requires": { + "hoek": "2.16.3" + } + }, + "brace-expansion": { + "version": "1.1.7", + "bundled": true, + "requires": { + "balanced-match": "0.4.2", + "concat-map": "0.0.1" + } + }, + "buffer-shims": { + "version": "1.0.0", + "bundled": true + }, + "caseless": { + "version": "0.12.0", + "bundled": true, + "optional": true + }, + "co": { + "version": "4.6.0", + "bundled": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "combined-stream": { + "version": "1.0.5", + "bundled": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true + }, + "cryptiles": { + "version": "2.0.5", + "bundled": true, + "requires": { + "boom": "2.10.1" + } + }, + "dashdash": { + "version": "1.14.1", + "bundled": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "optional": true + } + } + }, + "debug": { + "version": "2.6.8", + "bundled": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.4.2", + "bundled": true, + "optional": true + }, + "delayed-stream": { + "version": "1.0.0", + "bundled": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "ecc-jsbn": { + "version": "0.1.1", + "bundled": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "extend": { + "version": "3.0.1", + "bundled": true, + "optional": true + }, + "extsprintf": { + "version": "1.0.2", + "bundled": true + }, + "forever-agent": { + "version": "0.6.1", + "bundled": true, + "optional": true + }, + "form-data": { + "version": "2.1.4", + "bundled": true, + "optional": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.15" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true + }, + "fstream": { + "version": "1.0.11", + "bundled": true, + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.1" + } + }, + "fstream-ignore": { + "version": "1.0.5", + "bundled": true, + "optional": true, + "requires": { + "fstream": "1.0.11", + "inherits": "2.0.3", + "minimatch": "3.0.4" + } + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "optional": true, + "requires": { + "aproba": "1.1.1", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "getpass": { + "version": "0.1.7", + "bundled": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "optional": true + } + } + }, + "glob": { + "version": "7.1.2", + "bundled": 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" + } + }, + "graceful-fs": { + "version": "4.1.11", + "bundled": true + }, + "har-schema": { + "version": "1.0.5", + "bundled": true, + "optional": true + }, + "har-validator": { + "version": "4.2.1", + "bundled": true, + "optional": true, + "requires": { + "ajv": "4.11.8", + "har-schema": "1.0.5" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "optional": true + }, + "hawk": { + "version": "3.1.3", + "bundled": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "bundled": true + }, + "http-signature": { + "version": "1.1.1", + "bundled": true, + "optional": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.0", + "sshpk": "1.13.0" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true + }, + "ini": { + "version": "1.3.4", + "bundled": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true + }, + "isstream": { + "version": "0.1.2", + "bundled": true, + "optional": true + }, + "jodid25519": { + "version": "1.0.2", + "bundled": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "jsbn": { + "version": "0.1.1", + "bundled": true, + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "bundled": true, + "optional": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "bundled": true, + "optional": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "bundled": true, + "optional": true + }, + "jsonify": { + "version": "0.0.0", + "bundled": true, + "optional": true + }, + "jsprim": { + "version": "1.4.0", + "bundled": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.0.2", + "json-schema": "0.2.3", + "verror": "1.3.6" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "optional": true + } + } + }, + "mime-db": { + "version": "1.27.0", + "bundled": true + }, + "mime-types": { + "version": "2.1.15", + "bundled": true, + "requires": { + "mime-db": "1.27.0" + } + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "requires": { + "brace-expansion": "1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "optional": true + }, + "node-pre-gyp": { + "version": "0.6.39", + "bundled": true, + "optional": true, + "requires": { + "detect-libc": "1.0.2", + "hawk": "3.1.3", + "mkdirp": "0.5.1", + "nopt": "4.0.1", + "npmlog": "4.1.0", + "rc": "1.2.1", + "request": "2.81.0", + "rimraf": "2.6.1", + "semver": "5.3.0", + "tar": "2.2.1", + "tar-pack": "3.4.0" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "optional": true, + "requires": { + "abbrev": "1.1.0", + "osenv": "0.1.4" + } + }, + "npmlog": { + "version": "4.1.0", + "bundled": true, + "optional": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true + }, + "oauth-sign": { + "version": "0.8.2", + "bundled": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "osenv": { + "version": "0.1.4", + "bundled": true, + "optional": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true + }, + "performance-now": { + "version": "0.2.0", + "bundled": true, + "optional": true + }, + "process-nextick-args": { + "version": "1.0.7", + "bundled": true + }, + "punycode": { + "version": "1.4.1", + "bundled": true, + "optional": true + }, + "qs": { + "version": "6.4.0", + "bundled": true, + "optional": true + }, + "rc": { + "version": "1.2.1", + "bundled": true, + "optional": true, + "requires": { + "deep-extend": "0.4.2", + "ini": "1.3.4", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.2.9", + "bundled": true, + "requires": { + "buffer-shims": "1.0.0", + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "1.0.1", + "util-deprecate": "1.0.2" + } + }, + "request": { + "version": "2.81.0", + "bundled": true, + "optional": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "4.2.1", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.15", + "oauth-sign": "0.8.2", + "performance-now": "0.2.0", + "qs": "6.4.0", + "safe-buffer": "5.0.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.2", + "tunnel-agent": "0.6.0", + "uuid": "3.0.1" + } + }, + "rimraf": { + "version": "2.6.1", + "bundled": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.0.1", + "bundled": true + }, + "semver": { + "version": "5.3.0", + "bundled": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "optional": true + }, + "sntp": { + "version": "1.0.9", + "bundled": true, + "requires": { + "hoek": "2.16.3" + } + }, + "sshpk": { + "version": "1.13.0", + "bundled": true, + "optional": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jodid25519": "1.0.2", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "optional": true + } + } + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.0.1", + "bundled": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, + "stringstream": { + "version": "0.0.5", + "bundled": true, + "optional": true + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "optional": true + }, + "tar": { + "version": "2.2.1", + "bundled": true, + "requires": { + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" + } + }, + "tar-pack": { + "version": "3.4.0", + "bundled": true, + "optional": true, + "requires": { + "debug": "2.6.8", + "fstream": "1.0.11", + "fstream-ignore": "1.0.5", + "once": "1.4.0", + "readable-stream": "2.2.9", + "rimraf": "2.6.1", + "tar": "2.2.1", + "uid-number": "0.0.6" + } + }, + "tough-cookie": { + "version": "2.3.2", + "bundled": true, + "optional": true, + "requires": { + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "bundled": true, + "optional": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "bundled": true, + "optional": true + }, + "uid-number": { + "version": "0.0.6", + "bundled": true, + "optional": true + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true + }, + "uuid": { + "version": "3.0.1", + "bundled": true, + "optional": true + }, + "verror": { + "version": "1.3.6", + "bundled": true, + "optional": true, + "requires": { + "extsprintf": "1.0.2" + } + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "optional": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true + } + } + }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -2290,78 +3041,6 @@ } } }, - "github-app": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/github-app/-/github-app-3.2.0.tgz", - "integrity": "sha512-afKv6H9svvYcDILaKM5xcRY77dvfDoRmj7Vv2Rf+bNYu3ibNHDFifD5nk5DE4qw0CGBu6u559NQmo5vwOAyKJA==", - "requires": { - "github": "10.1.0", - "jsonwebtoken": "7.4.3" - }, - "dependencies": { - "agent-base": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-2.1.1.tgz", - "integrity": "sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=", - "requires": { - "extend": "3.0.1", - "semver": "5.0.3" - } - }, - "follow-redirects": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-0.0.7.tgz", - "integrity": "sha1-NLkLqyqRGqNHVx2pDyK9NuzYqRk=", - "requires": { - "debug": "2.6.9", - "stream-consume": "0.1.0" - } - }, - "github": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/github/-/github-10.1.0.tgz", - "integrity": "sha512-9id0pjUTIkmOrcGcIgLhpZZjIsXUTRzDpQUR5hqvtIwPC93Eq6/4DfWc8iqp0/E73lr7zp38+5TOddcPvuaDKw==", - "requires": { - "follow-redirects": "0.0.7", - "https-proxy-agent": "1.0.0", - "mime": "1.4.1", - "netrc": "0.1.4" - } - }, - "https-proxy-agent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", - "integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=", - "requires": { - "agent-base": "2.1.1", - "debug": "2.6.9", - "extend": "3.0.1" - } - }, - "jsonwebtoken": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-7.4.3.tgz", - "integrity": "sha1-d/UCHeBYtgWheD+hKD6ZgS5kVjg=", - "requires": { - "joi": "6.10.1", - "jws": "3.1.4", - "lodash.once": "4.1.1", - "ms": "2.0.0", - "xtend": "4.0.1" - } - }, - "semver": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.0.3.tgz", - "integrity": "sha1-d0Zt5YnNXTyV8TiqeLxWmjy10no=" - }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" - } - } - }, "github-webhook-handler": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/github-webhook-handler/-/github-webhook-handler-0.7.1.tgz", @@ -2551,19 +3230,6 @@ "whatwg-encoding": "1.0.3" } }, - "htmlparser2": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz", - "integrity": "sha1-G9+HrMoPP55T+k/M6w9LTLsAszg=", - "requires": { - "domelementtype": "1.3.0", - "domhandler": "2.4.1", - "domutils": "1.6.2", - "entities": "1.1.1", - "inherits": "2.0.3", - "readable-stream": "2.0.6" - } - }, "http-errors": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", @@ -2962,11 +3628,6 @@ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, - "isemail": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/isemail/-/isemail-1.2.0.tgz", - "integrity": "sha1-vgPfjMPineTSxd9lASY/H6RZXpo=" - }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -3546,24 +4207,6 @@ "merge-stream": "1.0.1" } }, - "joi": { - "version": "6.10.1", - "resolved": "https://registry.npmjs.org/joi/-/joi-6.10.1.tgz", - "integrity": "sha1-TVDDGAeRIgAP5fFq8f+OGRe3fgY=", - "requires": { - "hoek": "2.16.3", - "isemail": "1.2.0", - "moment": "2.20.1", - "topo": "1.1.0" - }, - "dependencies": { - "hoek": { - "version": "2.16.3", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", - "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" - } - } - }, "js-tokens": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", @@ -3588,6 +4231,7 @@ "version": "11.6.0", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.6.0.tgz", "integrity": "sha512-4lMxDCiQYK7qfVi9fKhDf2PpvXXeH/KAmcH6o0Ga7fApi8+lTBxRqGHWZ9B11SsK/pxQKOtsw413utw0M+hUrg==", + "dev": true, "requires": { "abab": "1.0.4", "acorn": "5.3.0", @@ -3620,12 +4264,14 @@ "ultron": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", - "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==" + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", + "dev": true }, "ws": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/ws/-/ws-4.0.0.tgz", "integrity": "sha512-QYslsH44bH8O7/W2815u5DpnCpXWpEK44FmaHffNwgJI4JMaSZONgPBTOfrxJ29mXKbXak+LsJ2uAkDTYq2ptQ==", + "dev": true, "requires": { "async-limiter": "1.0.0", "safe-buffer": "5.1.1", @@ -3769,7 +4415,8 @@ "left-pad": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.2.0.tgz", - "integrity": "sha1-0wpzxrggHY99jnlWupYWCHpo4O4=" + "integrity": "sha1-0wpzxrggHY99jnlWupYWCHpo4O4=", + "dev": true }, "leven": { "version": "2.1.0", @@ -3859,7 +4506,8 @@ "lodash.sortby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", - "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=" + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", + "dev": true }, "longest": { "version": "1.0.1", @@ -4000,7 +4648,8 @@ "moment": { "version": "2.20.1", "resolved": "https://registry.npmjs.org/moment/-/moment-2.20.1.tgz", - "integrity": "sha1-1usaRsvMFKKy+UNBEsH/iQfzE/0=" + "integrity": "sha1-1usaRsvMFKKy+UNBEsH/iQfzE/0=", + "optional": true }, "morgan": { "version": "1.9.0", @@ -4316,7 +4965,8 @@ "parse5": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", - "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==" + "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", + "dev": true }, "parseurl": { "version": "1.3.2", @@ -4496,7 +5146,8 @@ "pn": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", - "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==" + "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==", + "dev": true }, "prelude-ls": { "version": "1.1.2", @@ -5183,6 +5834,14 @@ } } }, + "probot-scheduler": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/probot-scheduler/-/probot-scheduler-1.0.3.tgz", + "integrity": "sha512-3uDySfjaJn4JdbLej1GuMgZ2OFPCtmp5TWO38rCBjNWQLjF7zxE+XhfZn1uAzazcfqk5WyVl6Zq5zVmJqOGB/g==", + "requires": { + "bottleneck": "1.16.0" + } + }, "probot-slack-status": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/probot-slack-status/-/probot-slack-status-0.2.2.tgz", @@ -6108,6 +6767,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.1.tgz", "integrity": "sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY=", + "dev": true, "requires": { "lodash": "4.17.4" } @@ -6116,6 +6776,7 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.5.tgz", "integrity": "sha1-UoF3D2jgyXGeUWP9P6tIIhX0/aU=", + "dev": true, "requires": { "request-promise-core": "1.1.1", "stealthy-require": "1.1.1", @@ -6251,6 +6912,7 @@ "anymatch": "1.3.2", "exec-sh": "0.2.1", "fb-watchman": "2.0.0", + "fsevents": "1.1.3", "minimatch": "3.0.4", "minimist": "1.2.0", "walker": "1.0.7", @@ -6515,7 +7177,8 @@ "stealthy-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", - "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=" + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", + "dev": true }, "stream-consume": { "version": "0.1.0", @@ -6734,21 +7397,6 @@ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=" }, - "topo": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/topo/-/topo-1.1.0.tgz", - "integrity": "sha1-6ddRYV0buH3IZdsYL6HKCl71NtU=", - "requires": { - "hoek": "2.16.3" - }, - "dependencies": { - "hoek": { - "version": "2.16.3", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", - "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" - } - } - }, "tough-cookie": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", @@ -6761,6 +7409,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", + "dev": true, "requires": { "punycode": "2.1.0" }, @@ -6768,7 +7417,8 @@ "punycode": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.0.tgz", - "integrity": "sha1-X4Y+3Im5bbCQdLrXlHvwkFbKTn0=" + "integrity": "sha1-X4Y+3Im5bbCQdLrXlHvwkFbKTn0=", + "dev": true } } }, @@ -6844,117 +7494,6 @@ "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz", "integrity": "sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po=" }, - "unfurl": { - "version": "github:probot/unfurl#b9d45188fb696b76fca979f23a6b9eccf4e5a1a3", - "requires": { - "ejs": "2.5.7", - "jsdom": "11.6.0", - "probot": "2.0.0", - "probot-attachments": "github:probot/attachments#bfeb5d0e9def50c5cd69cbbaf1db1687b38cc5d2", - "unfurl.js": "1.1.6" - }, - "dependencies": { - "agent-base": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-2.1.1.tgz", - "integrity": "sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=", - "requires": { - "extend": "3.0.1", - "semver": "5.0.3" - }, - "dependencies": { - "semver": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.0.3.tgz", - "integrity": "sha1-d0Zt5YnNXTyV8TiqeLxWmjy10no=" - } - } - }, - "follow-redirects": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-0.0.7.tgz", - "integrity": "sha1-NLkLqyqRGqNHVx2pDyK9NuzYqRk=", - "requires": { - "debug": "2.6.9", - "stream-consume": "0.1.0" - } - }, - "github": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/github/-/github-10.1.0.tgz", - "integrity": "sha512-9id0pjUTIkmOrcGcIgLhpZZjIsXUTRzDpQUR5hqvtIwPC93Eq6/4DfWc8iqp0/E73lr7zp38+5TOddcPvuaDKw==", - "requires": { - "follow-redirects": "0.0.7", - "https-proxy-agent": "1.0.0", - "mime": "1.4.1", - "netrc": "0.1.4" - } - }, - "github-webhook-handler": { - "version": "github:rvagg/github-webhook-handler#7cfcb5b724a7735f132778cf15245cac8547ff60", - "requires": { - "bl": "1.1.2", - "buffer-equal-constant-time": "1.0.1" - } - }, - "https-proxy-agent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", - "integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=", - "requires": { - "agent-base": "2.1.1", - "debug": "2.6.9", - "extend": "3.0.1" - } - }, - "probot": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/probot/-/probot-2.0.0.tgz", - "integrity": "sha512-F6pKZq+SczjNLFI6p2KroqJrIx2pzwvHqDFRjQScLpb7Nt1UvASMWGcUdUf+Spnx+K1gkpW4RzlQEQD9MhvYow==", - "requires": { - "bottleneck": "1.16.0", - "bunyan": "1.8.12", - "bunyan-format": "0.2.1", - "bunyan-sentry-stream": "1.2.1", - "cache-manager": "2.6.0", - "commander": "2.13.0", - "dotenv": "4.0.0", - "express": "4.16.2", - "github": "10.1.0", - "github-app": "3.2.0", - "github-webhook-handler": "github:rvagg/github-webhook-handler#7cfcb5b724a7735f132778cf15245cac8547ff60", - "js-yaml": "3.10.0", - "pkg-conf": "2.1.0", - "promise-events": "0.1.4", - "raven": "2.3.0", - "resolve": "1.5.0", - "semver": "5.5.0" - } - }, - "probot-attachments": { - "version": "github:probot/attachments#bfeb5d0e9def50c5cd69cbbaf1db1687b38cc5d2" - } - } - }, - "unfurl.js": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/unfurl.js/-/unfurl.js-1.1.6.tgz", - "integrity": "sha1-L2Ycvov50xtvbsIv4eGnFKJFxN8=", - "requires": { - "debug": "2.6.9", - "htmlparser2": "3.9.2", - "lodash": "4.17.4", - "pify": "2.3.0", - "request": "2.83.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" - } - } - }, "uniq": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", @@ -7043,6 +7582,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz", "integrity": "sha1-gqwr/2PZUOqeMYmlimViX+3xkEU=", + "dev": true, "requires": { "browser-process-hrtime": "0.1.2" } @@ -7096,6 +7636,7 @@ "version": "6.4.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.4.0.tgz", "integrity": "sha512-Z0CVh/YE217Foyb488eo+iBv+r7eAQ0wSTyApi9n06jhcA3z6Nidg/EGvl0UFkg7kMdKxfBzzr+o9JF+cevgMg==", + "dev": true, "requires": { "lodash.sortby": "4.7.0", "tr46": "1.0.1", @@ -7141,12 +7682,6 @@ } } }, - "wip-bot": { - "version": "github:gr2m/wip-bot#bc66a0892bae2448f58c4224d6c4909e6abf8d76", - "requires": { - "probot": "5.0.0" - } - }, "wordwrap": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", @@ -7233,7 +7768,8 @@ "xml-name-validator": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", - "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==" + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", + "dev": true }, "xtend": { "version": "2.1.2", diff --git a/package.json b/package.json index ed8206b..aa5f328 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "probot": "^5.0.0", "probot-config": "^0.1.0", "probot-gpg-status": "^0.5.4", + "probot-scheduler": "^1.0.3", "probot-slack-status": "^0.2.2", "unfurl": "github:probot/unfurl", "wip-bot": "github:gr2m/wip-bot" diff --git a/scripts/assign-approved-pr-to-test.js b/scripts/assign-approved-pr-to-test.js index 36da82b..e8041d0 100644 --- a/scripts/assign-approved-pr-to-test.js +++ b/scripts/assign-approved-pr-to-test.js @@ -4,7 +4,8 @@ // // Dependencies: // github: "^13.1.0" -// probot-config "^0.1.0" +// probot-config: "^0.1.0" +// probot-scheduler: "^1.0.3" // probot-slack-status: "^0.2.2" // // Author: @@ -12,6 +13,7 @@ const getConfig = require('probot-config') const defaultConfig = require('../lib/config') +const createScheduler = require('probot-scheduler') const Slack = require('probot-slack-status') let slackClient = null @@ -23,26 +25,84 @@ module.exports = function(robot) { slackClient = slack }) - robot.on('pull_request_review.submitted', context => assignPullRequestToTest(context, robot)) - robot.on('pull_request_review.edited', context => assignPullRequestToTest(context, robot)) + createScheduler(robot, { interval: 10 * 60 * 1000 }) + robot.on('schedule.repository', context => checkOpenPullRequests(robot, context)) } -async function getReviewApprovalState(github, payload) { - const ownerName = payload.repository.owner.login - const repoName = payload.repository.name - const prNumber = payload.pull_request.number +async function getReviewApprovalState(github, robot, repo, pullRequest) { + const ownerName = repo.owner.login + const repoName = repo.name + const prNumber = pullRequest.number + const threshold = 2 - const ghreviews = await github.pullRequests.getReviews({owner: ownerName, repo: repoName, number: prNumber}) - const approvedReviews = ghreviews.data.filter(review => review.state === 'APPROVED') - if (approvedReviews.length >= 2) { - const reviewsWithChangesRequested = ghreviews.data.filter(review => review.state === 'CHANGES_REQUESTED') + var finalReviewsMap = new Map() + const ghreviews = await github.paginate( + github.pullRequests.getReviews({owner: ownerName, repo: repoName, number: prNumber}), + res => res.data) + for (var review of ghreviews) { + finalReviewsMap.set(review.user.id, review.state) + } + var finalReviews = Array.from(finalReviewsMap.values()) + if (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) { - return 'approved' + var isGreen = await isStatusGreen(github, robot, repo, pullRequest) + if (isGreen) { + return 'approved' + } } } return 'pending' } + +async function isStatusGreen(github, robot, repo, pullRequest) { + const ownerName = repo.owner.login + const repoName = repo.name + + // Accumulate all the statuses by chronological order and check if we have a green light + var finalStatesMap = new Map() + const ghstatuses = await github.paginate( + github.repos.getStatuses({owner: ownerName, repo: repoName, ref: pullRequest.head.sha}), + res => res.data) + var sortedStatuses = Array.from(ghstatuses).sort((a, b) => { + if (a.updated_at < b.updated_at) { + return -1 + } + if (a.updated_at > b.updated_at) { + return 1 + } + + // dates must be equal + return 0 + }) + for (var status of sortedStatuses) { + finalStatesMap.set(status.context, status.state) + } + var finalStates = Array.from(finalStatesMap.values()) + const statusStates = finalStates.filter(state => state === 'success') + + if (process.env.DRY_RUN_PR_TO_TEST) { + robot.log.debug(finalStates) + } + + return statusStates.length == finalStates.length +} + +async function getProjectFromName(github, ownerName, repoName, projectBoardName) { + ghprojects = await github.projects.getRepoProjects({ + owner: ownerName, + repo: repoName, + state: "open" + }) + + return ghprojects.data.find(p => p.name === projectBoardName) +} async function getProjectCardForPullRequest(github, robot, columnId, pullRequestUrl) { const ghcards = await github.projects.getProjectCards({column_id: columnId}) @@ -51,51 +111,31 @@ async function getProjectCardForPullRequest(github, robot, columnId, pullRequest return ghcard } -async function assignPullRequestToTest(context, robot) { - // Make sure we don't listen to our own messages - if (context.isBot) { return } - - const payload = context.payload +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 = defaultConfig(robot, '.github/github-bot.yml') - const ownerName = payload.repository.owner.login - const repoName = payload.repository.name - const prNumber = payload.pull_request.number + const projectBoardConfig = config['project-board'] - if (!config['project-board']) { - return; + if (!projectBoardConfig) { + return } - robot.log(`assignPullRequestToTest - Handling Pull Request #${prNumber} on repo ${ownerName}/${repoName}`) - - state = getReviewApprovalState(github, payload) - - const reviewColumnName = config['project-board']['review-column-name'] - const testColumnName = config['project-board']['test-column-name'] - if (state === 'approved') { - srcColumnName = reviewColumnName - dstColumnName = testColumnName - } else { - srcColumnName = testColumnName - dstColumnName = reviewColumnName - } + 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 { - ghprojects = await github.projects.getRepoProjects({ - owner: ownerName, - repo: repoName, - state: "open" - }) - // Find "Pipeline for QA" project - const projectBoardName = config['project-board'].name - const project = ghprojects.data.find(p => p.name === projectBoardName) + project = await getProjectFromName(github, ownerName, repoName, projectBoardConfig.name) if (!project) { - robot.log.error(`Couldn't find project ${projectBoardName} in repo ${ownerName}/${repoName}`) + robot.log.error(`Couldn't find project ${projectBoardConfig.name} in repo ${ownerName}/${repoName}`) return } @@ -104,69 +144,125 @@ async function assignPullRequestToTest(context, robot) { // Fetch column IDs try { ghcolumns = await github.projects.getProjectColumns({ project_id: project.id }) - - const srcColumn = ghcolumns.data.find(c => c.name === srcColumnName) - if (!srcColumn) { - robot.log.error(`Couldn't find ${srcColumnName} column in project ${project.name}`) - return - } - - const dstColumn = ghcolumns.data.find(c => c.name === dstColumnName) - if (!dstColumn) { - robot.log.error(`Couldn't find ${dstColumnName} column in project ${project.name}`) - return - } - - robot.log.debug(`Fetched ${srcColumn.name} (${srcColumn.id}), ${dstColumn.name} (${dstColumn.id}) columns`) - - // Move PR card to the destination column - let ghcard = null - try { - ghcard = await getProjectCardForPullRequest(github, robot, srcColumn.id, payload.pull_request.issue_url) - } catch (err) { - robot.log.error(`Failed to retrieve project card for the PR, aborting: ${err}`, srcColumn.id, payload.pull_request.issue_url) - return - } - - // Send message to Slack - const slackHelper = require('../lib/slack') - - if (ghcard) { - try { - robot.log.trace(`Found card in source column ${ghcard.id}`, srcColumn.id) - - // 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.debug(`Moved card: ${ghcard.url}`, ghcard.id) - } catch (err) { - robot.log.error(`Couldn't move project card for the PR: ${err}`, srcColumn.id, dstColumn.id, payload.pull_request.id) - slackHelper.sendMessage(robot, slackClient, config.slack.notification.room, `I couldn't move the PR to ${dstColumnName} in ${projectBoardName} project :confused:\n${payload.pull_request.html_url}`) - return - } - } else { - try { - robot.log.debug(`Didn't find card in source column`, srcColumn.id) - - // It wasn't in source column, 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: payload.pull_request.id - }) - - robot.log.debug(`Created card: ${ghcard.data.url}`, ghcard.data.id) - } catch (err) { - robot.log.error(`Couldn't create project card for the PR: ${err}`, dstColumn.id, payload.pull_request.id) - return - } - } - - slackHelper.sendMessage(robot, slackClient, config.slack.notification.room, `Assigned PR to ${dstColumnName} in ${projectBoardName} project\n${payload.pull_request.html_url}`) } 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) } } catch (err) { robot.log.error(`Couldn't fetch the github projects for repo: ${err}`, ownerName, repoName) } } + +async function assignPullRequestToCorrectColumn(github, robot, repo, pullRequest, reviewColumn, testColumn, room) { + const ownerName = repo.owner.login + const repoName = repo.name + const prNumber = pullRequest.number + + try { + state = await getReviewApprovalState(github, robot, repo, pullRequest) + } catch (err) { + robot.log.error(`Couldn't calculate the PR approval state: ${err}`, ownerName, repoName, prNumber) + } + + if (state === 'approved') { + srcColumn = reviewColumn + dstColumn = testColumn + } else { + srcColumn = testColumn + dstColumn = reviewColumn + } + + 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 { + ghcard = await getProjectCardForPullRequest(github, robot, srcColumn.id, pullRequest.issue_url) + } catch (err) { + 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) { + // 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}`) + } + 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, robot, dstColumn.id, pullRequest.issue_url) + if (ghcard) { + robot.log.trace(`Found card in target column, ignoring`, ghcard.id, dstColumn.id) + return + } + } catch (err) { + 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) { + // 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) { + // We normally arrive here because there is already a card for the PR in another column + robot.log.debug(`Couldn't create project card for the PR: ${err}`, dstColumn.id, pullRequest.id) + 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}`) + } +} diff --git a/scripts/assign-new-pr-to-review.js b/scripts/assign-new-pr-to-review.js index e6237e1..01e797b 100644 --- a/scripts/assign-new-pr-to-review.js +++ b/scripts/assign-new-pr-to-review.js @@ -4,7 +4,7 @@ // // Dependencies: // github: "^13.1.0" -// probot-config "^0.1.0" +// probot-config: "^0.1.0" // probot-slack-status: "^0.2.2" // // Author: @@ -79,27 +79,31 @@ async function assignPullRequestToReview(context, robot) { } robot.log.debug(`Fetched ${column.name} column (${column.id})`) - - // Create project card for the PR in the REVIEW column - try { - 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) - - // 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}`) - } catch (err) { - robot.log.error(`Couldn't create project card for the PR: ${err}`, column.id, payload.pull_request.id) - } } catch (err) { robot.log.error(`Couldn't fetch the github columns for project: ${err}`, ownerName, repoName, project.id) + return } } catch (err) { 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({ + column_id: column.id, + content_type: 'PullRequest', + content_id: payload.pull_request.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}`) + } catch (err) { + robot.log.error(`Couldn't create project card for the PR: ${err}`, column.id, payload.pull_request.id) } } diff --git a/scripts/assign-to-bounty-awaiting-for-approval.js b/scripts/assign-to-bounty-awaiting-for-approval.js index a09e3e6..1557e44 100644 --- a/scripts/assign-to-bounty-awaiting-for-approval.js +++ b/scripts/assign-to-bounty-awaiting-for-approval.js @@ -4,7 +4,7 @@ // // Dependencies: // github: "^13.1.0" -// probot-config "^0.1.0" +// probot-config: "^0.1.0" // probot-slack-status: "^0.2.2" // // Author: @@ -80,27 +80,31 @@ async function assignIssueToBountyAwaitingForApproval(context, robot) { } robot.log.debug(`Fetched ${column.name} column (${column.id})`) - - // Create project card for the issue in the bounty-awaiting-approval column - try { - ghcard = await github.projects.createProjectCard({ - column_id: column.id, - content_type: 'Issue', - content_id: payload.issue.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 issue to ${approvalColumnName} in ${projectBoardName} project\n${payload.issue.html_url}`) - } catch (err) { - robot.log.error(`Couldn't create project card for the issue: ${err}`, column.id, payload.issue.id) - } } catch (err) { robot.log.error(`Couldn't fetch the github columns for project: ${err}`, ownerName, repoName, project.id) + return } } catch (err) { robot.log.error(`Couldn't fetch the github projects for repo: ${err}`, ownerName, repoName) + return + } + + // Create project card for the issue in the bounty-awaiting-approval column + try { + if (!process.env.DRY_RUN) { + ghcard = await github.projects.createProjectCard({ + column_id: column.id, + content_type: 'Issue', + content_id: payload.issue.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 issue to ${approvalColumnName} in ${projectBoardName} project\n${payload.issue.html_url}`) + } catch (err) { + robot.log.error(`Couldn't create project card for the issue: ${err}`, column.id, payload.issue.id) } } diff --git a/scripts/greet-new-contributor.js b/scripts/greet-new-contributor.js index 993fa64..d430499 100644 --- a/scripts/greet-new-contributor.js +++ b/scripts/greet-new-contributor.js @@ -4,7 +4,7 @@ // // Dependencies: // github: "^13.1.0" -// probot-config "^0.1.0" +// probot-config: "^0.1.0" // probot-slack-status: "^0.2.2" // // Author: @@ -59,12 +59,14 @@ async function greetNewContributor(context, robot) { if (userPullRequests.length === 1) { try { const welcomeMessage = config['welcome-bot'].message - await github.issues.createComment({ - owner: ownerName, - repo: repoName, - number: prNumber, - body: welcomeMessage - }) + if (!process.env.DRY_RUN) { + await github.issues.createComment({ + owner: ownerName, + repo: repoName, + number: prNumber, + body: welcomeMessage + }) + } // Send message to Slack const slackHelper = require('../lib/slack')