mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-30 22:53:59 +00:00 
			
		
		
		
	[CI] Only mention codeowners once (#9727)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
		
							
								
								
									
										61
									
								
								.github/workflows/codeowner-review-request.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										61
									
								
								.github/workflows/codeowner-review-request.yml
									
									
									
									
										vendored
									
									
								
							| @@ -178,6 +178,51 @@ jobs: | |||||||
|                 reviewedUsers.add(review.user.login); |                 reviewedUsers.add(review.user.login); | ||||||
|               }); |               }); | ||||||
|  |  | ||||||
|  |               // Check for previous comments from this workflow to avoid duplicate pings | ||||||
|  |               const { data: comments } = await github.rest.issues.listComments({ | ||||||
|  |                 owner, | ||||||
|  |                 repo, | ||||||
|  |                 issue_number: pr_number | ||||||
|  |               }); | ||||||
|  |  | ||||||
|  |               const previouslyPingedUsers = new Set(); | ||||||
|  |               const previouslyPingedTeams = new Set(); | ||||||
|  |  | ||||||
|  |               // Look for comments from github-actions bot that contain codeowner pings | ||||||
|  |               const workflowComments = comments.filter(comment => | ||||||
|  |                 comment.user.type === 'Bot' && | ||||||
|  |                 comment.user.login === 'github-actions[bot]' && | ||||||
|  |                 comment.body.includes("I've automatically requested reviews from codeowners") | ||||||
|  |               ); | ||||||
|  |  | ||||||
|  |               // Extract previously mentioned users and teams from workflow comments | ||||||
|  |               for (const comment of workflowComments) { | ||||||
|  |                 // Match @username patterns (not team mentions) | ||||||
|  |                 const userMentions = comment.body.match(/@([a-zA-Z0-9_.-]+)(?![/])/g) || []; | ||||||
|  |                 userMentions.forEach(mention => { | ||||||
|  |                   const username = mention.slice(1); // remove @ | ||||||
|  |                   previouslyPingedUsers.add(username); | ||||||
|  |                 }); | ||||||
|  |  | ||||||
|  |                 // Match @org/team patterns | ||||||
|  |                 const teamMentions = comment.body.match(/@[a-zA-Z0-9_.-]+\/([a-zA-Z0-9_.-]+)/g) || []; | ||||||
|  |                 teamMentions.forEach(mention => { | ||||||
|  |                   const teamName = mention.split('/')[1]; | ||||||
|  |                   previouslyPingedTeams.add(teamName); | ||||||
|  |                 }); | ||||||
|  |               } | ||||||
|  |  | ||||||
|  |               console.log(`Found ${previouslyPingedUsers.size} previously pinged users and ${previouslyPingedTeams.size} previously pinged teams`); | ||||||
|  |  | ||||||
|  |               // Remove users who have already been pinged in previous workflow comments | ||||||
|  |               previouslyPingedUsers.forEach(user => { | ||||||
|  |                 matchedOwners.delete(user); | ||||||
|  |               }); | ||||||
|  |  | ||||||
|  |               previouslyPingedTeams.forEach(team => { | ||||||
|  |                 matchedTeams.delete(team); | ||||||
|  |               }); | ||||||
|  |  | ||||||
|               // Remove only users who have already submitted reviews (not just requested reviewers) |               // Remove only users who have already submitted reviews (not just requested reviewers) | ||||||
|               reviewedUsers.forEach(reviewer => { |               reviewedUsers.forEach(reviewer => { | ||||||
|                 matchedOwners.delete(reviewer); |                 matchedOwners.delete(reviewer); | ||||||
| @@ -192,7 +237,7 @@ jobs: | |||||||
|               const teamsList = Array.from(matchedTeams); |               const teamsList = Array.from(matchedTeams); | ||||||
|  |  | ||||||
|               if (reviewersList.length === 0 && teamsList.length === 0) { |               if (reviewersList.length === 0 && teamsList.length === 0) { | ||||||
|                 console.log('No eligible reviewers found (all may already be requested or reviewed)'); |                 console.log('No eligible reviewers found (all may already be requested, reviewed, or previously pinged)'); | ||||||
|                 return; |                 return; | ||||||
|               } |               } | ||||||
|  |  | ||||||
| @@ -227,7 +272,8 @@ jobs: | |||||||
|                   console.log('All codeowners are already requested reviewers or have reviewed'); |                   console.log('All codeowners are already requested reviewers or have reviewed'); | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 // Add a comment to the PR mentioning what happened (include all matched codeowners) |                 // Only add a comment if there are new codeowners to mention (not previously pinged) | ||||||
|  |                 if (reviewersList.length > 0 || teamsList.length > 0) { | ||||||
|                   const commentBody = createCommentBody(reviewersList, teamsList, fileMatches.size, true); |                   const commentBody = createCommentBody(reviewersList, teamsList, fileMatches.size, true); | ||||||
|  |  | ||||||
|                   await github.rest.issues.createComment({ |                   await github.rest.issues.createComment({ | ||||||
| @@ -236,11 +282,16 @@ jobs: | |||||||
|                     issue_number: pr_number, |                     issue_number: pr_number, | ||||||
|                     body: commentBody |                     body: commentBody | ||||||
|                   }); |                   }); | ||||||
|  |                   console.log(`Added comment mentioning ${reviewersList.length} users and ${teamsList.length} teams`); | ||||||
|  |                 } else { | ||||||
|  |                   console.log('No new codeowners to mention in comment (all previously pinged)'); | ||||||
|  |                 } | ||||||
|               } catch (error) { |               } catch (error) { | ||||||
|                 if (error.status === 422) { |                 if (error.status === 422) { | ||||||
|                   console.log('Some reviewers may already be requested or unavailable:', error.message); |                   console.log('Some reviewers may already be requested or unavailable:', error.message); | ||||||
|  |  | ||||||
|                   // Try to add a comment even if review request failed |                   // Only try to add a comment if there are new codeowners to mention | ||||||
|  |                   if (reviewersList.length > 0 || teamsList.length > 0) { | ||||||
|                     const commentBody = createCommentBody(reviewersList, teamsList, fileMatches.size, false); |                     const commentBody = createCommentBody(reviewersList, teamsList, fileMatches.size, false); | ||||||
|  |  | ||||||
|                     try { |                     try { | ||||||
| @@ -250,9 +301,13 @@ jobs: | |||||||
|                         issue_number: pr_number, |                         issue_number: pr_number, | ||||||
|                         body: commentBody |                         body: commentBody | ||||||
|                       }); |                       }); | ||||||
|  |                       console.log(`Added fallback comment mentioning ${reviewersList.length} users and ${teamsList.length} teams`); | ||||||
|                     } catch (commentError) { |                     } catch (commentError) { | ||||||
|                       console.log('Failed to add comment:', commentError.message); |                       console.log('Failed to add comment:', commentError.message); | ||||||
|                     } |                     } | ||||||
|  |                   } else { | ||||||
|  |                     console.log('No new codeowners to mention in fallback comment'); | ||||||
|  |                   } | ||||||
|                 } else { |                 } else { | ||||||
|                   throw error; |                   throw error; | ||||||
|                 } |                 } | ||||||
|   | |||||||
							
								
								
									
										45
									
								
								.github/workflows/issue-codeowner-notify.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										45
									
								
								.github/workflows/issue-codeowner-notify.yml
									
									
									
									
										vendored
									
									
								
							| @@ -92,10 +92,49 @@ jobs: | |||||||
