Quellcode durchsuchen

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 vor 10 Stunden
Ursprung
Commit
abff9471ce
1 geänderte Dateien mit 65 neuen und 6 gelöschten Zeilen
  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;