@@ -34,26 +34,35 @@ module.exports = async ({ github, context, core }) => {
3434 return ;
3535 }
3636
37- // --- Helper : check if a user has admin or maintain permission on a repo (cached) ---
38- const maintainerCache = new Map ( ) ;
39- async function isMaintainer ( owner , repoName , username ) {
37+ // --- Helpers : check user permission on a repo (cached) ---
38+ const roleCache = new Map ( ) ;
39+ async function getRole ( owner , repoName , username ) {
4040 const key = `${ owner } /${ repoName } :${ username } ` ;
41- if ( maintainerCache . has ( key ) ) return maintainerCache . get ( key ) ;
42- let result = false ;
41+ if ( roleCache . has ( key ) ) return roleCache . get ( key ) ;
42+ let roleName = null ;
4343 try {
4444 const { data } = await github . rest . repos . getCollaboratorPermissionLevel ( {
4545 owner,
4646 repo : repoName ,
4747 username,
4848 } ) ;
49- // permission field uses legacy values (admin/write/read/none) where
50- // maintain maps to write. Use role_name for the actual role.
51- result = [ 'admin' , 'maintain' ] . includes ( data . role_name ) ;
49+ roleName = data . role_name ;
5250 } catch {
53- // noop — result stays false
51+ // noop — roleName stays null
5452 }
55- maintainerCache . set ( key , result ) ;
56- return result ;
53+ roleCache . set ( key , roleName ) ;
54+ return roleName ;
55+ }
56+
57+ async function hasWriteAccess ( owner , repoName , username ) {
58+ const role = await getRole ( owner , repoName , username ) ;
59+ // role_name values: admin, maintain, push, triage, pull (+ custom roles)
60+ return [ 'admin' , 'maintain' , 'push' , 'write' ] . includes ( role ) ;
61+ }
62+
63+ async function isMaintainer ( owner , repoName , username ) {
64+ const role = await getRole ( owner , repoName , username ) ;
65+ return [ 'admin' , 'maintain' ] . includes ( role ) ;
5766 }
5867
5968 // --- Step 1: Skip if a maintainer reopened the PR ---
@@ -67,14 +76,14 @@ module.exports = async ({ github, context, core }) => {
6776 }
6877 }
6978
70- // --- Step 2: Check if PR author is a maintainer (admin or maintain role) ---
71- const authorIsMaintainer = await isMaintainer ( repo . owner , repo . repo , prAuthor ) ;
72- if ( authorIsMaintainer ) {
73- core . info ( `PR author ${ prAuthor } has admin/maintain access. Skipping.` ) ;
79+ // --- Step 2: Check if PR author has write access (admin, maintain, or write role) ---
80+ const authorHasWriteAccess = await hasWriteAccess ( repo . owner , repo . repo , prAuthor ) ;
81+ if ( authorHasWriteAccess ) {
82+ core . info ( `PR author ${ prAuthor } has write+ access. Skipping.` ) ;
7483 core . setOutput ( 'skipped' , 'true' ) ;
7584 return ;
7685 }
77- core . info ( `PR author ${ prAuthor } is not a maintainer .` ) ;
86+ core . info ( `PR author ${ prAuthor } does not have write access .` ) ;
7887
7988 // --- Step 3: Parse issue references from PR body ---
8089 const body = pullRequest . body || '' ;
0 commit comments