Skip to content
This repository has been archived by the owner on Jul 21, 2024. It is now read-only.

Commit

Permalink
fix: fix existing bug for this pr
Browse files Browse the repository at this point in the history
  • Loading branch information
sotayamashita committed Mar 29, 2020
1 parent 30c7563 commit f67961e
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 157 deletions.
25 changes: 12 additions & 13 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
const debug = require("debug")("probot:pr-triage");
const Raven = require("raven");
const Sentry = require("@sentry/node");
const PRTriage = require("./lib/pr-triage");

Raven.config(
process.env.NODE_ENV === "production" &&
"https://[email protected]/1222067"
).install();
if (process.env.NODE_ENV === "production") {
Sentry.init({
dsn: "https://[email protected]/1222067"
});
}

function probotPlugin(robot) {
const events = [
Expand All @@ -26,16 +27,14 @@ async function triage(context) {
const prTriage = forRepository(context);
const pullRequest = getPullRequest(context);

Raven.context(() => {
Raven.setContext({
extra: {
owner: context.repo()["owner"],
repo: context.repo()["repo"],
number: pullRequest.number
}
try {
Sentry.configureScope(scope => {
scope.setExtra("pull_request_url", pullRequest.url);
});
prTriage.triage(pullRequest);
});
} catch (e) {
Sentry.captureMessage(e);
}
}

function forRepository(context) {
Expand Down
169 changes: 84 additions & 85 deletions lib/pr-triage.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,9 @@ class PRTriage {

async triage(pullRequest) {
Object.assign(this.pullRequest, pullRequest);
const { owner, repo } = this.config;
const number = this.pullRequest.number;

await this._ensurePRTriageLabelExists();
const state = await this._getState();

switch (state) {
case PRTriage.STATE.WIP:
case PRTriage.STATE.UNREVIED:
Expand All @@ -47,15 +44,6 @@ class PRTriage {
case PRTriage.STATE.DRAFT:
case PRTriage.STATE.MERGED:
this._updateLabel(state);
this.logger(
"%s/%s#%s is labeld as %s",
owner,
repo,
number,
Object.keys(PRTriage.STATE).find(k => {
return PRTriage.STATE[k] === state;
})
);
break;
default:
throw new Error("Undefined state");
Expand All @@ -72,7 +60,7 @@ class PRTriage {
}

const reviews = await this._getUniqueReviews();
const numNeededReviews = await this._getRequiredNumberOfReviews();
const requiredNumberOfReviews = await this._getRequiredNumberOfReviews();
const numRequestedReviewsRemaining = await this._getRequestedNumberOfReviews();

if (reviews.length === 0) {
Expand All @@ -88,7 +76,7 @@ class PRTriage {
if (changeRequestedReviews.length > 0) {
return PRTriage.STATE.CHANGES_REQUESTED;
} else if (
approvedReviews.length < numNeededReviews ||
approvedReviews.length < requiredNumberOfReviews ||
numRequestedReviewsRemaining > 0
) {
// Mark if partially approved if:
Expand All @@ -102,56 +90,9 @@ class PRTriage {
}
}

/**
* Get the number of required number of reviews according to branch protections
* @return {Promise<number>} The number of required approving reviews, or 1 if branch protections are not set up.
* @private
*/
async _getRequiredNumberOfReviews() {
const { owner, repo } = this.config;
const branch = this.pullRequest.base.ref;
const branchProtections = await this.github.repos.getBranchProtection({
owner,
repo,
branch
});

const requiredReviews =
branchProtections.data.required_pull_request_reviews;
return (
(requiredReviews && requiredReviews.required_approving_review_count) || 1
);
}

/**
* Get the number of users and teams that have been requested to review the PR
* @return {Promise<number>}
* @private
*/
async _getRequestedNumberOfReviews() {
const { owner, repo } = this.config;
const pullNumber = this.pullRequest.number;
const requestedReviewsObj = await this.github.pulls.listReviewRequests({
owner,
repo,
pullNumber
});

return (
requestedReviewsObj.data.teams.length +
requestedReviewsObj.data.users.length
);
}

async _getUniqueReviews() {
const { owner, repo } = this.config;
const pullNumber = this.pullRequest.number;
const reviews = await this._getReviews();
const sha = this.pullRequest.head.sha;

const reviews =
(await this.github.pulls.listReviews({ owner, repo, pullNumber }))
.data || [];

const uniqueReviews = reviews
.filter(review => review.commit_id === sha)
.filter(
Expand Down Expand Up @@ -186,16 +127,90 @@ class PRTriage {
return Object.values(uniqueReviews);
}

/**
* Get the number of required number of reviews according to branch protections
* @return {Promise<number>} The number of required approving reviews, or 1 if Administration Permission is not granted or Branch Protection is not set up
* @private
*/
async _getRequiredNumberOfReviews() {
const { owner, repo } = this.config;
const branch = this.pullRequest.base.ref;
return (
this.github.repos
// See: https://developer.github.com/v3/previews/#require-multiple-approving-reviews
.getBranchProtection({
owner,
repo,
branch,
mediaType: {
previews: ["luke-cage"]
}
})
.then(res => {
return res.data.required_pull_request_reviews
.required_approving_review_count;
})
.catch(err => {
// Return the minium number of reviews if it's 403 or 403 because Administration Permission is not granted (403) or Branch Protection is not set up(404)
if (err.status === 404 || err.status === 403) {
return 1;
}
throw err;
})
);
}

/**
* Get the number of users and teams that have been requested to review the PR
* @return {Promise<number>}
* @private
*/
async _getRequestedNumberOfReviews() {
const { owner, repo } = this.config;
const pull_number = this.pullRequest.number;
return this.github.pulls
.listReviewRequests({ owner, repo, pull_number })
.then(res => res.data.teams.length + res.data.users.length);
}

async _getReviews() {
const { owner, repo } = this.config;
// Ignore inconsitent variable name conversation
// because of https://octokit.github.io/rest.js/v17#pulls-list-reviews
const pull_number = this.pullRequest.number;
return this.github.pulls
.listReviews({ owner, repo, pull_number })
.then(res => res.data || []);
}

async _ensurePRTriageLabelExists() {
for (const labelObj in this._getFilteredConfigObjByRegex(/label_*/)) {
await this._createLabel(labelObj);
const labelKeys = Object.keys(this._getFilteredConfigObjByRegex(/label_*/));
for (let i = 0; i < labelKeys.length; i++) {
await this._createLabel(labelKeys[i]);
}
}

async _updateLabel(labelKey) {
const currentLabelKey = await this._getCurrentLabelKey();
if (currentLabelKey) {
if (labelKey === PRTriage.STATE.WIP) {
this._removeLabel(currentLabelKey);
} else if (currentLabelKey !== labelKey) {
this._removeLabel(currentLabelKey);
this._addLabel(labelKey);
}
} else {
if (labelKey !== PRTriage.STATE.WIP) {
this._addLabel(labelKey);
}
}
}

async _createLabel(key) {
const { owner, repo } = this.config;
const labelObj = this._getConfigObj(key);

// Create a label to repository if the label is not created.
return this.github.issues
.getLabel({ owner, repo, name: labelObj.name })
.catch(() => {
Expand All @@ -210,15 +225,15 @@ class PRTriage {

async _addLabel(key) {
const { owner, repo } = this.config;
const number = this.pullRequest.number;
const issue_number = this.pullRequest.number;
const labelObj = this._getConfigObj(key);

// Check if a label does not exist. If it does, it addes the label.
// Add a label to issue if it does not exist.
return this._getLabel(key).catch(() => {
return this.github.issues.addLabels({
owner,
repo,
number,
issue_number,
labels: [labelObj.name]
});
});
Expand All @@ -229,14 +244,14 @@ class PRTriage {
const issue_number = this.pullRequest.number;
const labelObj = this._getConfigObj(key);

// Check if a label exists. If it does, it removes the label.
// Remove the label from a issue if it exists.
return this._getLabel(key).then(
labelObj => {
return this.github.issues
.removeLabel({ owner, repo, issue_number, name: labelObj.name })
.catch(err => {
// Ignore if it's a 404 because then the label was already removed
if (err.code !== 404) {
if (err.status !== 404) {
throw err;
}
});
Expand All @@ -245,22 +260,6 @@ class PRTriage {
); // Do nothing for error handling.
}

async _updateLabel(labelKey) {
const currentLabelKey = await this._getCurrentLabelKey();
if (currentLabelKey) {
if (labelKey === PRTriage.STATE.WIP) {
this._removeLabel(currentLabelKey);
} else if (currentLabelKey !== labelKey) {
this._removeLabel(currentLabelKey);
this._addLabel(labelKey);
}
} else {
if (labelKey !== PRTriage.STATE.WIP) {
this._addLabel(labelKey);
}
}
}

_getLabel(key) {
return new Promise((resolve, reject) => {
for (const label of this.pullRequest.labels) {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"author": "Sam Yamashita",
"license": "Apache-2.0",
"dependencies": {
"@sentry/node": "^5.14.2",
"debug": "^4.1.1",
"dotenv": "^8.0.0",
"probot": "^9.2.10",
Expand All @@ -48,7 +49,6 @@
"nodemon": "^2.0.1",
"prettier": "1.19.1",
"probot-config": "^1.0.0",
"raven": "^2.6.3",
"semantic-release": "^17.0.2",
"smee-client": "^1.1.0",
"validate-commit-msg": "^2.14.0"
Expand Down
7 changes: 5 additions & 2 deletions test/fixtures/payload.json
Original file line number Diff line number Diff line change
Expand Up @@ -224,8 +224,11 @@
}
}
},
"none": {
"data": {}
"not_defined": {
"status": 404
},
"not_allowed": {
"status": 403
}
}
}
Loading

0 comments on commit f67961e

Please sign in to comment.