فهرست منبع

fix(triage): respect manual game/engine labels and skip closed issues (#5097)

The triage bot re-added game and engine labels a maintainer removed by
hand, because removing a label triggers the job again and it re-derives
them from the issue text. It also ran on closed issues.

Only run the label jobs on open issues, and keep a game/engine label as
a person last left it (removed or added), like the Linux support label
override. The backfill job follows the same rule.
Daniel Gibbs 10 ساعت پیش
والد
کامیت
abff9471ce
1فایلهای تغییر یافته به همراه65 افزوده شده و 6 حذف شده
  1. 65 6
      .github/workflows/action-issue-triage-automation.yml

+ 65 - 6
.github/workflows/action-issue-triage-automation.yml

@@ -69,7 +69,7 @@ env:
 
 jobs:
   issue-regex-labeler:
-    if: github.repository_owner == 'GameServerManagers' && github.event_name == 'issues' && (github.event.action == 'opened' || github.event.action == 'edited')
+    if: github.repository_owner == 'GameServerManagers' && github.event_name == 'issues' && github.event.issue.state == 'open' && (github.event.action == 'opened' || github.event.action == 'edited')
     runs-on: ubuntu-latest
     steps:
       - name: Issue Labeler
@@ -82,7 +82,7 @@ jobs:
           sync-labels: 0
 
   issue-ai-maintenance:
-    if: github.repository_owner == 'GameServerManagers' && (github.event_name == 'issues' || github.event_name == 'issue_comment')
+    if: github.repository_owner == 'GameServerManagers' && (github.event_name == 'issues' || github.event_name == 'issue_comment') && github.event.issue.state == 'open'
     runs-on: ubuntu-latest
     steps:
       - name: Reconcile issue labels and AI triage
@@ -819,8 +819,37 @@ jobs:
             }
 
             // Avoid pointless API calls.
-            const finalAdds = [...labelsToAdd].filter((label) => !existingLabels.has(label));
-            const finalRemoves = [...labelsToRemove].filter((label) => existingLabels.has(label));
+            let finalAdds = [...labelsToAdd].filter((label) => !existingLabels.has(label));
+            let finalRemoves = [...labelsToRemove].filter((label) => existingLabels.has(label));
+
+            const isGameOrEngineLabel = (label) => label.startsWith('game: ') || label.startsWith('engine: ');
+            if ([...finalAdds, ...finalRemoves].some(isGameOrEngineLabel)) {
+              try {
+                const issueEvents = await github.paginate(github.rest.issues.listEvents, {
+                  owner,
+                  repo,
+                  issue_number: issueNumber,
+                  per_page: 100,
+                });
+                const lastManualLabelEvent = new Map();
+                for (const e of issueEvents) {
+                  if (!['labeled', 'unlabeled'].includes(e.event) || !e.label?.name) continue;
+                  lastManualLabelEvent.set(e.label.name, e.actor?.type === 'Bot' ? null : e.event);
+                }
+                finalAdds = finalAdds.filter((label) => {
+                  if (!isGameOrEngineLabel(label) || lastManualLabelEvent.get(label) !== 'unlabeled') return true;
+                  console.log(`Label "${label}" was removed manually; not adding it back.`);
+                  return false;
+                });
+                finalRemoves = finalRemoves.filter((label) => {
+                  if (!isGameOrEngineLabel(label) || lastManualLabelEvent.get(label) !== 'labeled') return true;
+                  console.log(`Label "${label}" was added manually; keeping it.`);
+                  return false;
+                });
+              } catch (err) {
+                console.log(`Could not read issue events: ${err.message}`);
+              }
+            }
 
             for (const label of finalRemoves) {
               try {
@@ -2199,8 +2228,38 @@ jobs:
                 }
 
                 // Apply changes
-                const finalAdds = [...labelsToAdd].filter((label) => !existingLabels.has(label));
-                const finalRemoves = [...labelsToRemove].filter((label) => existingLabels.has(label));
+                let finalAdds = [...labelsToAdd].filter((label) => !existingLabels.has(label));
+                let finalRemoves = [...labelsToRemove].filter((label) => existingLabels.has(label));
+
+                const isGameOrEngineLabel = (label) => label.startsWith('game: ') || label.startsWith('engine: ');
+                if ([...finalAdds, ...finalRemoves].some(isGameOrEngineLabel)) {
+                  try {
+                    const issueEvents = await github.paginate(github.rest.issues.listEvents, {
+                      owner,
+                      repo,
+                      issue_number: rawIssue.number,
+                      per_page: 100,
+                    });
+                    const lastManualLabelEvent = new Map();
+                    for (const e of issueEvents) {
+                      if (!['labeled', 'unlabeled'].includes(e.event) || !e.label?.name) continue;
+                      lastManualLabelEvent.set(e.label.name, e.actor?.type === 'Bot' ? null : e.event);
+                    }
+                    finalAdds = finalAdds.filter((label) => {
+                      if (!isGameOrEngineLabel(label) || lastManualLabelEvent.get(label) !== 'unlabeled') return true;
+                      console.log(`#${rawIssue.number}: "${label}" was removed manually; not adding it back`);
+                      return false;
+                    });
+                    finalRemoves = finalRemoves.filter((label) => {
+                      if (!isGameOrEngineLabel(label) || lastManualLabelEvent.get(label) !== 'labeled') return true;
+                      console.log(`#${rawIssue.number}: "${label}" was added manually; keeping it`);
+                      return false;
+                    });
+                  } catch (err) {
+                    if (isApiRateLimitError(err)) throw err;
+                    console.log(`#${rawIssue.number}: could not read issue events: ${err.message}`);
+                  }
+                }
 
                 let labelAdded = 0;
                 let labelRemoved = 0;