├── .eslintrc ├── .travis.yml ├── CONTRIBUTING ├── LICENSE ├── OWNERS.yaml ├── README.md ├── app.yaml ├── gce └── startup-script.sh ├── index.js ├── package.json ├── src ├── git.js ├── github.js ├── owner.js └── repo-file.js ├── test ├── fixtures │ ├── actions │ │ ├── opened.35.json │ │ ├── opened.36.author-is-owner.json │ │ ├── pull_request_review.35.submitted.json │ │ └── rerequested.35.json │ ├── check-runs │ │ ├── check-runs.create.json │ │ ├── check-runs.get.35.empty.json │ │ ├── check-runs.get.35.json │ │ └── check-runs.get.35.multiple.json │ ├── files │ │ ├── files.35.json │ │ ├── files.35.multiple.json │ │ └── files.36.json │ ├── pulls │ │ └── pull_request.35.json │ ├── reviews │ │ ├── reviews.35.approved.json │ │ └── reviews.35.json │ └── teams │ │ └── teams.json └── index.test.js └── yarn.lock /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "parserOptions": { 4 | "ecmaVersion": 6, 5 | "sourceType": "module", 6 | "ecmaFeatures": { 7 | "modules": true, 8 | "arrowFunctions": true, 9 | "blockBindings": true, 10 | "forOf": false, 11 | "destructuring": true, 12 | "spread": true 13 | } 14 | }, 15 | "env": { 16 | "es6": true, 17 | "node": true 18 | }, 19 | "globals": { 20 | "it": false, 21 | "chai": false, 22 | "expect": false, 23 | "describe": false, 24 | "beforeEach": false, 25 | "afterEach": false, 26 | "before": false, 27 | "after": false, 28 | "AMP": false, 29 | "assert": false, 30 | "sinon": true, 31 | "sandbox": true, 32 | "context": false, 33 | "global": false, 34 | "describes": true, 35 | "OwnersMap": false, 36 | "GitHubStatusPost": false, 37 | "FileOwner": false, 38 | "FileOwners": false, 39 | "PullRequestInfo": false 40 | }, 41 | "rules": { 42 | "array-bracket-spacing": [2, "never"], 43 | "arrow-parens": [2, "as-needed"], 44 | "arrow-spacing": 2, 45 | "comma-dangle": [2, "always-multiline"], 46 | "computed-property-spacing": [2, "never"], 47 | "curly": 2, 48 | "dot-location": [2, "property"], 49 | "eol-last": 2, 50 | "indent": [2, 2, { "SwitchCase": 1 }], 51 | "key-spacing": 2, 52 | "max-len": [2, 80, 4, { 53 | "ignoreComments": true, 54 | "ignoreUrls": true, 55 | "ignorePattern": "" 56 | }], 57 | "no-alert": 2, 58 | "no-debugger": 2, 59 | "no-div-regex": 2, 60 | "no-dupe-keys": 2, 61 | "no-eval": 2, 62 | "no-extend-native": 2, 63 | "no-extra-bind": 2, 64 | "no-implicit-coercion": [2, { "boolean": false }], 65 | "no-implied-eval": 2, 66 | "no-iterator": 2, 67 | "no-lone-blocks": 2, 68 | "no-multi-spaces": 2, 69 | "no-native-reassign": 2, 70 | "no-redeclare": 2, 71 | "no-script-url": 2, 72 | "no-self-compare": 2, 73 | "no-sequences": 2, 74 | "no-spaced-func": 2, 75 | "no-throw-literal": 2, 76 | "no-trailing-spaces": 2, 77 | "no-unused-expressions": 0, 78 | "no-unused-vars": [2, { 79 | "argsIgnorePattern": "^var_|opt_|unused", 80 | "varsIgnorePattern": "AmpElement|Def|Interface$" 81 | }], 82 | "no-var": 2, 83 | "no-useless-call": 2, 84 | "no-useless-concat": 2, 85 | "no-undef": 2, 86 | "no-warning-comments": [2, { "terms": ["do not submit"], "location": "anywhere" }], 87 | "object-curly-spacing": [2, "never", { 88 | "objectsInObjects": false, 89 | "arraysInObjects": false 90 | }], 91 | "prefer-const": 2, 92 | "quotes": [2, "single", "avoid-escape"], 93 | "radix": 2, 94 | "semi": 2, 95 | "space-before-blocks": 2, 96 | "space-before-function-paren": [2, "never"], 97 | "space-in-parens": 2, 98 | "space-infix-ops": 2, 99 | "space-unary-ops": [1, { "words": true, "nonwords": false }], 100 | "keyword-spacing": 2, 101 | "wrap-iife": [2, "any"] 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | sudo: required # See http://docs.travis-ci.com/user/trusty-ci-environment/ 3 | dist: trusty 4 | node_js: 5 | - "lts/*" 6 | script: 7 | - npm run test 8 | cache: 9 | yarn: true 10 | directories: 11 | - node_modules 12 | group: deprecated # https://github.com/travis-ci/travis-ci/issues/6928 13 | -------------------------------------------------------------------------------- /CONTRIBUTING: -------------------------------------------------------------------------------- 1 | Want to contribute? Great! First, read this page (including the small print at the end). 2 | 3 | ### Before you contribute 4 | Before we can use your code, you must sign the 5 | [Google Individual Contributor License Agreement] 6 | (https://cla.developers.google.com/about/google-individual) 7 | (CLA), which you can do online. The CLA is necessary mainly because you own the 8 | copyright to your changes, even after your contribution becomes part of our 9 | codebase, so we need your permission to use and distribute your code. We also 10 | need to be sure of various other things—for instance that you'll tell us if you 11 | know that your code infringes on other people's patents. You don't have to sign 12 | the CLA until after you've submitted your code for review and a member has 13 | approved it, but you must do it before we can put your code into our codebase. 14 | Before you start working on a larger contribution, you should get in touch with 15 | us first through the issue tracker with your idea so that we can help out and 16 | possibly guide you. Coordinating up front makes it much easier to avoid 17 | frustration later on. 18 | 19 | ### Code reviews 20 | All submissions, including submissions by project members, require review. We 21 | use GitHub pull requests for this purpose. 22 | 23 | ### The small print 24 | Contributions made by corporations are covered by a different agreement than 25 | the one above, the 26 | [Software Grant and Corporate Contributor License Agreement] 27 | (https://cla.developers.google.com/about/google-corporate). 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright 2016, Google Inc. 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /OWNERS.yaml: -------------------------------------------------------------------------------- 1 | - erwinmombay 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 16 | 17 | # Github Owners Bot 18 | 19 | A web service that suggests approvers for a GitHub pull request based on OWNERS 20 | files and enforces reviews by OWNERS as a GitHub status check. 21 | 22 | ## Getting Started 23 | 24 | - Clone the github-owners-bot repository. 25 | `git clone git@github.com:google/github-owners-bot.git ${directory}` 26 | 27 | - Clone the target repository to be evaluated. 28 | The github-owners-bot app requires a local copy of the target repository that 29 | we evaluate. You will need to set the `GITHUB_REPO_DIR` environment variable 30 | to the path of that target repository. 31 | ex. `git clone git@github.com:ampproject/amphtml.git ${target_directory}` 32 | 33 | - Set the `REPO_DIR` environment variable to the `target_repository` path 34 | that was used in the step above. 35 | 36 | - Set the `APP_ID` environment variable to your GitHub probot application. 37 | 38 | - Set the `NODE_ENV` environment variable to "development". 39 | 40 | - Set the `WEBHOOK_SECRET` environment variable to match what you set up 41 | on your GitHub Webhook pages. 42 | 43 | - Install the `amp-owners-bot` GitHub on the remote target repository (This should 44 | be the same repository that you had closed for the local target repository) 45 | 46 | - Go back into the `github-owners-bot` directory and run `yarn`. 47 | 48 | - Run `npm run dev` to start the local server. You can also run `LOG_LEVEL=trace npm run dev` 49 | for maximum logging while developing the application. 50 | -------------------------------------------------------------------------------- /app.yaml: -------------------------------------------------------------------------------- 1 | runtime: nodejs 2 | vm: true 3 | 4 | # Temporary setting to keep gcloud from uploading node_modules 5 | skip_files: 6 | - ^node_modules$ 7 | -------------------------------------------------------------------------------- /gce/startup-script.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | # Copyright 2015-2016, Google, Inc. 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # [START startup] 16 | set -v 17 | 18 | REPO="my/repo" 19 | APP_DIR="/opt/app" 20 | REPO_DIR="/opt/repo" 21 | GITHUB_BOT_USERNAME="mybotsname" 22 | SECRET_TOKEN="mysecrettoken" 23 | CLOUD_BUCKET="gs://my-cloud-bucket" 24 | GITHUB_ACCESS_TOKEN="" 25 | OAUTH2_CLIENT_ID="" 26 | OAUTH2_CLIENT_SECRET="" 27 | 28 | # Talk to the metadata server to get the project id 29 | PROJECTID=$(curl -s "http://metadata.google.internal/computeMetadata/v1/project/project-id" -H "Metadata-Flavor: Google") 30 | 31 | 32 | # Install logging monitor. The monitor will automatically pick up logs sent to 33 | # syslog. 34 | # [START logging] 35 | curl -s "https://storage.googleapis.com/signals-agents/logging/google-fluentd-install.sh" | bash 36 | service google-fluentd restart & 37 | # [END logging] 38 | 39 | # Install dependencies from apt 40 | apt-get update 41 | apt-get install -yq ca-certificates git nodejs build-essential supervisor 42 | 43 | # Install nodejs 44 | mkdir /opt/nodejs 45 | curl https://nodejs.org/dist/v6.9.1/node-v6.9.1-linux-x64.tar.gz | tar xvzf - -C /opt/nodejs --strip-components=1 46 | ln -s /opt/nodejs/bin/node /usr/bin/node 47 | ln -s /opt/nodejs/bin/npm /usr/bin/npm 48 | 49 | # Get the application source code from the Google Cloud Repository. 50 | # git requires $HOME and it's not set during the startup script. 51 | export HOME=/root 52 | git config --global credential.helper gcloud.sh 53 | git clone https://source.developers.google.com/p/$PROJECTID "${APP_DIR}" 54 | 55 | # Install app dependencies 56 | cd "${APP_DIR}" 57 | npm install 58 | npm run start 59 | 60 | git clone "https://github.com/${REPO}.git" "${REPO_DIR}" 61 | 62 | # Create a nodeapp user. The application will run as this user. 63 | useradd -m -d /home/nodeapp nodeapp 64 | chown -R nodeapp:nodeapp "${APP_DIR}" 65 | chown -R nodeapp:nodeapp "${REPO_DIR}" 66 | 67 | # Configure supervisor to run the node app. 68 | cat >/etc/supervisor/conf.d/node-app.conf << EOF 69 | [program:nodeapp] 70 | directory=${APP_DIR} 71 | command=npm start 72 | autostart=true 73 | autorestart=true 74 | user=nodeapp 75 | environment=HOME="/home/nodeapp",USER="nodeapp",NODE_ENV="production",GCLOUD_PROJECT="${PROJECTID}",CLOUD_BUCKET="${CLOUD_BUCKET}",DATA_BACKEND="datastore",OAUTH2_CLIENT_ID="${OAUTH2_CLIENT_ID}",OAUTH2_CLIENT_SECRET="${OAUTH2_CLIENT_SECRET}",GITHUB_ACCESS_TOKEN="${GITHUB_ACCESS_TOKEN}",GITHUB_REPO_DIR="${REPO_DIR}",SECRET_TOKEN="${SECRET_TOKEN}",GITHUB_BOT_USERNAME="${GITHUB_BOT_USERNAME}" 76 | stdout_logfile=syslog 77 | stderr_logfile=syslog 78 | EOF 79 | 80 | supervisorctl reread 81 | supervisorctl update 82 | 83 | # Application should now be running under supervisor 84 | # [END startup] 85 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS-IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | const {PullRequest, Teams} = require('./src/github'); 18 | 19 | module.exports = app => { 20 | app.on(['pull_request.opened', 'pull_request.synchronized'], onPullRequest) 21 | app.on('check_run.rerequested', onCheckRunRerequest) 22 | app.on('pull_request_review.submitted', onPullRequestReview); 23 | 24 | // Probot does not stream properly to GCE logs so we need to hook into 25 | // bunyan explicitly and stream it to process.stdout. 26 | app.log.target.addStream({ 27 | name: 'app-custom-stream', 28 | stream: process.stdout, 29 | level: process.LOG_LEVEL || 'info', 30 | }); 31 | 32 | async function processPullRequest(context, pullRequest) { 33 | const pr = new PullRequest(context, pullRequest); 34 | const teams = await new Teams(context).list(); 35 | return await pr.processOpened(); 36 | } 37 | 38 | async function onPullRequest(context) { 39 | return await processPullRequest(context, context.payload.pull_request); 40 | } 41 | 42 | async function onCheckRunRerequest(context) { 43 | const payload = context.payload; 44 | const pr = await PullRequest.get(context, payload.repository.owner.login, 45 | payload.repository.name, payload.check_run.check_suite.pull_requests[0].number); 46 | 47 | return await processPullRequest(context, pr.data); 48 | } 49 | 50 | async function onPullRequestReview(context) { 51 | const payload = context.payload; 52 | const pr = await PullRequest.get(context, payload.repository.owner.login, 53 | payload.repository.name, payload.pull_request.number); 54 | 55 | return await processPullRequest(context, pr.data); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "github-owners-bot", 3 | "author": "Google Inc.", 4 | "private": true, 5 | "version": "0.0.1", 6 | "repository": "http://github.com/ampproject/github-owners-bot", 7 | "description": "A web service that suggests approvers for a GitHub pull request based on OWNERS files and enforces reviews by OWNERS as a GitHub status check.", 8 | "engines": { 9 | "node": "^10.11" 10 | }, 11 | "scripts": { 12 | "dev": "nodemon", 13 | "start": "probot run ./index.js", 14 | "test": "jest", 15 | "test:watch": "jest --watch --notify --notifyMode=change" 16 | }, 17 | "license": "Apache-2.0", 18 | "dependencies": { 19 | "lodash": "4.17.11", 20 | "probot": "7.5.0", 21 | "sleep-promise": "8.0.1", 22 | "yamljs": "0.3.0" 23 | }, 24 | "devDependencies": { 25 | "jest": "23.6.0", 26 | "nock": "10.0.6", 27 | "nodemon": "1.18.9", 28 | "sinon": "7.2.3", 29 | "smee-client": "1.0.2" 30 | }, 31 | "standard": { 32 | "env": [ 33 | "jest" 34 | ] 35 | }, 36 | "nodemonConfig": { 37 | "exec": "npm start", 38 | "watch": [ 39 | ".env", 40 | "." 41 | ] 42 | }, 43 | "jest": { 44 | "testEnvironment": "node" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/git.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2016 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS-IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | const {Owner, createOwnersMap} = require('./owner'); 18 | const child_process = require('child_process'); 19 | const yaml = require('yamljs'); 20 | const path = require('path'); 21 | const util = require('util'); 22 | const exec = util.promisify(require('child_process').exec); 23 | const fs = require('fs').promises; 24 | 25 | const matcher = /your branch is up-to-date|your branch is up to date/i; 26 | 27 | function yamlReader(str) { 28 | return yaml.parse(str); 29 | } 30 | 31 | class Git { 32 | 33 | constructor(context) { 34 | this.context = context; 35 | } 36 | 37 | /** 38 | * Reads the actual OWNER file on the file system and parses it using the 39 | * passed in `formatReader` and returns an `OwnersMap`. 40 | */ 41 | async ownersParser(formatReader, pathToRepoDir, ownersPaths) { 42 | const promises = ownersPaths.map(ownerPath => { 43 | const fullPath = path.resolve(pathToRepoDir, ownerPath); 44 | return fs.readFile(fullPath).then(file => { 45 | const config = formatReader(file.toString()); 46 | if (!config) { 47 | const str = `No config found for ${fullPath}`; 48 | this.context.log.error(str); 49 | // This handles OWNERS.yaml files that are empty. 50 | return null; 51 | } 52 | return new Owner(config, pathToRepoDir, ownerPath); 53 | }); 54 | }); 55 | return Promise.all(promises).then(createOwnersMap); 56 | } 57 | 58 | /** 59 | * Retrieves all the OWNERS paths inside a repository. 60 | * @return {!Promise} 61 | */ 62 | async getOwnersFilesForBranch(author, dirPath, targetBranch) { 63 | // NOTE: for some reason `git ls-tree --full-tree -r HEAD **/OWNERS* 64 | // doesn't work from here. 65 | const cmd = `cd ${dirPath} && git checkout ${targetBranch} ` + 66 | '&& git ls-tree --full-tree -r HEAD | ' + 67 | 'cut -f2 | grep OWNERS.yaml$'; 68 | const {stdout, stderr} = await exec(cmd); 69 | if (stderr) { 70 | // TODO: Usually stderr here might occur when branch is already master. 71 | this.context.log.warn(['getOwnersFilesForBranch'], stderr); 72 | } 73 | this.context.log.debug('[getOwnersFilesForBranch]', stdout); 74 | // Construct the owners map. 75 | const ownersPaths = stdoutToArray(stdout) 76 | // Remove unneeded string. We only want the file paths. 77 | .filter(x => !(matcher.test(x))); 78 | return this.ownersParser(yamlReader, dirPath, ownersPaths, author); 79 | } 80 | 81 | /** 82 | * cd's into an assumed git directory on the file system and does a hard 83 | * reset to the remote branch. 84 | */ 85 | pullLatestForRepo(dirPath, remote, branch) { 86 | const cmd = `cd ${dirPath} && git fetch ${remote} ${branch} && ` + 87 | `git checkout -B ${branch} ${remote}/${branch}`; 88 | return exec(cmd); 89 | } 90 | } 91 | 92 | function stdoutToArray(res) { 93 | return res.split('\n').filter(x => !!x); 94 | } 95 | 96 | module.exports = {Git}; 97 | -------------------------------------------------------------------------------- /src/github.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2016 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS-IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | const {RepoFile} = require('./repo-file'); 18 | const {Owner} = require('./owner'); 19 | const {Git} = require('./git'); 20 | const _ = require('lodash'); 21 | const sleep = require('sleep-promise'); 22 | 23 | 24 | /** 25 | * Maps the github json payload to a simpler data structure. 26 | */ 27 | class PullRequest { 28 | 29 | constructor(context, pr) { 30 | 31 | this.name = 'ampproject/owners-check'; 32 | 33 | this.nameMatcher = new RegExp('owners bot|owners-check', 'i'); 34 | 35 | this.git = new Git(context); 36 | this.context = context; 37 | this.github = context.github; 38 | 39 | this.id = pr.number; 40 | this.author = pr.user.login; 41 | this.state = pr.state; 42 | 43 | this.owner = pr.base.repo.owner.login; 44 | this.repo = pr.base.repo.name; 45 | 46 | // Ref here is the branch name 47 | this.headRef = pr.head.ref; 48 | this.headSha = pr.head.sha; 49 | 50 | // Base is usually master 51 | this.baseRef = pr.base.ref; 52 | this.baseSha = pr.base.sha; 53 | 54 | this.options = { 55 | owner: this.owner, 56 | repo: this.repo, 57 | }; 58 | } 59 | 60 | async processOpened() { 61 | const prInfo = await this.getMeta(); 62 | let reviewers = Object.values(prInfo.fileOwners).map(fileOwner => { 63 | return fileOwner.owner.dirOwners; 64 | }); 65 | reviewers = _.union(...reviewers); 66 | const checkOutputText = this.buildCheckOutput(prInfo); 67 | const checkRuns = await this.getCheckRun(); 68 | const {hasCheckRun, checkRun} = this.hasCheckRun(checkRuns); 69 | if (hasCheckRun) { 70 | return this.updateCheckRun(checkRun, checkOutputText, 71 | prInfo.approvalsMet); 72 | } 73 | return this.createCheckRun(checkOutputText, prInfo.approvalsMet); 74 | } 75 | 76 | async getMeta() { 77 | const fileOwners = await Owner.getOwners(this.git, this); 78 | const reviews = await this.getUniqueReviews(); 79 | this.context.log.debug('[getMeta]', reviews); 80 | const approvalsMet = this.areAllApprovalsMet(fileOwners, reviews); 81 | const reviewersWhoApproved = this.getReviewersWhoApproved(reviews); 82 | return {fileOwners, reviews, approvalsMet, reviewersWhoApproved}; 83 | } 84 | 85 | /** 86 | * Retrieves the pull request json payload from the github API 87 | * and pulls out the files that have been changed in any way 88 | * and returns type RepoFile[]. 89 | * @return {!Promise>} 90 | */ 91 | async listFiles() { 92 | const res = await this.github.pullRequests.listFiles({ 93 | number: this.id, 94 | ...this.options, 95 | }); 96 | this.context.log.debug('[listFiles]', res.data); 97 | return res.data.map(item => new RepoFile(item.filename)); 98 | } 99 | 100 | async getUniqueReviews() { 101 | const reviews = await this.getReviews(); 102 | // This should always pick out the first instance. 103 | return _.uniqBy(reviews, 'username'); 104 | } 105 | 106 | async getReviews() { 107 | const res = await this.github.pullRequests.listReviews({ 108 | number: this.id, 109 | ...this.options, 110 | }); 111 | this.context.log.debug('[getReviews]', res.data); 112 | // Sort by latest submitted_at date first since users and state 113 | // are not unique. 114 | const reviews = res.data.map(x => new Review(x)).sort((a, b) => { 115 | return b.submitted_at - a.submitted_at; 116 | }); 117 | return reviews; 118 | } 119 | 120 | /** 121 | * @param {!Array} 122 | * @return {!Promise} 123 | */ 124 | async setReviewers(reviewers) { 125 | } 126 | 127 | areAllApprovalsMet(fileOwners, reviews) { 128 | const reviewersWhoApproved = this.getReviewersWhoApproved(reviews); 129 | return Object.keys(fileOwners).every(path => { 130 | const fileOwner = fileOwners[path]; 131 | const owner = fileOwner.owner; 132 | _.intersection(owner.dirOwners, reviewersWhoApproved); 133 | return _.intersection(owner.dirOwners, reviewersWhoApproved).length > 0; 134 | }); 135 | } 136 | 137 | getReviewersWhoApproved(reviews) { 138 | const reviewersWhoApproved = reviews.filter(x => { 139 | return x.state === 'approved'; 140 | }).map(x => x.username); 141 | // If you're the author, then you yourself are assumed to approve your own 142 | // PR. 143 | reviewersWhoApproved.push(this.author); 144 | return reviewersWhoApproved; 145 | } 146 | 147 | 148 | async createCheckRun(text, areApprovalsMet) { 149 | // We need to add a delay on the PR creation and check creation since 150 | // GitHub might not be ready. 151 | await sleep(2000); 152 | const conclusion = areApprovalsMet ? 'success' : 'failure'; 153 | return this.github.checks.create(this.context.repo({ 154 | name: this.name, 155 | head_branch: this.headRef, 156 | head_sha: this.headSha, 157 | status: 'completed', 158 | conclusion: 'neutral', 159 | completed_at: new Date(), 160 | output: { 161 | title: this.name, 162 | summary: `The check was a ${conclusion}!`, 163 | text, 164 | } 165 | })); 166 | } 167 | 168 | async updateCheckRun(checkRun, text, areApprovalsMet) { 169 | this.context.log.debug('[updateCheckRun]', checkRun); 170 | const conclusion = areApprovalsMet ? 'success' : 'failure'; 171 | return this.github.checks.update(this.context.repo({ 172 | check_run_id: checkRun.id, 173 | status: 'completed', 174 | conclusion: 'neutral', 175 | name: this.name, 176 | completed_at: new Date(), 177 | output: { 178 | title: this.name, 179 | summary: `The check was a ${conclusion}!`, 180 | text, 181 | } 182 | })); 183 | } 184 | 185 | async getCheckRun() { 186 | const res = await this.github.checks.listForRef({ 187 | owner: this.owner, 188 | repo: this.repo, 189 | ref: this.headSha, 190 | }); 191 | this.context.log.debug('[getCheckRun]', res); 192 | return res.data; 193 | } 194 | 195 | /** 196 | * @return {{hasChecRun: boolean, checkRun: !Object|undefined}} 197 | */ 198 | hasCheckRun(checkRuns) { 199 | const hasCheckRun = checkRuns.total_count > 0; 200 | const [checkRun] = checkRuns.check_runs.filter(x => { 201 | return x.head_sha === this.headSha && this.nameMatcher.test(x.name); 202 | }); 203 | const tuple = {hasCheckRun: hasCheckRun && !!checkRun, checkRun}; 204 | this.context.log.debug('[hasCheckRun]', tuple); 205 | return tuple; 206 | } 207 | 208 | /** 209 | * @return {string} 210 | */ 211 | buildCheckOutput(prInfo) { 212 | let text = Object.values(prInfo.fileOwners) 213 | .filter(fileOwner => { 214 | // Omit sections that has a required reviewer who has approved. 215 | return !_.intersection(prInfo.reviewersWhoApproved, 216 | fileOwner.owner.dirOwners).length; 217 | }).map(fileOwner => { 218 | const fileOwnerHeader = `## possible reviewers: ${fileOwner.owner.dirOwners.join(', ')}`; 219 | const files = fileOwner.files.map(file => { 220 | return ` - ${file.path}\n`; 221 | }).join(''); 222 | return `\n${fileOwnerHeader}\n${files}`; 223 | }).join(''); 224 | this.context.log.debug('[buildCheckOutput]', text); 225 | return text; 226 | } 227 | 228 | static async get(context, owner, repo, number) { 229 | return await context.github.pullRequests.get(context.repo({ 230 | number, 231 | })); 232 | } 233 | } 234 | 235 | class PullRequestComment { 236 | 237 | constructor(json) { 238 | this.id = json.id; 239 | this.type = 'pull_request_review_id' in json ? 'pulls' : 'issues'; 240 | this.author = json.user.login; 241 | this.body = json.body; 242 | this.createdAt = new Date(json.created_at); 243 | this.updatedAt = new Date(json.updated_at); 244 | this.url = json.url; 245 | } 246 | } 247 | 248 | class Label { 249 | 250 | constructor(json) { 251 | this.id = json.id; 252 | this.url = json.url; 253 | this.name = json.name; 254 | this.color = json.color; 255 | this.default = json.default; 256 | } 257 | } 258 | 259 | class Sender { 260 | 261 | constructor(json) { 262 | this.username = json.login; 263 | } 264 | } 265 | 266 | class Review { 267 | 268 | constructor(json) { 269 | this.id = json.id; 270 | this.username = json.user.login; 271 | this.state = json.state.toLowerCase(); 272 | this.submitted_at = new Date(json.submitted_at); 273 | } 274 | 275 | isApproved() { 276 | return this.state == 'approved'; 277 | } 278 | } 279 | 280 | class Teams { 281 | 282 | constructor(context) { 283 | this.context = context; 284 | this.github = context.github; 285 | } 286 | 287 | async list() { 288 | return this.github.repos.listTeams(this.context.repo()); 289 | } 290 | } 291 | 292 | module.exports = {PullRequest, PullRequestComment, Label, Sender, Review, Teams}; 293 | -------------------------------------------------------------------------------- /src/owner.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2016 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS-IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | const path = require('path'); 18 | 19 | /** 20 | * @fileoverview Contains classes and functions in relation to "OWNER" files 21 | * and theyre evaluation. 22 | */ 23 | 24 | /** 25 | * Represents an OWNER file found in the repo. 26 | */ 27 | class Owner { 28 | 29 | constructor(config, pathToRepoDir, filePath) { 30 | // We want it have the leading ./ to evaluate `.` later on 31 | this.path = /^\./.test(filePath) ? filePath : `.${path.sep}${filePath}`; 32 | this.dirname = path.dirname(this.path); 33 | this.fullpath = path.join(pathToRepoDir, this.path); 34 | this.score = (this.dirname.match(/\//g) || []).length; 35 | 36 | this.dirOwners = []; 37 | this.fileOwners = Object.create(null); 38 | this.parseConfig_(config); 39 | } 40 | 41 | /** 42 | * @param {!Object} config 43 | */ 44 | parseConfig_(config) { 45 | config.forEach(entry => { 46 | if (typeof entry === 'string') { 47 | this.dirOwners.push(entry); 48 | } 49 | }); 50 | this.dirOwners.sort(); 51 | } 52 | 53 | /** 54 | * @param {!Git} git 55 | * @param {!PullRequest} pr 56 | */ 57 | static async getOwners(git, pr) { 58 | // Update the local target repository of the latest from master 59 | git.pullLatestForRepo(process.env.GITHUB_REPO_DIR, 'origin', 'master'); 60 | const promises = Promise.all([ 61 | pr.listFiles(), 62 | git.getOwnersFilesForBranch(pr.author, process.env.GITHUB_REPO_DIR, 63 | 'master'), 64 | ]); 65 | const res = await promises; 66 | const [files, ownersMap] = res; 67 | const owners = findOwners(files, ownersMap); 68 | pr.context.log.debug('[getOwners]', owners); 69 | return owners; 70 | } 71 | } 72 | 73 | /** 74 | * Returns a list of github usernames that can be "approvers" for the set 75 | * of files. It first tries to find the interection across the files and if 76 | * there are none it will return the union across usernames. 77 | */ 78 | function findOwners(files, ownersMap) { 79 | const fileOwners = Object.create(null); 80 | files.forEach(file => { 81 | const owner = findClosestOwnersFile(file, ownersMap); 82 | if (!fileOwners[owner.dirname]) { 83 | fileOwners[owner.dirname] = { 84 | owner, 85 | files: [file], 86 | }; 87 | } else { 88 | fileOwners[owner.dirname].files.push(file); 89 | } 90 | }); 91 | return fileOwners; 92 | } 93 | 94 | /** 95 | * Using the `ownersMap` key which is the path to the actual OWNER file 96 | * in the repo, we simulate a folder traversal by splitting the path and 97 | * finding the closest OWNER file for a RepoFile. 98 | */ 99 | function findClosestOwnersFile(file, ownersMap) { 100 | let dirname = file.dirname; 101 | let owner = ownersMap[dirname]; 102 | const dirs = dirname.split(path.sep); 103 | 104 | while (!owner && dirs.pop() && dirs.length) { 105 | dirname = dirs.join(path.sep); 106 | owner = ownersMap[dirname]; 107 | } 108 | return owner; 109 | } 110 | 111 | function createOwnersMap(owners) { 112 | return owners.reduce((ownersMap, owner) => { 113 | // Handles empty OWNERS.yaml files. 114 | if (!owner) { 115 | return ownersMap; 116 | } 117 | if (owner.dirOwners.length) { 118 | ownersMap[owner.dirname] = owner; 119 | } 120 | return ownersMap; 121 | }, Object.create(null)); 122 | } 123 | 124 | module.exports = {Owner, findOwners, findClosestOwnersFile, createOwnersMap}; 125 | -------------------------------------------------------------------------------- /src/repo-file.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2016 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS-IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | const path = require('path'); 18 | 19 | /** 20 | * Represents the File that has been changed from the repository. 21 | * This is hydrated from the github pull request api. 22 | */ 23 | class RepoFile { 24 | 25 | constructor(filePath) { 26 | // We want it have the leading ./ to evaluate `.` later on 27 | this.path = /^\./.test(filePath) ? filePath : `.${path.sep}${filePath}`; 28 | this.dirname = path.dirname(this.path); 29 | } 30 | } 31 | 32 | module.exports = {RepoFile}; 33 | -------------------------------------------------------------------------------- /test/fixtures/actions/opened.35.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": "opened", 3 | "number": 35, 4 | "pull_request": { 5 | "url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls/35", 6 | "id": 246688458, 7 | "node_id": "MDExOlB1bGxSZXF1ZXN0MjQ2Njg4NDU4", 8 | "html_url": "https://github.com/erwinmombay/github-owners-bot-test-repo/pull/35", 9 | "diff_url": "https://github.com/erwinmombay/github-owners-bot-test-repo/pull/35.diff", 10 | "patch_url": "https://github.com/erwinmombay/github-owners-bot-test-repo/pull/35.patch", 11 | "issue_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues/35", 12 | "number": 35, 13 | "state": "open", 14 | "locked": false, 15 | "title": "Update file.txt", 16 | "user": { 17 | "login": "ampprojectbot", 18 | "id": 23269078, 19 | "node_id": "MDQ6VXNlcjIzMjY5MDc4", 20 | "avatar_url": "https://avatars3.githubusercontent.com/u/23269078?v=4", 21 | "gravatar_id": "", 22 | "url": "https://api.github.com/users/ampprojectbot", 23 | "html_url": "https://github.com/ampprojectbot", 24 | "followers_url": "https://api.github.com/users/ampprojectbot/followers", 25 | "following_url": "https://api.github.com/users/ampprojectbot/following{/other_user}", 26 | "gists_url": "https://api.github.com/users/ampprojectbot/gists{/gist_id}", 27 | "starred_url": "https://api.github.com/users/ampprojectbot/starred{/owner}{/repo}", 28 | "subscriptions_url": "https://api.github.com/users/ampprojectbot/subscriptions", 29 | "organizations_url": "https://api.github.com/users/ampprojectbot/orgs", 30 | "repos_url": "https://api.github.com/users/ampprojectbot/repos", 31 | "events_url": "https://api.github.com/users/ampprojectbot/events{/privacy}", 32 | "received_events_url": "https://api.github.com/users/ampprojectbot/received_events", 33 | "type": "User", 34 | "site_admin": false 35 | }, 36 | "body": "", 37 | "created_at": "2019-01-22T17:22:51Z", 38 | "updated_at": "2019-01-22T17:22:51Z", 39 | "closed_at": null, 40 | "merged_at": null, 41 | "merge_commit_sha": null, 42 | "assignee": null, 43 | "assignees": [ 44 | 45 | ], 46 | "requested_reviewers": [ 47 | 48 | ], 49 | "requested_teams": [ 50 | 51 | ], 52 | "labels": [ 53 | 54 | ], 55 | "milestone": null, 56 | "commits_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls/35/commits", 57 | "review_comments_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls/35/comments", 58 | "review_comment_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls/comments{/number}", 59 | "comments_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues/35/comments", 60 | "statuses_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/statuses/9272f18514cbd3fa935b3ced62ae1c2bf6efa76d", 61 | "head": { 62 | "label": "erwinmombay:ampprojectbot-patch-3", 63 | "ref": "ampprojectbot-patch-3", 64 | "sha": "9272f18514cbd3fa935b3ced62ae1c2bf6efa76d", 65 | "user": { 66 | "login": "erwinmombay", 67 | "id": 354746, 68 | "node_id": "MDQ6VXNlcjM1NDc0Ng==", 69 | "avatar_url": "https://avatars1.githubusercontent.com/u/354746?v=4", 70 | "gravatar_id": "", 71 | "url": "https://api.github.com/users/erwinmombay", 72 | "html_url": "https://github.com/erwinmombay", 73 | "followers_url": "https://api.github.com/users/erwinmombay/followers", 74 | "following_url": "https://api.github.com/users/erwinmombay/following{/other_user}", 75 | "gists_url": "https://api.github.com/users/erwinmombay/gists{/gist_id}", 76 | "starred_url": "https://api.github.com/users/erwinmombay/starred{/owner}{/repo}", 77 | "subscriptions_url": "https://api.github.com/users/erwinmombay/subscriptions", 78 | "organizations_url": "https://api.github.com/users/erwinmombay/orgs", 79 | "repos_url": "https://api.github.com/users/erwinmombay/repos", 80 | "events_url": "https://api.github.com/users/erwinmombay/events{/privacy}", 81 | "received_events_url": "https://api.github.com/users/erwinmombay/received_events", 82 | "type": "User", 83 | "site_admin": false 84 | }, 85 | "repo": { 86 | "id": 72889098, 87 | "node_id": "MDEwOlJlcG9zaXRvcnk3Mjg4OTA5OA==", 88 | "name": "github-owners-bot-test-repo", 89 | "full_name": "erwinmombay/github-owners-bot-test-repo", 90 | "private": false, 91 | "owner": { 92 | "login": "erwinmombay", 93 | "id": 354746, 94 | "node_id": "MDQ6VXNlcjM1NDc0Ng==", 95 | "avatar_url": "https://avatars1.githubusercontent.com/u/354746?v=4", 96 | "gravatar_id": "", 97 | "url": "https://api.github.com/users/erwinmombay", 98 | "html_url": "https://github.com/erwinmombay", 99 | "followers_url": "https://api.github.com/users/erwinmombay/followers", 100 | "following_url": "https://api.github.com/users/erwinmombay/following{/other_user}", 101 | "gists_url": "https://api.github.com/users/erwinmombay/gists{/gist_id}", 102 | "starred_url": "https://api.github.com/users/erwinmombay/starred{/owner}{/repo}", 103 | "subscriptions_url": "https://api.github.com/users/erwinmombay/subscriptions", 104 | "organizations_url": "https://api.github.com/users/erwinmombay/orgs", 105 | "repos_url": "https://api.github.com/users/erwinmombay/repos", 106 | "events_url": "https://api.github.com/users/erwinmombay/events{/privacy}", 107 | "received_events_url": "https://api.github.com/users/erwinmombay/received_events", 108 | "type": "User", 109 | "site_admin": false 110 | }, 111 | "html_url": "https://github.com/erwinmombay/github-owners-bot-test-repo", 112 | "description": null, 113 | "fork": false, 114 | "url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo", 115 | "forks_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/forks", 116 | "keys_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/keys{/key_id}", 117 | "collaborators_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/collaborators{/collaborator}", 118 | "teams_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/teams", 119 | "hooks_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/hooks", 120 | "issue_events_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues/events{/number}", 121 | "events_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/events", 122 | "assignees_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/assignees{/user}", 123 | "branches_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/branches{/branch}", 124 | "tags_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/tags", 125 | "blobs_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/blobs{/sha}", 126 | "git_tags_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/tags{/sha}", 127 | "git_refs_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/refs{/sha}", 128 | "trees_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/trees{/sha}", 129 | "statuses_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/statuses/{sha}", 130 | "languages_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/languages", 131 | "stargazers_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/stargazers", 132 | "contributors_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/contributors", 133 | "subscribers_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/subscribers", 134 | "subscription_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/subscription", 135 | "commits_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/commits{/sha}", 136 | "git_commits_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/commits{/sha}", 137 | "comments_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/comments{/number}", 138 | "issue_comment_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues/comments{/number}", 139 | "contents_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/contents/{+path}", 140 | "compare_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/compare/{base}...{head}", 141 | "merges_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/merges", 142 | "archive_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/{archive_format}{/ref}", 143 | "downloads_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/downloads", 144 | "issues_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues{/number}", 145 | "pulls_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls{/number}", 146 | "milestones_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/milestones{/number}", 147 | "notifications_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/notifications{?since,all,participating}", 148 | "labels_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/labels{/name}", 149 | "releases_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/releases{/id}", 150 | "deployments_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/deployments", 151 | "created_at": "2016-11-04T22:11:38Z", 152 | "updated_at": "2018-12-18T20:11:29Z", 153 | "pushed_at": "2019-01-22T17:22:47Z", 154 | "git_url": "git://github.com/erwinmombay/github-owners-bot-test-repo.git", 155 | "ssh_url": "git@github.com:erwinmombay/github-owners-bot-test-repo.git", 156 | "clone_url": "https://github.com/erwinmombay/github-owners-bot-test-repo.git", 157 | "svn_url": "https://github.com/erwinmombay/github-owners-bot-test-repo", 158 | "homepage": null, 159 | "size": 17, 160 | "stargazers_count": 0, 161 | "watchers_count": 0, 162 | "language": null, 163 | "has_issues": true, 164 | "has_projects": true, 165 | "has_downloads": true, 166 | "has_wiki": true, 167 | "has_pages": false, 168 | "forks_count": 4, 169 | "mirror_url": null, 170 | "archived": false, 171 | "open_issues_count": 29, 172 | "license": null, 173 | "forks": 4, 174 | "open_issues": 29, 175 | "watchers": 0, 176 | "default_branch": "master" 177 | } 178 | }, 179 | "base": { 180 | "label": "erwinmombay:master", 181 | "ref": "master", 182 | "sha": "e896a1ed550e296573e46bcb7d0ab23afa3bbedf", 183 | "user": { 184 | "login": "erwinmombay", 185 | "id": 354746, 186 | "node_id": "MDQ6VXNlcjM1NDc0Ng==", 187 | "avatar_url": "https://avatars1.githubusercontent.com/u/354746?v=4", 188 | "gravatar_id": "", 189 | "url": "https://api.github.com/users/erwinmombay", 190 | "html_url": "https://github.com/erwinmombay", 191 | "followers_url": "https://api.github.com/users/erwinmombay/followers", 192 | "following_url": "https://api.github.com/users/erwinmombay/following{/other_user}", 193 | "gists_url": "https://api.github.com/users/erwinmombay/gists{/gist_id}", 194 | "starred_url": "https://api.github.com/users/erwinmombay/starred{/owner}{/repo}", 195 | "subscriptions_url": "https://api.github.com/users/erwinmombay/subscriptions", 196 | "organizations_url": "https://api.github.com/users/erwinmombay/orgs", 197 | "repos_url": "https://api.github.com/users/erwinmombay/repos", 198 | "events_url": "https://api.github.com/users/erwinmombay/events{/privacy}", 199 | "received_events_url": "https://api.github.com/users/erwinmombay/received_events", 200 | "type": "User", 201 | "site_admin": false 202 | }, 203 | "repo": { 204 | "id": 72889098, 205 | "node_id": "MDEwOlJlcG9zaXRvcnk3Mjg4OTA5OA==", 206 | "name": "github-owners-bot-test-repo", 207 | "full_name": "erwinmombay/github-owners-bot-test-repo", 208 | "private": false, 209 | "owner": { 210 | "login": "erwinmombay", 211 | "id": 354746, 212 | "node_id": "MDQ6VXNlcjM1NDc0Ng==", 213 | "avatar_url": "https://avatars1.githubusercontent.com/u/354746?v=4", 214 | "gravatar_id": "", 215 | "url": "https://api.github.com/users/erwinmombay", 216 | "html_url": "https://github.com/erwinmombay", 217 | "followers_url": "https://api.github.com/users/erwinmombay/followers", 218 | "following_url": "https://api.github.com/users/erwinmombay/following{/other_user}", 219 | "gists_url": "https://api.github.com/users/erwinmombay/gists{/gist_id}", 220 | "starred_url": "https://api.github.com/users/erwinmombay/starred{/owner}{/repo}", 221 | "subscriptions_url": "https://api.github.com/users/erwinmombay/subscriptions", 222 | "organizations_url": "https://api.github.com/users/erwinmombay/orgs", 223 | "repos_url": "https://api.github.com/users/erwinmombay/repos", 224 | "events_url": "https://api.github.com/users/erwinmombay/events{/privacy}", 225 | "received_events_url": "https://api.github.com/users/erwinmombay/received_events", 226 | "type": "User", 227 | "site_admin": false 228 | }, 229 | "html_url": "https://github.com/erwinmombay/github-owners-bot-test-repo", 230 | "description": null, 231 | "fork": false, 232 | "url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo", 233 | "forks_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/forks", 234 | "keys_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/keys{/key_id}", 235 | "collaborators_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/collaborators{/collaborator}", 236 | "teams_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/teams", 237 | "hooks_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/hooks", 238 | "issue_events_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues/events{/number}", 239 | "events_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/events", 240 | "assignees_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/assignees{/user}", 241 | "branches_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/branches{/branch}", 242 | "tags_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/tags", 243 | "blobs_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/blobs{/sha}", 244 | "git_tags_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/tags{/sha}", 245 | "git_refs_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/refs{/sha}", 246 | "trees_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/trees{/sha}", 247 | "statuses_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/statuses/{sha}", 248 | "languages_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/languages", 249 | "stargazers_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/stargazers", 250 | "contributors_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/contributors", 251 | "subscribers_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/subscribers", 252 | "subscription_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/subscription", 253 | "commits_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/commits{/sha}", 254 | "git_commits_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/commits{/sha}", 255 | "comments_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/comments{/number}", 256 | "issue_comment_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues/comments{/number}", 257 | "contents_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/contents/{+path}", 258 | "compare_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/compare/{base}...{head}", 259 | "merges_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/merges", 260 | "archive_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/{archive_format}{/ref}", 261 | "downloads_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/downloads", 262 | "issues_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues{/number}", 263 | "pulls_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls{/number}", 264 | "milestones_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/milestones{/number}", 265 | "notifications_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/notifications{?since,all,participating}", 266 | "labels_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/labels{/name}", 267 | "releases_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/releases{/id}", 268 | "deployments_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/deployments", 269 | "created_at": "2016-11-04T22:11:38Z", 270 | "updated_at": "2018-12-18T20:11:29Z", 271 | "pushed_at": "2019-01-22T17:22:47Z", 272 | "git_url": "git://github.com/erwinmombay/github-owners-bot-test-repo.git", 273 | "ssh_url": "git@github.com:erwinmombay/github-owners-bot-test-repo.git", 274 | "clone_url": "https://github.com/erwinmombay/github-owners-bot-test-repo.git", 275 | "svn_url": "https://github.com/erwinmombay/github-owners-bot-test-repo", 276 | "homepage": null, 277 | "size": 17, 278 | "stargazers_count": 0, 279 | "watchers_count": 0, 280 | "language": null, 281 | "has_issues": true, 282 | "has_projects": true, 283 | "has_downloads": true, 284 | "has_wiki": true, 285 | "has_pages": false, 286 | "forks_count": 4, 287 | "mirror_url": null, 288 | "archived": false, 289 | "open_issues_count": 29, 290 | "license": null, 291 | "forks": 4, 292 | "open_issues": 29, 293 | "watchers": 0, 294 | "default_branch": "master" 295 | } 296 | }, 297 | "_links": { 298 | "self": { 299 | "href": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls/35" 300 | }, 301 | "html": { 302 | "href": "https://github.com/erwinmombay/github-owners-bot-test-repo/pull/35" 303 | }, 304 | "issue": { 305 | "href": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues/35" 306 | }, 307 | "comments": { 308 | "href": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues/35/comments" 309 | }, 310 | "review_comments": { 311 | "href": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls/35/comments" 312 | }, 313 | "review_comment": { 314 | "href": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls/comments{/number}" 315 | }, 316 | "commits": { 317 | "href": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls/35/commits" 318 | }, 319 | "statuses": { 320 | "href": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/statuses/9272f18514cbd3fa935b3ced62ae1c2bf6efa76d" 321 | } 322 | }, 323 | "author_association": "COLLABORATOR", 324 | "merged": false, 325 | "mergeable": null, 326 | "rebaseable": null, 327 | "mergeable_state": "unknown", 328 | "merged_by": null, 329 | "comments": 0, 330 | "review_comments": 0, 331 | "maintainer_can_modify": false, 332 | "commits": 1, 333 | "additions": 1, 334 | "deletions": 0, 335 | "changed_files": 1 336 | }, 337 | "repository": { 338 | "id": 72889098, 339 | "node_id": "MDEwOlJlcG9zaXRvcnk3Mjg4OTA5OA==", 340 | "name": "github-owners-bot-test-repo", 341 | "full_name": "erwinmombay/github-owners-bot-test-repo", 342 | "private": false, 343 | "owner": { 344 | "login": "erwinmombay", 345 | "id": 354746, 346 | "node_id": "MDQ6VXNlcjM1NDc0Ng==", 347 | "avatar_url": "https://avatars1.githubusercontent.com/u/354746?v=4", 348 | "gravatar_id": "", 349 | "url": "https://api.github.com/users/erwinmombay", 350 | "html_url": "https://github.com/erwinmombay", 351 | "followers_url": "https://api.github.com/users/erwinmombay/followers", 352 | "following_url": "https://api.github.com/users/erwinmombay/following{/other_user}", 353 | "gists_url": "https://api.github.com/users/erwinmombay/gists{/gist_id}", 354 | "starred_url": "https://api.github.com/users/erwinmombay/starred{/owner}{/repo}", 355 | "subscriptions_url": "https://api.github.com/users/erwinmombay/subscriptions", 356 | "organizations_url": "https://api.github.com/users/erwinmombay/orgs", 357 | "repos_url": "https://api.github.com/users/erwinmombay/repos", 358 | "events_url": "https://api.github.com/users/erwinmombay/events{/privacy}", 359 | "received_events_url": "https://api.github.com/users/erwinmombay/received_events", 360 | "type": "User", 361 | "site_admin": false 362 | }, 363 | "html_url": "https://github.com/erwinmombay/github-owners-bot-test-repo", 364 | "description": null, 365 | "fork": false, 366 | "url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo", 367 | "forks_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/forks", 368 | "keys_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/keys{/key_id}", 369 | "collaborators_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/collaborators{/collaborator}", 370 | "teams_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/teams", 371 | "hooks_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/hooks", 372 | "issue_events_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues/events{/number}", 373 | "events_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/events", 374 | "assignees_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/assignees{/user}", 375 | "branches_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/branches{/branch}", 376 | "tags_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/tags", 377 | "blobs_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/blobs{/sha}", 378 | "git_tags_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/tags{/sha}", 379 | "git_refs_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/refs{/sha}", 380 | "trees_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/trees{/sha}", 381 | "statuses_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/statuses/{sha}", 382 | "languages_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/languages", 383 | "stargazers_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/stargazers", 384 | "contributors_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/contributors", 385 | "subscribers_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/subscribers", 386 | "subscription_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/subscription", 387 | "commits_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/commits{/sha}", 388 | "git_commits_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/commits{/sha}", 389 | "comments_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/comments{/number}", 390 | "issue_comment_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues/comments{/number}", 391 | "contents_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/contents/{+path}", 392 | "compare_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/compare/{base}...{head}", 393 | "merges_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/merges", 394 | "archive_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/{archive_format}{/ref}", 395 | "downloads_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/downloads", 396 | "issues_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues{/number}", 397 | "pulls_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls{/number}", 398 | "milestones_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/milestones{/number}", 399 | "notifications_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/notifications{?since,all,participating}", 400 | "labels_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/labels{/name}", 401 | "releases_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/releases{/id}", 402 | "deployments_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/deployments", 403 | "created_at": "2016-11-04T22:11:38Z", 404 | "updated_at": "2018-12-18T20:11:29Z", 405 | "pushed_at": "2019-01-22T17:22:47Z", 406 | "git_url": "git://github.com/erwinmombay/github-owners-bot-test-repo.git", 407 | "ssh_url": "git@github.com:erwinmombay/github-owners-bot-test-repo.git", 408 | "clone_url": "https://github.com/erwinmombay/github-owners-bot-test-repo.git", 409 | "svn_url": "https://github.com/erwinmombay/github-owners-bot-test-repo", 410 | "homepage": null, 411 | "size": 17, 412 | "stargazers_count": 0, 413 | "watchers_count": 0, 414 | "language": null, 415 | "has_issues": true, 416 | "has_projects": true, 417 | "has_downloads": true, 418 | "has_wiki": true, 419 | "has_pages": false, 420 | "forks_count": 4, 421 | "mirror_url": null, 422 | "archived": false, 423 | "open_issues_count": 29, 424 | "license": null, 425 | "forks": 4, 426 | "open_issues": 29, 427 | "watchers": 0, 428 | "default_branch": "master" 429 | }, 430 | "sender": { 431 | "login": "ampprojectbot", 432 | "id": 23269078, 433 | "node_id": "MDQ6VXNlcjIzMjY5MDc4", 434 | "avatar_url": "https://avatars3.githubusercontent.com/u/23269078?v=4", 435 | "gravatar_id": "", 436 | "url": "https://api.github.com/users/ampprojectbot", 437 | "html_url": "https://github.com/ampprojectbot", 438 | "followers_url": "https://api.github.com/users/ampprojectbot/followers", 439 | "following_url": "https://api.github.com/users/ampprojectbot/following{/other_user}", 440 | "gists_url": "https://api.github.com/users/ampprojectbot/gists{/gist_id}", 441 | "starred_url": "https://api.github.com/users/ampprojectbot/starred{/owner}{/repo}", 442 | "subscriptions_url": "https://api.github.com/users/ampprojectbot/subscriptions", 443 | "organizations_url": "https://api.github.com/users/ampprojectbot/orgs", 444 | "repos_url": "https://api.github.com/users/ampprojectbot/repos", 445 | "events_url": "https://api.github.com/users/ampprojectbot/events{/privacy}", 446 | "received_events_url": "https://api.github.com/users/ampprojectbot/received_events", 447 | "type": "User", 448 | "site_admin": false 449 | }, 450 | "installation": { 451 | "id": 588033, 452 | "node_id": "MDIzOkludGVncmF0aW9uSW5zdGFsbGF0aW9uNTg4MDMz" 453 | } 454 | } 455 | -------------------------------------------------------------------------------- /test/fixtures/actions/opened.36.author-is-owner.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": "opened", 3 | "number": 36, 4 | "pull_request": { 5 | "url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls/36", 6 | "id": 252420215, 7 | "node_id": "MDExOlB1bGxSZXF1ZXN0MjUyNDIwMjE1", 8 | "html_url": "https://github.com/erwinmombay/github-owners-bot-test-repo/pull/36", 9 | "diff_url": "https://github.com/erwinmombay/github-owners-bot-test-repo/pull/36.diff", 10 | "patch_url": "https://github.com/erwinmombay/github-owners-bot-test-repo/pull/36.patch", 11 | "issue_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues/36", 12 | "number": 36, 13 | "state": "open", 14 | "locked": false, 15 | "title": "Create new-file.txt", 16 | "user": { 17 | "login": "erwinmombay", 18 | "id": 354746, 19 | "node_id": "MDQ6VXNlcjM1NDc0Ng==", 20 | "avatar_url": "https://avatars1.githubusercontent.com/u/354746?v=4", 21 | "gravatar_id": "", 22 | "url": "https://api.github.com/users/erwinmombay", 23 | "html_url": "https://github.com/erwinmombay", 24 | "followers_url": "https://api.github.com/users/erwinmombay/followers", 25 | "following_url": "https://api.github.com/users/erwinmombay/following{/other_user}", 26 | "gists_url": "https://api.github.com/users/erwinmombay/gists{/gist_id}", 27 | "starred_url": "https://api.github.com/users/erwinmombay/starred{/owner}{/repo}", 28 | "subscriptions_url": "https://api.github.com/users/erwinmombay/subscriptions", 29 | "organizations_url": "https://api.github.com/users/erwinmombay/orgs", 30 | "repos_url": "https://api.github.com/users/erwinmombay/repos", 31 | "events_url": "https://api.github.com/users/erwinmombay/events{/privacy}", 32 | "received_events_url": "https://api.github.com/users/erwinmombay/received_events", 33 | "type": "User", 34 | "site_admin": false 35 | }, 36 | "body": "", 37 | "created_at": "2019-02-12T18:16:53Z", 38 | "updated_at": "2019-02-12T18:16:53Z", 39 | "closed_at": null, 40 | "merged_at": null, 41 | "merge_commit_sha": null, 42 | "assignee": null, 43 | "assignees": [ 44 | 45 | ], 46 | "requested_reviewers": [ 47 | 48 | ], 49 | "requested_teams": [ 50 | 51 | ], 52 | "labels": [ 53 | 54 | ], 55 | "milestone": null, 56 | "commits_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls/36/commits", 57 | "review_comments_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls/36/comments", 58 | "review_comment_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls/comments{/number}", 59 | "comments_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues/36/comments", 60 | "statuses_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/statuses/c7fdbd7f947fca608b20006da8535af5384ab699", 61 | "head": { 62 | "label": "erwinmombay:erwinmombay-patch-4", 63 | "ref": "erwinmombay-patch-4", 64 | "sha": "c7fdbd7f947fca608b20006da8535af5384ab699", 65 | "user": { 66 | "login": "erwinmombay", 67 | "id": 354746, 68 | "node_id": "MDQ6VXNlcjM1NDc0Ng==", 69 | "avatar_url": "https://avatars1.githubusercontent.com/u/354746?v=4", 70 | "gravatar_id": "", 71 | "url": "https://api.github.com/users/erwinmombay", 72 | "html_url": "https://github.com/erwinmombay", 73 | "followers_url": "https://api.github.com/users/erwinmombay/followers", 74 | "following_url": "https://api.github.com/users/erwinmombay/following{/other_user}", 75 | "gists_url": "https://api.github.com/users/erwinmombay/gists{/gist_id}", 76 | "starred_url": "https://api.github.com/users/erwinmombay/starred{/owner}{/repo}", 77 | "subscriptions_url": "https://api.github.com/users/erwinmombay/subscriptions", 78 | "organizations_url": "https://api.github.com/users/erwinmombay/orgs", 79 | "repos_url": "https://api.github.com/users/erwinmombay/repos", 80 | "events_url": "https://api.github.com/users/erwinmombay/events{/privacy}", 81 | "received_events_url": "https://api.github.com/users/erwinmombay/received_events", 82 | "type": "User", 83 | "site_admin": false 84 | }, 85 | "repo": { 86 | "id": 72889098, 87 | "node_id": "MDEwOlJlcG9zaXRvcnk3Mjg4OTA5OA==", 88 | "name": "github-owners-bot-test-repo", 89 | "full_name": "erwinmombay/github-owners-bot-test-repo", 90 | "private": false, 91 | "owner": { 92 | "login": "erwinmombay", 93 | "id": 354746, 94 | "node_id": "MDQ6VXNlcjM1NDc0Ng==", 95 | "avatar_url": "https://avatars1.githubusercontent.com/u/354746?v=4", 96 | "gravatar_id": "", 97 | "url": "https://api.github.com/users/erwinmombay", 98 | "html_url": "https://github.com/erwinmombay", 99 | "followers_url": "https://api.github.com/users/erwinmombay/followers", 100 | "following_url": "https://api.github.com/users/erwinmombay/following{/other_user}", 101 | "gists_url": "https://api.github.com/users/erwinmombay/gists{/gist_id}", 102 | "starred_url": "https://api.github.com/users/erwinmombay/starred{/owner}{/repo}", 103 | "subscriptions_url": "https://api.github.com/users/erwinmombay/subscriptions", 104 | "organizations_url": "https://api.github.com/users/erwinmombay/orgs", 105 | "repos_url": "https://api.github.com/users/erwinmombay/repos", 106 | "events_url": "https://api.github.com/users/erwinmombay/events{/privacy}", 107 | "received_events_url": "https://api.github.com/users/erwinmombay/received_events", 108 | "type": "User", 109 | "site_admin": false 110 | }, 111 | "html_url": "https://github.com/erwinmombay/github-owners-bot-test-repo", 112 | "description": null, 113 | "fork": false, 114 | "url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo", 115 | "forks_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/forks", 116 | "keys_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/keys{/key_id}", 117 | "collaborators_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/collaborators{/collaborator}", 118 | "teams_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/teams", 119 | "hooks_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/hooks", 120 | "issue_events_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues/events{/number}", 121 | "events_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/events", 122 | "assignees_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/assignees{/user}", 123 | "branches_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/branches{/branch}", 124 | "tags_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/tags", 125 | "blobs_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/blobs{/sha}", 126 | "git_tags_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/tags{/sha}", 127 | "git_refs_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/refs{/sha}", 128 | "trees_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/trees{/sha}", 129 | "statuses_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/statuses/{sha}", 130 | "languages_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/languages", 131 | "stargazers_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/stargazers", 132 | "contributors_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/contributors", 133 | "subscribers_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/subscribers", 134 | "subscription_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/subscription", 135 | "commits_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/commits{/sha}", 136 | "git_commits_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/commits{/sha}", 137 | "comments_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/comments{/number}", 138 | "issue_comment_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues/comments{/number}", 139 | "contents_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/contents/{+path}", 140 | "compare_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/compare/{base}...{head}", 141 | "merges_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/merges", 142 | "archive_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/{archive_format}{/ref}", 143 | "downloads_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/downloads", 144 | "issues_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues{/number}", 145 | "pulls_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls{/number}", 146 | "milestones_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/milestones{/number}", 147 | "notifications_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/notifications{?since,all,participating}", 148 | "labels_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/labels{/name}", 149 | "releases_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/releases{/id}", 150 | "deployments_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/deployments", 151 | "created_at": "2016-11-04T22:11:38Z", 152 | "updated_at": "2019-01-23T03:33:46Z", 153 | "pushed_at": "2019-02-12T18:16:49Z", 154 | "git_url": "git://github.com/erwinmombay/github-owners-bot-test-repo.git", 155 | "ssh_url": "git@github.com:erwinmombay/github-owners-bot-test-repo.git", 156 | "clone_url": "https://github.com/erwinmombay/github-owners-bot-test-repo.git", 157 | "svn_url": "https://github.com/erwinmombay/github-owners-bot-test-repo", 158 | "homepage": null, 159 | "size": 19, 160 | "stargazers_count": 0, 161 | "watchers_count": 0, 162 | "language": null, 163 | "has_issues": true, 164 | "has_projects": true, 165 | "has_downloads": true, 166 | "has_wiki": true, 167 | "has_pages": false, 168 | "forks_count": 4, 169 | "mirror_url": null, 170 | "archived": false, 171 | "open_issues_count": 30, 172 | "license": null, 173 | "forks": 4, 174 | "open_issues": 30, 175 | "watchers": 0, 176 | "default_branch": "master" 177 | } 178 | }, 179 | "base": { 180 | "label": "erwinmombay:master", 181 | "ref": "master", 182 | "sha": "a84eaffa317f205856b2b315daf4a03f93f9ddad", 183 | "user": { 184 | "login": "erwinmombay", 185 | "id": 354746, 186 | "node_id": "MDQ6VXNlcjM1NDc0Ng==", 187 | "avatar_url": "https://avatars1.githubusercontent.com/u/354746?v=4", 188 | "gravatar_id": "", 189 | "url": "https://api.github.com/users/erwinmombay", 190 | "html_url": "https://github.com/erwinmombay", 191 | "followers_url": "https://api.github.com/users/erwinmombay/followers", 192 | "following_url": "https://api.github.com/users/erwinmombay/following{/other_user}", 193 | "gists_url": "https://api.github.com/users/erwinmombay/gists{/gist_id}", 194 | "starred_url": "https://api.github.com/users/erwinmombay/starred{/owner}{/repo}", 195 | "subscriptions_url": "https://api.github.com/users/erwinmombay/subscriptions", 196 | "organizations_url": "https://api.github.com/users/erwinmombay/orgs", 197 | "repos_url": "https://api.github.com/users/erwinmombay/repos", 198 | "events_url": "https://api.github.com/users/erwinmombay/events{/privacy}", 199 | "received_events_url": "https://api.github.com/users/erwinmombay/received_events", 200 | "type": "User", 201 | "site_admin": false 202 | }, 203 | "repo": { 204 | "id": 72889098, 205 | "node_id": "MDEwOlJlcG9zaXRvcnk3Mjg4OTA5OA==", 206 | "name": "github-owners-bot-test-repo", 207 | "full_name": "erwinmombay/github-owners-bot-test-repo", 208 | "private": false, 209 | "owner": { 210 | "login": "erwinmombay", 211 | "id": 354746, 212 | "node_id": "MDQ6VXNlcjM1NDc0Ng==", 213 | "avatar_url": "https://avatars1.githubusercontent.com/u/354746?v=4", 214 | "gravatar_id": "", 215 | "url": "https://api.github.com/users/erwinmombay", 216 | "html_url": "https://github.com/erwinmombay", 217 | "followers_url": "https://api.github.com/users/erwinmombay/followers", 218 | "following_url": "https://api.github.com/users/erwinmombay/following{/other_user}", 219 | "gists_url": "https://api.github.com/users/erwinmombay/gists{/gist_id}", 220 | "starred_url": "https://api.github.com/users/erwinmombay/starred{/owner}{/repo}", 221 | "subscriptions_url": "https://api.github.com/users/erwinmombay/subscriptions", 222 | "organizations_url": "https://api.github.com/users/erwinmombay/orgs", 223 | "repos_url": "https://api.github.com/users/erwinmombay/repos", 224 | "events_url": "https://api.github.com/users/erwinmombay/events{/privacy}", 225 | "received_events_url": "https://api.github.com/users/erwinmombay/received_events", 226 | "type": "User", 227 | "site_admin": false 228 | }, 229 | "html_url": "https://github.com/erwinmombay/github-owners-bot-test-repo", 230 | "description": null, 231 | "fork": false, 232 | "url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo", 233 | "forks_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/forks", 234 | "keys_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/keys{/key_id}", 235 | "collaborators_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/collaborators{/collaborator}", 236 | "teams_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/teams", 237 | "hooks_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/hooks", 238 | "issue_events_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues/events{/number}", 239 | "events_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/events", 240 | "assignees_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/assignees{/user}", 241 | "branches_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/branches{/branch}", 242 | "tags_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/tags", 243 | "blobs_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/blobs{/sha}", 244 | "git_tags_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/tags{/sha}", 245 | "git_refs_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/refs{/sha}", 246 | "trees_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/trees{/sha}", 247 | "statuses_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/statuses/{sha}", 248 | "languages_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/languages", 249 | "stargazers_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/stargazers", 250 | "contributors_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/contributors", 251 | "subscribers_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/subscribers", 252 | "subscription_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/subscription", 253 | "commits_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/commits{/sha}", 254 | "git_commits_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/commits{/sha}", 255 | "comments_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/comments{/number}", 256 | "issue_comment_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues/comments{/number}", 257 | "contents_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/contents/{+path}", 258 | "compare_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/compare/{base}...{head}", 259 | "merges_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/merges", 260 | "archive_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/{archive_format}{/ref}", 261 | "downloads_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/downloads", 262 | "issues_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues{/number}", 263 | "pulls_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls{/number}", 264 | "milestones_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/milestones{/number}", 265 | "notifications_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/notifications{?since,all,participating}", 266 | "labels_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/labels{/name}", 267 | "releases_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/releases{/id}", 268 | "deployments_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/deployments", 269 | "created_at": "2016-11-04T22:11:38Z", 270 | "updated_at": "2019-01-23T03:33:46Z", 271 | "pushed_at": "2019-02-12T18:16:49Z", 272 | "git_url": "git://github.com/erwinmombay/github-owners-bot-test-repo.git", 273 | "ssh_url": "git@github.com:erwinmombay/github-owners-bot-test-repo.git", 274 | "clone_url": "https://github.com/erwinmombay/github-owners-bot-test-repo.git", 275 | "svn_url": "https://github.com/erwinmombay/github-owners-bot-test-repo", 276 | "homepage": null, 277 | "size": 19, 278 | "stargazers_count": 0, 279 | "watchers_count": 0, 280 | "language": null, 281 | "has_issues": true, 282 | "has_projects": true, 283 | "has_downloads": true, 284 | "has_wiki": true, 285 | "has_pages": false, 286 | "forks_count": 4, 287 | "mirror_url": null, 288 | "archived": false, 289 | "open_issues_count": 30, 290 | "license": null, 291 | "forks": 4, 292 | "open_issues": 30, 293 | "watchers": 0, 294 | "default_branch": "master" 295 | } 296 | }, 297 | "_links": { 298 | "self": { 299 | "href": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls/36" 300 | }, 301 | "html": { 302 | "href": "https://github.com/erwinmombay/github-owners-bot-test-repo/pull/36" 303 | }, 304 | "issue": { 305 | "href": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues/36" 306 | }, 307 | "comments": { 308 | "href": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues/36/comments" 309 | }, 310 | "review_comments": { 311 | "href": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls/36/comments" 312 | }, 313 | "review_comment": { 314 | "href": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls/comments{/number}" 315 | }, 316 | "commits": { 317 | "href": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls/36/commits" 318 | }, 319 | "statuses": { 320 | "href": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/statuses/c7fdbd7f947fca608b20006da8535af5384ab699" 321 | } 322 | }, 323 | "author_association": "OWNER", 324 | "merged": false, 325 | "mergeable": null, 326 | "rebaseable": null, 327 | "mergeable_state": "unknown", 328 | "merged_by": null, 329 | "comments": 0, 330 | "review_comments": 0, 331 | "maintainer_can_modify": false, 332 | "commits": 1, 333 | "additions": 1, 334 | "deletions": 0, 335 | "changed_files": 1 336 | }, 337 | "repository": { 338 | "id": 72889098, 339 | "node_id": "MDEwOlJlcG9zaXRvcnk3Mjg4OTA5OA==", 340 | "name": "github-owners-bot-test-repo", 341 | "full_name": "erwinmombay/github-owners-bot-test-repo", 342 | "private": false, 343 | "owner": { 344 | "login": "erwinmombay", 345 | "id": 354746, 346 | "node_id": "MDQ6VXNlcjM1NDc0Ng==", 347 | "avatar_url": "https://avatars1.githubusercontent.com/u/354746?v=4", 348 | "gravatar_id": "", 349 | "url": "https://api.github.com/users/erwinmombay", 350 | "html_url": "https://github.com/erwinmombay", 351 | "followers_url": "https://api.github.com/users/erwinmombay/followers", 352 | "following_url": "https://api.github.com/users/erwinmombay/following{/other_user}", 353 | "gists_url": "https://api.github.com/users/erwinmombay/gists{/gist_id}", 354 | "starred_url": "https://api.github.com/users/erwinmombay/starred{/owner}{/repo}", 355 | "subscriptions_url": "https://api.github.com/users/erwinmombay/subscriptions", 356 | "organizations_url": "https://api.github.com/users/erwinmombay/orgs", 357 | "repos_url": "https://api.github.com/users/erwinmombay/repos", 358 | "events_url": "https://api.github.com/users/erwinmombay/events{/privacy}", 359 | "received_events_url": "https://api.github.com/users/erwinmombay/received_events", 360 | "type": "User", 361 | "site_admin": false 362 | }, 363 | "html_url": "https://github.com/erwinmombay/github-owners-bot-test-repo", 364 | "description": null, 365 | "fork": false, 366 | "url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo", 367 | "forks_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/forks", 368 | "keys_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/keys{/key_id}", 369 | "collaborators_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/collaborators{/collaborator}", 370 | "teams_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/teams", 371 | "hooks_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/hooks", 372 | "issue_events_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues/events{/number}", 373 | "events_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/events", 374 | "assignees_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/assignees{/user}", 375 | "branches_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/branches{/branch}", 376 | "tags_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/tags", 377 | "blobs_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/blobs{/sha}", 378 | "git_tags_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/tags{/sha}", 379 | "git_refs_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/refs{/sha}", 380 | "trees_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/trees{/sha}", 381 | "statuses_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/statuses/{sha}", 382 | "languages_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/languages", 383 | "stargazers_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/stargazers", 384 | "contributors_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/contributors", 385 | "subscribers_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/subscribers", 386 | "subscription_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/subscription", 387 | "commits_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/commits{/sha}", 388 | "git_commits_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/commits{/sha}", 389 | "comments_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/comments{/number}", 390 | "issue_comment_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues/comments{/number}", 391 | "contents_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/contents/{+path}", 392 | "compare_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/compare/{base}...{head}", 393 | "merges_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/merges", 394 | "archive_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/{archive_format}{/ref}", 395 | "downloads_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/downloads", 396 | "issues_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues{/number}", 397 | "pulls_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls{/number}", 398 | "milestones_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/milestones{/number}", 399 | "notifications_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/notifications{?since,all,participating}", 400 | "labels_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/labels{/name}", 401 | "releases_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/releases{/id}", 402 | "deployments_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/deployments", 403 | "created_at": "2016-11-04T22:11:38Z", 404 | "updated_at": "2019-01-23T03:33:46Z", 405 | "pushed_at": "2019-02-12T18:16:49Z", 406 | "git_url": "git://github.com/erwinmombay/github-owners-bot-test-repo.git", 407 | "ssh_url": "git@github.com:erwinmombay/github-owners-bot-test-repo.git", 408 | "clone_url": "https://github.com/erwinmombay/github-owners-bot-test-repo.git", 409 | "svn_url": "https://github.com/erwinmombay/github-owners-bot-test-repo", 410 | "homepage": null, 411 | "size": 19, 412 | "stargazers_count": 0, 413 | "watchers_count": 0, 414 | "language": null, 415 | "has_issues": true, 416 | "has_projects": true, 417 | "has_downloads": true, 418 | "has_wiki": true, 419 | "has_pages": false, 420 | "forks_count": 4, 421 | "mirror_url": null, 422 | "archived": false, 423 | "open_issues_count": 30, 424 | "license": null, 425 | "forks": 4, 426 | "open_issues": 30, 427 | "watchers": 0, 428 | "default_branch": "master" 429 | }, 430 | "sender": { 431 | "login": "erwinmombay", 432 | "id": 354746, 433 | "node_id": "MDQ6VXNlcjM1NDc0Ng==", 434 | "avatar_url": "https://avatars1.githubusercontent.com/u/354746?v=4", 435 | "gravatar_id": "", 436 | "url": "https://api.github.com/users/erwinmombay", 437 | "html_url": "https://github.com/erwinmombay", 438 | "followers_url": "https://api.github.com/users/erwinmombay/followers", 439 | "following_url": "https://api.github.com/users/erwinmombay/following{/other_user}", 440 | "gists_url": "https://api.github.com/users/erwinmombay/gists{/gist_id}", 441 | "starred_url": "https://api.github.com/users/erwinmombay/starred{/owner}{/repo}", 442 | "subscriptions_url": "https://api.github.com/users/erwinmombay/subscriptions", 443 | "organizations_url": "https://api.github.com/users/erwinmombay/orgs", 444 | "repos_url": "https://api.github.com/users/erwinmombay/repos", 445 | "events_url": "https://api.github.com/users/erwinmombay/events{/privacy}", 446 | "received_events_url": "https://api.github.com/users/erwinmombay/received_events", 447 | "type": "User", 448 | "site_admin": false 449 | }, 450 | "installation": { 451 | "id": 588033, 452 | "node_id": "MDIzOkludGVncmF0aW9uSW5zdGFsbGF0aW9uNTg4MDMz" 453 | } 454 | } 455 | -------------------------------------------------------------------------------- /test/fixtures/actions/pull_request_review.35.submitted.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": "submitted", 3 | "review": { 4 | "id": 208201048, 5 | "node_id": "MDE3OlB1bGxSZXF1ZXN0UmV2aWV3MjA4MjAxMDQ4", 6 | "user": { 7 | "login": "erwinmombay", 8 | "id": 354746, 9 | "node_id": "MDQ6VXNlcjM1NDc0Ng==", 10 | "avatar_url": "https://avatars1.githubusercontent.com/u/354746?v=4", 11 | "gravatar_id": "", 12 | "url": "https://api.github.com/users/erwinmombay", 13 | "html_url": "https://github.com/erwinmombay", 14 | "followers_url": "https://api.github.com/users/erwinmombay/followers", 15 | "following_url": "https://api.github.com/users/erwinmombay/following{/other_user}", 16 | "gists_url": "https://api.github.com/users/erwinmombay/gists{/gist_id}", 17 | "starred_url": "https://api.github.com/users/erwinmombay/starred{/owner}{/repo}", 18 | "subscriptions_url": "https://api.github.com/users/erwinmombay/subscriptions", 19 | "organizations_url": "https://api.github.com/users/erwinmombay/orgs", 20 | "repos_url": "https://api.github.com/users/erwinmombay/repos", 21 | "events_url": "https://api.github.com/users/erwinmombay/events{/privacy}", 22 | "received_events_url": "https://api.github.com/users/erwinmombay/received_events", 23 | "type": "User", 24 | "site_admin": false 25 | }, 26 | "body": "", 27 | "commit_id": "9272f18514cbd3fa935b3ced62ae1c2bf6efa76d", 28 | "submitted_at": "2019-02-26T20:53:31Z", 29 | "state": "approved", 30 | "html_url": "https://github.com/erwinmombay/github-owners-bot-test-repo/pull/35#pullrequestreview-208201048", 31 | "pull_request_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls/35", 32 | "author_association": "OWNER", 33 | "_links": { 34 | "html": { 35 | "href": "https://github.com/erwinmombay/github-owners-bot-test-repo/pull/35#pullrequestreview-208201048" 36 | }, 37 | "pull_request": { 38 | "href": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls/35" 39 | } 40 | } 41 | }, 42 | "pull_request": { 43 | "url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls/35", 44 | "id": 246688458, 45 | "node_id": "MDExOlB1bGxSZXF1ZXN0MjQ2Njg4NDU4", 46 | "html_url": "https://github.com/erwinmombay/github-owners-bot-test-repo/pull/35", 47 | "diff_url": "https://github.com/erwinmombay/github-owners-bot-test-repo/pull/35.diff", 48 | "patch_url": "https://github.com/erwinmombay/github-owners-bot-test-repo/pull/35.patch", 49 | "issue_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues/35", 50 | "number": 35, 51 | "state": "open", 52 | "locked": false, 53 | "title": "Update file.txt", 54 | "user": { 55 | "login": "ampprojectbot", 56 | "id": 23269078, 57 | "node_id": "MDQ6VXNlcjIzMjY5MDc4", 58 | "avatar_url": "https://avatars3.githubusercontent.com/u/23269078?v=4", 59 | "gravatar_id": "", 60 | "url": "https://api.github.com/users/ampprojectbot", 61 | "html_url": "https://github.com/ampprojectbot", 62 | "followers_url": "https://api.github.com/users/ampprojectbot/followers", 63 | "following_url": "https://api.github.com/users/ampprojectbot/following{/other_user}", 64 | "gists_url": "https://api.github.com/users/ampprojectbot/gists{/gist_id}", 65 | "starred_url": "https://api.github.com/users/ampprojectbot/starred{/owner}{/repo}", 66 | "subscriptions_url": "https://api.github.com/users/ampprojectbot/subscriptions", 67 | "organizations_url": "https://api.github.com/users/ampprojectbot/orgs", 68 | "repos_url": "https://api.github.com/users/ampprojectbot/repos", 69 | "events_url": "https://api.github.com/users/ampprojectbot/events{/privacy}", 70 | "received_events_url": "https://api.github.com/users/ampprojectbot/received_events", 71 | "type": "User", 72 | "site_admin": false 73 | }, 74 | "body": "", 75 | "created_at": "2019-01-22T17:22:51Z", 76 | "updated_at": "2019-02-26T20:53:31Z", 77 | "closed_at": null, 78 | "merged_at": null, 79 | "merge_commit_sha": "95fe33cbfa4cb9d528e64982345c1cde39b71b81", 80 | "assignee": null, 81 | "assignees": [ 82 | 83 | ], 84 | "requested_reviewers": [ 85 | 86 | ], 87 | "requested_teams": [ 88 | 89 | ], 90 | "labels": [ 91 | 92 | ], 93 | "milestone": null, 94 | "commits_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls/35/commits", 95 | "review_comments_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls/35/comments", 96 | "review_comment_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls/comments{/number}", 97 | "comments_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues/35/comments", 98 | "statuses_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/statuses/9272f18514cbd3fa935b3ced62ae1c2bf6efa76d", 99 | "head": { 100 | "label": "erwinmombay:ampprojectbot-patch-3", 101 | "ref": "ampprojectbot-patch-3", 102 | "sha": "9272f18514cbd3fa935b3ced62ae1c2bf6efa76d", 103 | "user": { 104 | "login": "erwinmombay", 105 | "id": 354746, 106 | "node_id": "MDQ6VXNlcjM1NDc0Ng==", 107 | "avatar_url": "https://avatars1.githubusercontent.com/u/354746?v=4", 108 | "gravatar_id": "", 109 | "url": "https://api.github.com/users/erwinmombay", 110 | "html_url": "https://github.com/erwinmombay", 111 | "followers_url": "https://api.github.com/users/erwinmombay/followers", 112 | "following_url": "https://api.github.com/users/erwinmombay/following{/other_user}", 113 | "gists_url": "https://api.github.com/users/erwinmombay/gists{/gist_id}", 114 | "starred_url": "https://api.github.com/users/erwinmombay/starred{/owner}{/repo}", 115 | "subscriptions_url": "https://api.github.com/users/erwinmombay/subscriptions", 116 | "organizations_url": "https://api.github.com/users/erwinmombay/orgs", 117 | "repos_url": "https://api.github.com/users/erwinmombay/repos", 118 | "events_url": "https://api.github.com/users/erwinmombay/events{/privacy}", 119 | "received_events_url": "https://api.github.com/users/erwinmombay/received_events", 120 | "type": "User", 121 | "site_admin": false 122 | }, 123 | "repo": { 124 | "id": 72889098, 125 | "node_id": "MDEwOlJlcG9zaXRvcnk3Mjg4OTA5OA==", 126 | "name": "github-owners-bot-test-repo", 127 | "full_name": "erwinmombay/github-owners-bot-test-repo", 128 | "private": false, 129 | "owner": { 130 | "login": "erwinmombay", 131 | "id": 354746, 132 | "node_id": "MDQ6VXNlcjM1NDc0Ng==", 133 | "avatar_url": "https://avatars1.githubusercontent.com/u/354746?v=4", 134 | "gravatar_id": "", 135 | "url": "https://api.github.com/users/erwinmombay", 136 | "html_url": "https://github.com/erwinmombay", 137 | "followers_url": "https://api.github.com/users/erwinmombay/followers", 138 | "following_url": "https://api.github.com/users/erwinmombay/following{/other_user}", 139 | "gists_url": "https://api.github.com/users/erwinmombay/gists{/gist_id}", 140 | "starred_url": "https://api.github.com/users/erwinmombay/starred{/owner}{/repo}", 141 | "subscriptions_url": "https://api.github.com/users/erwinmombay/subscriptions", 142 | "organizations_url": "https://api.github.com/users/erwinmombay/orgs", 143 | "repos_url": "https://api.github.com/users/erwinmombay/repos", 144 | "events_url": "https://api.github.com/users/erwinmombay/events{/privacy}", 145 | "received_events_url": "https://api.github.com/users/erwinmombay/received_events", 146 | "type": "User", 147 | "site_admin": false 148 | }, 149 | "html_url": "https://github.com/erwinmombay/github-owners-bot-test-repo", 150 | "description": null, 151 | "fork": false, 152 | "url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo", 153 | "forks_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/forks", 154 | "keys_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/keys{/key_id}", 155 | "collaborators_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/collaborators{/collaborator}", 156 | "teams_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/teams", 157 | "hooks_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/hooks", 158 | "issue_events_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues/events{/number}", 159 | "events_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/events", 160 | "assignees_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/assignees{/user}", 161 | "branches_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/branches{/branch}", 162 | "tags_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/tags", 163 | "blobs_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/blobs{/sha}", 164 | "git_tags_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/tags{/sha}", 165 | "git_refs_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/refs{/sha}", 166 | "trees_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/trees{/sha}", 167 | "statuses_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/statuses/{sha}", 168 | "languages_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/languages", 169 | "stargazers_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/stargazers", 170 | "contributors_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/contributors", 171 | "subscribers_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/subscribers", 172 | "subscription_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/subscription", 173 | "commits_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/commits{/sha}", 174 | "git_commits_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/commits{/sha}", 175 | "comments_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/comments{/number}", 176 | "issue_comment_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues/comments{/number}", 177 | "contents_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/contents/{+path}", 178 | "compare_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/compare/{base}...{head}", 179 | "merges_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/merges", 180 | "archive_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/{archive_format}{/ref}", 181 | "downloads_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/downloads", 182 | "issues_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues{/number}", 183 | "pulls_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls{/number}", 184 | "milestones_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/milestones{/number}", 185 | "notifications_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/notifications{?since,all,participating}", 186 | "labels_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/labels{/name}", 187 | "releases_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/releases{/id}", 188 | "deployments_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/deployments", 189 | "created_at": "2016-11-04T22:11:38Z", 190 | "updated_at": "2019-01-23T03:33:46Z", 191 | "pushed_at": "2019-02-13T03:46:55Z", 192 | "git_url": "git://github.com/erwinmombay/github-owners-bot-test-repo.git", 193 | "ssh_url": "git@github.com:erwinmombay/github-owners-bot-test-repo.git", 194 | "clone_url": "https://github.com/erwinmombay/github-owners-bot-test-repo.git", 195 | "svn_url": "https://github.com/erwinmombay/github-owners-bot-test-repo", 196 | "homepage": null, 197 | "size": 21, 198 | "stargazers_count": 0, 199 | "watchers_count": 0, 200 | "language": null, 201 | "has_issues": true, 202 | "has_projects": true, 203 | "has_downloads": true, 204 | "has_wiki": true, 205 | "has_pages": false, 206 | "forks_count": 4, 207 | "mirror_url": null, 208 | "archived": false, 209 | "open_issues_count": 31, 210 | "license": null, 211 | "forks": 4, 212 | "open_issues": 31, 213 | "watchers": 0, 214 | "default_branch": "master" 215 | } 216 | }, 217 | "base": { 218 | "label": "erwinmombay:master", 219 | "ref": "master", 220 | "sha": "e896a1ed550e296573e46bcb7d0ab23afa3bbedf", 221 | "user": { 222 | "login": "erwinmombay", 223 | "id": 354746, 224 | "node_id": "MDQ6VXNlcjM1NDc0Ng==", 225 | "avatar_url": "https://avatars1.githubusercontent.com/u/354746?v=4", 226 | "gravatar_id": "", 227 | "url": "https://api.github.com/users/erwinmombay", 228 | "html_url": "https://github.com/erwinmombay", 229 | "followers_url": "https://api.github.com/users/erwinmombay/followers", 230 | "following_url": "https://api.github.com/users/erwinmombay/following{/other_user}", 231 | "gists_url": "https://api.github.com/users/erwinmombay/gists{/gist_id}", 232 | "starred_url": "https://api.github.com/users/erwinmombay/starred{/owner}{/repo}", 233 | "subscriptions_url": "https://api.github.com/users/erwinmombay/subscriptions", 234 | "organizations_url": "https://api.github.com/users/erwinmombay/orgs", 235 | "repos_url": "https://api.github.com/users/erwinmombay/repos", 236 | "events_url": "https://api.github.com/users/erwinmombay/events{/privacy}", 237 | "received_events_url": "https://api.github.com/users/erwinmombay/received_events", 238 | "type": "User", 239 | "site_admin": false 240 | }, 241 | "repo": { 242 | "id": 72889098, 243 | "node_id": "MDEwOlJlcG9zaXRvcnk3Mjg4OTA5OA==", 244 | "name": "github-owners-bot-test-repo", 245 | "full_name": "erwinmombay/github-owners-bot-test-repo", 246 | "private": false, 247 | "owner": { 248 | "login": "erwinmombay", 249 | "id": 354746, 250 | "node_id": "MDQ6VXNlcjM1NDc0Ng==", 251 | "avatar_url": "https://avatars1.githubusercontent.com/u/354746?v=4", 252 | "gravatar_id": "", 253 | "url": "https://api.github.com/users/erwinmombay", 254 | "html_url": "https://github.com/erwinmombay", 255 | "followers_url": "https://api.github.com/users/erwinmombay/followers", 256 | "following_url": "https://api.github.com/users/erwinmombay/following{/other_user}", 257 | "gists_url": "https://api.github.com/users/erwinmombay/gists{/gist_id}", 258 | "starred_url": "https://api.github.com/users/erwinmombay/starred{/owner}{/repo}", 259 | "subscriptions_url": "https://api.github.com/users/erwinmombay/subscriptions", 260 | "organizations_url": "https://api.github.com/users/erwinmombay/orgs", 261 | "repos_url": "https://api.github.com/users/erwinmombay/repos", 262 | "events_url": "https://api.github.com/users/erwinmombay/events{/privacy}", 263 | "received_events_url": "https://api.github.com/users/erwinmombay/received_events", 264 | "type": "User", 265 | "site_admin": false 266 | }, 267 | "html_url": "https://github.com/erwinmombay/github-owners-bot-test-repo", 268 | "description": null, 269 | "fork": false, 270 | "url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo", 271 | "forks_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/forks", 272 | "keys_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/keys{/key_id}", 273 | "collaborators_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/collaborators{/collaborator}", 274 | "teams_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/teams", 275 | "hooks_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/hooks", 276 | "issue_events_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues/events{/number}", 277 | "events_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/events", 278 | "assignees_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/assignees{/user}", 279 | "branches_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/branches{/branch}", 280 | "tags_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/tags", 281 | "blobs_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/blobs{/sha}", 282 | "git_tags_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/tags{/sha}", 283 | "git_refs_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/refs{/sha}", 284 | "trees_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/trees{/sha}", 285 | "statuses_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/statuses/{sha}", 286 | "languages_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/languages", 287 | "stargazers_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/stargazers", 288 | "contributors_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/contributors", 289 | "subscribers_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/subscribers", 290 | "subscription_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/subscription", 291 | "commits_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/commits{/sha}", 292 | "git_commits_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/commits{/sha}", 293 | "comments_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/comments{/number}", 294 | "issue_comment_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues/comments{/number}", 295 | "contents_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/contents/{+path}", 296 | "compare_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/compare/{base}...{head}", 297 | "merges_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/merges", 298 | "archive_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/{archive_format}{/ref}", 299 | "downloads_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/downloads", 300 | "issues_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues{/number}", 301 | "pulls_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls{/number}", 302 | "milestones_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/milestones{/number}", 303 | "notifications_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/notifications{?since,all,participating}", 304 | "labels_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/labels{/name}", 305 | "releases_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/releases{/id}", 306 | "deployments_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/deployments", 307 | "created_at": "2016-11-04T22:11:38Z", 308 | "updated_at": "2019-01-23T03:33:46Z", 309 | "pushed_at": "2019-02-13T03:46:55Z", 310 | "git_url": "git://github.com/erwinmombay/github-owners-bot-test-repo.git", 311 | "ssh_url": "git@github.com:erwinmombay/github-owners-bot-test-repo.git", 312 | "clone_url": "https://github.com/erwinmombay/github-owners-bot-test-repo.git", 313 | "svn_url": "https://github.com/erwinmombay/github-owners-bot-test-repo", 314 | "homepage": null, 315 | "size": 21, 316 | "stargazers_count": 0, 317 | "watchers_count": 0, 318 | "language": null, 319 | "has_issues": true, 320 | "has_projects": true, 321 | "has_downloads": true, 322 | "has_wiki": true, 323 | "has_pages": false, 324 | "forks_count": 4, 325 | "mirror_url": null, 326 | "archived": false, 327 | "open_issues_count": 31, 328 | "license": null, 329 | "forks": 4, 330 | "open_issues": 31, 331 | "watchers": 0, 332 | "default_branch": "master" 333 | } 334 | }, 335 | "_links": { 336 | "self": { 337 | "href": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls/35" 338 | }, 339 | "html": { 340 | "href": "https://github.com/erwinmombay/github-owners-bot-test-repo/pull/35" 341 | }, 342 | "issue": { 343 | "href": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues/35" 344 | }, 345 | "comments": { 346 | "href": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues/35/comments" 347 | }, 348 | "review_comments": { 349 | "href": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls/35/comments" 350 | }, 351 | "review_comment": { 352 | "href": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls/comments{/number}" 353 | }, 354 | "commits": { 355 | "href": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls/35/commits" 356 | }, 357 | "statuses": { 358 | "href": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/statuses/9272f18514cbd3fa935b3ced62ae1c2bf6efa76d" 359 | } 360 | }, 361 | "author_association": "COLLABORATOR" 362 | }, 363 | "repository": { 364 | "id": 72889098, 365 | "node_id": "MDEwOlJlcG9zaXRvcnk3Mjg4OTA5OA==", 366 | "name": "github-owners-bot-test-repo", 367 | "full_name": "erwinmombay/github-owners-bot-test-repo", 368 | "private": false, 369 | "owner": { 370 | "login": "erwinmombay", 371 | "id": 354746, 372 | "node_id": "MDQ6VXNlcjM1NDc0Ng==", 373 | "avatar_url": "https://avatars1.githubusercontent.com/u/354746?v=4", 374 | "gravatar_id": "", 375 | "url": "https://api.github.com/users/erwinmombay", 376 | "html_url": "https://github.com/erwinmombay", 377 | "followers_url": "https://api.github.com/users/erwinmombay/followers", 378 | "following_url": "https://api.github.com/users/erwinmombay/following{/other_user}", 379 | "gists_url": "https://api.github.com/users/erwinmombay/gists{/gist_id}", 380 | "starred_url": "https://api.github.com/users/erwinmombay/starred{/owner}{/repo}", 381 | "subscriptions_url": "https://api.github.com/users/erwinmombay/subscriptions", 382 | "organizations_url": "https://api.github.com/users/erwinmombay/orgs", 383 | "repos_url": "https://api.github.com/users/erwinmombay/repos", 384 | "events_url": "https://api.github.com/users/erwinmombay/events{/privacy}", 385 | "received_events_url": "https://api.github.com/users/erwinmombay/received_events", 386 | "type": "User", 387 | "site_admin": false 388 | }, 389 | "html_url": "https://github.com/erwinmombay/github-owners-bot-test-repo", 390 | "description": null, 391 | "fork": false, 392 | "url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo", 393 | "forks_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/forks", 394 | "keys_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/keys{/key_id}", 395 | "collaborators_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/collaborators{/collaborator}", 396 | "teams_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/teams", 397 | "hooks_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/hooks", 398 | "issue_events_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues/events{/number}", 399 | "events_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/events", 400 | "assignees_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/assignees{/user}", 401 | "branches_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/branches{/branch}", 402 | "tags_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/tags", 403 | "blobs_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/blobs{/sha}", 404 | "git_tags_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/tags{/sha}", 405 | "git_refs_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/refs{/sha}", 406 | "trees_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/trees{/sha}", 407 | "statuses_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/statuses/{sha}", 408 | "languages_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/languages", 409 | "stargazers_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/stargazers", 410 | "contributors_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/contributors", 411 | "subscribers_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/subscribers", 412 | "subscription_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/subscription", 413 | "commits_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/commits{/sha}", 414 | "git_commits_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/commits{/sha}", 415 | "comments_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/comments{/number}", 416 | "issue_comment_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues/comments{/number}", 417 | "contents_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/contents/{+path}", 418 | "compare_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/compare/{base}...{head}", 419 | "merges_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/merges", 420 | "archive_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/{archive_format}{/ref}", 421 | "downloads_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/downloads", 422 | "issues_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues{/number}", 423 | "pulls_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls{/number}", 424 | "milestones_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/milestones{/number}", 425 | "notifications_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/notifications{?since,all,participating}", 426 | "labels_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/labels{/name}", 427 | "releases_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/releases{/id}", 428 | "deployments_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/deployments", 429 | "created_at": "2016-11-04T22:11:38Z", 430 | "updated_at": "2019-01-23T03:33:46Z", 431 | "pushed_at": "2019-02-13T03:46:55Z", 432 | "git_url": "git://github.com/erwinmombay/github-owners-bot-test-repo.git", 433 | "ssh_url": "git@github.com:erwinmombay/github-owners-bot-test-repo.git", 434 | "clone_url": "https://github.com/erwinmombay/github-owners-bot-test-repo.git", 435 | "svn_url": "https://github.com/erwinmombay/github-owners-bot-test-repo", 436 | "homepage": null, 437 | "size": 21, 438 | "stargazers_count": 0, 439 | "watchers_count": 0, 440 | "language": null, 441 | "has_issues": true, 442 | "has_projects": true, 443 | "has_downloads": true, 444 | "has_wiki": true, 445 | "has_pages": false, 446 | "forks_count": 4, 447 | "mirror_url": null, 448 | "archived": false, 449 | "open_issues_count": 31, 450 | "license": null, 451 | "forks": 4, 452 | "open_issues": 31, 453 | "watchers": 0, 454 | "default_branch": "master" 455 | }, 456 | "sender": { 457 | "login": "erwinmombay", 458 | "id": 354746, 459 | "node_id": "MDQ6VXNlcjM1NDc0Ng==", 460 | "avatar_url": "https://avatars1.githubusercontent.com/u/354746?v=4", 461 | "gravatar_id": "", 462 | "url": "https://api.github.com/users/erwinmombay", 463 | "html_url": "https://github.com/erwinmombay", 464 | "followers_url": "https://api.github.com/users/erwinmombay/followers", 465 | "following_url": "https://api.github.com/users/erwinmombay/following{/other_user}", 466 | "gists_url": "https://api.github.com/users/erwinmombay/gists{/gist_id}", 467 | "starred_url": "https://api.github.com/users/erwinmombay/starred{/owner}{/repo}", 468 | "subscriptions_url": "https://api.github.com/users/erwinmombay/subscriptions", 469 | "organizations_url": "https://api.github.com/users/erwinmombay/orgs", 470 | "repos_url": "https://api.github.com/users/erwinmombay/repos", 471 | "events_url": "https://api.github.com/users/erwinmombay/events{/privacy}", 472 | "received_events_url": "https://api.github.com/users/erwinmombay/received_events", 473 | "type": "User", 474 | "site_admin": false 475 | }, 476 | "installation": { 477 | "id": 588033, 478 | "node_id": "MDIzOkludGVncmF0aW9uSW5zdGFsbGF0aW9uNTg4MDMz" 479 | } 480 | } 481 | -------------------------------------------------------------------------------- /test/fixtures/actions/rerequested.35.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": "rerequested", 3 | "check_run": { 4 | "id": 65826077, 5 | "node_id": "MDg6Q2hlY2tSdW42NTgyNjA3Nw==", 6 | "head_sha": "f73f33ef2005ee244695ee3445bd82c12ed37735", 7 | "external_id": "", 8 | "url": "https://api.github.com/repos/erwinmombay/amphtml/check-runs/65826077", 9 | "html_url": "https://github.com/erwinmombay/amphtml/runs/65826077", 10 | "details_url": "https://www.ampproject.org", 11 | "status": "completed", 12 | "conclusion": "failure", 13 | "started_at": "2019-02-19T23:22:36Z", 14 | "completed_at": "2019-02-19T23:22:35Z", 15 | "output": { 16 | "title": "AMP Owners bot reviewers check", 17 | "summary": "The check was a failure!", 18 | "text": "\n## possible reviewers: danielrozenberg,erwinmombay,rsimha\n - ./build-system/app.js\n \n## possible reviewers: aghassemi\n - ./extensions/amp-font/0.1/test/test-fontloader.js\n", 19 | "annotations_count": 0, 20 | "annotations_url": "https://api.github.com/repos/erwinmombay/amphtml/check-runs/65826077/annotations" 21 | }, 22 | "name": "ampproject/owners-check", 23 | "check_suite": { 24 | "id": 66518117, 25 | "node_id": "MDEwOkNoZWNrU3VpdGU2NjUxODExNw==", 26 | "head_branch": "test-again", 27 | "head_sha": "f73f33ef2005ee244695ee3445bd82c12ed37735", 28 | "status": "completed", 29 | "conclusion": "failure", 30 | "url": "https://api.github.com/repos/erwinmombay/amphtml/check-suites/66518117", 31 | "before": "0000000000000000000000000000000000000000", 32 | "after": "f73f33ef2005ee244695ee3445bd82c12ed37735", 33 | "pull_requests": [ 34 | { 35 | "url": "https://api.github.com/repos/erwinmombay/amphtml/pulls/9", 36 | "id": 254442336, 37 | "number": 35, 38 | "head": { 39 | "ref": "test-again", 40 | "sha": "f73f33ef2005ee244695ee3445bd82c12ed37735", 41 | "repo": { 42 | "id": 43843790, 43 | "url": "https://api.github.com/repos/erwinmombay/amphtml", 44 | "name": "amphtml" 45 | } 46 | }, 47 | "base": { 48 | "ref": "master", 49 | "sha": "86f2e28d87cccdec5fb2993fdba2c63cd8545658", 50 | "repo": { 51 | "id": 43843790, 52 | "url": "https://api.github.com/repos/erwinmombay/amphtml", 53 | "name": "amphtml" 54 | } 55 | } 56 | } 57 | ], 58 | "app": { 59 | "id": 22611, 60 | "node_id": "MDM6QXBwMjI2MTE=", 61 | "owner": { 62 | "login": "ampprojectbot", 63 | "id": 23269078, 64 | "node_id": "MDQ6VXNlcjIzMjY5MDc4", 65 | "avatar_url": "https://avatars3.githubusercontent.com/u/23269078?v=4", 66 | "gravatar_id": "", 67 | "url": "https://api.github.com/users/ampprojectbot", 68 | "html_url": "https://github.com/ampprojectbot", 69 | "followers_url": "https://api.github.com/users/ampprojectbot/followers", 70 | "following_url": "https://api.github.com/users/ampprojectbot/following{/other_user}", 71 | "gists_url": "https://api.github.com/users/ampprojectbot/gists{/gist_id}", 72 | "starred_url": "https://api.github.com/users/ampprojectbot/starred{/owner}{/repo}", 73 | "subscriptions_url": "https://api.github.com/users/ampprojectbot/subscriptions", 74 | "organizations_url": "https://api.github.com/users/ampprojectbot/orgs", 75 | "repos_url": "https://api.github.com/users/ampprojectbot/repos", 76 | "events_url": "https://api.github.com/users/ampprojectbot/events{/privacy}", 77 | "received_events_url": "https://api.github.com/users/ampprojectbot/received_events", 78 | "type": "User", 79 | "site_admin": false 80 | }, 81 | "name": "amp-owners-bot", 82 | "description": "A bot that verifies that all \"owners\" of a file set has approved a pull request.\r\n\r\nusers OWNERS.yaml files in a repository to find the set of owners.", 83 | "external_url": "https://www.ampproject.org", 84 | "html_url": "https://github.com/apps/amp-owners-bot", 85 | "created_at": "2018-12-20T18:50:10Z", 86 | "updated_at": "2019-01-18T19:48:17Z" 87 | }, 88 | "created_at": "2019-02-19T23:07:04Z", 89 | "updated_at": "2019-02-19T23:22:36Z" 90 | }, 91 | "app": { 92 | "id": 22611, 93 | "node_id": "MDM6QXBwMjI2MTE=", 94 | "owner": { 95 | "login": "ampprojectbot", 96 | "id": 23269078, 97 | "node_id": "MDQ6VXNlcjIzMjY5MDc4", 98 | "avatar_url": "https://avatars3.githubusercontent.com/u/23269078?v=4", 99 | "gravatar_id": "", 100 | "url": "https://api.github.com/users/ampprojectbot", 101 | "html_url": "https://github.com/ampprojectbot", 102 | "followers_url": "https://api.github.com/users/ampprojectbot/followers", 103 | "following_url": "https://api.github.com/users/ampprojectbot/following{/other_user}", 104 | "gists_url": "https://api.github.com/users/ampprojectbot/gists{/gist_id}", 105 | "starred_url": "https://api.github.com/users/ampprojectbot/starred{/owner}{/repo}", 106 | "subscriptions_url": "https://api.github.com/users/ampprojectbot/subscriptions", 107 | "organizations_url": "https://api.github.com/users/ampprojectbot/orgs", 108 | "repos_url": "https://api.github.com/users/ampprojectbot/repos", 109 | "events_url": "https://api.github.com/users/ampprojectbot/events{/privacy}", 110 | "received_events_url": "https://api.github.com/users/ampprojectbot/received_events", 111 | "type": "User", 112 | "site_admin": false 113 | }, 114 | "name": "amp-owners-bot", 115 | "description": "A bot that verifies that all \"owners\" of a file set has approved a pull request.\r\n\r\nusers OWNERS.yaml files in a repository to find the set of owners.", 116 | "external_url": "https://www.ampproject.org", 117 | "html_url": "https://github.com/apps/amp-owners-bot", 118 | "created_at": "2018-12-20T18:50:10Z", 119 | "updated_at": "2019-01-18T19:48:17Z" 120 | }, 121 | "pull_requests": [ 122 | { 123 | "url": "https://api.github.com/repos/erwinmombay/amphtml/pulls/9", 124 | "id": 254442336, 125 | "number": 9, 126 | "head": { 127 | "ref": "test-again", 128 | "sha": "f73f33ef2005ee244695ee3445bd82c12ed37735", 129 | "repo": { 130 | "id": 43843790, 131 | "url": "https://api.github.com/repos/erwinmombay/amphtml", 132 | "name": "amphtml" 133 | } 134 | }, 135 | "base": { 136 | "ref": "master", 137 | "sha": "86f2e28d87cccdec5fb2993fdba2c63cd8545658", 138 | "repo": { 139 | "id": 43843790, 140 | "url": "https://api.github.com/repos/erwinmombay/amphtml", 141 | "name": "amphtml" 142 | } 143 | } 144 | } 145 | ] 146 | }, 147 | "repository": { 148 | "id": 43843790, 149 | "node_id": "MDEwOlJlcG9zaXRvcnk0Mzg0Mzc5MA==", 150 | "name": "github-owners-bot-test-repo", 151 | "full_name": "erwinmombay/amphtml", 152 | "private": false, 153 | "owner": { 154 | "login": "erwinmombay", 155 | "id": 354746, 156 | "node_id": "MDQ6VXNlcjM1NDc0Ng==", 157 | "avatar_url": "https://avatars1.githubusercontent.com/u/354746?v=4", 158 | "gravatar_id": "", 159 | "url": "https://api.github.com/users/erwinmombay", 160 | "html_url": "https://github.com/erwinmombay", 161 | "followers_url": "https://api.github.com/users/erwinmombay/followers", 162 | "following_url": "https://api.github.com/users/erwinmombay/following{/other_user}", 163 | "gists_url": "https://api.github.com/users/erwinmombay/gists{/gist_id}", 164 | "starred_url": "https://api.github.com/users/erwinmombay/starred{/owner}{/repo}", 165 | "subscriptions_url": "https://api.github.com/users/erwinmombay/subscriptions", 166 | "organizations_url": "https://api.github.com/users/erwinmombay/orgs", 167 | "repos_url": "https://api.github.com/users/erwinmombay/repos", 168 | "events_url": "https://api.github.com/users/erwinmombay/events{/privacy}", 169 | "received_events_url": "https://api.github.com/users/erwinmombay/received_events", 170 | "type": "User", 171 | "site_admin": false 172 | }, 173 | "html_url": "https://github.com/erwinmombay/amphtml", 174 | "description": null, 175 | "fork": true, 176 | "url": "https://api.github.com/repos/erwinmombay/amphtml", 177 | "forks_url": "https://api.github.com/repos/erwinmombay/amphtml/forks", 178 | "keys_url": "https://api.github.com/repos/erwinmombay/amphtml/keys{/key_id}", 179 | "collaborators_url": "https://api.github.com/repos/erwinmombay/amphtml/collaborators{/collaborator}", 180 | "teams_url": "https://api.github.com/repos/erwinmombay/amphtml/teams", 181 | "hooks_url": "https://api.github.com/repos/erwinmombay/amphtml/hooks", 182 | "issue_events_url": "https://api.github.com/repos/erwinmombay/amphtml/issues/events{/number}", 183 | "events_url": "https://api.github.com/repos/erwinmombay/amphtml/events", 184 | "assignees_url": "https://api.github.com/repos/erwinmombay/amphtml/assignees{/user}", 185 | "branches_url": "https://api.github.com/repos/erwinmombay/amphtml/branches{/branch}", 186 | "tags_url": "https://api.github.com/repos/erwinmombay/amphtml/tags", 187 | "blobs_url": "https://api.github.com/repos/erwinmombay/amphtml/git/blobs{/sha}", 188 | "git_tags_url": "https://api.github.com/repos/erwinmombay/amphtml/git/tags{/sha}", 189 | "git_refs_url": "https://api.github.com/repos/erwinmombay/amphtml/git/refs{/sha}", 190 | "trees_url": "https://api.github.com/repos/erwinmombay/amphtml/git/trees{/sha}", 191 | "statuses_url": "https://api.github.com/repos/erwinmombay/amphtml/statuses/{sha}", 192 | "languages_url": "https://api.github.com/repos/erwinmombay/amphtml/languages", 193 | "stargazers_url": "https://api.github.com/repos/erwinmombay/amphtml/stargazers", 194 | "contributors_url": "https://api.github.com/repos/erwinmombay/amphtml/contributors", 195 | "subscribers_url": "https://api.github.com/repos/erwinmombay/amphtml/subscribers", 196 | "subscription_url": "https://api.github.com/repos/erwinmombay/amphtml/subscription", 197 | "commits_url": "https://api.github.com/repos/erwinmombay/amphtml/commits{/sha}", 198 | "git_commits_url": "https://api.github.com/repos/erwinmombay/amphtml/git/commits{/sha}", 199 | "comments_url": "https://api.github.com/repos/erwinmombay/amphtml/comments{/number}", 200 | "issue_comment_url": "https://api.github.com/repos/erwinmombay/amphtml/issues/comments{/number}", 201 | "contents_url": "https://api.github.com/repos/erwinmombay/amphtml/contents/{+path}", 202 | "compare_url": "https://api.github.com/repos/erwinmombay/amphtml/compare/{base}...{head}", 203 | "merges_url": "https://api.github.com/repos/erwinmombay/amphtml/merges", 204 | "archive_url": "https://api.github.com/repos/erwinmombay/amphtml/{archive_format}{/ref}", 205 | "downloads_url": "https://api.github.com/repos/erwinmombay/amphtml/downloads", 206 | "issues_url": "https://api.github.com/repos/erwinmombay/amphtml/issues{/number}", 207 | "pulls_url": "https://api.github.com/repos/erwinmombay/amphtml/pulls{/number}", 208 | "milestones_url": "https://api.github.com/repos/erwinmombay/amphtml/milestones{/number}", 209 | "notifications_url": "https://api.github.com/repos/erwinmombay/amphtml/notifications{?since,all,participating}", 210 | "labels_url": "https://api.github.com/repos/erwinmombay/amphtml/labels{/name}", 211 | "releases_url": "https://api.github.com/repos/erwinmombay/amphtml/releases{/id}", 212 | "deployments_url": "https://api.github.com/repos/erwinmombay/amphtml/deployments", 213 | "created_at": "2015-10-07T20:45:56Z", 214 | "updated_at": "2019-02-12T20:51:10Z", 215 | "pushed_at": "2019-02-21T19:32:39Z", 216 | "git_url": "git://github.com/erwinmombay/amphtml.git", 217 | "ssh_url": "git@github.com:erwinmombay/amphtml.git", 218 | "clone_url": "https://github.com/erwinmombay/amphtml.git", 219 | "svn_url": "https://github.com/erwinmombay/amphtml", 220 | "homepage": "", 221 | "size": 618148, 222 | "stargazers_count": 0, 223 | "watchers_count": 0, 224 | "language": "JavaScript", 225 | "has_issues": false, 226 | "has_projects": true, 227 | "has_downloads": false, 228 | "has_wiki": false, 229 | "has_pages": false, 230 | "forks_count": 0, 231 | "mirror_url": null, 232 | "archived": false, 233 | "open_issues_count": 11, 234 | "license": { 235 | "key": "apache-2.0", 236 | "name": "Apache License 2.0", 237 | "spdx_id": "Apache-2.0", 238 | "url": "https://api.github.com/licenses/apache-2.0", 239 | "node_id": "MDc6TGljZW5zZTI=" 240 | }, 241 | "forks": 0, 242 | "open_issues": 11, 243 | "watchers": 0, 244 | "default_branch": "master" 245 | }, 246 | "sender": { 247 | "login": "erwinmombay", 248 | "id": 354746, 249 | "node_id": "MDQ6VXNlcjM1NDc0Ng==", 250 | "avatar_url": "https://avatars1.githubusercontent.com/u/354746?v=4", 251 | "gravatar_id": "", 252 | "url": "https://api.github.com/users/erwinmombay", 253 | "html_url": "https://github.com/erwinmombay", 254 | "followers_url": "https://api.github.com/users/erwinmombay/followers", 255 | "following_url": "https://api.github.com/users/erwinmombay/following{/other_user}", 256 | "gists_url": "https://api.github.com/users/erwinmombay/gists{/gist_id}", 257 | "starred_url": "https://api.github.com/users/erwinmombay/starred{/owner}{/repo}", 258 | "subscriptions_url": "https://api.github.com/users/erwinmombay/subscriptions", 259 | "organizations_url": "https://api.github.com/users/erwinmombay/orgs", 260 | "repos_url": "https://api.github.com/users/erwinmombay/repos", 261 | "events_url": "https://api.github.com/users/erwinmombay/events{/privacy}", 262 | "received_events_url": "https://api.github.com/users/erwinmombay/received_events", 263 | "type": "User", 264 | "site_admin": false 265 | }, 266 | "installation": { 267 | "id": 588033, 268 | "node_id": "MDIzOkludGVncmF0aW9uSW5zdGFsbGF0aW9uNTg4MDMz" 269 | } 270 | } 271 | -------------------------------------------------------------------------------- /test/fixtures/check-runs/check-runs.create.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "owners approvals", 3 | "head_sha": "e0da784dc5a4c2dfbf3fc8846d474687cbc82d3a", 4 | "status": "completed", 5 | "output": { 6 | "title": "required owners for each file", 7 | "summary": "this is a test" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /test/fixtures/check-runs/check-runs.get.35.empty.json: -------------------------------------------------------------------------------- 1 | { 2 | "total_count": 0, 3 | "check_runs": [] 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/check-runs/check-runs.get.35.json: -------------------------------------------------------------------------------- 1 | { 2 | "total_count": 1, 3 | "check_runs": [ 4 | { 5 | "id": 53472313, 6 | "node_id": "MDg6Q2hlY2tSdW41MzQ3MjMxMw==", 7 | "head_sha": "9272f18514cbd3fa935b3ced62ae1c2bf6efa76d", 8 | "external_id": "", 9 | "url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/check-runs/53472313", 10 | "html_url": "https://github.com/erwinmombay/github-owners-bot-test-repo/runs/53472313", 11 | "details_url": "https://www.ampproject.org", 12 | "status": "completed", 13 | "conclusion": "failure", 14 | "started_at": "2019-01-23T03:33:53Z", 15 | "completed_at": "2019-01-23T03:33:52Z", 16 | "output": { 17 | "title": "Probot check!", 18 | "summary": "The check has passed!", 19 | "text": null, 20 | "annotations_count": 0, 21 | "annotations_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/check-runs/53472313/annotations" 22 | }, 23 | "name": "ampproject/owners-check", 24 | "check_suite": { 25 | "id": 52508974 26 | }, 27 | "app": { 28 | "id": 22611, 29 | "node_id": "MDM6QXBwMjI2MTE=", 30 | "owner": { 31 | "login": "ampprojectbot", 32 | "id": 23269078, 33 | "node_id": "MDQ6VXNlcjIzMjY5MDc4", 34 | "avatar_url": "https://avatars3.githubusercontent.com/u/23269078?v=4", 35 | "gravatar_id": "", 36 | "url": "https://api.github.com/users/ampprojectbot", 37 | "html_url": "https://github.com/ampprojectbot", 38 | "followers_url": "https://api.github.com/users/ampprojectbot/followers", 39 | "following_url": "https://api.github.com/users/ampprojectbot/following{/other_user}", 40 | "gists_url": "https://api.github.com/users/ampprojectbot/gists{/gist_id}", 41 | "starred_url": "https://api.github.com/users/ampprojectbot/starred{/owner}{/repo}", 42 | "subscriptions_url": "https://api.github.com/users/ampprojectbot/subscriptions", 43 | "organizations_url": "https://api.github.com/users/ampprojectbot/orgs", 44 | "repos_url": "https://api.github.com/users/ampprojectbot/repos", 45 | "events_url": "https://api.github.com/users/ampprojectbot/events{/privacy}", 46 | "received_events_url": "https://api.github.com/users/ampprojectbot/received_events", 47 | "type": "User", 48 | "site_admin": false 49 | }, 50 | "name": "amp-owners-bot", 51 | "description": "A bot that verifies that all \"owners\" of a file set has approved a pull request.\r\n\r\nusers OWNERS.yaml files in a repository to find the set of owners.", 52 | "external_url": "https://www.ampproject.org", 53 | "html_url": "https://github.com/apps/amp-owners-bot", 54 | "created_at": "2018-12-20T18:50:10Z", 55 | "updated_at": "2019-01-18T19:48:17Z" 56 | }, 57 | "pull_requests": [ 58 | { 59 | "url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls/35", 60 | "id": 246688458, 61 | "number": 35, 62 | "head": { 63 | "ref": "ampprojectbot-patch-3", 64 | "sha": "9272f18514cbd3fa935b3ced62ae1c2bf6efa76d", 65 | "repo": { 66 | "id": 72889098, 67 | "url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo", 68 | "name": "github-owners-bot-test-repo" 69 | } 70 | }, 71 | "base": { 72 | "ref": "master", 73 | "sha": "e896a1ed550e296573e46bcb7d0ab23afa3bbedf", 74 | "repo": { 75 | "id": 72889098, 76 | "url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo", 77 | "name": "github-owners-bot-test-repo" 78 | } 79 | } 80 | } 81 | ] 82 | } 83 | ] 84 | } 85 | -------------------------------------------------------------------------------- /test/fixtures/check-runs/check-runs.get.35.multiple.json: -------------------------------------------------------------------------------- 1 | { 2 | "total_count": 1, 3 | "check_runs": [ 4 | { 5 | "id": 53472315, 6 | "node_id": "MDg6Q2hlY2tSdW41MzQ3MjMxMw==", 7 | "head_sha": "9272f18514cbd3fa935b3ced62ae1c2bf6efa76d", 8 | "external_id": "", 9 | "url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/check-runs/53472313", 10 | "html_url": "https://github.com/erwinmombay/github-owners-bot-test-repo/runs/53472313", 11 | "details_url": "https://www.ampproject.org", 12 | "status": "completed", 13 | "conclusion": "failure", 14 | "started_at": "2019-01-23T03:33:53Z", 15 | "completed_at": "2019-01-23T03:33:52Z", 16 | "output": { 17 | "title": "Probot check!", 18 | "summary": "The check has passed!", 19 | "text": null, 20 | "annotations_count": 0, 21 | "annotations_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/check-runs/53472313/annotations" 22 | }, 23 | "name": "ampproject/owners-check", 24 | "check_suite": { 25 | "id": 52508974 26 | }, 27 | "app": { 28 | "id": 22611, 29 | "node_id": "MDM6QXBwMjI2MTE=", 30 | "owner": { 31 | "login": "ampprojectbot", 32 | "id": 23269078, 33 | "node_id": "MDQ6VXNlcjIzMjY5MDc4", 34 | "avatar_url": "https://avatars3.githubusercontent.com/u/23269078?v=4", 35 | "gravatar_id": "", 36 | "url": "https://api.github.com/users/ampprojectbot", 37 | "html_url": "https://github.com/ampprojectbot", 38 | "followers_url": "https://api.github.com/users/ampprojectbot/followers", 39 | "following_url": "https://api.github.com/users/ampprojectbot/following{/other_user}", 40 | "gists_url": "https://api.github.com/users/ampprojectbot/gists{/gist_id}", 41 | "starred_url": "https://api.github.com/users/ampprojectbot/starred{/owner}{/repo}", 42 | "subscriptions_url": "https://api.github.com/users/ampprojectbot/subscriptions", 43 | "organizations_url": "https://api.github.com/users/ampprojectbot/orgs", 44 | "repos_url": "https://api.github.com/users/ampprojectbot/repos", 45 | "events_url": "https://api.github.com/users/ampprojectbot/events{/privacy}", 46 | "received_events_url": "https://api.github.com/users/ampprojectbot/received_events", 47 | "type": "User", 48 | "site_admin": false 49 | }, 50 | "name": "amp-owners-bot", 51 | "description": "A bot that verifies that all \"owners\" of a file set has approved a pull request.\r\n\r\nusers OWNERS.yaml files in a repository to find the set of owners.", 52 | "external_url": "https://www.ampproject.org", 53 | "html_url": "https://github.com/apps/amp-owners-bot", 54 | "created_at": "2018-12-20T18:50:10Z", 55 | "updated_at": "2019-01-18T19:48:17Z" 56 | }, 57 | "pull_requests": [ 58 | { 59 | "url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls/35", 60 | "id": 246688458, 61 | "number": 35, 62 | "head": { 63 | "ref": "ampprojectbot-patch-3", 64 | "sha": "9272f18514cbd3fa935b3ced62ae1c2bf6efa76d", 65 | "repo": { 66 | "id": 72889098, 67 | "url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo", 68 | "name": "github-owners-bot-test-repo" 69 | } 70 | }, 71 | "base": { 72 | "ref": "master", 73 | "sha": "e896a1ed550e296573e46bcb7d0ab23afa3bbedf", 74 | "repo": { 75 | "id": 72889098, 76 | "url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo", 77 | "name": "github-owners-bot-test-repo" 78 | } 79 | } 80 | } 81 | ] 82 | }, 83 | { 84 | "id": 53472313, 85 | "node_id": "MDg6Q2hlY2tSdW41MzQ3MjMxMw==", 86 | "head_sha": "9272f18514cbd3fa935b3ced62ae1c2bf6efa76d", 87 | "external_id": "", 88 | "url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/check-runs/53472313", 89 | "html_url": "https://github.com/erwinmombay/github-owners-bot-test-repo/runs/53472313", 90 | "details_url": "https://www.ampproject.org", 91 | "status": "completed", 92 | "conclusion": "failure", 93 | "started_at": "2019-01-23T03:33:53Z", 94 | "completed_at": "2019-01-23T03:33:52Z", 95 | "output": { 96 | "title": "Probot check!", 97 | "summary": "The check has passed!", 98 | "text": null, 99 | "annotations_count": 0, 100 | "annotations_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/check-runs/53472313/annotations" 101 | }, 102 | "name": "some other check from the same bot", 103 | "check_suite": { 104 | "id": 52508974 105 | }, 106 | "app": { 107 | "id": 22611, 108 | "node_id": "MDM6QXBwMjI2MTE=", 109 | "owner": { 110 | "login": "ampprojectbot", 111 | "id": 23269078, 112 | "node_id": "MDQ6VXNlcjIzMjY5MDc4", 113 | "avatar_url": "https://avatars3.githubusercontent.com/u/23269078?v=4", 114 | "gravatar_id": "", 115 | "url": "https://api.github.com/users/ampprojectbot", 116 | "html_url": "https://github.com/ampprojectbot", 117 | "followers_url": "https://api.github.com/users/ampprojectbot/followers", 118 | "following_url": "https://api.github.com/users/ampprojectbot/following{/other_user}", 119 | "gists_url": "https://api.github.com/users/ampprojectbot/gists{/gist_id}", 120 | "starred_url": "https://api.github.com/users/ampprojectbot/starred{/owner}{/repo}", 121 | "subscriptions_url": "https://api.github.com/users/ampprojectbot/subscriptions", 122 | "organizations_url": "https://api.github.com/users/ampprojectbot/orgs", 123 | "repos_url": "https://api.github.com/users/ampprojectbot/repos", 124 | "events_url": "https://api.github.com/users/ampprojectbot/events{/privacy}", 125 | "received_events_url": "https://api.github.com/users/ampprojectbot/received_events", 126 | "type": "User", 127 | "site_admin": false 128 | }, 129 | "name": "amp-owners-bot", 130 | "description": "A bot that verifies that all \"owners\" of a file set has approved a pull request.\r\n\r\nusers OWNERS.yaml files in a repository to find the set of owners.", 131 | "external_url": "https://www.ampproject.org", 132 | "html_url": "https://github.com/apps/amp-owners-bot", 133 | "created_at": "2018-12-20T18:50:10Z", 134 | "updated_at": "2019-01-18T19:48:17Z" 135 | }, 136 | "pull_requests": [ 137 | { 138 | "url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls/35", 139 | "id": 246688458, 140 | "number": 35, 141 | "head": { 142 | "ref": "ampprojectbot-patch-3", 143 | "sha": "9272f18514cbd3fa935b3ced62ae1c2bf6efa76d", 144 | "repo": { 145 | "id": 72889098, 146 | "url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo", 147 | "name": "github-owners-bot-test-repo" 148 | } 149 | }, 150 | "base": { 151 | "ref": "master", 152 | "sha": "e896a1ed550e296573e46bcb7d0ab23afa3bbedf", 153 | "repo": { 154 | "id": 72889098, 155 | "url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo", 156 | "name": "github-owners-bot-test-repo" 157 | } 158 | } 159 | } 160 | ] 161 | } 162 | ] 163 | } 164 | -------------------------------------------------------------------------------- /test/fixtures/files/files.35.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "sha": "eeae1593f4ecbae3f4453c9ceee2940a0e98ddca", 4 | "filename": "dir2/dir1/dir1/file.txt", 5 | "status": "modified", 6 | "additions": 1, 7 | "deletions": 0, 8 | "changes": 1, 9 | "blob_url": "https://github.com/erwinmombay/github-owners-bot-test-repo/blob/9272f18514cbd3fa935b3ced62ae1c2bf6efa76d/dir2/dir1/dir1/file.txt", 10 | "raw_url": "https://github.com/erwinmombay/github-owners-bot-test-repo/raw/9272f18514cbd3fa935b3ced62ae1c2bf6efa76d/dir2/dir1/dir1/file.txt", 11 | "contents_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/contents/dir2/dir1/dir1/file.txt?ref=9272f18514cbd3fa935b3ced62ae1c2bf6efa76d", 12 | "patch": "@@ -1 +1,2 @@\n test again\r\n+again\r" 13 | } 14 | ] 15 | -------------------------------------------------------------------------------- /test/fixtures/files/files.35.multiple.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "sha": "eeae1593f4ecbae3f4453c9ceee2940a0e98ddca", 4 | "filename": "dir2/dir1/dir1/file.txt", 5 | "status": "modified", 6 | "additions": 1, 7 | "deletions": 0, 8 | "changes": 1, 9 | "blob_url": "https://github.com/erwinmombay/github-owners-bot-test-repo/blob/9272f18514cbd3fa935b3ced62ae1c2bf6efa76d/dir2/dir1/dir1/file.txt", 10 | "raw_url": "https://github.com/erwinmombay/github-owners-bot-test-repo/raw/9272f18514cbd3fa935b3ced62ae1c2bf6efa76d/dir2/dir1/dir1/file.txt", 11 | "contents_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/contents/dir2/dir1/dir1/file.txt?ref=9272f18514cbd3fa935b3ced62ae1c2bf6efa76d", 12 | "patch": "@@ -1 +1,2 @@\n test again\r\n+again\r" 13 | }, 14 | { 15 | "sha": "eeae1593f4ecbae3f4453c9ceee2940a0e98ddcx", 16 | "filename": "dir2/dir1/dir1/file-2.txt", 17 | "status": "modified", 18 | "additions": 1, 19 | "deletions": 0, 20 | "changes": 1, 21 | "blob_url": "https://github.com/erwinmombay/github-owners-bot-test-repo/blob/9272f18514cbd3fa935b3ced62ae1c2bf6efa76x/dir2/dir1/dir1/file-2.txt", 22 | "raw_url": "https://github.com/erwinmombay/github-owners-bot-test-repo/raw/9272f18514cbd3fa935b3ced62ae1c2bf6efa76x/dir2/dir1/dir1/file-2.txt", 23 | "contents_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/contents/dir2/dir1/dir1/file.txt?ref=9272f18514cbd3fa935b3ced62ae1c2bf6efa76x", 24 | "patch": "@@ -1 +1,2 @@\n test again on another file\r\n+again\r" 25 | } 26 | ] 27 | -------------------------------------------------------------------------------- /test/fixtures/files/files.36.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "sha": "3b2aed8e02b2d051b18268f41c4fee799fe90aa9", 4 | "filename": "dir2/new-file.txt", 5 | "status": "added", 6 | "additions": 1, 7 | "deletions": 0, 8 | "changes": 1, 9 | "blob_url": "https://github.com/erwinmombay/github-owners-bot-test-repo/blob/c7fdbd7f947fca608b20006da8535af5384ab699/dir2/new-file.txt", 10 | "raw_url": "https://github.com/erwinmombay/github-owners-bot-test-repo/raw/c7fdbd7f947fca608b20006da8535af5384ab699/dir2/new-file.txt", 11 | "contents_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/contents/dir2/new-file.txt?ref=c7fdbd7f947fca608b20006da8535af5384ab699", 12 | "patch": "@@ -0,0 +1 @@\n+this is a new file" 13 | } 14 | ] 15 | -------------------------------------------------------------------------------- /test/fixtures/pulls/pull_request.35.json: -------------------------------------------------------------------------------- 1 | { 2 | "url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls/35", 3 | "id": 246688458, 4 | "node_id": "MDExOlB1bGxSZXF1ZXN0MjQ2Njg4NDU4", 5 | "html_url": "https://github.com/erwinmombay/github-owners-bot-test-repo/pull/35", 6 | "diff_url": "https://github.com/erwinmombay/github-owners-bot-test-repo/pull/35.diff", 7 | "patch_url": "https://github.com/erwinmombay/github-owners-bot-test-repo/pull/35.patch", 8 | "issue_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues/35", 9 | "number": 35, 10 | "state": "open", 11 | "locked": false, 12 | "title": "Update file.txt", 13 | "user": { 14 | "login": "ampprojectbot", 15 | "id": 23269078, 16 | "node_id": "MDQ6VXNlcjIzMjY5MDc4", 17 | "avatar_url": "https://avatars3.githubusercontent.com/u/23269078?v=4", 18 | "gravatar_id": "", 19 | "url": "https://api.github.com/users/ampprojectbot", 20 | "html_url": "https://github.com/ampprojectbot", 21 | "followers_url": "https://api.github.com/users/ampprojectbot/followers", 22 | "following_url": "https://api.github.com/users/ampprojectbot/following{/other_user}", 23 | "gists_url": "https://api.github.com/users/ampprojectbot/gists{/gist_id}", 24 | "starred_url": "https://api.github.com/users/ampprojectbot/starred{/owner}{/repo}", 25 | "subscriptions_url": "https://api.github.com/users/ampprojectbot/subscriptions", 26 | "organizations_url": "https://api.github.com/users/ampprojectbot/orgs", 27 | "repos_url": "https://api.github.com/users/ampprojectbot/repos", 28 | "events_url": "https://api.github.com/users/ampprojectbot/events{/privacy}", 29 | "received_events_url": "https://api.github.com/users/ampprojectbot/received_events", 30 | "type": "User", 31 | "site_admin": false 32 | }, 33 | "body": "", 34 | "created_at": "2019-01-22T17:22:51Z", 35 | "updated_at": "2019-02-26T20:53:31Z", 36 | "closed_at": null, 37 | "merged_at": null, 38 | "merge_commit_sha": "95fe33cbfa4cb9d528e64982345c1cde39b71b81", 39 | "assignee": null, 40 | "assignees": [], 41 | "requested_reviewers": [], 42 | "requested_teams": [], 43 | "labels": [], 44 | "milestone": null, 45 | "commits_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls/35/commits", 46 | "review_comments_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls/35/comments", 47 | "review_comment_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls/comments{/number}", 48 | "comments_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues/35/comments", 49 | "statuses_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/statuses/9272f18514cbd3fa935b3ced62ae1c2bf6efa76d", 50 | "head": { 51 | "label": "erwinmombay:ampprojectbot-patch-3", 52 | "ref": "ampprojectbot-patch-3", 53 | "sha": "9272f18514cbd3fa935b3ced62ae1c2bf6efa76d", 54 | "user": { 55 | "login": "erwinmombay", 56 | "id": 354746, 57 | "node_id": "MDQ6VXNlcjM1NDc0Ng==", 58 | "avatar_url": "https://avatars1.githubusercontent.com/u/354746?v=4", 59 | "gravatar_id": "", 60 | "url": "https://api.github.com/users/erwinmombay", 61 | "html_url": "https://github.com/erwinmombay", 62 | "followers_url": "https://api.github.com/users/erwinmombay/followers", 63 | "following_url": "https://api.github.com/users/erwinmombay/following{/other_user}", 64 | "gists_url": "https://api.github.com/users/erwinmombay/gists{/gist_id}", 65 | "starred_url": "https://api.github.com/users/erwinmombay/starred{/owner}{/repo}", 66 | "subscriptions_url": "https://api.github.com/users/erwinmombay/subscriptions", 67 | "organizations_url": "https://api.github.com/users/erwinmombay/orgs", 68 | "repos_url": "https://api.github.com/users/erwinmombay/repos", 69 | "events_url": "https://api.github.com/users/erwinmombay/events{/privacy}", 70 | "received_events_url": "https://api.github.com/users/erwinmombay/received_events", 71 | "type": "User", 72 | "site_admin": false 73 | }, 74 | "repo": { 75 | "id": 72889098, 76 | "node_id": "MDEwOlJlcG9zaXRvcnk3Mjg4OTA5OA==", 77 | "name": "github-owners-bot-test-repo", 78 | "full_name": "erwinmombay/github-owners-bot-test-repo", 79 | "private": false, 80 | "owner": { 81 | "login": "erwinmombay", 82 | "id": 354746, 83 | "node_id": "MDQ6VXNlcjM1NDc0Ng==", 84 | "avatar_url": "https://avatars1.githubusercontent.com/u/354746?v=4", 85 | "gravatar_id": "", 86 | "url": "https://api.github.com/users/erwinmombay", 87 | "html_url": "https://github.com/erwinmombay", 88 | "followers_url": "https://api.github.com/users/erwinmombay/followers", 89 | "following_url": "https://api.github.com/users/erwinmombay/following{/other_user}", 90 | "gists_url": "https://api.github.com/users/erwinmombay/gists{/gist_id}", 91 | "starred_url": "https://api.github.com/users/erwinmombay/starred{/owner}{/repo}", 92 | "subscriptions_url": "https://api.github.com/users/erwinmombay/subscriptions", 93 | "organizations_url": "https://api.github.com/users/erwinmombay/orgs", 94 | "repos_url": "https://api.github.com/users/erwinmombay/repos", 95 | "events_url": "https://api.github.com/users/erwinmombay/events{/privacy}", 96 | "received_events_url": "https://api.github.com/users/erwinmombay/received_events", 97 | "type": "User", 98 | "site_admin": false 99 | }, 100 | "html_url": "https://github.com/erwinmombay/github-owners-bot-test-repo", 101 | "description": null, 102 | "fork": false, 103 | "url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo", 104 | "forks_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/forks", 105 | "keys_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/keys{/key_id}", 106 | "collaborators_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/collaborators{/collaborator}", 107 | "teams_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/teams", 108 | "hooks_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/hooks", 109 | "issue_events_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues/events{/number}", 110 | "events_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/events", 111 | "assignees_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/assignees{/user}", 112 | "branches_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/branches{/branch}", 113 | "tags_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/tags", 114 | "blobs_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/blobs{/sha}", 115 | "git_tags_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/tags{/sha}", 116 | "git_refs_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/refs{/sha}", 117 | "trees_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/trees{/sha}", 118 | "statuses_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/statuses/{sha}", 119 | "languages_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/languages", 120 | "stargazers_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/stargazers", 121 | "contributors_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/contributors", 122 | "subscribers_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/subscribers", 123 | "subscription_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/subscription", 124 | "commits_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/commits{/sha}", 125 | "git_commits_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/commits{/sha}", 126 | "comments_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/comments{/number}", 127 | "issue_comment_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues/comments{/number}", 128 | "contents_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/contents/{+path}", 129 | "compare_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/compare/{base}...{head}", 130 | "merges_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/merges", 131 | "archive_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/{archive_format}{/ref}", 132 | "downloads_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/downloads", 133 | "issues_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues{/number}", 134 | "pulls_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls{/number}", 135 | "milestones_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/milestones{/number}", 136 | "notifications_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/notifications{?since,all,participating}", 137 | "labels_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/labels{/name}", 138 | "releases_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/releases{/id}", 139 | "deployments_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/deployments", 140 | "created_at": "2016-11-04T22:11:38Z", 141 | "updated_at": "2019-01-23T03:33:46Z", 142 | "pushed_at": "2019-02-13T03:46:55Z", 143 | "git_url": "git://github.com/erwinmombay/github-owners-bot-test-repo.git", 144 | "ssh_url": "git@github.com:erwinmombay/github-owners-bot-test-repo.git", 145 | "clone_url": "https://github.com/erwinmombay/github-owners-bot-test-repo.git", 146 | "svn_url": "https://github.com/erwinmombay/github-owners-bot-test-repo", 147 | "homepage": null, 148 | "size": 21, 149 | "stargazers_count": 0, 150 | "watchers_count": 0, 151 | "language": null, 152 | "has_issues": true, 153 | "has_projects": true, 154 | "has_downloads": true, 155 | "has_wiki": true, 156 | "has_pages": false, 157 | "forks_count": 4, 158 | "mirror_url": null, 159 | "archived": false, 160 | "open_issues_count": 31, 161 | "license": null, 162 | "forks": 4, 163 | "open_issues": 31, 164 | "watchers": 0, 165 | "default_branch": "master" 166 | } 167 | }, 168 | "base": { 169 | "label": "erwinmombay:master", 170 | "ref": "master", 171 | "sha": "e896a1ed550e296573e46bcb7d0ab23afa3bbedf", 172 | "user": { 173 | "login": "erwinmombay", 174 | "id": 354746, 175 | "node_id": "MDQ6VXNlcjM1NDc0Ng==", 176 | "avatar_url": "https://avatars1.githubusercontent.com/u/354746?v=4", 177 | "gravatar_id": "", 178 | "url": "https://api.github.com/users/erwinmombay", 179 | "html_url": "https://github.com/erwinmombay", 180 | "followers_url": "https://api.github.com/users/erwinmombay/followers", 181 | "following_url": "https://api.github.com/users/erwinmombay/following{/other_user}", 182 | "gists_url": "https://api.github.com/users/erwinmombay/gists{/gist_id}", 183 | "starred_url": "https://api.github.com/users/erwinmombay/starred{/owner}{/repo}", 184 | "subscriptions_url": "https://api.github.com/users/erwinmombay/subscriptions", 185 | "organizations_url": "https://api.github.com/users/erwinmombay/orgs", 186 | "repos_url": "https://api.github.com/users/erwinmombay/repos", 187 | "events_url": "https://api.github.com/users/erwinmombay/events{/privacy}", 188 | "received_events_url": "https://api.github.com/users/erwinmombay/received_events", 189 | "type": "User", 190 | "site_admin": false 191 | }, 192 | "repo": { 193 | "id": 72889098, 194 | "node_id": "MDEwOlJlcG9zaXRvcnk3Mjg4OTA5OA==", 195 | "name": "github-owners-bot-test-repo", 196 | "full_name": "erwinmombay/github-owners-bot-test-repo", 197 | "private": false, 198 | "owner": { 199 | "login": "erwinmombay", 200 | "id": 354746, 201 | "node_id": "MDQ6VXNlcjM1NDc0Ng==", 202 | "avatar_url": "https://avatars1.githubusercontent.com/u/354746?v=4", 203 | "gravatar_id": "", 204 | "url": "https://api.github.com/users/erwinmombay", 205 | "html_url": "https://github.com/erwinmombay", 206 | "followers_url": "https://api.github.com/users/erwinmombay/followers", 207 | "following_url": "https://api.github.com/users/erwinmombay/following{/other_user}", 208 | "gists_url": "https://api.github.com/users/erwinmombay/gists{/gist_id}", 209 | "starred_url": "https://api.github.com/users/erwinmombay/starred{/owner}{/repo}", 210 | "subscriptions_url": "https://api.github.com/users/erwinmombay/subscriptions", 211 | "organizations_url": "https://api.github.com/users/erwinmombay/orgs", 212 | "repos_url": "https://api.github.com/users/erwinmombay/repos", 213 | "events_url": "https://api.github.com/users/erwinmombay/events{/privacy}", 214 | "received_events_url": "https://api.github.com/users/erwinmombay/received_events", 215 | "type": "User", 216 | "site_admin": false 217 | }, 218 | "html_url": "https://github.com/erwinmombay/github-owners-bot-test-repo", 219 | "description": null, 220 | "fork": false, 221 | "url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo", 222 | "forks_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/forks", 223 | "keys_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/keys{/key_id}", 224 | "collaborators_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/collaborators{/collaborator}", 225 | "teams_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/teams", 226 | "hooks_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/hooks", 227 | "issue_events_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues/events{/number}", 228 | "events_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/events", 229 | "assignees_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/assignees{/user}", 230 | "branches_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/branches{/branch}", 231 | "tags_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/tags", 232 | "blobs_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/blobs{/sha}", 233 | "git_tags_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/tags{/sha}", 234 | "git_refs_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/refs{/sha}", 235 | "trees_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/trees{/sha}", 236 | "statuses_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/statuses/{sha}", 237 | "languages_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/languages", 238 | "stargazers_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/stargazers", 239 | "contributors_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/contributors", 240 | "subscribers_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/subscribers", 241 | "subscription_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/subscription", 242 | "commits_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/commits{/sha}", 243 | "git_commits_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/git/commits{/sha}", 244 | "comments_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/comments{/number}", 245 | "issue_comment_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues/comments{/number}", 246 | "contents_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/contents/{+path}", 247 | "compare_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/compare/{base}...{head}", 248 | "merges_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/merges", 249 | "archive_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/{archive_format}{/ref}", 250 | "downloads_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/downloads", 251 | "issues_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues{/number}", 252 | "pulls_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls{/number}", 253 | "milestones_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/milestones{/number}", 254 | "notifications_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/notifications{?since,all,participating}", 255 | "labels_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/labels{/name}", 256 | "releases_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/releases{/id}", 257 | "deployments_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/deployments", 258 | "created_at": "2016-11-04T22:11:38Z", 259 | "updated_at": "2019-01-23T03:33:46Z", 260 | "pushed_at": "2019-02-13T03:46:55Z", 261 | "git_url": "git://github.com/erwinmombay/github-owners-bot-test-repo.git", 262 | "ssh_url": "git@github.com:erwinmombay/github-owners-bot-test-repo.git", 263 | "clone_url": "https://github.com/erwinmombay/github-owners-bot-test-repo.git", 264 | "svn_url": "https://github.com/erwinmombay/github-owners-bot-test-repo", 265 | "homepage": null, 266 | "size": 21, 267 | "stargazers_count": 0, 268 | "watchers_count": 0, 269 | "language": null, 270 | "has_issues": true, 271 | "has_projects": true, 272 | "has_downloads": true, 273 | "has_wiki": true, 274 | "has_pages": false, 275 | "forks_count": 4, 276 | "mirror_url": null, 277 | "archived": false, 278 | "open_issues_count": 31, 279 | "license": null, 280 | "forks": 4, 281 | "open_issues": 31, 282 | "watchers": 0, 283 | "default_branch": "master" 284 | } 285 | }, 286 | "_links": { 287 | "self": { 288 | "href": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls/35" 289 | }, 290 | "html": { 291 | "href": "https://github.com/erwinmombay/github-owners-bot-test-repo/pull/35" 292 | }, 293 | "issue": { 294 | "href": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues/35" 295 | }, 296 | "comments": { 297 | "href": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/issues/35/comments" 298 | }, 299 | "review_comments": { 300 | "href": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls/35/comments" 301 | }, 302 | "review_comment": { 303 | "href": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls/comments{/number}" 304 | }, 305 | "commits": { 306 | "href": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls/35/commits" 307 | }, 308 | "statuses": { 309 | "href": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/statuses/9272f18514cbd3fa935b3ced62ae1c2bf6efa76d" 310 | } 311 | }, 312 | "author_association": "COLLABORATOR", 313 | "merged": false, 314 | "mergeable": true, 315 | "rebaseable": true, 316 | "mergeable_state": "clean", 317 | "merged_by": null, 318 | "comments": 0, 319 | "review_comments": 1, 320 | "maintainer_can_modify": false, 321 | "commits": 1, 322 | "additions": 1, 323 | "deletions": 0, 324 | "changed_files": 1 325 | } 326 | -------------------------------------------------------------------------------- /test/fixtures/reviews/reviews.35.approved.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 208194465, 4 | "node_id": "MDE3OlB1bGxSZXF1ZXN0UmV2aWV3MjA4MTk0NDY1", 5 | "user": { 6 | "login": "erwinmombay", 7 | "id": 354746, 8 | "node_id": "MDQ6VXNlcjM1NDc0Ng==", 9 | "avatar_url": "https://avatars1.githubusercontent.com/u/354746?v=4", 10 | "gravatar_id": "", 11 | "url": "https://api.github.com/users/erwinmombay", 12 | "html_url": "https://github.com/erwinmombay", 13 | "followers_url": "https://api.github.com/users/erwinmombay/followers", 14 | "following_url": "https://api.github.com/users/erwinmombay/following{/other_user}", 15 | "gists_url": "https://api.github.com/users/erwinmombay/gists{/gist_id}", 16 | "starred_url": "https://api.github.com/users/erwinmombay/starred{/owner}{/repo}", 17 | "subscriptions_url": "https://api.github.com/users/erwinmombay/subscriptions", 18 | "organizations_url": "https://api.github.com/users/erwinmombay/orgs", 19 | "repos_url": "https://api.github.com/users/erwinmombay/repos", 20 | "events_url": "https://api.github.com/users/erwinmombay/events{/privacy}", 21 | "received_events_url": "https://api.github.com/users/erwinmombay/received_events", 22 | "type": "User", 23 | "site_admin": false 24 | }, 25 | "body": "", 26 | "state": "APPROVED", 27 | "html_url": "https://github.com/erwinmombay/github-owners-bot-test-repo/pull/35#pullrequestreview-208194465", 28 | "pull_request_url": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls/35", 29 | "author_association": "OWNER", 30 | "_links": { 31 | "html": { 32 | "href": "https://github.com/erwinmombay/github-owners-bot-test-repo/pull/35#pullrequestreview-208194465" 33 | }, 34 | "pull_request": { 35 | "href": "https://api.github.com/repos/erwinmombay/github-owners-bot-test-repo/pulls/35" 36 | } 37 | }, 38 | "submitted_at": "2019-02-26T20:39:13Z", 39 | "commit_id": "9272f18514cbd3fa935b3ced62ae1c2bf6efa76d" 40 | } 41 | ] 42 | -------------------------------------------------------------------------------- /test/fixtures/reviews/reviews.35.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /test/fixtures/teams/teams.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /test/index.test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS-IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | const nock = require('nock') 18 | const owners = require('..') 19 | const {Probot} = require('probot') 20 | const Git = require('../src/git').Git; 21 | const Owner = require('../src/owner').Owner; 22 | const sinon = require('sinon'); 23 | 24 | const opened35 = require('./fixtures/actions/opened.35') 25 | const opened36 = require('./fixtures/actions/opened.36.author-is-owner') 26 | const rerequest35 = require('./fixtures/actions/rerequested.35'); 27 | const review35 = require('./fixtures/actions/pull_request_review.35.submitted'); 28 | 29 | const files35 = require('./fixtures/files/files.35'); 30 | const files35Multiple = require('./fixtures/files/files.35.multiple'); 31 | const files36 = require('./fixtures/files/files.36'); 32 | 33 | const reviews35 = require('./fixtures/reviews/reviews.35'); 34 | const reviews35Approved = require('./fixtures/reviews/reviews.35.approved'); 35 | 36 | const checkruns35 = require('./fixtures/check-runs/check-runs.get.35'); 37 | const checkruns35Multiple = require('./fixtures/check-runs/check-runs.get.35.multiple'); 38 | const checkruns35Empty = require('./fixtures/check-runs/check-runs.get.35.empty'); 39 | const checkRunsCreate = require('./fixtures/check-runs/check-runs.create'); 40 | 41 | const pullRequest35 = require('./fixtures/pulls/pull_request.35'); 42 | 43 | const teams = require('./fixtures/teams/teams'); 44 | 45 | 46 | nock.disableNetConnect(); 47 | jest.setTimeout(30000); 48 | 49 | const ownersYamlStruct = { 50 | '.': { 51 | 'path': './OWNERS.yaml', 52 | 'dirname': '.', 53 | 'fullpath': '/Users/erwinm/dev/github-owners-bot-test-repo/OWNERS.yaml', 54 | 'score': 0, 55 | 'dirOwners': [ 56 | 'donttrustthisbot' 57 | ], 58 | 'fileOwners': {} 59 | }, 60 | './dir1': { 61 | 'path': './dir1/OWNERS.yaml', 62 | 'dirname': './dir1', 63 | 'fullpath': '/Users/erwinm/dev/github-owners-bot-test-repo/dir1/OWNERS.yaml', 64 | 'score': 1, 65 | 'dirOwners': [ 66 | 'donttrustthisbot' 67 | ], 68 | 'fileOwners': {} 69 | }, 70 | './dir2': { 71 | 'path': './dir2/OWNERS.yaml', 72 | 'dirname': './dir2', 73 | 'fullpath': '/Users/erwinm/dev/github-owners-bot-test-repo/dir2/OWNERS.yaml', 74 | 'score': 1, 75 | 'dirOwners': [ 76 | 'erwinmombay' 77 | ], 78 | 'fileOwners': {} 79 | }, 80 | './dir2/dir1/dir1': { 81 | 'path': './dir2/dir1/dir1/OWNERS.yaml', 82 | 'dirname': './dir2/dir1/dir1', 83 | 'fullpath': '/Users/erwinm/dev/github-owners-bot-test-repo/dir2/dir1/dir1/OWNERS.yaml', 84 | 'score': 3, 85 | 'dirOwners': [ 86 | 'erwinmombay' 87 | ], 88 | 'fileOwners': {} 89 | } 90 | }; 91 | 92 | describe('owners bot', () => { 93 | let probot; 94 | let sandbox; 95 | 96 | beforeEach(() => { 97 | sandbox = sinon.createSandbox(); 98 | sandbox.stub(Git.prototype, 'pullLatestForRepo').returns(null); 99 | sandbox.stub(Git.prototype, 'getOwnersFilesForBranch') 100 | .returns(ownersYamlStruct); 101 | 102 | probot = new Probot({}) 103 | const app = probot.load(owners); 104 | 105 | // just return a test token 106 | app.app = () => 'test'; 107 | }) 108 | 109 | afterEach(() => { 110 | sandbox.restore(); 111 | }); 112 | 113 | describe('when there are more than 1 checks on a PR', () => { 114 | 115 | test('it should update amp owners bot check when there is one', async () => { 116 | 117 | nock('https://api.github.com') 118 | .post('/app/installations/588033/access_tokens') 119 | .reply(200, {token: 'test'}); 120 | 121 | // We need the list of files on a pull request to evaluate the required 122 | // reviewers. 123 | nock('https://api.github.com') 124 | .get('/repos/erwinmombay/github-owners-bot-test-repo/pulls/35/files') 125 | .reply(200, files35); 126 | 127 | nock('https://api.github.com') 128 | .get('/repos/erwinmombay/github-owners-bot-test-repo/teams') 129 | .reply(200, teams); 130 | 131 | // We need the reviews to check if a pull request has been approved or 132 | // not. 133 | nock('https://api.github.com') 134 | .get('/repos/erwinmombay/github-owners-bot-test-repo/pulls/35/reviews') 135 | .reply(200, reviews35); 136 | 137 | nock('https://api.github.com') 138 | .get('/repos/erwinmombay/github-owners-bot-test-repo/commits/9272f18514cbd3fa935b3ced62ae1c2bf6efa76d/check-runs') 139 | .reply(200, checkruns35Multiple); 140 | 141 | // Test that a check-run is created 142 | nock('https://api.github.com') 143 | .patch('/repos/erwinmombay/github-owners-bot-test-repo/check-runs/53472315', body => { 144 | expect(body).toMatchObject({ 145 | //conclusion: 'failure', 146 | conclusion: 'neutral', 147 | output: { 148 | title: 'ampproject/owners-check', 149 | summary: 'The check was a failure!', 150 | text: '\n## possible reviewers: erwinmombay\n - ./dir2/dir1/dir1/file.txt\n', 151 | } 152 | }); 153 | return true; 154 | }).reply(200); 155 | 156 | await probot.receive({event: 'pull_request', payload: opened35}); 157 | }); 158 | }); 159 | 160 | describe('create check run', () => { 161 | 162 | test('with failure check when there are 0 reviews on a pull request', async () => { 163 | 164 | nock('https://api.github.com') 165 | .post('/app/installations/588033/access_tokens') 166 | .reply(200, {token: 'test'}); 167 | 168 | // We need the list of files on a pull request to evaluate the required 169 | // reviewers. 170 | nock('https://api.github.com') 171 | .get('/repos/erwinmombay/github-owners-bot-test-repo/pulls/35/files') 172 | .reply(200, files35); 173 | 174 | nock('https://api.github.com') 175 | .get('/repos/erwinmombay/github-owners-bot-test-repo/teams') 176 | .reply(200, teams); 177 | 178 | // We need the reviews to check if a pull request has been approved or 179 | // not. 180 | nock('https://api.github.com') 181 | .get('/repos/erwinmombay/github-owners-bot-test-repo/pulls/35/reviews') 182 | .reply(200, reviews35); 183 | 184 | // Get check runs for a specific commit 185 | nock('https://api.github.com') 186 | .get('/repos/erwinmombay/github-owners-bot-test-repo/commits/9272f18514cbd3fa935b3ced62ae1c2bf6efa76d/check-runs') 187 | .reply(200, checkruns35Empty); 188 | 189 | // Test that a check-run is created 190 | nock('https://api.github.com') 191 | .post('/repos/erwinmombay/github-owners-bot-test-repo/check-runs', body => { 192 | expect(body).toMatchObject({ 193 | name: 'ampproject/owners-check', 194 | head_branch: opened35.pull_request.head.ref, 195 | head_sha: opened35.pull_request.head.sha, 196 | status: 'completed', 197 | //conclusion: 'failure', 198 | conclusion: 'neutral', 199 | output: { 200 | title: 'ampproject/owners-check', 201 | summary: 'The check was a failure!', 202 | text: '\n## possible reviewers: erwinmombay\n - ./dir2/dir1/dir1/file.txt\n', 203 | } 204 | }); 205 | return true; 206 | }).reply(200); 207 | 208 | await probot.receive({event: 'pull_request', payload: opened35}); 209 | }); 210 | }); 211 | 212 | describe('update check run', () => { 213 | 214 | test('with failure check when there are 0 reviews on a pull request', async () => { 215 | 216 | nock('https://api.github.com') 217 | .post('/app/installations/588033/access_tokens') 218 | .reply(200, {token: 'test'}); 219 | 220 | // We need the list of files on a pull request to evaluate the required 221 | // reviewers. 222 | nock('https://api.github.com') 223 | .get('/repos/erwinmombay/github-owners-bot-test-repo/pulls/35/files') 224 | .reply(200, files35); 225 | 226 | nock('https://api.github.com') 227 | .get('/repos/erwinmombay/github-owners-bot-test-repo/teams') 228 | .reply(200, teams); 229 | 230 | // We need the reviews to check if a pull request has been approved or 231 | // not. 232 | nock('https://api.github.com') 233 | .get('/repos/erwinmombay/github-owners-bot-test-repo/pulls/35/reviews') 234 | .reply(200, reviews35); 235 | 236 | nock('https://api.github.com') 237 | .get('/repos/erwinmombay/github-owners-bot-test-repo/commits/9272f18514cbd3fa935b3ced62ae1c2bf6efa76d/check-runs') 238 | .reply(200, checkruns35); 239 | 240 | // Test that a check-run is created 241 | nock('https://api.github.com') 242 | .patch('/repos/erwinmombay/github-owners-bot-test-repo/check-runs/53472313', body => { 243 | expect(body).toMatchObject({ 244 | //conclusion: 'failure', 245 | conclusion: 'neutral', 246 | output: { 247 | title: 'ampproject/owners-check', 248 | summary: 'The check was a failure!', 249 | text: '\n## possible reviewers: erwinmombay\n - ./dir2/dir1/dir1/file.txt\n', 250 | } 251 | }); 252 | return true; 253 | }).reply(200); 254 | 255 | await probot.receive({event: 'pull_request', payload: opened35}); 256 | }); 257 | 258 | test('with failure check when there are 0 reviews on a pull request and multiple files', async () => { 259 | 260 | nock('https://api.github.com') 261 | .post('/app/installations/588033/access_tokens') 262 | .reply(200, {token: 'test'}); 263 | 264 | // We need the list of files on a pull request to evaluate the required 265 | // reviewers. 266 | nock('https://api.github.com') 267 | .get('/repos/erwinmombay/github-owners-bot-test-repo/pulls/35/files') 268 | .reply(200, files35Multiple); 269 | 270 | nock('https://api.github.com') 271 | .get('/repos/erwinmombay/github-owners-bot-test-repo/teams') 272 | .reply(200, teams); 273 | 274 | // We need the reviews to check if a pull request has been approved or 275 | // not. 276 | nock('https://api.github.com') 277 | .get('/repos/erwinmombay/github-owners-bot-test-repo/pulls/35/reviews') 278 | .reply(200, reviews35); 279 | 280 | nock('https://api.github.com') 281 | .get('/repos/erwinmombay/github-owners-bot-test-repo/commits/9272f18514cbd3fa935b3ced62ae1c2bf6efa76d/check-runs') 282 | .reply(200, checkruns35); 283 | 284 | // Test that a check-run is created 285 | nock('https://api.github.com') 286 | .patch('/repos/erwinmombay/github-owners-bot-test-repo/check-runs/53472313', body => { 287 | expect(body).toMatchObject({ 288 | //conclusion: 'failure', 289 | conclusion: 'neutral', 290 | output: { 291 | title: 'ampproject/owners-check', 292 | summary: 'The check was a failure!', 293 | text: '\n## possible reviewers: erwinmombay\n - ./dir2/dir1/dir1/file.txt\n - ./dir2/dir1/dir1/file-2.txt\n', 294 | } 295 | }); 296 | return true; 297 | }).reply(200); 298 | 299 | await probot.receive({event: 'pull_request', payload: opened35}); 300 | }); 301 | }); 302 | 303 | describe('rerequest check run', () => { 304 | 305 | test('should re-evaluate pull request', async () => { 306 | nock('https://api.github.com') 307 | .post('/app/installations/588033/access_tokens') 308 | .reply(200, {token: 'test'}); 309 | 310 | // We need the list of files on a pull request to evaluate the required 311 | // reviewers. 312 | nock('https://api.github.com') 313 | .get('/repos/erwinmombay/github-owners-bot-test-repo/pulls/35') 314 | .reply(200, pullRequest35); 315 | 316 | nock('https://api.github.com') 317 | .get('/repos/erwinmombay/github-owners-bot-test-repo/teams') 318 | .reply(200, teams); 319 | 320 | // We need the list of files on a pull request to evaluate the required 321 | // reviewers. 322 | nock('https://api.github.com') 323 | .get('/repos/erwinmombay/github-owners-bot-test-repo/pulls/35/files') 324 | .reply(200, files35); 325 | 326 | // We need the reviews to check if a pull request has been approved or 327 | // not. 328 | nock('https://api.github.com') 329 | .get('/repos/erwinmombay/github-owners-bot-test-repo/pulls/35/reviews') 330 | .reply(200, reviews35); 331 | 332 | nock('https://api.github.com') 333 | .get('/repos/erwinmombay/github-owners-bot-test-repo/commits/9272f18514cbd3fa935b3ced62ae1c2bf6efa76d/check-runs') 334 | .reply(200, checkruns35Empty); 335 | 336 | // Test that a check-run is created 337 | nock('https://api.github.com') 338 | .post('/repos/erwinmombay/github-owners-bot-test-repo/check-runs', body => { 339 | expect(body).toMatchObject({ 340 | name: 'ampproject/owners-check', 341 | head_branch: opened35.pull_request.head.ref, 342 | head_sha: opened35.pull_request.head.sha, 343 | status: 'completed', 344 | //conclusion: 'failure', 345 | conclusion: 'neutral', 346 | output: { 347 | title: 'ampproject/owners-check', 348 | summary: 'The check was a failure!', 349 | text: '\n## possible reviewers: erwinmombay\n - ./dir2/dir1/dir1/file.txt\n', 350 | } 351 | }); 352 | return true; 353 | }).reply(200); 354 | 355 | await probot.receive({event: 'check_run', payload: rerequest35}); 356 | }); 357 | }); 358 | 359 | describe('has approvals met', () => { 360 | 361 | test('with passing check when there is 1 approver on a pull request', async () => { 362 | 363 | nock('https://api.github.com') 364 | .post('/app/installations/588033/access_tokens') 365 | .reply(200, {token: 'test'}); 366 | 367 | // We need the list of files on a pull request to evaluate the required 368 | // reviewers. 369 | nock('https://api.github.com') 370 | .get('/repos/erwinmombay/github-owners-bot-test-repo/pulls/35/files') 371 | .reply(200, files35); 372 | 373 | nock('https://api.github.com') 374 | .get('/repos/erwinmombay/github-owners-bot-test-repo/teams') 375 | .reply(200, teams); 376 | 377 | // We need the reviews to check if a pull request has been approved or 378 | // not. 379 | nock('https://api.github.com') 380 | .get('/repos/erwinmombay/github-owners-bot-test-repo/pulls/35/reviews') 381 | .reply(200, reviews35Approved); 382 | 383 | nock('https://api.github.com') 384 | .get('/repos/erwinmombay/github-owners-bot-test-repo/commits/9272f18514cbd3fa935b3ced62ae1c2bf6efa76d/check-runs') 385 | .reply(200, checkruns35Empty); 386 | 387 | // Test that a check-run is created 388 | nock('https://api.github.com') 389 | .post('/repos/erwinmombay/github-owners-bot-test-repo/check-runs', body => { 390 | expect(body).toMatchObject({ 391 | name: 'ampproject/owners-check', 392 | head_branch: opened35.pull_request.head.ref, 393 | head_sha: opened35.pull_request.head.sha, 394 | status: 'completed', 395 | //conclusion: 'success', 396 | conclusion: 'neutral', 397 | output: { 398 | title: 'ampproject/owners-check', 399 | summary: 'The check was a success!', 400 | text: '', 401 | } 402 | }); 403 | return true; 404 | }).reply(200); 405 | 406 | await probot.receive({event: 'pull_request', payload: opened35}); 407 | }); 408 | 409 | test('with passing check when author themselves are owners', async () => { 410 | 411 | nock('https://api.github.com') 412 | .post('/app/installations/588033/access_tokens') 413 | .reply(200, {token: 'test'}); 414 | 415 | // We need the list of files on a pull request to evaluate the required 416 | // reviewers. 417 | nock('https://api.github.com') 418 | .get('/repos/erwinmombay/github-owners-bot-test-repo/pulls/36/files') 419 | .reply(200, files36); 420 | 421 | nock('https://api.github.com') 422 | .get('/repos/erwinmombay/github-owners-bot-test-repo/teams') 423 | .reply(200, teams); 424 | 425 | // We need the reviews to check if a pull request has been approved or 426 | // not. 427 | nock('https://api.github.com') 428 | .get('/repos/erwinmombay/github-owners-bot-test-repo/pulls/36/reviews') 429 | .reply(200, reviews35); 430 | 431 | nock('https://api.github.com') 432 | .get('/repos/erwinmombay/github-owners-bot-test-repo/commits/c7fdbd7f947fca608b20006da8535af5384ab699/check-runs') 433 | .reply(200, checkruns35Empty); 434 | 435 | //// Test that a check-run is created 436 | nock('https://api.github.com') 437 | .post('/repos/erwinmombay/github-owners-bot-test-repo/check-runs', body => { 438 | expect(body).toMatchObject({ 439 | name: 'ampproject/owners-check', 440 | head_branch: opened36.pull_request.head.ref, 441 | head_sha: opened36.pull_request.head.sha, 442 | status: 'completed', 443 | //conclusion: 'success', 444 | conclusion: 'neutral', 445 | output: { 446 | title: 'ampproject/owners-check', 447 | summary: 'The check was a success!', 448 | text: '', 449 | } 450 | }); 451 | return true; 452 | }).reply(200); 453 | 454 | await probot.receive({event: 'pull_request', payload: opened36}); 455 | }); 456 | }); 457 | 458 | describe('pull request review', () => { 459 | 460 | test('triggers pull request re-evaluation', async () => { 461 | 462 | nock('https://api.github.com') 463 | .post('/app/installations/588033/access_tokens') 464 | .reply(200, {token: 'test'}); 465 | 466 | 467 | nock('https://api.github.com') 468 | .get('/repos/erwinmombay/github-owners-bot-test-repo/pulls/35') 469 | .reply(200, pullRequest35); 470 | // We need the list of files on a pull request to evaluate the required 471 | // reviewers. 472 | nock('https://api.github.com') 473 | .get('/repos/erwinmombay/github-owners-bot-test-repo/pulls/35/files') 474 | .reply(200, files35); 475 | 476 | nock('https://api.github.com') 477 | .get('/repos/erwinmombay/github-owners-bot-test-repo/teams') 478 | .reply(200, teams); 479 | 480 | // We need the reviews to check if a pull request has been approved or 481 | // not. 482 | nock('https://api.github.com') 483 | .get('/repos/erwinmombay/github-owners-bot-test-repo/pulls/35/reviews') 484 | .reply(200, reviews35Approved); 485 | 486 | nock('https://api.github.com') 487 | .get('/repos/erwinmombay/github-owners-bot-test-repo/commits/9272f18514cbd3fa935b3ced62ae1c2bf6efa76d/check-runs') 488 | .reply(200, checkruns35Empty); 489 | 490 | // Test that a check-run is created 491 | nock('https://api.github.com') 492 | .post('/repos/erwinmombay/github-owners-bot-test-repo/check-runs', body => { 493 | expect(body).toMatchObject({ 494 | name: 'ampproject/owners-check', 495 | head_branch: opened35.pull_request.head.ref, 496 | head_sha: opened35.pull_request.head.sha, 497 | status: 'completed', 498 | //conclusion: 'success', 499 | conclusion: 'neutral', 500 | output: { 501 | title: 'ampproject/owners-check', 502 | summary: 'The check was a success!', 503 | text: '', 504 | } 505 | }); 506 | return true; 507 | }).reply(200); 508 | 509 | await probot.receive({event: 'pull_request_review', payload: review35}); 510 | }); 511 | }); 512 | }); 513 | --------------------------------------------------------------------------------