Test #58303 (the "automatically assign a PR assignee" PR) #28
This file contains hidden or 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: Assign Committer | |
on: | |
# Important security note: Do NOT use `actions/checkout` | |
# or any other method for checking out the pull request's source code. | |
# This is because the pull request's source code is untrusted, but the | |
# GITHUB_TOKEN has write permissions (because of the `on: pull_request_target` event). | |
# | |
# Quoting from the GitHub Docs: | |
# > For workflows that are triggered by the pull_request_target event, the GITHUB_TOKEN is granted | |
# > read/write repository permission unless the permissions key is specified and the workflow can access secrets, | |
# > even when it is triggered from a fork. | |
# > | |
# > Although the workflow runs in the context of the base of the pull request, | |
# > you should make sure that you do not check out, build, or run untrusted code from the pull request with this event. | |
# | |
# Source: https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#pull_request_target | |
# | |
# See also: https://securitylab.github.com/resources/github-actions-preventing-pwn-requests/ | |
pull_request_target: | |
types: [opened, reopened, ready_for_review] | |
# Permissions for the `GITHUB_TOKEN`: | |
permissions: | |
pull-requests: write # Needed in order to assign a user as the PR assignee | |
jobs: | |
assign-reviewer: | |
runs-on: ubuntu-latest | |
if: ${{ github.event.pull_request.draft != true }} | |
steps: | |
# Important security note: As discussed above, do NOT use `actions/checkout` | |
# or any other method for checking out the pull request's source code. | |
# This is because the pull request's source code is untrusted, but the | |
# GITHUB_TOKEN has write permissions (because of the `on: pull_request_target` event). | |
- name: Add Assignee | |
# We pin all third-party actions to a full length commit SHA | |
# https://docs.github.com/en/actions/security-for-github-actions/security-guides/security-hardening-for-github-actions#using-third-party-actions | |
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 | |
with: | |
retries: 5 # retry GitHub API requests up to 5 times, with exponential backoff | |
retry-exempt-status-codes: 403 | |
script: | | |
if (context.payload.pull_request.assignees.length === 0) { | |
const prAuthor = context.payload.pull_request.user.login; | |
// Check if the PR is opened by a collaborator on the repo (aka a committer) | |
// We use the /repos/{owner}/{repo}/collaborators/{username} endpoint to avoid | |
// neeing org scope permissions | |
const { data: isCollaborator } = await github.rest.repos.checkCollaborator({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
username: prAuthor, | |
}); | |
if (isCollaborator) { | |
// The PR author is a committer, so we skip assigning them | |
console.log(`Skipping PR authored by committer: ${prAuthor}`); | |
return; | |
} | |
// Load the list of assignable reviewres the JuliaLang/pr-assignment repo | |
// at https://github.com/JuliaLang/pr-assignment/blob/main/users.txt | |
// NOTE to reviewers: If you want to be assigned to new PRs, please add your | |
// GitHub username to that file | |
// Load file contents | |
const { data: fileContents } = await github.rest.repos.getContent({ | |
owner: 'JuliaLang', | |
repo: 'pr-assignment', | |
filepath: 'users.txt', | |
ref: 'main', | |
}); | |
// Find lines that match ^(@[a-zA-Z0-9]+)(\s*#.*)?\n$ and extract the usernames | |
const reviewer_candidates = fileContents | |
.split('\n') | |
.map(line => line.match(/^(@[a-zA-Z0-9]+)(\s*#.*)?\n$/)) | |
.filter(match => match !== null) | |
.map(match => match[1].substring(1)); // Remove the @ symbol | |
// Assign random committer | |
await github.rest.issues.addAssignees({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
issue_number: context.payload.pull_request.number, | |
assignees: reviewer_candidates[Math.floor(Math.random()*reviewer_candidates.length)], | |
}); | |
// Add the "pr review" label | |
await github.rest.issues.addLabels({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
issue_number: context.payload.pull_request.number, | |
labels: ['status: waiting for PR reviewer'], | |
}); | |
} | |
} |