Files
ghostty/.github/scripts/approve-contributor.nu
Mitchell Hashimoto 39e610d0ee approved PR gate
2026-02-15 06:53:29 -08:00

107 lines
3.5 KiB
Plaintext
Executable File

#!/usr/bin/env nu
use github.nu
# Approve a contributor by adding them to the APPROVED_CONTRIBUTORS file.
#
# This script checks if a comment matches "lgtm", verifies the commenter has
# write access, and adds the issue author to the approved list if not already
# present.
#
# Environment variables required:
# GITHUB_TOKEN - GitHub API token with repo access. If this isn't
# set then we'll attempt to read from `gh` if it exists.
#
# Outputs a status to stdout: "skipped", "already", or "added"
#
# Examples:
#
# # Dry run (default) - see what would happen
# ./approve-contributor.nu 123 456789
#
# # Actually approve a contributor
# ./approve-contributor.nu 123 456789 --dry-run=false
#
def main [
issue_id: int, # GitHub issue number
comment_id: int, # GitHub comment ID
--repo (-R): string = "ghostty-org/ghostty", # Repository in "owner/repo" format
--approved-file: string = ".github/APPROVED_CONTRIBUTORS", # Path to approved contributors file
--dry-run = true, # Print what would happen without making changes
] {
let owner = ($repo | split row "/" | first)
let repo_name = ($repo | split row "/" | last)
# Fetch issue and comment data from GitHub API
let issue_data = github api "get" $"/repos/($owner)/($repo_name)/issues/($issue_id)"
let comment_data = github api "get" $"/repos/($owner)/($repo_name)/issues/comments/($comment_id)"
let issue_author = $issue_data.user.login
let commenter = $comment_data.user.login
let comment_body = ($comment_data.body | default "")
# Check if comment matches "lgtm"
if not ($comment_body | str trim | parse -r '(?i)^\s*lgtm\b' | is-not-empty) {
print "Comment does not match lgtm"
print "skipped"
return
}
# Check if commenter has write access
let permission = try {
github api "get" $"/repos/($owner)/($repo_name)/collaborators/($commenter)/permission" | get permission
} catch {
print $"($commenter) does not have collaborator access"
print "skipped"
return
}
if not ($permission in ["admin", "write"]) {
print $"($commenter) does not have write access"
print "skipped"
return
}
# Read approved contributors file
let content = open $approved_file
let approved_list = $content
| lines
| each { |line| $line | str trim | str downcase }
| where { |line| ($line | is-not-empty) and (not ($line | str starts-with "#")) }
# Check if already approved
if ($issue_author | str downcase) in $approved_list {
print $"($issue_author) is already approved"
if not $dry_run {
github api "post" $"/repos/($owner)/($repo_name)/issues/($issue_id)/comments" {
body: $"@($issue_author) is already in the approved contributors list."
}
} else {
print "(dry-run) Would post 'already approved' comment"
}
print "already"
return
}
if $dry_run {
print $"(dry-run) Would add ($issue_author) to ($approved_file)"
print "added"
return
}
# Add contributor to the file and sort (preserving comments at top)
let lines = $content | lines
let comments = $lines | where { |line| ($line | str starts-with "#") or ($line | str trim | is-empty) }
let contributors = $lines
| where { |line| not (($line | str starts-with "#") or ($line | str trim | is-empty)) }
| append $issue_author
| sort -i
let new_content = ($comments | append $contributors | str join "\n") + "\n"
$new_content | save -f $approved_file
print $"Added ($issue_author) to approved contributors"
print "added"
}