build(deps): bump nokogiri from 1.12.0 to 1.14.3 in /docs #238
Workflow file for this run
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Triage | |
on: | |
pull_request_target: | |
types: | |
- opened | |
- synchronize | |
- reopened | |
- closed | |
- labeled | |
- unlabeled | |
schedule: | |
- cron: "0 */3 * * *" # every 3 hours | |
jobs: | |
review: | |
runs-on: ubuntu-latest | |
if: startsWith(github.repository, 'Homebrew/') | |
steps: | |
- name: Re-run this workflow | |
if: github.event_name == 'schedule' || github.event.action == 'closed' | |
uses: reitermarkus/rerun-workflow@64cba9e834916060e77b7dad424d086837fdd0a6 | |
with: | |
token: ${{ secrets.HOMEBREW_GITHUB_PUBLIC_REPO_TOKEN }} | |
continuous-label: waiting for feedback | |
trigger-labels: critical | |
workflow: triage.yml | |
- name: Review pull request | |
if: > | |
(github.event_name == 'pull_request' || github.event_name == 'pull_request_target') && | |
github.event.action != 'closed' && github.event.pull_request.state != 'closed' | |
uses: actions/github-script@v4.0.2 | |
with: | |
github-token: ${{ secrets.HOMEBREW_GITHUB_PUBLIC_REPO_TOKEN }} | |
script: | | |
async function approvePullRequest(pullRequestNumber) { | |
const reviews = await approvalsByAuthenticatedUser(pullRequestNumber) | |
if (reviews.length > 0) { | |
return | |
} | |
await github.pulls.createReview({ | |
...context.repo, | |
pull_number: pullRequestNumber, | |
event: 'APPROVE', | |
}) | |
} | |
async function findComment(pullRequestNumber, id) { | |
const { data: comments } = await github.issues.listComments({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
issue_number: pullRequestNumber, | |
}) | |
const regex = new RegExp(`<!--\\s*#${id}\\s*-->`) | |
return comments.filter(comment => comment.body.match(regex))[0] | |
} | |
async function createOrUpdateComment(pullRequestNumber, id, message) { | |
const beginComment = await findComment(pullRequestNumber, id) | |
const body = `<!-- #${id} -->\n\n${message}` | |
if (beginComment) { | |
await github.issues.updateComment({ | |
...context.repo, | |
comment_id: beginComment.id, | |
body, | |
}) | |
} else { | |
await github.issues.createComment({ | |
...context.repo, | |
issue_number: pullRequestNumber, | |
body, | |
}) | |
} | |
} | |
async function approvalsByAuthenticatedUser(pullRequestNumber) { | |
const { data: user } = await github.users.getAuthenticated() | |
const { data: reviews } = await github.pulls.listReviews({ | |
...context.repo, | |
pull_number: pullRequestNumber, | |
}) | |
const approvals = reviews.filter(review => review.state == 'APPROVED') | |
return approvals.filter(review => review.user.login == user.login) | |
} | |
async function dismissApprovals(pullRequestNumber, message) { | |
const reviews = await approvalsByAuthenticatedUser(pullRequestNumber) | |
for (const review of reviews) { | |
await github.pulls.dismissReview({ | |
...context.repo, | |
pull_number: pullRequestNumber, | |
review_id: review.id, | |
message: message | |
}); | |
} | |
} | |
function offsetDate(start, offsetHours, skippedDays) { | |
let end = new Date(start) | |
end.setUTCHours(end.getUTCHours() + (offsetHours % 24)) | |
while (skippedDays.includes(end.getUTCDay()) || offsetHours >= 24) { | |
if (!skippedDays.includes(end.getUTCDay())) { | |
offsetHours -= 24 | |
} | |
end.setUTCDate(end.getUTCDate() + 1) | |
} | |
if (skippedDays.includes(start.getUTCDay())) { | |
end.setUTCHours(offsetHours, 0, 0) | |
} | |
return end | |
} | |
function formatDate(date) { | |
return date.toISOString().replace(/\.\d+Z$/, ' UTC').replace('T', ' at ') | |
} | |
async function reviewPullRequest(pullRequestNumber) { | |
const { data: pullRequest } = await github.pulls.get({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
pull_number: pullRequestNumber, | |
}) | |
const { data: user } = await github.users.getAuthenticated() | |
if (pullRequest.user.login == user.login) { | |
core.warning('Pull request author is a bot.') | |
return | |
} | |
if (pullRequest.author_association != 'MEMBER') { | |
core.warning('Pull request author is not a member.') | |
return | |
} | |
const reviewLabel = 'waiting for feedback' | |
const criticalLabel = 'critical' | |
const labels = pullRequest.labels.map(label => label.name) | |
const hasReviewLabel = labels.includes(reviewLabel) | |
const hasCriticalLabel = labels.includes(criticalLabel) | |
const offsetHours = 24 | |
const skippedDays = [ | |
6, // Saturday | |
0, // Sunday | |
] | |
const currentDate = new Date() | |
const reviewStartDate = new Date(pullRequest.created_at) | |
const reviewEndDate = offsetDate(reviewStartDate, offsetHours, skippedDays) | |
const reviewEnded = currentDate > reviewEndDate | |
if (reviewEnded || hasCriticalLabel) { | |
let message | |
if (hasCriticalLabel && !reviewEnded) { | |
message = `Review period skipped due to \`${criticalLabel}\` label.` | |
} else { | |
message = 'Review period ended.' | |
} | |
if (hasReviewLabel) { | |
await github.issues.removeLabel({ | |
...context.repo, | |
issue_number: pullRequestNumber, | |
name: reviewLabel, | |
}) | |
} | |
core.info(message) | |
await createOrUpdateComment(pullRequestNumber, 'review-period-end', message) | |
await approvePullRequest(pullRequestNumber) | |
} else { | |
const message = `Review period will end on ${formatDate(reviewEndDate)}.` | |
core.info(message) | |
await dismissApprovals(pullRequestNumber, 'Review period has not ended yet.') | |
await createOrUpdateComment(pullRequestNumber, 'review-period-begin', message) | |
const endComment = await findComment(pullRequestNumber, 'review-period-end') | |
if (endComment) { | |
await github.issues.deleteComment({ | |
...context.repo, | |
comment_id: endComment.id, | |
}) | |
} | |
await github.issues.addLabels({ | |
...context.repo, | |
issue_number: pullRequestNumber, | |
labels: [reviewLabel], | |
}) | |
core.setFailed('Review period has not ended yet.') | |
} | |
} | |
await reviewPullRequest(context.issue.number) |