|
| 1 | +name: Release Comment Handler |
| 2 | + |
| 3 | +on: |
| 4 | + issues: |
| 5 | + types: |
| 6 | + - labeled |
| 7 | + |
| 8 | +jobs: |
| 9 | + comment_on_label: |
| 10 | + if: github.event.label.name == 'prerelease' || github.event.label.name == 'fixed' |
| 11 | + runs-on: ubuntu-latest |
| 12 | + permissions: |
| 13 | + issues: write |
| 14 | + contents: read |
| 15 | + steps: |
| 16 | + - name: Gather participants |
| 17 | + id: participants |
| 18 | + uses: actions/github-script@v7 |
| 19 | + with: |
| 20 | + script: | |
| 21 | + console.log("=== WORKFLOW START ==="); |
| 22 | + const issue_number = context.payload.issue.number; |
| 23 | + const repo = context.repo; |
| 24 | +
|
| 25 | + console.log(`Processing issue #${issue_number} in ${repo.owner}/${repo.repo}`); |
| 26 | +
|
| 27 | + // Get issue details (for author) |
| 28 | + const issue = context.payload.issue; |
| 29 | + const author = issue.user.login; |
| 30 | + console.log(`Issue author: ${author}`); |
| 31 | +
|
| 32 | + // Use a Set to track all unique participants (normalized to lowercase for deduplication) |
| 33 | + const all_participants = new Set(); |
| 34 | + |
| 35 | + // Add the issue author |
| 36 | + all_participants.add(author.toLowerCase()); |
| 37 | + console.log(`Added author to participants: ${author.toLowerCase()}`); |
| 38 | +
|
| 39 | + // Get all comments and add commenters |
| 40 | + console.log("=== FETCHING COMMENTS ==="); |
| 41 | + const comments = await github.paginate( |
| 42 | + github.rest.issues.listComments, |
| 43 | + { ...repo, issue_number } |
| 44 | + ); |
| 45 | + console.log(`Found ${comments.length} comments`); |
| 46 | + |
| 47 | + if (comments.length === 0) { |
| 48 | + console.log("❌ NO COMMENTS FOUND - This might be why no users are tagged"); |
| 49 | + } |
| 50 | + |
| 51 | + comments.forEach((c, index) => { |
| 52 | + const commenter = c.user.login.toLowerCase(); |
| 53 | + all_participants.add(commenter); |
| 54 | + console.log(`Comment #${index + 1}: Added commenter: ${commenter} (original: ${c.user.login})`); |
| 55 | + }); |
| 56 | +
|
| 57 | + // Get all reactions from comments |
| 58 | + let totalCommentReactions = 0; |
| 59 | + for (const comment of comments) { |
| 60 | + const reactions = await github.paginate( |
| 61 | + github.rest.reactions.listForIssueComment, |
| 62 | + { ...repo, comment_id: comment.id } |
| 63 | + ); |
| 64 | + totalCommentReactions += reactions.length; |
| 65 | + reactions.forEach(r => { |
| 66 | + const reactor = r.user.login.toLowerCase(); |
| 67 | + all_participants.add(reactor); |
| 68 | + console.log(`Added comment reactor: ${reactor}`); |
| 69 | + }); |
| 70 | + } |
| 71 | + console.log(`Processed ${totalCommentReactions} reactions from comments`); |
| 72 | + |
| 73 | + // Get reactions on main issue body |
| 74 | + const issue_reactions = await github.paginate( |
| 75 | + github.rest.reactions.listForIssue, |
| 76 | + { ...repo, issue_number } |
| 77 | + ); |
| 78 | + console.log(`Found ${issue_reactions.length} reactions on issue body`); |
| 79 | + |
| 80 | + issue_reactions.forEach(r => { |
| 81 | + const reactor = r.user.login.toLowerCase(); |
| 82 | + all_participants.add(reactor); |
| 83 | + console.log(`Added issue reactor: ${reactor}`); |
| 84 | + }); |
| 85 | +
|
| 86 | + console.log(`Total unique participants before bot filtering: ${all_participants.size}`); |
| 87 | + console.log(`Participants: ${Array.from(all_participants).join(', ')}`); |
| 88 | +
|
| 89 | + // Filter out bot users |
| 90 | + const isBotUser = (username) => { |
| 91 | + const lowerUsername = username.toLowerCase(); |
| 92 | + return lowerUsername.endsWith('[bot]') || |
| 93 | + lowerUsername === 'dependabot' || |
| 94 | + lowerUsername === 'renovate' || |
| 95 | + lowerUsername === 'greenkeeper' || |
| 96 | + lowerUsername === 'codecov' || |
| 97 | + lowerUsername === 'coveralls' || |
| 98 | + lowerUsername.startsWith('dependabot[') || |
| 99 | + lowerUsername.includes('-bot') || |
| 100 | + lowerUsername.includes('_bot'); |
| 101 | + }; |
| 102 | +
|
| 103 | + // Convert Set to array and filter out bots |
| 104 | + const all_users = Array.from(all_participants).filter(user => !isBotUser(user)); |
| 105 | + |
| 106 | + const filteredBots = Array.from(all_participants).filter(user => isBotUser(user)); |
| 107 | + console.log(`Filtered out ${filteredBots.length} bot users: ${filteredBots.join(', ')}`); |
| 108 | + console.log(`Final participants count: ${all_users.length}`); |
| 109 | + console.log(`Final participants: ${all_users.join(', ')}`); |
| 110 | +
|
| 111 | + if (all_users.length === 0) { |
| 112 | + console.log("No participants to mention after filtering"); |
| 113 | + const fs = require('fs'); |
| 114 | + fs.appendFileSync(process.env.GITHUB_ENV, 'MENTIONS=\n'); |
| 115 | + return; |
| 116 | + } |
| 117 | +
|
| 118 | + const mentions = all_users.map(u => `@${u}`).join(' '); |
| 119 | + console.log(`Generated mentions: ${mentions}`); |
| 120 | + console.log(`Setting environment variable 'MENTIONS' to: "${mentions}"`); |
| 121 | +
|
| 122 | + const fs = require('fs'); |
| 123 | + fs.appendFileSync(process.env.GITHUB_ENV, `MENTIONS=${mentions}\n`); |
| 124 | + return { mentions: mentions }; |
| 125 | + result-encoding: string |
| 126 | + |
| 127 | + - name: Add label comment |
| 128 | + uses: actions/github-script@v7 |
| 129 | + with: |
| 130 | + script: | |
| 131 | + console.log("=== STEP 2: ADD COMMENT ==="); |
| 132 | + console.log("Environment variable access:"); |
| 133 | + console.log("process.env.MENTIONS:", process.env.MENTIONS); |
| 134 | + |
| 135 | + const mentions = process.env.MENTIONS || ''; |
| 136 | + const labelName = context.payload.label.name; |
| 137 | + |
| 138 | + console.log(`Processing label: ${labelName}`); |
| 139 | + console.log(`Mentions received: "${mentions}"`); |
| 140 | + console.log(`Mentions length: ${mentions.length}`); |
| 141 | + console.log(`Mentions trimmed length: ${mentions.trim().length}`); |
| 142 | + |
| 143 | + let message; |
| 144 | + |
| 145 | + if (labelName === 'prerelease') { |
| 146 | + console.log("Processing prerelease label"); |
| 147 | + if (mentions.trim() === "") { |
| 148 | + console.log("No participants to mention for prerelease. Skipping comment creation."); |
| 149 | + return; |
| 150 | + } |
| 151 | + message = `${mentions}\n\nA fix for this issue is now available in the next pre-releases of C#DK/C#. If you'd like to try out the fix, please see [these instructions](https://github.com/microsoft/vscode-dotnettools/wiki/Installing-and-updating-pre%E2%80%90release-versions-of-C%23-Dev-Kit-and-C%23-Extension) to update or try pre-release versions.`; |
| 152 | + console.log("Generated prerelease message"); |
| 153 | + } else if (labelName === 'fixed') { |
| 154 | + console.log("Processing fixed label"); |
| 155 | + message = mentions.trim() !== "" |
| 156 | + ? `${mentions}\n\nThis issue has been fixed! Please update to the latest versions of VS Code, C# Dev Kit, and the C# extension.` |
| 157 | + : `This issue has been fixed! Please update to the latest versions of VS Code, C# Dev Kit, and the C# extension.`; |
| 158 | + console.log(`Generated fixed message ${mentions.trim() !== "" ? "with" : "without"} mentions`); |
| 159 | + } |
| 160 | +
|
| 161 | + console.log(`Final message length: ${message.length}`); |
| 162 | + console.log(`Creating comment on issue #${context.payload.issue.number}`); |
| 163 | +
|
| 164 | + await github.rest.issues.createComment({ |
| 165 | + ...context.repo, |
| 166 | + issue_number: context.payload.issue.number, |
| 167 | + body: message |
| 168 | + }); |
| 169 | + |
| 170 | + console.log("Comment created successfully"); |
0 commit comments