@@ -59,8 +59,22 @@ const getInfoFromGithubNewAPI = info => {
5959 return requestGithub ( uri ) ;
6060} ;
6161
62+ const isBotUser = ( login ) => {
63+ const botPatterns = [
64+ 'github-actions' ,
65+ 'dependabot' ,
66+ 'renovate' ,
67+ 'greenkeeper' ,
68+ 'snyk-bot' ,
69+ 'codecov' ,
70+ 'coveralls'
71+ ] ;
72+ const lowerLogin = login . toLowerCase ( ) ;
73+ return botPatterns . some ( pattern => lowerLogin . includes ( pattern ) ) || lowerLogin . endsWith ( '[bot]' ) ;
74+ } ;
75+
6276const format = list => {
63- return list . filter ( item => item ) . map ( item => {
77+ return list . filter ( item => item && ! isBotUser ( item . login ) ) . map ( item => {
6478 return {
6579 login : item . login ,
6680 avatar_url : item . avatar_url ,
@@ -103,7 +117,9 @@ exports.getAuthor = async (options = {}) => {
103117 const ownersPath = options . owners ? path . resolve ( cwd , options . owners ) : null ;
104118
105119 let authorList = [ ] ;
120+ let contributorList = [ ] ;
106121
122+ // First, get contributors from GitHub or git log
107123 if ( _ . isExistedFile ( originPkg ) ) {
108124 try {
109125 const pkg = require ( originPkg ) ;
@@ -119,49 +135,53 @@ exports.getAuthor = async (options = {}) => {
119135 if ( repoUrl ) {
120136 const info = await getRepoInfo ( repoUrl ) ;
121137 const infoList = await getInfoFromGithubNewAPI ( info ) ;
122- authorList = format ( infoList ) ;
138+ contributorList = format ( infoList ) ;
123139 }
124140 }
125141 } catch ( e ) {
126142 }
127143 } else if ( pointGithubRepoUrl ) {
128144 const info = await getRepoInfo ( pointGithubRepoUrl ) ;
129145 const infoList = await getInfoFromGithubNewAPI ( info ) ;
130- authorList = format ( infoList ) ;
146+ contributorList = format ( infoList ) ;
131147 }
132148
133- if ( ! authorList . length ) {
149+ if ( ! contributorList . length ) {
134150 if ( ! _ . isExistedDir ( dotGitDir ) ) {
135- authorList = [ ] ;
151+ contributorList = [ ] ;
136152 } else {
137153 const mailList = gitLog2MailList ( ) ;
138154 const infoList = await getInfoFromGithub ( _ . uniq ( mailList ) ) ;
139- authorList = format ( infoList ) ;
155+ contributorList = format ( infoList ) ;
140156 }
141157 }
142158
159+ // Process owners first (they get priority)
143160 if ( ownersPath ) {
144161 const owners = parseOwnersFile ( ownersPath ) ;
145162 if ( owners . length ) {
146163 owners . forEach ( login => {
147- authorList . push ( {
148- login,
149- avatar_url : `https://avatars.githubusercontent.com/${ login } ?v=4` ,
150- html_url : `https://github.com/${ login } `
151- } ) ;
164+ // Skip bot users
165+ if ( ! isBotUser ( login ) ) {
166+ authorList . push ( {
167+ login,
168+ avatar_url : `https://avatars.githubusercontent.com/${ login } ?v=4` ,
169+ html_url : `https://github.com/${ login } `
170+ } ) ;
171+ }
152172 } ) ;
153173 }
154174 }
155175
156- // Deduplicate by login
157- const uniqueAuthors = new Map ( ) ;
158- authorList . forEach ( author => {
159- if ( ! uniqueAuthors . has ( author . login ) ) {
160- uniqueAuthors . set ( author . login , author ) ;
176+ // Then append contributors that are not already in the owners list
177+ const ownersLoginSet = new Set ( authorList . map ( author => author . login ) ) ;
178+ contributorList . forEach ( contributor => {
179+ if ( ! ownersLoginSet . has ( contributor . login ) ) {
180+ authorList . push ( contributor ) ;
161181 }
162182 } ) ;
163183
164- return Array . from ( uniqueAuthors . values ( ) ) ;
184+ return authorList ;
165185} ;
166186
167187const ifHasZh = ( readMeContext ) => {
0 commit comments