Skip to content

Commit

Permalink
Merge pull request #9 from Doist/luke/ignore-prs-with-failing-checks
Browse files Browse the repository at this point in the history
feat: Ignore PRs with failing checks
  • Loading branch information
lukemerrett authored Aug 26, 2024
2 parents 4c9c91e + 074d17d commit e18f894
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 3 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ jobs:
ignore_authors: 'tom, renovate'
ignore_draft_prs: true
ignore_labels: 'do not merge, blocked'
ignore_prs_with_failing_checks: true
review_time_ms: 86400000 # 1 day in milliseconds
twist_url: 'https://twist.com/api/v3/integration_incoming/post_data?install_id=[install id]&install_token=[install token]'
token: ${{ secrets.DOIST_BOT_TOKEN }}
Expand All @@ -44,6 +45,7 @@ jobs:
|ignore_authors|no|`tom, renovate`|Usernames of PR creators who's PRs will be ignored|
|ignore_draft_prs|no|`false`|Whether we should ignore draft PRs when checking reviews, defaults to false|
|ignore_labels|no|`do not merge, blocked`|If provided any PRs with these labels will skip the review reminder check|
|ignore_prs_with_failing_checks|no|`false`|If the PR has any pending or failing status checks, ignore it|

## Development

Expand Down
4 changes: 4 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ inputs:
ignore_labels:
description: 'If provided any PRs with these labels will skip the review reminder check'
required: false
ignore_prs_with_failing_checks:
description: 'If the PR has any pending or failing status checks, ignore it'
required: true
default: false
runs:
using: 'node20'
main: 'dist/index.js'
33 changes: 32 additions & 1 deletion dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9553,6 +9553,9 @@ const TWIST_URL = core.getInput('twist_url', { required: true });
const REMINDER_MESSAGE = core.getInput('message', { required: true });
const IGNORE_DRAFT_PRS = core.getBooleanInput('ignore_draft_prs', { required: true });
const IGNORE_LABELS = core.getInput('ignore_labels', { required: false });
const IGNORE_PRS_WITH_FAILING_CHECKS = core.getBooleanInput('ignore_prs_with_failing_checks', {
required: true,
});
function run() {
return __awaiter(this, void 0, void 0, function* () {
const pullRequests = yield (0, pullrequest_1.fetchPullRequests)(GITHUB_TOKEN, GITHUB_REPO_OWNER, GITHUB_REPO);
Expand All @@ -9561,6 +9564,13 @@ function run() {
core.info(`Ignoring #${pullRequest.number} "${pullRequest.title}"`);
continue;
}
if (IGNORE_PRS_WITH_FAILING_CHECKS) {
const prPassingStatusChecks = yield (0, pullrequest_1.isPRPassingStatusChecks)(GITHUB_TOKEN, GITHUB_REPO_OWNER, GITHUB_REPO, pullRequest);
if (prPassingStatusChecks === false) {
core.info(`Ignoring #${pullRequest.number} "${pullRequest.title} as the status checks are failing"`);
continue;
}
}
core.info(`Checking #${pullRequest.number} "${pullRequest.title}"`);
const remind = yield (0, pullrequest_1.isMissingReview)(pullRequest, REVIEW_TIME_MS, GITHUB_TOKEN, GITHUB_REPO_OWNER, GITHUB_REPO);
if (remind) {
Expand Down Expand Up @@ -9619,7 +9629,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
});
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.isMissingReview = exports.shouldIgnore = exports.fetchPullRequests = void 0;
exports.isMissingReview = exports.isPRPassingStatusChecks = exports.shouldIgnore = exports.fetchPullRequests = void 0;
const github = __importStar(__nccwpck_require__(5438));
/**
* Get a list of all currently open pull requests in a repository
Expand Down Expand Up @@ -9674,6 +9684,27 @@ function shouldIgnore(pullRequest, ignoreAuthors, ignoreDraftPRs, ignoreLabels)
return false;
}
exports.shouldIgnore = shouldIgnore;
/**
* Returns whether the passed in PR has all it's status checks passing.
* @param gitHubToken The token used to authenticate with GitHub to access the repo
* @param repoOwner The owner of the repo
* @param repo The name of the repo
* @param pullRequest The pull request to check.
* @returns True if the status checks are passing, false if they are in progress or failing.
*/
function isPRPassingStatusChecks(gitHubToken, repoOwner, repo, pullRequest) {
return __awaiter(this, void 0, void 0, function* () {
const octokit = github.getOctokit(gitHubToken);
const { data } = yield octokit.rest.repos.getCombinedStatusForRef({
owner: repoOwner,
repo,
ref: pullRequest.head.ref,
});
// Possible values are `success,pending,error,failure`
return data.state === 'success';
});
}
exports.isPRPassingStatusChecks = isPRPassingStatusChecks;
/**
* Identifies whether the PR being passed in has not had any review activity in the last 24 hours.
*
Expand Down
2 changes: 1 addition & 1 deletion dist/index.js.map

Large diffs are not rendered by default.

26 changes: 25 additions & 1 deletion src/main.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import * as core from '@actions/core'
import * as github from '@actions/github'

import { fetchPullRequests, isMissingReview, shouldIgnore } from './pullrequest'
import {
fetchPullRequests,
isMissingReview,
isPRPassingStatusChecks,
shouldIgnore,
} from './pullrequest'
import { sendReminder } from './reminder'

const GITHUB_REPO_OWNER = github.context.repo.owner
Expand All @@ -14,6 +19,9 @@ const TWIST_URL = core.getInput('twist_url', { required: true })
const REMINDER_MESSAGE = core.getInput('message', { required: true })
const IGNORE_DRAFT_PRS = core.getBooleanInput('ignore_draft_prs', { required: true })
const IGNORE_LABELS = core.getInput('ignore_labels', { required: false })
const IGNORE_PRS_WITH_FAILING_CHECKS = core.getBooleanInput('ignore_prs_with_failing_checks', {
required: true,
})

async function run(): Promise<void> {
const pullRequests = await fetchPullRequests(GITHUB_TOKEN, GITHUB_REPO_OWNER, GITHUB_REPO)
Expand All @@ -23,6 +31,22 @@ async function run(): Promise<void> {
continue
}

if (IGNORE_PRS_WITH_FAILING_CHECKS) {
const prPassingStatusChecks = await isPRPassingStatusChecks(
GITHUB_TOKEN,
GITHUB_REPO_OWNER,
GITHUB_REPO,
pullRequest,
)

if (prPassingStatusChecks === false) {
core.info(
`Ignoring #${pullRequest.number} "${pullRequest.title} as the status checks are failing"`,
)
continue
}
}

core.info(`Checking #${pullRequest.number} "${pullRequest.title}"`)
const remind = await isMissingReview(
pullRequest,
Expand Down
25 changes: 25 additions & 0 deletions src/pullrequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,31 @@ export function shouldIgnore(
return false
}

/**
* Returns whether the passed in PR has all it's status checks passing.
* @param gitHubToken The token used to authenticate with GitHub to access the repo
* @param repoOwner The owner of the repo
* @param repo The name of the repo
* @param pullRequest The pull request to check.
* @returns True if the status checks are passing, false if they are in progress or failing.
*/
export async function isPRPassingStatusChecks(
gitHubToken: string,
repoOwner: string,
repo: string,
pullRequest: PullRequest,
): Promise<boolean> {
const octokit = github.getOctokit(gitHubToken)
const { data } = await octokit.rest.repos.getCombinedStatusForRef({
owner: repoOwner,
repo,
ref: pullRequest.head.ref,
})

// Possible values are `success,pending,error,failure`
return data.state === 'success'
}

/**
* Identifies whether the PR being passed in has not had any review activity in the last 24 hours.
*
Expand Down
7 changes: 7 additions & 0 deletions src/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ type PullRequestLabel = {
name: string
}

/** The head refernece for the PR (eg the branch reference) */
type PullRequestHead = {
ref: string
}

/** Details of a pending pull request on GitHub */
type PullRequest = {
/** PR number */
Expand All @@ -25,6 +30,8 @@ type PullRequest = {
draft?: boolean
/** Collection of labels associated with the PR */
labels: PullRequestLabel[] | undefined
/** Details on the branch the PR is coming from */
head: PullRequestHead
}

/** Result expected from our GraphQL request to GitHub for PR details */
Expand Down

0 comments on commit e18f894

Please sign in to comment.