|                 mention !== `@${issueAuthor}` |                 mention !== `@${issueAuthor}` | ||||||
|               ); |               ); | ||||||
|  |  | ||||||
|               const allMentions = [...filteredUserOwners, ...teamOwners]; |               // Check for previous comments from this workflow to avoid duplicate pings | ||||||
|  |               const { data: comments } = await github.rest.issues.listComments({ | ||||||
|  |                 owner, | ||||||
|  |                 repo, | ||||||
|  |                 issue_number: issue_number | ||||||
|  |               }); | ||||||
|  |  | ||||||
|  |               const previouslyPingedUsers = new Set(); | ||||||
|  |               const previouslyPingedTeams = new Set(); | ||||||
|  |  | ||||||
|  |               // Look for comments from github-actions bot that contain codeowner pings for this component | ||||||
|  |               const workflowComments = comments.filter(comment => | ||||||
|  |                 comment.user.type === 'Bot' && | ||||||
|  |                 comment.user.login === 'github-actions[bot]' && | ||||||
|  |                 comment.body.includes(`component: ${componentName}`) && | ||||||
|  |                 comment.body.includes("you've been identified as a codeowner") | ||||||
|  |               ); | ||||||
|  |  | ||||||
|  |               // Extract previously mentioned users and teams from workflow comments | ||||||
|  |               for (const comment of workflowComments) { | ||||||
|  |                 // Match @username patterns (not team mentions) | ||||||
|  |                 const userMentions = comment.body.match(/@([a-zA-Z0-9_.-]+)(?![/])/g) || []; | ||||||
|  |                 userMentions.forEach(mention => { | ||||||
|  |                   previouslyPingedUsers.add(mention); // Keep @ prefix for easy comparison | ||||||
|  |                 }); | ||||||
|  |  | ||||||
|  |                 // Match @org/team patterns | ||||||
|  |                 const teamMentions = comment.body.match(/@[a-zA-Z0-9_.-]+\/[a-zA-Z0-9_.-]+/g) || []; | ||||||
|  |                 teamMentions.forEach(mention => { | ||||||
|  |                   previouslyPingedTeams.add(mention); | ||||||
|  |                 }); | ||||||
|  |               } | ||||||
|  |  | ||||||
|  |               console.log(`Found ${previouslyPingedUsers.size} previously pinged users and ${previouslyPingedTeams.size} previously pinged teams for component ${componentName}`); | ||||||
|  |  | ||||||
|  |               // Remove previously pinged users and teams | ||||||
|  |               const newUserOwners = filteredUserOwners.filter(mention => !previouslyPingedUsers.has(mention)); | ||||||
|  |               const newTeamOwners = teamOwners.filter(mention => !previouslyPingedTeams.has(mention)); | ||||||
|  |  | ||||||
|  |               const allMentions = [...newUserOwners, ...newTeamOwners]; | ||||||
|  |  | ||||||
|               if (allMentions.length === 0) { |               if (allMentions.length === 0) { | ||||||
|                 console.log('No codeowners to notify (issue author is the only codeowner)'); |                 console.log('No new codeowners to notify (all previously pinged or issue author is the only codeowner)'); | ||||||
|                 return; |                 return; | ||||||
|               } |               } | ||||||
|  |  | ||||||
| @@ -111,7 +150,7 @@ jobs: | |||||||
|                 body: commentBody |                 body: commentBody | ||||||
|               }); |               }); | ||||||
|  |  | ||||||
|               console.log(`Successfully notified codeowners: ${mentionString}`); |               console.log(`Successfully notified new codeowners: ${mentionString}`); | ||||||
|  |  | ||||||
|             } catch (error) { |             } catch (error) { | ||||||
|               console.log('Failed to process codeowner notifications:', error.message); |               console.log('Failed to process codeowner notifications:', error.message); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user