Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions .github/workflows/auto-assign-pr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
name: Auto Assign PR to Author

on:
Copy link
Member

@DaniPopes DaniPopes Sep 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be on workflow_call?

Copy link
Member Author

@o-az o-az Sep 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right under it: https://github.com/ithacaxyz/ci/blob/o-az/auto-assign-pr/.github/workflows/auto-assign-pr.yml#L6

including pull_request so that it applies to this repo as well

(ie assign PRs in this repo to author - eg #1 (comment))

pull_request:
types: [opened, reopened]
workflow_call:

defaults:
run:
shell: bash

jobs:
auto-assign:
name: Auto Assign
# Permissions the called workflow requests (Caller workflow must still grant these scopes to GITHUB_TOKEN)
permissions:
issues: write
pull-requests: write
runs-on: ubuntu-latest
steps:
- name: Auto assign PR to author (with permission checks)
uses: actions/github-script@v7
with:
script: |
const pr = context.payload.pull_request

if (!pr) {
core.warning('No pull_request payload detected. Ensure this is triggered by a pull_request event or called from a workflow triggered by pull_request. Skipping.')
return
}

const prAuthor = pr.user?.login
const isBot = pr.user?.type === 'Bot'
const assoc = pr.author_association
const allowedAssocs = ['MEMBER', 'OWNER', 'COLLABORATOR']

core.info(`PR #${pr.number} author: ${prAuthor}`)
core.info(`Author association: ${assoc}`)
core.info(`Current assignees: ${pr.assignees?.map(a => a.login).join(', ') || 'none'}`)

// Skip for bots
if (isBot) {
core.info('Skipping: PR author is a Bot.')
return
}

// Skip for non-internal contributors (e.g., forks)
if (!allowedAssocs.includes(assoc)) {
core.info(`Skipping: author association (${assoc}) is not internal (MEMBER/OWNER/COLLABORATOR).`)
return
}

// Skip if assignees already present
if (Array.isArray(pr.assignees) && pr.assignees.length > 0) {
core.info('PR already has assignees, skipping.')
return
}

// Attempt to assign; provide descriptive errors on permission failure
try {
await github.rest.issues.addAssignees({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pr.number,
assignees: [prAuthor]
})
core.info(`Successfully assigned PR #${pr.number} to ${prAuthor}`)
} catch (error) {
if (error.status === 403 || error.status === 404) {
const lines = [
`Failed to assign PR #${pr.number} to ${prAuthor} due to insufficient permissions for GITHUB_TOKEN.`,
`Error: ${error.message}`,
].join('\n')
core.setFailed(lines)
return
}

core.setFailed(`Failed to assign PR: ${error.message}`)
core.warning('Possible reasons:')
console.info('- Default workflow permissions are not "write"')
console.info('- Caller workflow does not explicitly grant write permissions to GITHUB_TOKEN')
}