@@ -117,8 +117,13 @@ function contributorProfile(author) {
117117 return { login : displayName , displayName } ;
118118}
119119
120- function formatContributorCard ( author ) {
121- const { login, displayName } = contributorProfile ( author ) ;
120+ function formatContributorCard ( authorOrObj ) {
121+ let login , displayName ;
122+ if ( typeof authorOrObj === 'object' && authorOrObj !== null ) {
123+ ( { login, displayName } = authorOrObj ) ;
124+ } else {
125+ ( { login, displayName } = contributorProfile ( authorOrObj ) ) ;
126+ }
122127 const safeLogin = encodeURIComponent ( login ) ;
123128 const safeDisplayName = escapeHtml ( displayName ) ;
124129 const githubAvatarUrl = `https://github.com/${ safeLogin } .png?size=96` ;
@@ -130,16 +135,26 @@ function formatContributorCard(author) {
130135 ] . join ( '\n' ) ;
131136}
132137
133- function listContributors ( commits ) {
138+ function listContributors ( commits , externalLogins = [ ] ) {
134139 const seen = new Set ( ) ;
135140 const contributors = [ ] ;
141+
142+ // Use external logins from GitHub API if available
143+ for ( const login of externalLogins ) {
144+ const safeLogin = String ( login || '' ) . trim ( ) ;
145+ if ( ! safeLogin || seen . has ( safeLogin ) ) continue ;
146+ seen . add ( safeLogin ) ;
147+ contributors . push ( { login : safeLogin , displayName : safeLogin } ) ;
148+ }
149+
150+ // Fallback to commit authors for missing entries
136151 for ( const commit of commits ) {
137- const contributor = formatContributorName ( commit . author ) ;
138- const key = contributor . toLowerCase ( ) ;
139- if ( seen . has ( key ) ) continue ;
140- seen . add ( key ) ;
141- contributors . push ( contributor ) ;
152+ const { login, displayName } = contributorProfile ( commit . author ) ;
153+ if ( ! login || seen . has ( login ) ) continue ;
154+ seen . add ( login ) ;
155+ contributors . push ( { login, displayName } ) ;
142156 }
157+
143158 return contributors ;
144159}
145160
@@ -179,7 +194,7 @@ function formatChangeSummary(commits) {
179194 return lines ;
180195}
181196
182- function formatChangelog ( { repository = '' , previousTag = '' , currentTag = '' , currentRef = 'HEAD' , commits = [ ] } ) {
197+ function formatChangelog ( { repository = '' , previousTag = '' , currentTag = '' , currentRef = 'HEAD' , commits = [ ] , externalLogins = [ ] } ) {
183198 const lines = [ ] ;
184199
185200 if ( ! previousTag ) {
@@ -217,7 +232,7 @@ function formatChangelog({ repository = '', previousTag = '', currentTag = '', c
217232 }
218233
219234 lines . push ( '### Contributors' ) ;
220- const contributors = listContributors ( commits ) ;
235+ const contributors = listContributors ( commits , externalLogins ) ;
221236 if ( ! contributors . length ) {
222237 lines . push ( '- Unknown contributor' ) ;
223238 } else {
@@ -248,12 +263,26 @@ function main(env = process.env) {
248263 const previousTag = selectPreviousSemverTag ( tags , currentTag ) ;
249264 const currentRef = resolveCurrentRef ( currentTag ) ;
250265 const commits = previousTag ? readCommits ( previousTag , currentRef ) : [ ] ;
266+
267+ // Load external logins from GitHub API if available
268+ let externalLogins = [ ] ;
269+ const contributorsFile = env . CONTRIBUTORS_FILE ;
270+ if ( contributorsFile && fs . existsSync ( contributorsFile ) ) {
271+ try {
272+ const content = fs . readFileSync ( contributorsFile , 'utf8' ) ;
273+ externalLogins = content . trim ( ) . split ( / \r ? \n / ) . map ( line => line . trim ( ) ) . filter ( Boolean ) ;
274+ } catch ( e ) {
275+ console . warn ( `Failed to read contributors file: ${ e . message } ` ) ;
276+ }
277+ }
278+
251279 const changelog = formatChangelog ( {
252280 repository : env . GITHUB_REPOSITORY || '' ,
253281 previousTag,
254282 currentTag,
255283 currentRef,
256- commits
284+ commits,
285+ externalLogins
257286 } ) ;
258287
259288 console . log ( changelog . trimEnd ( ) ) ;
0 commit comments